33 * Copyright (c) "2025" . The DeepCausality Authors and Contributors. All Rights Reserved.
44 */
55
6+ use crate :: traits:: causable:: {
7+ causable_reasoning_deterministic, causable_reasoning_mixed, causable_reasoning_probabilistic,
8+ } ;
69use crate :: {
710 AggregateLogic , Causable , CausalityError , IdentificationValue , NumericalValue ,
811 PropagatingEffect ,
@@ -42,46 +45,32 @@ where
4245 // Default implementations for all other methods are provided below.
4346 //
4447
45- /// Evaluates a linear chain of causes where each link is strictly expected to be deterministic.
48+ /// Evaluates a collection of `Causable` items, aggregating their deterministic
49+ /// boolean outcomes (`true`/`false`) based on a specified `AggregateLogic`.
4650 ///
47- /// The chain is considered active only if every single cause in the collection
48- /// evaluates to `PropagatingEffect::Deterministic(true)`. If any cause evaluates
49- /// to `Deterministic(false)`, the chain evaluation stops and returns that effect.
51+ /// This function requires that every item in the collection evaluates to a
52+ /// `PropagatingEffect::Deterministic` variant. If any item returns a different
53+ /// variant, the function will fail with a `CausalityError`, ensuring strict
54+ /// type checking at runtime.
5055 ///
5156 /// # Arguments
52- /// * `effect` - A single `PropagatingEffect` object (e.g., a Map or Graph) that all causes will use.
57+ /// * `effect` - A `PropagatingEffect` to be passed to each `Causable` item.
58+ /// * `logic` - The `AggregateLogic` (e.g., `All`, `Any`, `None`, `Some(k)`)
59+ /// that defines how the boolean results are combined into a final `Deterministic` outcome.
5360 ///
5461 /// # Errors
55- /// Returns a `CausalityError` if any cause in the chain produces a non-deterministic effect.
56- fn evaluate_deterministic_propagation (
62+ /// Returns a `CausalityError` if any `Causable` item returns a non-deterministic effect.
63+ fn evaluate_deterministic (
5764 & self ,
5865 effect : & PropagatingEffect ,
59- _logic : & AggregateLogic ,
66+ logic : & AggregateLogic ,
6067 ) -> Result < PropagatingEffect , CausalityError > {
61- for cause in self . get_all_items ( ) {
62- let effect = cause. evaluate ( effect) ?;
63-
64- // This function enforces a strict deterministic contract.
65- match effect {
66- PropagatingEffect :: Deterministic ( true ) => {
67- // The link is active, continue to the next one.
68- continue ;
69- }
70- PropagatingEffect :: Deterministic ( false ) => {
71- // The chain is deterministically broken. This is a valid final outcome.
72- return Ok ( PropagatingEffect :: Deterministic ( false ) ) ;
73- }
74- _ => {
75- // Any other effect type is a contract violation for this function.
76- return Err ( CausalityError ( format ! (
77- "evaluate_deterministic_propagation encountered a non-deterministic effect: {effect:?}. Only Deterministic effects are allowed."
78- ) ) ) ;
79- }
80- }
81- }
82-
83- // If the entire loop completes, all links were deterministically true.
84- Ok ( PropagatingEffect :: Deterministic ( true ) )
68+ // Delegate to private impl in causable_reasoning_deterministic
69+ causable_reasoning_deterministic:: _evaluate_deterministic_logic (
70+ self . get_all_items ( ) ,
71+ effect,
72+ logic,
73+ )
8574 }
8675
8776 /// Evaluates a linear chain of causes where each link is expected to be probabilistic.
@@ -95,118 +84,51 @@ where
9584 ///
9685 /// # Errors
9786 /// Returns a `CausalityError` if a `ContextualLink` is encountered.
98- fn evaluate_probabilistic_propagation (
87+ fn evaluate_probabilistic (
9988 & self ,
10089 effect : & PropagatingEffect ,
101- _logic : & AggregateLogic ,
90+ logic : & AggregateLogic ,
91+ threshold : NumericalValue ,
10292 ) -> Result < PropagatingEffect , CausalityError > {
103- let mut cumulative_prob: NumericalValue = 1.0 ;
104-
105- for cause in self . get_all_items ( ) {
106- let effect = cause. evaluate ( effect) ?;
107-
108- match effect {
109- PropagatingEffect :: Probabilistic ( p) => {
110- cumulative_prob *= p;
111- }
112- PropagatingEffect :: Deterministic ( true ) => {
113- // This is equivalent to multiplying by 1.0, so we do nothing and continue.
114- }
115- PropagatingEffect :: Deterministic ( false ) => {
116- // If any link is deterministically false, the entire chain's probability is zero.
117- return Ok ( PropagatingEffect :: Probabilistic ( 0.0 ) ) ;
118- }
119- PropagatingEffect :: Halting => {
120- // Halting always takes precedence and stops the chain.
121- return Ok ( PropagatingEffect :: Halting ) ;
122- }
123- PropagatingEffect :: ContextualLink ( _, _) => {
124- // Contextual links are not meaningful in a probabilistic aggregation.
125- return Err ( CausalityError (
126- "Encountered a ContextualLink in a probabilistic chain evaluation." . into ( ) ,
127- ) ) ;
128- }
129- _ => {
130- // Other variants are not handled in this mode.
131- return Err ( CausalityError ( format ! (
132- "evaluate_probabilistic_propagation encountered an unhandled effect: {effect:?}"
133- ) ) ) ;
134- }
135- }
136- }
137-
138- Ok ( PropagatingEffect :: Probabilistic ( cumulative_prob) )
93+ // Delegate to private impl in causable_reasoning_probabilistic
94+ causable_reasoning_probabilistic:: _evaluate_probabilistic_logic (
95+ self . get_all_items ( ) ,
96+ effect,
97+ logic,
98+ threshold,
99+ )
139100 }
140101
141102 /// Evaluates a linear chain of causes that may contain a mix of deterministic and
142- /// probabilistic effects, aggregating them into a final effect.
103+ /// probabilistic effects, aggregating them into a final deterministic outcome.
104+ ///
105+ /// This method converts all effects (`Deterministic`, `Probabilistic`, `Numerical`)
106+ /// into a numerical value (where true=1.0, false=0.0) and aggregates them by
107+ /// multiplication. The final cumulative probability is then compared against a
108+ /// threshold (0.5) to produce a final `Deterministic(true)` or `Deterministic(false)`.
109+ ///
110+ /// This approach is robust, order-independent, and provides a consistent result.
143111 ///
144112 /// # Arguments
145113 /// * `effect` - A single `PropagatingEffect` object that all causes will use.
146114 ///
147115 /// # Errors
148- /// Returns a `CausalityError` if a `ContextualLink` is encountered.
149- fn evaluate_mixed_propagation (
116+ /// Returns a `CausalityError` if a `ContextualLink` is encountered, as it cannot be
117+ /// converted to a numerical probability.
118+ fn evaluate_mixed (
150119 & self ,
151120 effect : & PropagatingEffect ,
152- _logic : & AggregateLogic ,
121+ logic : & AggregateLogic ,
122+ threshold : NumericalValue ,
153123 ) -> Result < PropagatingEffect , CausalityError > {
154- // The chain starts as deterministically true. It can transition to probabilistic.
155- let mut aggregated_effect = PropagatingEffect :: Deterministic ( true ) ;
156-
157- for cause in self . get_all_items ( ) {
158- let current_effect = cause. evaluate ( effect) ?;
159-
160- // Update the aggregated effect based on the current effect.
161- aggregated_effect = match ( aggregated_effect, current_effect) {
162- // Halting takes precedence over everything.
163- ( _, PropagatingEffect :: Halting ) => return Ok ( PropagatingEffect :: Halting ) ,
164-
165- // Deterministic false breaks the chain.
166- ( _, PropagatingEffect :: Deterministic ( false ) ) => {
167- return Ok ( PropagatingEffect :: Deterministic ( false ) ) ;
168- }
169-
170- // ContextualLink is invalid in this context.
171- ( _, PropagatingEffect :: ContextualLink ( _, _) ) => {
172- return Err ( CausalityError (
173- "Encountered a ContextualLink in a mixed-chain evaluation." . into ( ) ,
174- ) ) ;
175- }
176-
177- // If the chain is deterministic and the new effect is true, it remains deterministic true.
178- (
179- PropagatingEffect :: Deterministic ( true ) ,
180- PropagatingEffect :: Deterministic ( true ) ,
181- ) => PropagatingEffect :: Deterministic ( true ) ,
182-
183- // If the chain is deterministic and the new effect is probabilistic, the chain becomes probabilistic.
184- ( PropagatingEffect :: Deterministic ( true ) , PropagatingEffect :: Probabilistic ( p) ) => {
185- PropagatingEffect :: Probabilistic ( p)
186- }
187-
188- // If the chain is already probabilistic and the new effect is true, the probability is unchanged.
189- ( PropagatingEffect :: Probabilistic ( p) , PropagatingEffect :: Deterministic ( true ) ) => {
190- PropagatingEffect :: Probabilistic ( p)
191- }
192-
193- // If the chain is probabilistic and the new effect is also probabilistic, multiply them.
194- ( PropagatingEffect :: Probabilistic ( p1) , PropagatingEffect :: Probabilistic ( p2) ) => {
195- PropagatingEffect :: Probabilistic ( p1 * p2)
196- }
197-
198- // Other combinations should not be possible due to the guards above.
199- ( agg, curr) => {
200- return Err ( CausalityError ( format ! (
201- "Unhandled effect combination in mixed chain: Agg: {agg:?}, Curr: {curr:?}"
202- ) ) ) ;
203- }
204- } ;
205- }
206-
207- Ok ( aggregated_effect)
124+ // Delegate to private impl in causable_reasoning_mixed
125+ causable_reasoning_mixed:: _evaluate_mixed_logic (
126+ self . get_all_items ( ) ,
127+ effect,
128+ logic,
129+ threshold,
130+ )
208131 }
209-
210132 /// Generates an explanation by concatenating the `explain()` text of all causes.
211133 ///
212134 /// Each explanation is formatted and separated by newlines.
0 commit comments