Struct GraphSolver

Source
pub struct GraphSolver<'a, 'b> { /* private fields */ }
Expand description

The graph solver is a transient object which can execute the tasks described in a graph. It is designed to be generated and dropped on every execution.

Implementations§

Source§

impl<'a, 'b> GraphSolver<'a, 'b>

Source

pub fn new( graph: &'a Graph, last_cache: &'b mut ValuesCache, ) -> GraphSolver<'a, 'b>

creates a solver for graph ‘graph’, using cache from a previous solve. the cache may be empty.

Examples found in repository?
examples/seq10k.rs (line 35)
6fn main() {
7    let mut g = Graph::new();
8
9    let max = 10000;
10
11    // generate 10000 nodes
12    for i in 1..max {
13        let name: String = format!("task{}", i);
14        g.add_node(create_node!(name: name, ( input : u32) -> (output : u32)
15                                 { 
16                                     output = input +1 ;
17                                 }))
18            .unwrap();
19    }
20
21
22    // add sequential linking
23    for i in 1..max - 1 {
24        let src = format!("task{}::output", i);
25        let sink = format!("task{}::input", i + 1);
26        g.bind_asset(src.as_str(), sink.as_str())
27            .expect("binding must be doable");
28    }
29
30    g.define_freestanding_asset("start", 0u32).expect("could not create asset");
31        g.bind_asset("start", "task1::input")
32            .expect("could not bind first tast to start value");
33
34    let mut cache = ValuesCache::new();
35    let mut solver = GraphSolver::new(&g, &mut cache);
36
37    let last_task = format!("task{}", max-1);
38    solver.execute(last_task.as_str()).expect("this should run");
39}
More examples
Hide additional examples
examples/simple.rs (line 48)
6fn main() {
7    let mut g = Graph::new();
8
9    g.add_node(create_node!(
10                gen_one () -> (one: u32) {
11                    println!("              gen one");
12                    one = 1u32;
13                }
14            )).unwrap();
15
16    g.add_node(create_node!(
17                plus_one (one: u32) -> (plusone : u32) {
18                    println!("              plusone");
19                    plusone = one + 1u32;
20                }
21            )).unwrap();
22
23    g.add_node(create_node!(
24                the_one_task  (one: u32, plusone : u32) ->
25                              (last_value: f32) {
26                    println!("              the one task");
27                    last_value = (one + plusone) as f32;
28                }
29            )).unwrap();
30
31    g.add_node(create_node!(
32                list (list : Vec<u32>) -> () {
33                    println!("             list");
34                }
35            )).unwrap();
36
37    g.bind_asset("gen_one::one", "plus_one::one")
38        .expect("binding must be doable");
39    g.bind_asset("gen_one::one", "the_one_task::one")
40        .expect("binding must be doable");
41    g.bind_asset("plus_one::plusone", "the_one_task::plusone")
42        .expect("binding must be doable");
43
44    let mut cache = ValuesCache::new();
45
46    for _ in 0..10 {
47        {
48            let mut solver = GraphSolver::new(&g, &mut cache);
49            assert!(solver.execute("nop").is_err());
50
51            solver.execute("the_one_task").expect("could not execute");
52
53            println!("{:?}", solver.get_values());
54
55            assert!(
56                solver
57                    .get_value::<u32>("gen_one::one")
58                    .expect("never created?") == 1
59            );
60            assert!(
61                solver
62                    .get_value::<u32>("plus_one::plusone")
63                    .expect("never created?") == 2
64            );
65            assert!(
66                (solver
67                    .get_value::<f32>("the_one_task::last_value")
68                    .expect("not cached?") - 3.0)
69                    .abs() < 0.01
70            );
71        }
72
73        assert!(cache.get_value::<u32>("gen_one::one").expect("not cached?") == 1);
74        assert!(
75            cache
76                .get_value::<u32>("plus_one::plusone")
77                .expect("not cached?") == 2
78        );
79        assert!(
80            (cache
81                .get_value::<f32>("the_one_task::last_value")
82                .expect("not cached?") - 3.0)
83                .abs() < 0.01
84        );
85    }
86}
Source

pub fn get_binding(&self, name: &str) -> Result<&String, SolverError>

Source

pub fn execute(&mut self, name: &str) -> Result<SolverStatus, SolverError>

Executes a task by name, all tasks needed to provide Assets are transitively executed

Examples found in repository?
examples/seq10k.rs (line 38)
6fn main() {
7    let mut g = Graph::new();
8
9    let max = 10000;
10
11    // generate 10000 nodes
12    for i in 1..max {
13        let name: String = format!("task{}", i);
14        g.add_node(create_node!(name: name, ( input : u32) -> (output : u32)
15                                 { 
16                                     output = input +1 ;
17                                 }))
18            .unwrap();
19    }
20
21
22    // add sequential linking
23    for i in 1..max - 1 {
24        let src = format!("task{}::output", i);
25        let sink = format!("task{}::input", i + 1);
26        g.bind_asset(src.as_str(), sink.as_str())
27            .expect("binding must be doable");
28    }
29
30    g.define_freestanding_asset("start", 0u32).expect("could not create asset");
31        g.bind_asset("start", "task1::input")
32            .expect("could not bind first tast to start value");
33
34    let mut cache = ValuesCache::new();
35    let mut solver = GraphSolver::new(&g, &mut cache);
36
37    let last_task = format!("task{}", max-1);
38    solver.execute(last_task.as_str()).expect("this should run");
39}
More examples
Hide additional examples
examples/simple.rs (line 49)
6fn main() {
7    let mut g = Graph::new();
8
9    g.add_node(create_node!(
10                gen_one () -> (one: u32) {
11                    println!("              gen one");
12                    one = 1u32;
13                }
14            )).unwrap();
15
16    g.add_node(create_node!(
17                plus_one (one: u32) -> (plusone : u32) {
18                    println!("              plusone");
19                    plusone = one + 1u32;
20                }
21            )).unwrap();
22
23    g.add_node(create_node!(
24                the_one_task  (one: u32, plusone : u32) ->
25                              (last_value: f32) {
26                    println!("              the one task");
27                    last_value = (one + plusone) as f32;
28                }
29            )).unwrap();
30
31    g.add_node(create_node!(
32                list (list : Vec<u32>) -> () {
33                    println!("             list");
34                }
35            )).unwrap();
36
37    g.bind_asset("gen_one::one", "plus_one::one")
38        .expect("binding must be doable");
39    g.bind_asset("gen_one::one", "the_one_task::one")
40        .expect("binding must be doable");
41    g.bind_asset("plus_one::plusone", "the_one_task::plusone")
42        .expect("binding must be doable");
43
44    let mut cache = ValuesCache::new();
45
46    for _ in 0..10 {
47        {
48            let mut solver = GraphSolver::new(&g, &mut cache);
49            assert!(solver.execute("nop").is_err());
50
51            solver.execute("the_one_task").expect("could not execute");
52
53            println!("{:?}", solver.get_values());
54
55            assert!(
56                solver
57                    .get_value::<u32>("gen_one::one")
58                    .expect("never created?") == 1
59            );
60            assert!(
61                solver
62                    .get_value::<u32>("plus_one::plusone")
63                    .expect("never created?") == 2
64            );
65            assert!(
66                (solver
67                    .get_value::<f32>("the_one_task::last_value")
68                    .expect("not cached?") - 3.0)
69                    .abs() < 0.01
70            );
71        }
72
73        assert!(cache.get_value::<u32>("gen_one::one").expect("not cached?") == 1);
74        assert!(
75            cache
76                .get_value::<u32>("plus_one::plusone")
77                .expect("not cached?") == 2
78        );
79        assert!(
80            (cache
81                .get_value::<f32>("the_one_task::last_value")
82                .expect("not cached?") - 3.0)
83                .abs() < 0.01
84        );
85    }
86}
Source

pub fn execute_terminals(&mut self) -> Result<SolverStatus, SolverError>

Source

pub fn input_is_new<T>(&self, new_value: &T, name: &String) -> bool
where T: Clone + Comparable + 'static,

Check if the input is still valid. This function is used to compute if the input of a task has changed over iterations. if all inputs are cached and equal to current values, and a cached output is available. The output will be considered valid and the computation skipped

Source

pub fn input_is_new_str<T>(&self, new_value: &T, name: &str) -> bool
where T: Clone + Comparable + 'static,

Check if the input is still valid. This function is used to compute if the input of a task has changed over iterations. if all inputs are cached and equal to current values, and a cached output is available. The output will be considered valid and the computation skipped

Source

pub fn use_old_ouput<T: AsRef<str>>(&mut self, ouputs: &[T]) -> bool

function to decide whenever the set of values is still valid or the producing node of any of the values needs to be executed

Source

pub fn get_values(&self) -> &ValuesCache

Examples found in repository?
examples/simple.rs (line 53)
6fn main() {
7    let mut g = Graph::new();
8
9    g.add_node(create_node!(
10                gen_one () -> (one: u32) {
11                    println!("              gen one");
12                    one = 1u32;
13                }
14            )).unwrap();
15
16    g.add_node(create_node!(
17                plus_one (one: u32) -> (plusone : u32) {
18                    println!("              plusone");
19                    plusone = one + 1u32;
20                }
21            )).unwrap();
22
23    g.add_node(create_node!(
24                the_one_task  (one: u32, plusone : u32) ->
25                              (last_value: f32) {
26                    println!("              the one task");
27                    last_value = (one + plusone) as f32;
28                }
29            )).unwrap();
30
31    g.add_node(create_node!(
32                list (list : Vec<u32>) -> () {
33                    println!("             list");
34                }
35            )).unwrap();
36
37    g.bind_asset("gen_one::one", "plus_one::one")
38        .expect("binding must be doable");
39    g.bind_asset("gen_one::one", "the_one_task::one")
40        .expect("binding must be doable");
41    g.bind_asset("plus_one::plusone", "the_one_task::plusone")
42        .expect("binding must be doable");
43
44    let mut cache = ValuesCache::new();
45
46    for _ in 0..10 {
47        {
48            let mut solver = GraphSolver::new(&g, &mut cache);
49            assert!(solver.execute("nop").is_err());
50
51            solver.execute("the_one_task").expect("could not execute");
52
53            println!("{:?}", solver.get_values());
54
55            assert!(
56                solver
57                    .get_value::<u32>("gen_one::one")
58                    .expect("never created?") == 1
59            );
60            assert!(
61                solver
62                    .get_value::<u32>("plus_one::plusone")
63                    .expect("never created?") == 2
64            );
65            assert!(
66                (solver
67                    .get_value::<f32>("the_one_task::last_value")
68                    .expect("not cached?") - 3.0)
69                    .abs() < 0.01
70            );
71        }
72
73        assert!(cache.get_value::<u32>("gen_one::one").expect("not cached?") == 1);
74        assert!(
75            cache
76                .get_value::<u32>("plus_one::plusone")
77                .expect("not cached?") == 2
78        );
79        assert!(
80            (cache
81                .get_value::<f32>("the_one_task::last_value")
82                .expect("not cached?") - 3.0)
83                .abs() < 0.01
84        );
85    }
86}

Trait Implementations§

Source§

impl<'a, 'b> Cache for GraphSolver<'a, 'b>

Source§

fn get_value<T>(&self, name: &str) -> Result<T, SolverError>
where T: Clone + 'static,

Retrieves a value from the solver. It is required to know the name and type of the asset. Cast error will return SolveError::AssetWrongType
Source§

fn save_value<T>(&mut self, name: &String, value: T)
where T: Clone + 'static,

Saves a value to be available during execution. This routine can be used to feed initial values for Assets. i.e. unbond assets Assets not generated by any Task.
Source§

fn save_value_str<T>(&mut self, name: &str, value: T)
where T: Clone + 'static,

Saves a value to be available during execution. This routine can be used to feed initial values for Assets. i.e. unbond assets Assets not generated by any Task.
Source§

impl<'a, 'b> Drop for GraphSolver<'a, 'b>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

§

impl<'a, 'b> Freeze for GraphSolver<'a, 'b>

§

impl<'a, 'b> !RefUnwindSafe for GraphSolver<'a, 'b>

§

impl<'a, 'b> !Send for GraphSolver<'a, 'b>

§

impl<'a, 'b> !Sync for GraphSolver<'a, 'b>

§

impl<'a, 'b> Unpin for GraphSolver<'a, 'b>

§

impl<'a, 'b> !UnwindSafe for GraphSolver<'a, 'b>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.