Skip to content

Commit 4a7349a

Browse files
Merge pull request #295 from marvin-hansen/main
feat(deep_causality): Implemented Effect Ethos for Deontic Reasoning and Action-Guarding
2 parents 8b61cb3 + 69af6cd commit 4a7349a

File tree

120 files changed

+6471
-566
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

120 files changed

+6471
-566
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

MODULE.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ bazel_dep(name = "rules_rust", version = "0.63.0")
1515
###############################################################################
1616
RUST_EDITION = "2024"
1717

18-
RUST_VERSION = "1.88.0"
18+
RUST_VERSION = "1.89.0"
1919

2020
rust = use_extension("@rules_rust//rust:extensions.bzl", "rust")
2121
rust.toolchain(

MODULE.bazel.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build/scripts/example.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ echo "smoking: Simple causal model without Context"
1818
echo "--------------------------------"
1919
echo ""
2020

21-
select opt in cate csm dbn granger starter scm rcm quit;
21+
select opt in cate csm dbn ethos granger starter scm rcm quit;
2222
do
2323
case $opt in
2424

@@ -40,6 +40,12 @@ do
4040
break
4141
;;
4242

43+
ethos)
44+
echo "Selected example: ethos (CSM with Effect Ethos)"
45+
command cargo run --release --bin example_effect_ethos
46+
break
47+
;;
48+
4349
starter)
4450
echo "Selected example: Starter (Starter)"
4551
command cargo run --release --bin example-starter

deep_causality/src/errors/action_error.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,9 @@ impl fmt::Display for ActionError {
1717
write!(f, "ActionError: {}", self.0)
1818
}
1919
}
20+
21+
impl From<String> for ActionError {
22+
fn from(s: String) -> Self {
23+
ActionError(s)
24+
}
25+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* SPDX-License-Identifier: MIT
3+
* Copyright (c) "2025" . The DeepCausality Authors and Contributors. All Rights Reserved.
4+
*/
5+
6+
use crate::{ActionError, CausalityError, DeonticError};
7+
use std::error::Error;
8+
use std::fmt::{Display, Formatter};
9+
10+
#[derive(Debug)]
11+
pub enum CsmError {
12+
Action(ActionError),
13+
Causal(CausalityError),
14+
Deontic(DeonticError),
15+
Forbidden(String),
16+
}
17+
18+
impl Error for CsmError {
19+
fn source(&self) -> Option<&(dyn Error + 'static)> {
20+
match self {
21+
CsmError::Action(e) => Some(e),
22+
CsmError::Deontic(e) => Some(e),
23+
CsmError::Causal(e) => Some(e),
24+
CsmError::Forbidden(_) => None,
25+
}
26+
}
27+
}
28+
29+
impl Display for CsmError {
30+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
31+
match self {
32+
CsmError::Action(e) => write!(f, "CSM Action Error: {e}"),
33+
CsmError::Deontic(e) => write!(f, "CSM Deontic Error: {e}"),
34+
CsmError::Causal(e) => write!(f, "CSM Causal Error: {e}"),
35+
CsmError::Forbidden(s) => write!(f, "{s}"),
36+
}
37+
}
38+
}
39+
40+
impl From<ActionError> for CsmError {
41+
fn from(err: ActionError) -> Self {
42+
CsmError::Action(err)
43+
}
44+
}
45+
46+
impl From<DeonticError> for CsmError {
47+
fn from(err: DeonticError) -> Self {
48+
CsmError::Deontic(err)
49+
}
50+
}
51+
52+
impl From<CausalityError> for CsmError {
53+
fn from(err: CausalityError) -> Self {
54+
CsmError::Causal(err)
55+
}
56+
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/*
2+
* SPDX-License-Identifier: MIT
3+
* Copyright (c) "2025" . The DeepCausality Authors and Contributors. All Rights Reserved.
4+
*/
5+
6+
use crate::TeloidID;
7+
use std::error::Error;
8+
use std::fmt;
9+
use ultragraph::GraphError;
10+
11+
/// Errors related to the Deontic Inference process within the Effect Ethos.
12+
#[derive(Debug, Clone, PartialEq)]
13+
pub enum DeonticError {
14+
/// Failed to add a new teloid to the graph.
15+
FailedToAddTeloid,
16+
17+
/// Failed to add edge to the graph.
18+
FailedToAddEdge(usize, usize),
19+
20+
/// An operation was attempted on a graph that was not frozen.
21+
/// Deontic inference requires a static, immutable graph.
22+
GraphNotFrozen,
23+
24+
/// An mutation operation was attempted on a graph that was frozen.
25+
/// Mutation requires an unfrozen graph
26+
GraphIsFrozen,
27+
28+
/// The TeloidGraph is invalid because it contains a cycle, which would
29+
/// lead to infinite loops in reasoning.
30+
GraphIsCyclic,
31+
32+
/// A TeloidID exists in the graph or tag index but not in the TeloidStore,
33+
/// indicating a critical state inconsistency.
34+
TeloidNotFound { id: TeloidID },
35+
36+
/// The final set of active norms was empty or otherwise unable to produce
37+
/// a conclusive verdict.
38+
InconclusiveVerdict,
39+
40+
/// No applicable norms were found for a given action.
41+
NoRelevantNormsFound,
42+
43+
/// The CausalState is missing a context, which is required for deontic evaluation.
44+
MissingContext,
45+
46+
/// Wraps a lower-level error from the ultragraph crate.
47+
GraphError(GraphError),
48+
}
49+
50+
impl Error for DeonticError {
51+
fn source(&self) -> Option<&(dyn Error + 'static)> {
52+
match self {
53+
DeonticError::GraphError(e) => Some(e),
54+
_ => None,
55+
}
56+
}
57+
}
58+
59+
impl fmt::Display for DeonticError {
60+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61+
match self {
62+
DeonticError::GraphNotFrozen => {
63+
write!(
64+
f,
65+
"Deontic inference failed: The TeloidGraph must be frozen before evaluation."
66+
)
67+
}
68+
DeonticError::GraphIsFrozen => {
69+
write!(
70+
f,
71+
"Deontic inference failed: The TeloidGraph is frozen and cannot be modified."
72+
)
73+
}
74+
75+
DeonticError::GraphIsCyclic => {
76+
write!(
77+
f,
78+
"Deontic inference failed: The TeloidGraph contains a cycle and is invalid."
79+
)
80+
}
81+
DeonticError::TeloidNotFound { id } => {
82+
write!(
83+
f,
84+
"Deontic inference failed: Teloid with ID {} not found in store.",
85+
id
86+
)
87+
}
88+
DeonticError::InconclusiveVerdict => {
89+
write!(
90+
f,
91+
"Deontic inference failed: The final set of active norms was inconclusive."
92+
)
93+
}
94+
DeonticError::MissingContext => {
95+
write!(
96+
f,
97+
"Deontic inference failed: The CausalState is missing a context."
98+
)
99+
}
100+
DeonticError::GraphError(e) => {
101+
write!(
102+
f,
103+
"A graph operation failed during deontic inference: {}",
104+
e
105+
)
106+
}
107+
DeonticError::FailedToAddTeloid => {
108+
write!(f, "Failed to add a new teloid to the graph.")
109+
}
110+
DeonticError::FailedToAddEdge(source, target) => {
111+
write!(
112+
f,
113+
"Edge from {source} to {target} could not be created; a node may not exist or the edge already exists."
114+
)
115+
}
116+
DeonticError::NoRelevantNormsFound => {
117+
write!(
118+
f,
119+
"No relevant norms found, so the action cannot be decided. Please check if you have added the correct tags."
120+
)
121+
}
122+
}
123+
}
124+
}
125+
126+
impl From<GraphError> for DeonticError {
127+
fn from(err: GraphError) -> Self {
128+
match err {
129+
GraphError::GraphIsFrozen => DeonticError::GraphIsFrozen,
130+
GraphError::GraphNotFrozen => DeonticError::GraphNotFrozen,
131+
GraphError::GraphContainsCycle => DeonticError::GraphIsCyclic,
132+
GraphError::EdgeCreationError { source, target } => {
133+
DeonticError::FailedToAddEdge(source, target)
134+
}
135+
_ => DeonticError::GraphError(err),
136+
}
137+
}
138+
}

deep_causality/src/errors/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ mod causal_graph_index_error;
1111
mod causality_error;
1212
mod causality_graph_error;
1313
mod context_index_error;
14+
mod csm_error;
15+
mod deontic_error;
1416
mod index_error;
1517
mod model_build_error;
1618
mod model_generation_error;
@@ -25,6 +27,8 @@ pub use causal_graph_index_error::*;
2527
pub use causality_error::*;
2628
pub use causality_graph_error::*;
2729
pub use context_index_error::*;
30+
pub use csm_error::*;
31+
pub use deontic_error::*;
2832
pub use index_error::*;
2933
pub use model_build_error::*;
3034
pub use model_generation_error::*;

deep_causality/src/lib.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,18 +81,24 @@ pub use crate::traits::observable::ObservableReasoning;
8181
// Scalar Traits
8282
pub use crate::traits::scalar::scalar_projector::ScalarProjector;
8383
pub use crate::traits::scalar::scalar_value::ScalarValue;
84+
// Teloid Traits
85+
pub use crate::traits::telos::deontic_explainable::DeonticExplainable;
86+
pub use crate::traits::telos::deontic_inferable::DeonticInferable;
87+
pub use crate::traits::telos::teloid_storable::TeloidStorable;
88+
pub use crate::traits::telos::teloidable::Teloidable;
8489
// Transferable Trait
8590
pub use crate::traits::transferable::Transferable;
8691
//
8792
// Types
8893
//
8994
// Alias types
9095
pub use crate::types::alias_types::alias_base::*;
96+
pub use crate::types::alias_types::alias_csm::*;
9197
pub use crate::types::alias_types::alias_function::*;
9298
pub use crate::types::alias_types::alias_lock::*;
9399
pub use crate::types::alias_types::alias_primitives::*;
94100
pub use crate::types::alias_types::alias_uniform::*;
95-
pub use crate::types::alias_types::*;
101+
// pub use crate::types::alias_types::*;
96102
// Causal types
97103
pub use crate::types::causal_types::causal_type::CausaloidType;
98104
pub use crate::types::causal_types::causaloid::Causaloid;
@@ -136,7 +142,7 @@ pub use crate::types::context_node_types::time::time_kind::TimeKind;
136142
pub use crate::types::context_types::relation_kind::*;
137143
pub use crate::types::context_types::time_scale::TimeScale;
138144
// CSM types
139-
pub use crate::types::csm_types::CSM;
145+
pub use crate::types::csm_types::csm::CSM;
140146
pub use crate::types::csm_types::csm_action::CausalAction;
141147
pub use crate::types::csm_types::csm_state::CausalState;
142148
// Generative types
@@ -154,6 +160,18 @@ pub use crate::types::reasoning_types::propagating_effect::PropagatingEffect;
154160
//Symbolic types
155161
pub use crate::types::symbolic_types::symbolic_representation::SymbolicRepresentation;
156162
pub use crate::types::symbolic_types::symbolic_result::SymbolicResult;
163+
//
164+
// Teloid types
165+
pub use crate::types::telos_types::action_parameter_value::ActionParameterValue;
166+
pub use crate::types::telos_types::effect_ethos::EffectEthos;
167+
pub use crate::types::telos_types::proposed_action::ProposedAction;
168+
pub use crate::types::telos_types::tag_index::TagIndex;
169+
pub use crate::types::telos_types::teloid::{Teloid, TeloidMetaData};
170+
pub use crate::types::telos_types::teloid_graph::*;
171+
pub use crate::types::telos_types::teloid_modal::TeloidModal;
172+
pub use crate::types::telos_types::teloid_relation::TeloidRelation;
173+
pub use crate::types::telos_types::teloid_store::TeloidStore;
174+
pub use crate::types::telos_types::teloid_verdict::Verdict;
157175
// Utils
158176
//
159177
pub use crate::utils::time_utils::*;

deep_causality/src/traits/causable_graph/graph_reasoning/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ where
5959
/// further reasoning to the matching model i.e. a dedicated sub-graph. Ensure that all possible
6060
/// values of target_index exists in the graph before implementing adaptive reasoning.
6161
/// For more details, see section 5.10.3 Adaptive Reasoning in The EPP reference paper:
62-
/// https://github.com/deepcausality-rs/papers/blob/main/effect_propagation_process/epp.pdf
62+
/// <https://github.com/deepcausality-rs/papers/blob/main/effect_propagation_process/epp.pdf>
6363
///
6464
/// # Arguments
6565
///
@@ -170,7 +170,7 @@ where
170170
/// and thus RelayTo is not supposed to happen in the middle of the path. Therefore, the
171171
/// call-site must handle the occurrence i.e. when its a known final effect.
172172
/// For more details, see section 5.10.3 Adaptive Reasoning in The EPP reference paper:
173-
/// https://github.com/deepcausality-rs/papers/blob/main/effect_propagation_process/epp.pdf
173+
/// <https://github.com/deepcausality-rs/papers/blob/main/effect_propagation_process/epp.pdf>
174174
///
175175
/// # Arguments
176176
///

0 commit comments

Comments
 (0)