Skip to content

Commit d791449

Browse files
committed
Updated tests for deterministic input-output causaloids. Updated test utils. Improved causality graph evaluation logical clarity.
Signed-off-by: Marvin Hansen <[email protected]>
1 parent 512a6c0 commit d791449

File tree

4 files changed

+78
-36
lines changed

4 files changed

+78
-36
lines changed

deep_causality/src/utils_test/test_utils.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,29 @@ pub fn get_test_causaloid_deterministic() -> BaseCausaloid {
139139
Causaloid::new(id, causal_fn, description)
140140
}
141141

142+
pub fn get_test_causaloid_deterministic_input_output() -> BaseCausaloid {
143+
let id: IdentificationValue = 2;
144+
let description = "Inverts any input";
145+
146+
fn causal_fn(effect: &PropagatingEffect) -> Result<PropagatingEffect, CausalityError> {
147+
let obs =
148+
match effect {
149+
// If it's the Deterministic variant, extract the inner value.
150+
PropagatingEffect::Deterministic(val) => *val,
151+
// For any other type of effect, this function cannot proceed, so return an error.
152+
_ => return Err(CausalityError(
153+
"Causal function expected Numerical effect but received a different variant."
154+
.into(),
155+
)),
156+
};
157+
158+
// Just invert the value.
159+
Ok(PropagatingEffect::Deterministic(!obs))
160+
}
161+
162+
Causaloid::new(id, causal_fn, description)
163+
}
164+
142165
// BaseContext is a type alias for a basic context that can be used for testing
143166
// It matches the type signature of the base causaloid also uses in these tests.
144167
// See src/types/alias_types/csm_types for definition.

deep_causality/tests/types/causal_types/causaloid/causaloid_tests.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -352,24 +352,26 @@ fn test_explain_collection_success() {
352352
assert!(explanation.contains("evaluated to: PropagatingEffect::Deterministic(true)"));
353353
assert!(explanation.contains("evaluated to: PropagatingEffect::Deterministic(false)"));
354354
}
355+
355356
// This test covers an error path in explain() for a Collection Causaloid.
356357
#[test]
357358
fn test_explain_collection_with_sub_explain_error() {
358359
// Setup: A collection where one causaloid will not be evaluated due to short-circuiting.
359-
let true_causaloid = test_utils::get_test_causaloid_deterministic_true();
360+
let evaluated_causaloid = test_utils::get_test_causaloid_deterministic_true();
360361
let unevaluated_causaloid = test_utils::get_test_causaloid_deterministic(); // This one will remain unevaluated.
361362

362-
let causal_coll = vec![true_causaloid, unevaluated_causaloid];
363+
// Act: Evaluate the collection. The evaluation will stop after the first `true` effect.
364+
let effect = PropagatingEffect::Numerical(0.0);
365+
evaluated_causaloid.evaluate(&effect).unwrap();
366+
367+
// collection_causaloid is only partially evaluated.
368+
let causal_coll = vec![evaluated_causaloid, unevaluated_causaloid];
363369
let collection_causaloid = Causaloid::from_causal_collection(
364370
105,
365371
Arc::new(causal_coll),
366372
"Sub-explain Error Collection",
367373
);
368374

369-
// Act: Evaluate the collection. The evaluation will stop after the first `true` effect.
370-
let effect = PropagatingEffect::Numerical(0.0);
371-
collection_causaloid.evaluate(&effect).unwrap();
372-
373375
// Now, call explain. This will fail because the second causaloid was never evaluated.
374376
let result = collection_causaloid.explain();
375377

@@ -414,7 +416,7 @@ fn test_evaluate_singleton_with_context() {
414416
}
415417

416418
#[test]
417-
fn test_evaluate_collection_ignores_other_effects() {
419+
fn test_evaluate_collection_other_effect_err() {
418420
// Setup: A collection with causaloids that have effects other than Deterministic or Halting.
419421
let probabilistic_causaloid = test_utils::get_test_causaloid_probabilistic();
420422
let contextual_link_causaloid = test_utils::get_test_causaloid_contextual_link();
@@ -430,9 +432,9 @@ fn test_evaluate_collection_ignores_other_effects() {
430432

431433
// Act
432434
let effect = PropagatingEffect::Numerical(0.0);
433-
let res = collection_causaloid.evaluate(&effect).unwrap();
435+
let res = collection_causaloid.evaluate(&effect);
434436

435-
// Assert: The aggregation logic should ignore Probabilistic and ContextualLink,
436-
// resulting in an overall effect of Deterministic(false).
437-
assert_eq!(res, PropagatingEffect::Deterministic(false));
437+
// Assert: The collection should return an error because
438+
// it contains a causaloid with an effect other than Deterministic or Probabilistic.
439+
assert!(res.is_err())
438440
}

deep_causality/tests/types/causal_types/causaloid_graph/causality_graph_reasoning_all_tests.rs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,34 +18,46 @@ fn test_graph_evaluate() {
1818
assert!(g.contains_causaloid(root_index));
1919

2020
// Add causaloid A
21-
let causaloid_a = test_utils::get_test_causaloid_deterministic();
21+
let causaloid_a = test_utils::get_test_causaloid_deterministic_input_output();
2222
let idx_a = g
2323
.add_causaloid(causaloid_a)
2424
.expect("Failed to add causaloid A");
25+
26+
// Link A to root
2527
g.add_edge(root_index, idx_a).expect("Failed to add edge");
2628

2729
// Add causaloid B
28-
let causaloid_b = test_utils::get_test_causaloid_deterministic();
30+
let causaloid_b = test_utils::get_test_causaloid_deterministic_input_output();
2931
let idx_b = g
3032
.add_causaloid(causaloid_b)
3133
.expect("Failed to add causaloid B");
32-
g.add_edge(root_index, idx_b).expect("Failed to add edge");
3334

34-
// Add causaloid C
35-
let causaloid_c = test_utils::get_test_causaloid_deterministic();
36-
let idx_c = g
37-
.add_causaloid(causaloid_c)
38-
.expect("Failed to add causaloid C");
39-
g.add_edge(idx_a, idx_c).expect("Failed to add edge");
35+
// Link A to B
36+
g.add_edge(idx_a, idx_b).expect("Failed to add edge");
4037

38+
// Now, we have a graph like this:
39+
// root -> A -> B
4140
g.freeze();
4241

43-
// Evaluate the graph using the Causable::evaluate method
42+
// Create an initial effect to be applied to the root node
4443
let effect = PropagatingEffect::Numerical(0.99); // A value that will activate all nodes
45-
let res = g.evaluate(&effect);
44+
// Here we evaluate the effect on the root node only,
45+
let res = g.evaluate_shortest_path_between_causes(root_index, root_index, &effect);
46+
assert!(res.is_ok());
47+
// The root node returns Deterministic(true) because its causal function evaluates to true w.r.t. to effect
48+
assert_eq!(res.unwrap(), PropagatingEffect::Deterministic(true));
49+
50+
// Now, we evaluate the effect propagating from root to A
51+
// Root evaluates from Numerical to true; and A evaluates from Boolean true to Boolean false
52+
let res = g.evaluate_shortest_path_between_causes(root_index, idx_a, &effect);
53+
assert!(res.is_ok());
54+
assert_eq!(res.unwrap(), PropagatingEffect::Deterministic(false));
4655

47-
// Assert that evaluation was successful and the effect is as expected.
48-
// The graph's evaluate returns Deterministic(true) because the sink node C becomes active.
56+
// Now, we evaluate the effect propagating from root -> A -> B
57+
// Root evaluates from Numerical to true;
58+
// A evaluates from Boolean true to Boolean false;
59+
// B evaluates from Boolean false to Boolean true
60+
let res = g.evaluate_shortest_path_between_causes(root_index, idx_b, &effect);
4961
assert!(res.is_ok());
5062
assert_eq!(res.unwrap(), PropagatingEffect::Deterministic(true));
5163
}

deep_causality/tests/types/causal_types/causaloid_graph/causality_graph_reasoning_sub_tests.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,37 +10,42 @@ use deep_causality::*;
1010
fn test_evaluate_subgraph_from_cause() {
1111
let mut g = CausaloidGraph::new(0);
1212

13-
// Build a graph: root -> A, root -> B; A -> C
13+
// Add root causaloid
1414
let root_causaloid = test_utils::get_test_causaloid_deterministic();
1515
let root_index = g
1616
.add_root_causaloid(root_causaloid)
1717
.expect("Failed to add root index");
18+
assert!(g.contains_causaloid(root_index));
1819

19-
let causaloid_a = test_utils::get_test_causaloid_deterministic();
20+
// Add causaloid A
21+
let causaloid_a = test_utils::get_test_causaloid_deterministic_input_output();
2022
let idx_a = g
2123
.add_causaloid(causaloid_a)
2224
.expect("Failed to add causaloid A");
25+
26+
// Link A to root
2327
g.add_edge(root_index, idx_a).expect("Failed to add edge");
2428

25-
let causaloid_b = test_utils::get_test_causaloid_deterministic();
29+
// Add causaloid B
30+
let causaloid_b = test_utils::get_test_causaloid_deterministic_input_output();
2631
let idx_b = g
2732
.add_causaloid(causaloid_b)
2833
.expect("Failed to add causaloid B");
29-
g.add_edge(root_index, idx_b).expect("Failed to add edge");
3034

31-
let causaloid_c = test_utils::get_test_causaloid_deterministic();
32-
let idx_c = g
33-
.add_causaloid(causaloid_c)
34-
.expect("Failed to add causaloid C");
35-
g.add_edge(idx_a, idx_c).expect("Failed to add edge");
35+
// Link A to B
36+
g.add_edge(idx_a, idx_b).expect("Failed to add edge");
3637

38+
// Now, we have a graph like this:
39+
// root -> A -> B
3740
g.freeze();
3841

39-
// 2. Evaluate a subgraph starting from node A. This should activate nodes A and C.
40-
let effect = PropagatingEffect::Numerical(0.99);
42+
// 2. Evaluate a subgraph starting from node A. This should activate nodes A and B.
43+
let effect = PropagatingEffect::Deterministic(true);
4144
let res = g.evaluate_subgraph_from_cause(idx_a, &effect);
42-
4345
assert!(res.is_ok());
46+
// A evaluates from Boolean true to Boolean false;
47+
// B evaluates from Boolean false to Boolean true;
48+
// Thus the final effect is Deterministic(true)
4449
assert_eq!(res.unwrap(), PropagatingEffect::Deterministic(true));
4550
}
4651

0 commit comments

Comments
 (0)