1extern crate time;
2extern crate rand;
3
4use std::fmt::Debug;
5use labdef::*;
6use std::marker::PhantomData;
7
8use adapton::engine::*;
9use adapton::reflect;
10use adapton::engine::manage::*;
11use rand::{Rng, SeedableRng};
12use std::mem::swap;
13
14pub trait SampleGen {
15 fn sample(self:&mut Self) -> Option<Sample>;
16}
17
18pub struct LabEngineState<Input,EditSt,Output,
19 Editor:Generate<Input>+Edit<Input,EditSt>,
20 Archivist:ComputeDemand<Input,Output>> {
21 pub engine: Engine,
22 pub input: Option<(Input,EditSt)>,
23 inputdist: PhantomData<Editor>,
24 computer: PhantomData<Archivist>,
25 output: PhantomData<Output>,
26}
27
28pub struct LabState<R:Rng+Clone,
29 Input,EditSt,Output,
30 Editor:Generate<Input>+Edit<Input,EditSt>,
31 Archivist:ComputeDemand<Input,Output>> {
32 pub params: LabParams,
33 pub rng: Box<R>,
34 pub change_batch_num: usize,
35 pub dcg_state: LabEngineState<Input,EditSt,Output,Editor,Archivist>,
36 pub naive_state: LabEngineState<Input,EditSt,Output,Editor,Archivist>,
37 pub samples: Vec<Sample>,
38}
39
40
41fn get_engine_metrics<X,F:FnOnce() -> X> (params:&SampleParams, thunk:F) -> (X,EngineMetrics)
42{
43 if params.reflect_trace { reflect::dcg_reflect_begin(); };
44 let time_start = time::precise_time_ns();
45 let x = (thunk)();
46 let time_end = time::precise_time_ns();
47 let traces = if params.reflect_trace { reflect::dcg_reflect_end() } else { vec![ ] };
48 let dcg = if params.reflect_dcg { reflect::dcg_reflect_now() } else { None };
49 return (x, EngineMetrics{
50 time_ns:time_end - time_start,
51 reflect_traces:traces,
53 reflect_dcg:dcg,
54 })
55}
56
57fn get_engine_sample
58 <R:Rng+Clone,
59 Input:Clone+Debug,
60 EditSt,Output:Debug,
61 Editor:Generate<Input>+Edit<Input,EditSt>,
62 Archivist:ComputeDemand<Input,Output>
63 >
64 (rng:&mut R, params:&SampleParams, input:Option<(Input,EditSt)>) -> (Output,Input,EditSt,EngineSample)
65{
66 let mut rng2 = rng;
67
68 let ((edited_input, editst), process_input) : ((Input,EditSt),EngineMetrics) =
69 match input {
70 None =>
71 get_engine_metrics( params,
72 move || ( Editor::generate(&mut rng2, ¶ms.generate_params),
73 Editor::edit_init(&mut rng2, ¶ms.generate_params ))),
74 Some((input, editst)) =>
75 get_engine_metrics( params,
76 move || Editor::edit(input, editst, &mut rng2, ¶ms.generate_params))
77 };
78
79 let input2 = edited_input.clone();
80
81 let input2r =
82 if params.reflect_dcg {
83 Some(reflect::reflect_val(&input2))
84 } else { None };
85
86 let (output, compute_output): (Output,EngineMetrics)
87 = ns(name_of_str("compute"),
88 move ||
89 get_engine_metrics(
90 params, move ||
91 Archivist::compute(input2, params.demand)
92 ));
93
94 let outputr =
95 if params.reflect_dcg {
96 Some(reflect::reflect_val(&output))
97 } else { None };
98
99 let engine_sample = EngineSample{
100 process_input,
101 input: input2r,
102 compute_output,
103 output: outputr,
104 };
105
106 return (output, edited_input, editst, engine_sample)
107}
108
109fn get_sample_gen
110 <Input:Clone+Debug,
111 EditSt,
112 Output:Eq+Debug,
113 Editor:Generate<Input>+Edit<Input,EditSt>,
114 Archivist:ComputeDemand<Input,Output>>
115 (params:&LabParams)
116 -> LabState<rand::StdRng,Input,EditSt,Output,Editor,Archivist>
117{
118 let _ = init_dcg(); assert!(engine_is_dcg());
120 let empty_dcg = use_engine(Engine::Naive); let rng = SeedableRng::from_seed(params.sample_params.input_seeds.as_slice());
122 LabState{
124 params:params.clone(),
125 rng:Box::new(rng),
126 dcg_state:LabEngineState{
127 input: None,
128 engine: empty_dcg, output: PhantomData, inputdist: PhantomData, computer: PhantomData,
130 },
131 naive_state:LabEngineState{
132 input: None,
133 engine: Engine::Naive, output: PhantomData, inputdist: PhantomData, computer: PhantomData,
135 },
136 change_batch_num: 0,
137 samples:vec![],
138 }
139}
140
141impl<Input:Clone+Debug,EditSt,Output:Eq+Debug,
146 Editor:Generate<Input>+Edit<Input,EditSt>,
147 Archivist:ComputeDemand<Input,Output>>
148 SampleGen for LabState<rand::StdRng,Input,EditSt,Output,Editor,Archivist> {
149 fn sample (self:&mut Self) -> Option<Sample> {
150 if self.change_batch_num > self.params.change_batch_loopc {
151 None
152 } else { let mut dcg_state = LabEngineState{ input: None, engine: Engine::Naive,
154 output: PhantomData, inputdist: PhantomData, computer: PhantomData };
155 swap(&mut dcg_state, &mut self.dcg_state );
156 let mut naive_state = LabEngineState{ input: None, engine: Engine::Naive,
157 output: PhantomData, inputdist: PhantomData, computer: PhantomData };
158 swap(&mut naive_state, &mut self.naive_state );
159
160 let _ = use_engine(Engine::Naive); assert!(engine_is_naive());
163 let mut rng = self.rng.clone(); let (naive_output, naive_input_edited, naive_editst, naive_sample) =
165 get_engine_sample::<rand::StdRng,Input,EditSt,Output,Editor,Archivist>
166 (&mut rng, &self.params.sample_params, naive_state.input);
167 self.naive_state.input = Some((naive_input_edited, naive_editst)); let _ = use_engine(dcg_state.engine); assert!(engine_is_dcg()); let mut rng = self.rng.clone(); let (dcg_output, dcg_input_edited, dcg_editst, dcg_sample) =
175 get_engine_sample::<rand::StdRng,Input,EditSt,Output,Editor,Archivist>
176 (&mut rng, &self.params.sample_params, dcg_state.input);
177 self.dcg_state.engine = use_engine(Engine::Naive); self.dcg_state.input = Some((dcg_input_edited, dcg_editst)); self.rng = Box::new(*rng);
182
183 let output_valid = if self.params.sample_params.validate_output {
185 Some ( dcg_output == naive_output )
186 } else { None } ;
187
188 let sample = Sample{
189 batch_name:self.change_batch_num,
191 dcg_sample,
192 naive_sample,
193 output_valid,
194 };
195 self.change_batch_num += 1;
196 Some(sample)
197 }
198 }
199 }
200
201impl<Input:Clone+Debug,EditSt,Output:Eq+Debug,
204 Editor:'static+Generate<Input>+Edit<Input,EditSt>,
205 Archivist:'static+ComputeDemand<Input,Output>>
206 Lab for LabDef<Input,EditSt,Output,Editor,Archivist> {
207 fn name(self:&Self) -> Name { self.identity.clone() }
208 fn url(self:&Self) -> &Option<String> { &self.url }
209 fn run(self:&Self, params:&LabParams) -> LabResults
210 {
211 let mut st = get_sample_gen::<Input,EditSt,Output,Editor,Archivist>(params);
212 loop {
213 let sample = (&mut st).sample();
215 match sample {
219 Some(s) => {st.samples.push(s); continue},
220 None => break,
221 }
222 };
223 return LabResults {
224 samples: st.samples,
225 }
226 }
227 }