adapton_lab/
labdef.rs

1//use adapton::engine::Cnt; // Counters for engine costs
2use adapton::engine::Name; // Names, for naming things uniquely
3use adapton::reflect::DCG;
4use adapton::reflect::Val;
5use adapton::reflect::trace::Trace;
6use rand::Rng;
7use std::marker::PhantomData;
8
9/// A bit that controls how names are placed in the input; See `README.md` for more.
10#[derive(Clone,Debug)]
11pub enum NominalStrategy {
12  Regular,
13  ByContent,
14}
15
16/// Parameters for generating and editing input; See `README.md` for more.
17#[derive(Clone,Debug)]
18pub struct GenerateParams {
19  pub size: usize, 
20  pub gauge: usize, 
21  pub nominal_strategy:NominalStrategy
22}
23
24/// Generic method for generating a random input.
25/// See `README.md` for more.
26pub trait Generate<T> {
27  fn generate<R:Rng>(rng:&mut R, params:&GenerateParams) -> T;
28} 
29
30/// Generic process for editing an input randomly, in a stateful sequence of edits.
31/// See `README.md` for more.
32pub trait Edit<T,S> : Clone {
33  fn edit_init<R:Rng>(rng:&mut R, params:&GenerateParams) -> S;
34  fn edit<R:Rng>(pre_edit:T, edit_state:S, rng:&mut R, params:&GenerateParams) -> (T, S);
35}
36
37/// Generic notion of a computation to run naively and incrementally.
38/// It has specific `Input` and `Output` types, and a way to `compute`
39/// the `Output` from the `Input`.
40/// See `README.md` for more.
41pub trait Compute<Input,Output> {
42  fn compute(Input) -> Output;
43}
44
45/// Like Compute, but also provides a `demand` size, for lazy algorithms.
46pub trait ComputeDemand<Input,Output> {
47  fn compute(Input, usize) -> Output;
48}
49
50impl<Input,Output,X:Compute<Input,Output>> ComputeDemand<Input,Output> for X {
51  fn compute(inp:Input, _demand:usize) -> Output {
52    X::compute(inp)
53  }
54}
55
56/// _lab definition_: generic notion of an incremental computation
57/// that can be evaluated and tested.  We instantiate this structure
58/// once for each test in our test suite.  We implement the `LabDef`
59/// trait generically for this structure.  See `catalog` module for
60/// example instances.
61pub struct LabDef<Input,EditSt,Output,
62               Editor:   Generate<Input>+Edit<Input,EditSt>,
63               Archivist:ComputeDemand<Input,Output>> 
64{
65  pub identity:  Name,
66  pub url:       Option<String>,
67
68  pub editor:    PhantomData<Editor>,
69  pub archivist: PhantomData<Archivist>,
70
71  pub input:     PhantomData<Input>,
72  pub editst:    PhantomData<EditSt>,
73  pub output:    PhantomData<Output>
74}
75
76/// _lab_: Abstracts over parts of a lab definition of type `LabDef`:
77/// Hides the `Input`, `Output` and `Archivist` types of a `LabDef`.
78pub trait Lab {
79  fn name(self:&Self) -> Name;
80  fn url(self:&Self) -> &Option<String>;
81  fn run(self:&Self, params:&LabParams) -> LabResults;
82}
83
84/// Parameters to running a single lab experiment.
85#[derive(Clone,Debug)]
86pub struct LabParams {
87  pub sample_params: SampleParams,
88  // TODO: Pretty-print input and output structures; graphmovie dump of experiment
89  /// Number of change-batches to perform in a loop; each is interposed with computing the new output.
90  pub change_batch_loopc: usize,
91}
92
93/// Parameters for collecting a single sample.  In addition to these
94/// parameters, the experiment maintains a Rng based on the
95/// input_seeds, below; this Rng is given to Edit::edit to generate
96/// psuedo-random edits, in batches.  For each engine, this Rng is
97/// sequenced across successive samples.  Given an input_seeds vector,
98/// there is one unique Rng sequence for each engine's sequence of
99/// samples.
100#[derive(Clone,Debug)]
101pub struct SampleParams {
102  /// We convert this seed into a random-number-generator before generating and editing.
103  pub input_seeds:       Vec<usize>, 
104  /// Other parameters for generating the input.
105  pub generate_params:   GenerateParams, 
106  /// _demand_: For lazy algorithms, the number of output elements to
107  /// force, e.g., by producing a vector of output data.  Eager
108  /// algorithms ignore this parameter (they always produce _all_ of
109  /// their output).
110  pub demand: usize,
111  /// Whether to validate the output after each computation using the naive and DCG engines
112  pub validate_output:   bool,
113  /// Size of each batch of changes.
114  pub change_batch_size: usize,
115  /// Reflect the trace (See `adapton::engine::reflect::trace::Trace`).
116  pub reflect_trace: bool,
117  /// Reflect the DCG (See `adapton::engine::reflect::DCG`), including
118  /// its values (See `adapton::engine::reflect_val`).
119  pub reflect_dcg: bool,
120}
121
122/// The result of a lab is a sequence of samples.
123#[derive(Clone,Debug)]
124pub struct LabResults {
125  pub samples: Vec<Sample>
126}
127
128/// The experiment consists of a loop over samples.  For each sample,
129/// we switch back and forth between using the Naive engine, and using
130/// the DCG engine.  We want to interleave this way for each sample in
131/// order to compare outputs and metrics (counts and timings) on a
132/// fine-grained scale.
133#[derive(Clone,Debug)]
134pub struct Sample {
135  //pub params:       SampleParams,
136  pub batch_name:   usize,   // Index/name the change batches; one sample per compute + change batch
137  pub dcg_sample:   EngineSample,
138  pub naive_sample: EngineSample,
139  pub output_valid: Option<bool>
140}
141
142/// To sample a single engine, we record metrics for processing the
143/// input (left vertical edge in `README.md` diagram).
144#[derive(Clone,Debug)]
145pub struct EngineSample {
146  /// TODO: Rename: 'editor' (for editor role)
147  pub process_input:    EngineMetrics,
148  /// TODO: Rename: 'archivist' (for archivist role)
149  pub compute_output:   EngineMetrics,
150  
151  pub input: Option<Val>,
152  pub output: Option<Val>,
153}
154
155/// For each engine, for each sampled subcomputation, we record the
156/// real time (in nanoseconds) and engine-based counters for DCG costs.
157#[derive(Clone,Debug)]
158pub struct EngineMetrics {
159  /// Time in milliseconds.
160  pub time_ns:    u64,
161  /// Counts of engine (engine trace-level) operations (See
162  /// `engine::reflect::trace::Trace`) during the sample.
163//  pub engine_cnt: Cnt,
164  /// The reflected traces of the DCG during the sample; empty if this
165  /// option is disabled.
166  pub reflect_traces: Vec<Trace>,
167  /// The reflected version of the DCG, at the conclusion of the
168  /// sample; None if this option is disabled.
169  pub reflect_dcg: Option<DCG>,
170}