argumentation/lib.rs
1//! # argumentation
2//!
3//! Formal argumentation in Rust. Two independent layers:
4//!
5//! 1. **Abstract argumentation frameworks** ([`ArgumentationFramework`]) in the
6//! Dung 1995 tradition, with all canonical semantics: grounded, complete,
7//! preferred, stable, ideal, and semi-stable extensions, plus Caminada
8//! three-valued labellings.
9//! 2. **Structured argumentation** ([`aspic::StructuredSystem`]) in the ASPIC+
10//! tradition (Modgil & Prakken 2014), with strict and defeasible rules,
11//! preference-based defeat resolution via the last-link principle, and
12//! automatic generation of a Dung AF for evaluation.
13//!
14//! ## Quick example: abstract AF
15//!
16//! ```
17//! use argumentation::ArgumentationFramework;
18//!
19//! let mut af = ArgumentationFramework::new();
20//! af.add_argument("a");
21//! af.add_argument("b");
22//! af.add_argument("c");
23//! af.add_attack(&"a", &"b").unwrap();
24//! af.add_attack(&"b", &"c").unwrap();
25//!
26//! let grounded = af.grounded_extension();
27//! assert!(grounded.contains(&"a"));
28//! assert!(grounded.contains(&"c"));
29//! ```
30//!
31//! ## Quick example: ASPIC+ penguin
32//!
33//! ```
34//! use argumentation::aspic::{StructuredSystem, Literal};
35//!
36//! let mut sys = StructuredSystem::new();
37//! sys.add_ordinary(Literal::atom("penguin"));
38//! sys.add_strict_rule(vec![Literal::atom("penguin")], Literal::atom("bird"));
39//! let r1 = sys.add_defeasible_rule(
40//! vec![Literal::atom("bird")],
41//! Literal::atom("flies"),
42//! );
43//! let r2 = sys.add_defeasible_rule(
44//! vec![Literal::atom("penguin")],
45//! Literal::neg("flies"),
46//! );
47//! sys.prefer_rule(r2, r1).unwrap();
48//!
49//! let built = sys.build_framework().unwrap();
50//! let preferred = built.framework.preferred_extensions().unwrap();
51//! assert_eq!(preferred.len(), 1);
52//! ```
53//!
54//! ## Performance
55//!
56//! Extension enumeration is currently implemented via subset search, which is
57//! exponential in the number of arguments. The crate is correct and well-suited
58//! for small-to-medium frameworks (up to ~20 arguments). Larger instances
59//! require SAT-based enumeration; that's a planned future extension.
60//!
61//! ## Choosing a defeat ordering
62//!
63//! ASPIC+ defines two argument orderings for last-link defeat resolution:
64//!
65//! - [`aspic::DefeatOrdering::LastLink`] (default) compares the last
66//! defeasible rule of each argument, falling through to the last
67//! ordinary premise when both rule frontiers are empty. Appropriate
68//! for legal and normative reasoning.
69//! - [`aspic::DefeatOrdering::WeakestLink`] compares the full set of
70//! defeasible rules and ordinary premises used in an argument.
71//! Appropriate for empirical reasoning where a chain is only as strong
72//! as its weakest link.
73//!
74//! Select an ordering at system construction time:
75//!
76//! ```
77//! use argumentation::aspic::{StructuredSystem, DefeatOrdering};
78//!
79//! let _sys = StructuredSystem::with_ordering(DefeatOrdering::WeakestLink);
80//! ```
81//!
82//! ## References
83//!
84//! - Dung, P.M. (1995). *On the acceptability of arguments...* AIJ 77(2).
85//! - Modgil, S. & Prakken, H. (2014). *The ASPIC+ framework for structured argumentation.*
86//! Argument & Computation 5(1).
87//! - Caminada, M. (2006). *On the issue of reinstatement in argumentation.* JELIA.
88//! - Baroni, P., Caminada, M., Giacomin, M. (2011). *An introduction to argumentation semantics.*
89//! KER 26(4).
90
91#![deny(missing_docs)]
92#![warn(clippy::all)]
93
94pub mod aspic;
95pub mod error;
96pub mod framework;
97pub mod parsers;
98pub mod semantics;
99
100pub use aspic::StructuredSystem;
101pub use error::Error;
102pub use framework::ArgumentationFramework;
103pub use semantics::{Label, Labelling};
104
105/// Maximum number of arguments supported by the subset-enumeration
106/// extension algorithms before [`Error::TooLarge`] is returned.
107///
108/// This is exposed so that consumers can statically assert against it
109/// (e.g. in tests) or feature-check their framework sizes before calling
110/// exponential enumerators. The limit is set to 22, matching the
111/// crate-level claim of "practical up to ~20 arguments" with a small
112/// safety margin.
113pub const ENUMERATION_LIMIT: usize = semantics::ENUMERATION_LIMIT;
114
115#[cfg(test)]
116mod tests {
117 const _: () = assert!(crate::ENUMERATION_LIMIT >= 20);
118 const _: () = assert!(crate::ENUMERATION_LIMIT <= 25);
119
120 #[test]
121 fn enumeration_limit_matches_semantics() {
122 assert_eq!(
123 crate::ENUMERATION_LIMIT,
124 crate::semantics::ENUMERATION_LIMIT
125 );
126 }
127}