1use std::{
2 fmt::Display,
3 sync::atomic::{AtomicUsize, Ordering},
4};
5
6use derivative::Derivative;
7
8#[derive(Debug, Clone, PartialEq, Eq, Hash)]
9pub enum Formula {
10 Pred(Pred),
11 True,
12 False,
13 And(Box<Formula>, Box<Formula>),
14 Or(Box<Formula>, Box<Formula>),
15 Neg(Box<Formula>),
16 Imply(Box<Formula>, Box<Formula>),
17 Iff(Box<Formula>, Box<Formula>),
18 Forall(Var, Box<Formula>),
19 Exists(Var, Box<Formula>),
20}
21
22#[derive(Debug, Clone, PartialEq, Eq, Hash)]
23pub struct Pred {
24 id: String,
25 args: Box<Vec<Term>>,
26}
27
28#[derive(Debug, Clone, PartialEq, Eq, Hash)]
29pub enum Term {
30 Obj(Obj),
31 Var(Var),
32 Fun(Fun),
33}
34
35#[derive(Debug, Clone, PartialEq, Eq, Hash)]
36pub struct Obj {
37 id: String,
38}
39
40#[derive(Debug, Clone, Hash, PartialEq, Eq)]
41pub struct Var {
42 id: String,
43}
44
45#[derive(Debug, Clone, PartialEq, Eq, Hash)]
46pub struct Fun {
47 id: String,
48 args: Box<Vec<Term>>,
49}
50
51#[derive(Derivative)]
52#[derivative(Debug, PartialEq)]
53pub struct Clause {
54 #[derivative(PartialEq = "ignore")] id: usize,
56 formulas: Vec<Formula>,
57}
58
59impl Pred {
60 pub fn new(id: &str, args: Box<Vec<Term>>) -> Self {
61 Self {
62 id: id.to_string(),
63 args,
64 }
65 }
66
67 pub fn get_id(&self) -> &String {
68 &self.id
69 }
70
71 pub fn get_args(&self) -> &Box<Vec<Term>> {
72 &self.args
73 }
74}
75
76impl Obj {
77 pub fn new(id: &str) -> Self {
78 Self { id: id.to_string() }
79 }
80}
81
82impl Var {
83 pub fn new(id: &str) -> Self {
84 Self { id: id.to_string() }
85 }
86}
87
88impl Fun {
89 pub fn new(id: &str, args: Box<Vec<Term>>) -> Self {
90 Self {
91 id: id.to_string(),
92 args,
93 }
94 }
95
96 pub fn get_id(&self) -> &String {
97 &self.id
98 }
99
100 pub fn get_args(&self) -> &Box<Vec<Term>> {
101 &self.args
102 }
103}
104
105static CLAUSE_COUNTER: AtomicUsize = AtomicUsize::new(0);
106
107impl Clause {
108 pub fn new(formulas: Vec<Formula>) -> Self {
109 Self {
110 id: CLAUSE_COUNTER.fetch_add(1, Ordering::SeqCst),
111 formulas,
112 }
113 }
114
115 pub fn get_id(&self) -> usize {
116 self.id
117 }
118
119 pub fn get_formulas(&self) -> &Vec<Formula> {
120 &self.formulas
121 }
122}
123
124impl Display for Formula {
125 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126 match &self {
127 Formula::Pred(pred) => write!(f, "{pred}"),
128 Formula::True => write!(f, "true"),
129 Formula::False => write!(f, "false"),
130 Formula::And(l, r) => write!(f, "({l}) /\\ ({r})"),
131 Formula::Or(l, r) => write!(f, "({l}) \\/ ({r})"),
132 Formula::Neg(l) => write!(f, "~({l})"),
133 Formula::Imply(l, r) => write!(f, "({l}) -> ({r})"),
134 Formula::Iff(l, r) => write!(f, "({l}) <-> ({r})"),
135 Formula::Forall(v, l) => write!(f, "forall {v}.({l})"),
136 Formula::Exists(v, l) => write!(f, "exists {v}.({l})"),
137 }
138 }
139}
140
141impl Display for Pred {
142 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
143 write!(f, "{}(", self.id)?;
144 for (index, arg) in self.args.iter().enumerate() {
145 write!(f, "{arg}")?;
146 if index != self.args.len() - 1 {
147 write!(f, ", ")?;
148 }
149 }
150 write!(f, ")")
151 }
152}
153
154impl Display for Term {
155 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
156 match &self {
157 Term::Obj(Obj { id }) => write!(f, "{id}"),
158 Term::Var(Var { id }) => write!(f, "{id}"),
159 Term::Fun(func) => write!(f, "{func}"),
160 }
161 }
162}
163
164impl Display for Obj {
165 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
166 write!(f, "{}", self.id)
167 }
168}
169
170impl Display for Var {
171 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172 write!(f, "{}", self.id)
173 }
174}
175
176impl Display for Fun {
177 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
178 write!(f, "{}(", self.id)?;
179 for (index, arg) in self.args.iter().enumerate() {
180 write!(f, "{arg}")?;
181 if index != self.args.len() - 1 {
182 write!(f, ", ")?;
183 }
184 }
185 write!(f, ")")
186 }
187}
188
189impl Display for Clause {
190 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
191 write!(f, "C{}: {{", self.id)?;
192 for (index, arg) in self.formulas.iter().enumerate() {
193 write!(f, "{arg}")?;
194 if index != self.formulas.len() - 1 {
195 write!(f, ", ")?;
196 }
197 }
198 write!(f, "}}")
199 }
200}
201
202#[macro_export]
203macro_rules! And {
204 ($left:expr, $right:expr) => {
205 Formula::And(Box::new($left), Box::new($right))
206 };
207}
208
209#[macro_export]
210macro_rules! Or {
211 ($left:expr, $right:expr) => {
212 Formula::Or(Box::new($left), Box::new($right))
213 };
214}
215
216#[macro_export]
217macro_rules! Imply {
218 ($left:expr, $right:expr) => {
219 Formula::Imply(Box::new($left), Box::new($right))
220 };
221}
222
223#[macro_export]
224macro_rules! Iff {
225 ($left:expr, $right:expr) => {
226 Formula::Iff(Box::new($left), Box::new($right))
227 };
228}
229
230#[macro_export]
231macro_rules! Neg {
232 ($subformula:expr) => {
233 Formula::Neg(Box::new($subformula))
234 };
235}
236
237#[macro_export]
238macro_rules! Forall {
239 ($var:expr, $subformula:expr) => {
240 Formula::Forall(Var::new($var), Box::new($subformula))
241 };
242}
243
244#[macro_export]
245macro_rules! Exists {
246 ($var:expr, $subformula:expr) => {
247 Formula::Exists(Var::new($var), Box::new($subformula))
248 };
249}
250
251#[macro_export]
252macro_rules! Pred {
253 ($id:expr, [$($arg:expr),*]) => {
254 Formula::Pred(Pred::new($id, Box::new(vec![$($arg),*])))
255 };
256}
257
258#[macro_export]
259macro_rules! Obj {
260 ($name:expr) => {
261 Term::Obj(Obj::new($name))
262 };
263}
264
265#[macro_export]
266macro_rules! Var {
267 ($name:expr) => {
268 Term::Var(Var::new($name))
269 };
270}
271
272#[macro_export]
273macro_rules! Fun {
274 ($id:expr, [$($arg:expr),*]) => {
275 Term::Fun(Fun::new($id, Box::new(vec![$($arg),*])))
276 };
277}