Skip to content

Commit 6f90deb

Browse files
committed
refactor(deep_causality): promoted CSM modules from files into directories.
Signed-off-by: Marvin Hansen <[email protected]>
1 parent 7869c25 commit 6f90deb

File tree

4 files changed

+162
-143
lines changed

4 files changed

+162
-143
lines changed
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/*
2+
* SPDX-License-Identifier: MIT
3+
* Copyright (c) "2025" . The DeepCausality Authors and Contributors. All Rights Reserved.
4+
*/
5+
use crate::{
6+
ActionError, CSM, CausalState, CsmError, Datable, DeonticExplainable, DeonticInferable,
7+
PropagatingEffect, ProposedAction, SpaceTemporal, Spatial, Symbolic, TeloidModal, Temporal,
8+
};
9+
use std::collections::HashMap;
10+
use std::fmt::Debug;
11+
12+
#[allow(clippy::type_complexity)]
13+
impl<D, S, T, ST, SYM, VS, VT> CSM<D, S, T, ST, SYM, VS, VT>
14+
where
15+
D: Datable + Clone + Debug,
16+
S: Spatial<VS> + Clone + Debug,
17+
T: Temporal<VT> + Clone + Debug,
18+
ST: SpaceTemporal<VS, VT> + Clone + Debug,
19+
SYM: Symbolic + Clone + Debug,
20+
VS: Clone + Debug,
21+
VT: Clone + Debug,
22+
{
23+
/// Evaluates a single causal state at the index position id.
24+
/// If the state evaluates to `PropagatingEffect::Deterministic(true)`, the associated action is fired.
25+
///
26+
/// # Errors
27+
/// Returns `CsmError` if the state does not exist, evaluation fails, the effect is not
28+
/// deterministic, or the action fails to fire.
29+
pub fn eval_single_state(&self, id: usize, data: &PropagatingEffect) -> Result<(), CsmError> {
30+
let binding = self.state_actions.read().unwrap();
31+
32+
let (state, action) = binding.get(&id).ok_or_else(|| {
33+
CsmError::Action(
34+
format!("State {id} does not exist. Add it first before evaluating.").into(),
35+
)
36+
})?;
37+
38+
let effect = state.eval_with_data(data)?;
39+
40+
match &effect {
41+
PropagatingEffect::Deterministic(true) => {
42+
if let Some((ethos, tags)) = &self.effect_ethos {
43+
if let Some(context) = state.context() {
44+
let action_name = format!(
45+
"proposed action for CSM State: {} version: {}",
46+
state.id(),
47+
state.version()
48+
);
49+
50+
let proposed_action =
51+
self.create_proposed_action(action_name, state, &effect)?;
52+
let verdict = ethos.evaluate_action(&proposed_action, context, tags)?;
53+
54+
if verdict.outcome() == TeloidModal::Impermissible {
55+
let explanation = ethos.explain_verdict(&verdict)?;
56+
return Err(CsmError::Forbidden(explanation));
57+
} else {
58+
action.fire()?;
59+
}
60+
} else {
61+
return Err(CsmError::Action(ActionError::new(
62+
"Cannot evaluate action with ethos because state context is missing."
63+
.into(),
64+
)));
65+
}
66+
} else {
67+
action.fire()?;
68+
}
69+
Ok(())
70+
}
71+
PropagatingEffect::Deterministic(false) => {
72+
// State evaluated to false, do nothing.
73+
Ok(())
74+
}
75+
_ => {
76+
// The effect was not deterministic, which is an invalid state for a CSM.
77+
Err(CsmError::Action(ActionError(format!(
78+
"CSM[eval]: Invalid non-deterministic effect '{:?}' for state {}",
79+
effect,
80+
state.id()
81+
))))
82+
}
83+
}
84+
}
85+
86+
/// Evaluates all causal states in the CSM using their internal data.
87+
/// For each state that evaluates to `PropagatingEffect::Deterministic(true)`, the associated action is fired.
88+
///
89+
/// # Errors
90+
/// Returns `CsmError` if any state evaluation fails, produces a non-deterministic effect,
91+
/// or any triggered action fails to fire.
92+
pub fn eval_all_states(&self) -> Result<(), CsmError> {
93+
let binding = self.state_actions.read().unwrap();
94+
95+
for (_id, (state, action)) in binding.iter() {
96+
let effect = state.eval()?;
97+
98+
match &effect {
99+
PropagatingEffect::Deterministic(true) => {
100+
if let Some((ethos, tags)) = &self.effect_ethos {
101+
if let Some(context) = state.context() {
102+
let action_name = format!(
103+
"proposed action for CSM State: {} version: {}",
104+
state.id(),
105+
state.version()
106+
);
107+
108+
let proposed_action =
109+
self.create_proposed_action(action_name, state, &effect)?;
110+
let verdict = ethos.evaluate_action(&proposed_action, context, tags)?;
111+
112+
if verdict.outcome() == TeloidModal::Impermissible {
113+
let explanation = ethos.explain_verdict(&verdict)?;
114+
return Err(CsmError::Forbidden(explanation));
115+
} else {
116+
action.fire()?;
117+
}
118+
} else {
119+
return Err(CsmError::Action(ActionError::new(
120+
"Cannot evaluate action with ethos because state context is missing."
121+
.into(),
122+
)));
123+
}
124+
} else {
125+
action.fire()?
126+
}
127+
}
128+
PropagatingEffect::Deterministic(false) => {
129+
// State evaluated to false, do nothing, continue loop.
130+
}
131+
_ => {
132+
// The effect was not deterministic, which is an invalid state for a CSM.
133+
return Err(CsmError::Action(ActionError(format!(
134+
"CSM[eval]: Invalid non-deterministic effect '{:?}' for state {}",
135+
effect,
136+
state.id()
137+
))));
138+
}
139+
}
140+
}
141+
142+
Ok(())
143+
}
144+
145+
fn create_proposed_action(
146+
&self,
147+
action_name: String,
148+
state: &CausalState<D, S, T, ST, SYM, VS, VT>,
149+
effect: &PropagatingEffect,
150+
) -> Result<ProposedAction, CsmError> {
151+
let mut params = HashMap::new();
152+
params.insert("trigger_effect".to_string(), effect.clone().into());
153+
154+
Ok(ProposedAction::new(*state.id() as u64, action_name, params))
155+
}
156+
}

deep_causality/src/types/csm_types/csm.rs renamed to deep_causality/src/types/csm_types/csm/mod.rs

Lines changed: 4 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33
* Copyright (c) "2025" . The DeepCausality Authors and Contributors. All Rights Reserved.
44
*/
55

6-
use crate::{
7-
ActionError, CSMMap, CausalAction, CausalState, CsmError, DeonticExplainable, EffectEthos,
8-
PropagatingEffect, ProposedAction, StateAction, TeloidModal, TeloidTag, UpdateError,
9-
};
10-
use crate::{Datable, DeonticInferable, SpaceTemporal, Spatial, Symbolic, Temporal};
6+
mod eval;
7+
8+
use crate::{CSMMap, CausalAction, CausalState, EffectEthos, StateAction, TeloidTag, UpdateError};
9+
use crate::{Datable, SpaceTemporal, Spatial, Symbolic, Temporal};
1110
use std::collections::HashMap;
1211
use std::fmt::Debug;
1312
use std::sync::{Arc, RwLock};
@@ -140,69 +139,6 @@ where
140139
Ok(())
141140
}
142141

143-
/// Evaluates a single causal state at the index position id.
144-
/// If the state evaluates to `PropagatingEffect::Deterministic(true)`, the associated action is fired.
145-
///
146-
/// # Errors
147-
/// Returns `CsmError` if the state does not exist, evaluation fails, the effect is not
148-
/// deterministic, or the action fails to fire.
149-
pub fn eval_single_state(&self, id: usize, data: &PropagatingEffect) -> Result<(), CsmError> {
150-
let binding = self.state_actions.read().unwrap();
151-
152-
let (state, action) = binding.get(&id).ok_or_else(|| {
153-
CsmError::Action(
154-
format!("State {id} does not exist. Add it first before evaluating.").into(),
155-
)
156-
})?;
157-
158-
let effect = state.eval_with_data(data)?;
159-
160-
match &effect {
161-
PropagatingEffect::Deterministic(true) => {
162-
if let Some((ethos, tags)) = &self.effect_ethos {
163-
if let Some(context) = state.context() {
164-
let action_name = format!(
165-
"proposed action for CSM State: {} version: {}",
166-
state.id(),
167-
state.version()
168-
);
169-
170-
let proposed_action =
171-
self.create_proposed_action(action_name, state, &effect)?;
172-
let verdict = ethos.evaluate_action(&proposed_action, context, tags)?;
173-
174-
if verdict.outcome() == TeloidModal::Impermissible {
175-
let explanation = ethos.explain_verdict(&verdict)?;
176-
return Err(CsmError::Forbidden(explanation));
177-
} else {
178-
action.fire()?;
179-
}
180-
} else {
181-
return Err(CsmError::Action(ActionError::new(
182-
"Cannot evaluate action with ethos because state context is missing."
183-
.into(),
184-
)));
185-
}
186-
} else {
187-
action.fire()?;
188-
}
189-
Ok(())
190-
}
191-
PropagatingEffect::Deterministic(false) => {
192-
// State evaluated to false, do nothing.
193-
Ok(())
194-
}
195-
_ => {
196-
// The effect was not deterministic, which is an invalid state for a CSM.
197-
Err(CsmError::Action(ActionError(format!(
198-
"CSM[eval]: Invalid non-deterministic effect '{:?}' for state {}",
199-
effect,
200-
state.id()
201-
))))
202-
}
203-
}
204-
}
205-
206142
/// Updates a causal state with a new state at the index position idx.
207143
/// Returns UpdateError if the update operation failed.
208144
pub fn update_single_state(
@@ -226,65 +162,6 @@ where
226162
Ok(())
227163
}
228164

229-
/// Evaluates all causal states in the CSM using their internal data.
230-
/// For each state that evaluates to `PropagatingEffect::Deterministic(true)`, the associated action is fired.
231-
///
232-
/// # Errors
233-
/// Returns `CsmError` if any state evaluation fails, produces a non-deterministic effect,
234-
/// or any triggered action fails to fire.
235-
pub fn eval_all_states(&self) -> Result<(), CsmError> {
236-
let binding = self.state_actions.read().unwrap();
237-
238-
for (_id, (state, action)) in binding.iter() {
239-
let effect = state.eval()?;
240-
241-
match &effect {
242-
PropagatingEffect::Deterministic(true) => {
243-
if let Some((ethos, tags)) = &self.effect_ethos {
244-
if let Some(context) = state.context() {
245-
let action_name = format!(
246-
"proposed action for CSM State: {} version: {}",
247-
state.id(),
248-
state.version()
249-
);
250-
251-
let proposed_action =
252-
self.create_proposed_action(action_name, state, &effect)?;
253-
let verdict = ethos.evaluate_action(&proposed_action, context, tags)?;
254-
255-
if verdict.outcome() == TeloidModal::Impermissible {
256-
let explanation = ethos.explain_verdict(&verdict)?;
257-
return Err(CsmError::Forbidden(explanation));
258-
} else {
259-
action.fire()?;
260-
}
261-
} else {
262-
return Err(CsmError::Action(ActionError::new(
263-
"Cannot evaluate action with ethos because state context is missing."
264-
.into(),
265-
)));
266-
}
267-
} else {
268-
action.fire()?
269-
}
270-
}
271-
PropagatingEffect::Deterministic(false) => {
272-
// State evaluated to false, do nothing, continue loop.
273-
}
274-
_ => {
275-
// The effect was not deterministic, which is an invalid state for a CSM.
276-
return Err(CsmError::Action(ActionError(format!(
277-
"CSM[eval]: Invalid non-deterministic effect '{:?}' for state {}",
278-
effect,
279-
state.id()
280-
))));
281-
}
282-
}
283-
}
284-
285-
Ok(())
286-
}
287-
288165
/// Updates all causal state with a new state collection.
289166
/// Note, this operation erases all previous states in the CSM by generating a new collection.
290167
/// Returns UpdateError if the update operation failed.
@@ -302,16 +179,4 @@ where
302179
*self.state_actions.write().unwrap() = state_map;
303180
Ok(())
304181
}
305-
306-
fn create_proposed_action(
307-
&self,
308-
action_name: String,
309-
state: &CausalState<D, S, T, ST, SYM, VS, VT>,
310-
effect: &PropagatingEffect,
311-
) -> Result<ProposedAction, CsmError> {
312-
let mut params = HashMap::new();
313-
params.insert("trigger_effect".to_string(), effect.clone().into());
314-
315-
Ok(ProposedAction::new(*state.id() as u64, action_name, params))
316-
}
317182
}

deep_causality/src/types/csm_types/csm_state.rs renamed to deep_causality/src/types/csm_types/csm_state/mod.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@
33
* Copyright (c) "2025" . The DeepCausality Authors and Contributors. All Rights Reserved.
44
*/
55

6-
use crate::traits::contextuable::space_temporal::SpaceTemporal;
7-
use crate::traits::contextuable::spatial::Spatial;
8-
use crate::traits::contextuable::temporal::Temporal;
9-
use crate::{Causable, CausalityError, Causaloid, Context, Datable, PropagatingEffect, Symbolic};
6+
use crate::{Causable, Datable, SpaceTemporal, Spatial, Symbolic, Temporal};
7+
use crate::{CausalityError, Causaloid, Context, PropagatingEffect};
108
use deep_causality_macros::{Constructor, Getters};
119
use std::fmt::{Display, Formatter};
1210
use std::sync::Arc;

0 commit comments

Comments
 (0)