Skip to main content

argumentation_schemes/catalog/
causal.rs

1//! Causal schemes: reasoning about causes, effects, signs, and chains.
2//!
3//! Ref: Walton, Reed & Macagno 2008, Chapter 9 + Appendix 1.
4
5use crate::catalog::CAUSAL_ID_OFFSET;
6use crate::critical::CriticalQuestion;
7use crate::scheme::*;
8use crate::types::*;
9
10/// Return all causal schemes.
11pub fn all() -> Vec<SchemeSpec> {
12    vec![
13        argument_from_cause_to_effect(),
14        argument_from_correlation_to_cause(),
15        argument_from_sign(),
16        argument_from_gradual_slippery_slope(),
17    ]
18}
19
20/// Argument from Cause to Effect (Walton 2008 p.327).
21pub fn argument_from_cause_to_effect() -> SchemeSpec {
22    SchemeSpec {
23        id: SchemeId(CAUSAL_ID_OFFSET),
24        name: "Argument from Cause to Effect".into(),
25        category: SchemeCategory::Causal,
26        premises: vec![
27            PremiseSlot::new("cause", "The causal event or condition", SlotRole::Action),
28            PremiseSlot::new("effect", "The effect that follows", SlotRole::Consequence),
29        ],
30        conclusion: ConclusionTemplate::positive(
31            "?effect will occur because ?cause has occurred",
32            "?effect",
33        ),
34        critical_questions: vec![
35            CriticalQuestion::new(
36                1,
37                "Is there a strong causal link between ?cause and ?effect?",
38                Challenge::RuleValidity,
39            ),
40            CriticalQuestion::new(
41                2,
42                "Has ?cause actually occurred or will it occur?",
43                Challenge::PremiseTruth("cause".into()),
44            ),
45            CriticalQuestion::new(
46                3,
47                "Could something else prevent ?effect despite ?cause?",
48                Challenge::AlternativeCause,
49            ),
50        ],
51        metadata: SchemeMetadata {
52            citation: "Walton 2008 p.327".into(),
53            domain_tags: vec!["causal".into()],
54            presumptive: true,
55            strength: SchemeStrength::Moderate,
56        },
57    }
58}
59
60/// Argument from Correlation to Cause (Walton 2008 p.328).
61pub fn argument_from_correlation_to_cause() -> SchemeSpec {
62    SchemeSpec {
63        id: SchemeId(CAUSAL_ID_OFFSET + 1),
64        name: "Argument from Correlation to Cause".into(),
65        category: SchemeCategory::Causal,
66        premises: vec![
67            PremiseSlot::new("antecedent", "The first correlated event", SlotRole::Action),
68            PremiseSlot::new(
69                "consequent",
70                "The second correlated event",
71                SlotRole::Consequence,
72            ),
73        ],
74        conclusion: ConclusionTemplate::positive(
75            "?antecedent causes ?consequent",
76            "causes_?antecedent_to_?consequent",
77        ),
78        critical_questions: vec![
79            CriticalQuestion::new(
80                1,
81                "Is there a genuine correlation between ?antecedent and ?consequent?",
82                Challenge::PremiseTruth("antecedent".into()),
83            ),
84            CriticalQuestion::new(
85                2,
86                "Could both ?antecedent and ?consequent be caused by a third factor?",
87                Challenge::AlternativeCause,
88            ),
89            CriticalQuestion::new(
90                3,
91                "Could the causal direction be reversed (?consequent causes ?antecedent)?",
92                Challenge::AlternativeCause,
93            ),
94        ],
95        metadata: SchemeMetadata {
96            citation: "Walton 2008 p.328".into(),
97            domain_tags: vec!["causal".into()],
98            presumptive: true,
99            strength: SchemeStrength::Weak,
100        },
101    }
102}
103
104/// Argument from Sign (Walton 2008 p.329).
105pub fn argument_from_sign() -> SchemeSpec {
106    SchemeSpec {
107        id: SchemeId(CAUSAL_ID_OFFSET + 2),
108        name: "Argument from Sign".into(),
109        category: SchemeCategory::Causal,
110        premises: vec![
111            PremiseSlot::new("sign", "The observed sign or indicator", SlotRole::Property),
112            PremiseSlot::new(
113                "indicated",
114                "What the sign indicates",
115                SlotRole::Proposition,
116            ),
117        ],
118        conclusion: ConclusionTemplate::positive(
119            "?indicated is plausible based on ?sign",
120            "?indicated",
121        ),
122        critical_questions: vec![
123            CriticalQuestion::new(
124                1,
125                "Is ?sign a reliable indicator of ?indicated?",
126                Challenge::RuleValidity,
127            ),
128            CriticalQuestion::new(
129                2,
130                "Could ?sign indicate something other than ?indicated?",
131                Challenge::AlternativeCause,
132            ),
133        ],
134        metadata: SchemeMetadata {
135            citation: "Walton 2008 p.329".into(),
136            domain_tags: vec!["causal".into(), "abductive".into()],
137            presumptive: true,
138            strength: SchemeStrength::Weak,
139        },
140    }
141}
142
143/// Argument from Gradual Slippery Slope (Walton 2008 p.338).
144///
145/// Negated-conclusion scheme.
146pub fn argument_from_gradual_slippery_slope() -> SchemeSpec {
147    SchemeSpec {
148        id: SchemeId(CAUSAL_ID_OFFSET + 3),
149        name: "Argument from Gradual Slippery Slope".into(),
150        category: SchemeCategory::Causal,
151        premises: vec![
152            PremiseSlot::new(
153                "first_step",
154                "The initial innocuous action",
155                SlotRole::Action,
156            ),
157            PremiseSlot::new(
158                "final_outcome",
159                "The undesirable end state",
160                SlotRole::Consequence,
161            ),
162        ],
163        conclusion: ConclusionTemplate::negated(
164            "?first_step should not be taken because it leads to ?final_outcome",
165            "do_?first_step",
166        ),
167        critical_questions: vec![
168            CriticalQuestion::new(
169                1,
170                "Is there a plausible chain from ?first_step to ?final_outcome?",
171                Challenge::RuleValidity,
172            ),
173            CriticalQuestion::new(
174                2,
175                "Can the chain be stopped at some intermediate point?",
176                Challenge::AlternativeCause,
177            ),
178            CriticalQuestion::new(
179                3,
180                "Is ?final_outcome really as bad as claimed?",
181                Challenge::PremiseTruth("final_outcome".into()),
182            ),
183        ],
184        metadata: SchemeMetadata {
185            citation: "Walton 2008 p.338".into(),
186            domain_tags: vec!["causal".into(), "slippery_slope".into()],
187            presumptive: true,
188            strength: SchemeStrength::Weak,
189        },
190    }
191}
192
193#[cfg(test)]
194mod tests {
195    use super::*;
196
197    #[test]
198    fn all_returns_four_causal_schemes() {
199        assert_eq!(all().len(), 4);
200    }
201
202    #[test]
203    fn slippery_slope_has_negated_conclusion() {
204        assert!(argument_from_gradual_slippery_slope().conclusion.is_negated);
205    }
206
207    #[test]
208    fn causal_ids_are_in_offset_range() {
209        for s in all() {
210            assert!(s.id.0 >= CAUSAL_ID_OFFSET);
211            assert!(s.id.0 < CAUSAL_ID_OFFSET + 100);
212        }
213    }
214}