1use crate::{lambda::HashLambda, utils::ArgumentIterator};
2use ahash::HashMap;
3use std::{fmt::Write, hash::Hash, iter::empty};
4use thiserror::Error;
5
6use super::{
7 ActorOrEvent, BinOp, Constant, Expr, ExprPool, ExprRef, LambdaParseError, LanguageExpression,
8 MonOp, Variable,
9};
10use crate::{
11 lambda::{
12 LambdaExpr, LambdaExprRef, LambdaLanguageOfThought, LambdaPool, ReductionError,
13 RootedLambdaPool, types::LambdaType,
14 },
15 language::parser::parse_lot,
16};
17
18impl From<ExprRef> for LambdaExprRef {
19 fn from(value: ExprRef) -> Self {
20 LambdaExprRef(value.0)
21 }
22}
23
24impl From<LambdaExprRef> for ExprRef {
25 fn from(value: LambdaExprRef) -> Self {
26 ExprRef(value.0)
27 }
28}
29
30#[derive(Debug, Clone, Error, PartialEq, Eq)]
31pub enum LambdaConversionError {
32 #[error("There are still lambda terms in this pool")]
33 StillHasLambdaTerms,
34 #[error("Reducing lambda exprs in quantifiers is leading to a bug ({0})")]
35 ReductionError(#[from] ReductionError),
36}
37
38impl<'a> LambdaLanguageOfThought for Expr<'a> {
39 type Pool = LanguageExpression<'a>;
40 type ConversionError = LambdaConversionError;
41
42 fn n_children(&self) -> usize {
43 match self {
44 Expr::Quantifier { .. } | Expr::Binary(..) => 2,
45 Expr::Unary(..) => 1,
46 Expr::Variable(_) | Expr::Actor(_) | Expr::Event(_) | Expr::Constant(_) => 0,
47 }
48 }
49
50 fn inc_depth(&self) -> bool {
51 matches!(
52 self,
53 Expr::Quantifier { .. } | Expr::Unary(MonOp::Iota(_), _)
54 )
55 }
56
57 fn var_type(&self) -> Option<&LambdaType> {
58 match self {
59 Expr::Quantifier { var_type, .. } | Expr::Unary(MonOp::Iota(var_type), _) => {
60 match var_type {
61 ActorOrEvent::Actor => Some(LambdaType::a()),
62 ActorOrEvent::Event => Some(LambdaType::e()),
63 }
64 }
65 _ => None,
66 }
67 }
68
69 fn get_children(&self) -> impl Iterator<Item = LambdaExprRef> {
70 match self {
71 Expr::Quantifier {
72 restrictor,
73 subformula,
74 ..
75 } => vec![restrictor, subformula],
76 Expr::Binary(_, x, y) => vec![x, y],
77 Expr::Unary(_, x) => vec![x],
78 Expr::Constant(_) | Expr::Actor(_) | Expr::Event(_) | Expr::Variable(_) => vec![],
79 }
80 .into_iter()
81 .map(|x| LambdaExprRef(x.0))
82 }
83
84 fn change_children(&mut self, mut new_children: impl Iterator<Item = LambdaExprRef>) {
85 match self {
86 Expr::Quantifier {
87 restrictor,
88 subformula,
89 ..
90 } => {
91 *restrictor = ExprRef(new_children.next().unwrap().0);
92 *subformula = ExprRef(new_children.next().unwrap().0);
93 }
94 Expr::Binary(_, x, y) => {
95 *x = ExprRef(new_children.next().unwrap().0);
96 *y = ExprRef(new_children.next().unwrap().0);
97 }
98 Expr::Unary(_, x) => {
99 *x = ExprRef(new_children.next().unwrap().0);
100 }
101 Expr::Variable(_) | Expr::Actor(_) | Expr::Event(_) | Expr::Constant(_) => (),
102 }
103 }
104
105 fn remap_refs(&mut self, remap: &[usize]) {
106 match self {
107 Expr::Quantifier {
108 restrictor,
109 subformula,
110 ..
111 } => {
112 *restrictor = ExprRef(remap[restrictor.0 as usize] as u32);
113 *subformula = ExprRef(remap[subformula.0 as usize] as u32);
114 }
115 Expr::Binary(_, x, y) => {
116 *x = ExprRef(remap[x.0 as usize] as u32);
117 *y = ExprRef(remap[y.0 as usize] as u32);
118 }
119 Expr::Unary(_, x) => {
120 *x = ExprRef(remap[x.0 as usize] as u32);
121 }
122 Expr::Variable(_) | Expr::Actor(_) | Expr::Event(_) | Expr::Constant(_) => (),
123 }
124 }
125
126 fn get_type(&self) -> &LambdaType {
127 match self {
128 Expr::Quantifier { .. } => LambdaType::t(),
129 Expr::Variable(Variable::Actor(_)) | Expr::Actor(_) => LambdaType::a(),
130 Expr::Variable(Variable::Event(_)) | Expr::Event(_) => LambdaType::e(),
131 Expr::Binary(bin, ..) => match bin {
132 BinOp::AgentOf | BinOp::PatientOf | BinOp::And | BinOp::Or => LambdaType::t(),
133 },
134 Expr::Unary(mon_op, _) => match mon_op {
135 MonOp::Property(_, _) | MonOp::Not => LambdaType::t(),
136 MonOp::Iota(ActorOrEvent::Actor) => LambdaType::a(),
137 MonOp::Iota(ActorOrEvent::Event) => LambdaType::e(),
138 },
139 Expr::Constant(constant) => match constant {
140 Constant::Everyone | Constant::Property(_, ActorOrEvent::Actor) => LambdaType::at(),
141 Constant::EveryEvent | Constant::Property(_, ActorOrEvent::Event) => {
142 LambdaType::et()
143 }
144 Constant::Contradiction | Constant::Tautology => LambdaType::t(),
145 },
146 }
147 }
148
149 fn same_expr(&self, other: &Self) -> bool {
150 match self {
151 Expr::Quantifier {
152 quantifier: q1,
153 var_type: v1,
154 ..
155 } => {
156 matches!(other, Expr::Quantifier{ quantifier: q2, var_type: v2, .. } if q1==q2 && v1==v2)
157 }
158 Expr::Variable(_) | Expr::Actor(_) | Expr::Event(_) | Expr::Constant(_) => {
159 self == other
160 }
161 Expr::Binary(b1, ..) => matches!(other, Expr::Binary(b2, ..) if b1==b2),
162 Expr::Unary(m1, _) => matches!(other, Expr::Unary(m2,_) if m1==m2),
163 }
164 }
165
166 fn to_pool(pool: RootedLambdaPool<Self>) -> Result<Self::Pool, Self::ConversionError> {
167 let processed_pool = pool
168 .pool
169 .0
170 .into_iter()
171 .map(|x| match x {
172 LambdaExpr::LanguageOfThoughtExpr(x) => Ok(x),
173 LambdaExpr::BoundVariable(x, LambdaType::A) => {
174 Ok(Expr::Variable(Variable::Actor(x as u32)))
175 }
176 LambdaExpr::BoundVariable(x, LambdaType::E) => {
177 Ok(Expr::Variable(Variable::Event(x as u32)))
178 }
179 _ => Err(LambdaConversionError::StillHasLambdaTerms),
180 })
181 .collect::<Result<Vec<_>, LambdaConversionError>>()?;
182
183 Ok(LanguageExpression {
184 pool: ExprPool(processed_pool),
185 start: ExprRef(pool.root.0),
186 })
187 }
188
189 fn get_arguments(&self) -> impl Iterator<Item = LambdaType> {
190 match self {
191 Expr::Quantifier { .. } => {
192 ArgumentIterator::A([LambdaType::t().clone(), LambdaType::t().clone()].into_iter())
193 }
194 Expr::Binary(b, _, _) => {
195 ArgumentIterator::B(b.get_argument_type().into_iter().cloned())
196 }
197 Expr::Unary(mon_op, _) => {
198 ArgumentIterator::C([mon_op.get_argument_type().clone()].into_iter())
199 }
200 Expr::Variable(Variable::Event(_) | Variable::Actor(_))
201 | Expr::Actor(_)
202 | Expr::Event(_)
203 | Expr::Constant(_) => ArgumentIterator::D(empty()),
204 }
205 }
206
207 fn commutative(&self) -> bool {
208 matches!(self, Expr::Binary(BinOp::And | BinOp::Or, ..))
209 }
210}
211
212impl HashLambda for Expr<'_> {
213 fn hash_expr<H: std::hash::Hasher>(&self, state: &mut H) {
214 match self {
215 Expr::Quantifier {
216 quantifier,
217 var_type,
218 ..
219 } => {
220 0.hash(state);
221 quantifier.hash(state);
222 var_type.hash(state);
223 }
224 Expr::Variable(variable) => {
225 1.hash(state);
226 variable.hash(state);
227 }
228 Expr::Actor(a) => {
229 2.hash(state);
230 a.hash(state);
231 }
232 Expr::Event(b) => {
233 3.hash(state);
234 b.hash(state);
235 }
236 Expr::Binary(bin_op, ..) => {
237 4.hash(state);
238 bin_op.hash(state);
239 }
240 Expr::Unary(mon_op, _) => {
241 5.hash(state);
242 mon_op.hash(state);
243 }
244 Expr::Constant(constant) => {
245 6.hash(state);
246 constant.hash(state);
247 }
248 }
249 }
250}
251
252impl<'a> std::fmt::Display for RootedLambdaPool<'a, Expr<'a>> {
253 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
254 let (string, _) = self.string(self.root(), VarContext::default(), false);
255 write!(f, "{string}")
256 }
257}
258
259static VARIABLENAMES: [&str; 26] = [
260 "x", "y", "z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p",
261 "q", "r", "s", "t", "u", "v", "w",
262];
263
264static TRUTHS: [&str; 2] = ["phi", "psi"];
265
266static PREDICATENAMES: [&str; 3] = ["P", "Q", "R"];
267
268static OTHERFUNCTIONS: [&str; 4] = ["M", "N", "G", "K"];
269
270pub fn to_var(x: usize, t: Option<&LambdaType>) -> String {
271 let var_names = match t {
272 Some(t) if t == LambdaType::t() => TRUTHS.as_slice(),
273 Some(t) if t.is_one_place_function() => PREDICATENAMES.as_slice(),
274 Some(t) if t.is_function() => OTHERFUNCTIONS.as_slice(),
275 _ => VARIABLENAMES.as_slice(),
276 };
277
278 if x < var_names.len() {
279 var_names[x].to_string()
280 } else {
281 format!("{}{}", var_names[x % var_names.len()], x / var_names.len())
282 }
283}
284
285#[derive(Debug, Clone, Eq, PartialEq, Default)]
286pub(super) struct VarContext {
287 vars: HashMap<usize, usize>,
288 predicates: HashMap<usize, usize>,
289 other_functions: HashMap<usize, usize>,
290 truths: HashMap<usize, usize>,
291 depth: usize,
292}
293
294impl VarContext {
295 fn get_map(&self, t: Option<&LambdaType>) -> &HashMap<usize, usize> {
296 match t {
297 Some(t) if t == LambdaType::t() => &self.truths,
298 Some(t) if t.is_one_place_function() => &self.predicates,
299 Some(t) if t.is_function() => &self.other_functions,
300 _ => &self.vars,
301 }
302 }
303 fn get_map_mut(&mut self, t: Option<&LambdaType>) -> &mut HashMap<usize, usize> {
304 match t {
305 Some(t) if t == LambdaType::t() => &mut self.truths,
306 Some(t) if t.is_one_place_function() => &mut self.predicates,
307 Some(t) if t.is_function() => &mut self.other_functions,
308 _ => &mut self.vars,
309 }
310 }
311
312 pub(super) fn inc_depth_q(self, t: ActorOrEvent) -> (Self, String) {
313 let t: LambdaType = t.into();
314 self.inc_depth(&t)
315 }
316
317 pub(super) fn inc_depth(mut self, t: &LambdaType) -> (Self, String) {
318 let d = self.depth;
319 let map = self.get_map_mut(Some(t));
320 let n_var = map.len();
321 map.insert(d, n_var);
322 self.depth += 1;
323 (self, to_var(n_var, Some(t)))
324 }
325
326 pub(super) fn lambda_var(&self, bvar: usize, t: &LambdaType) -> String {
327 to_var(
328 *self.get_map(Some(t)).get(&(self.depth - bvar - 1)).unwrap(),
329 Some(t),
330 )
331 }
332}
333
334impl<'a> From<LanguageExpression<'a>> for RootedLambdaPool<'a, Expr<'a>> {
335 fn from(value: LanguageExpression<'a>) -> Self {
336 RootedLambdaPool {
337 pool: LambdaPool::from(
338 value
339 .pool
340 .0
341 .iter()
342 .map(|x| LambdaExpr::LanguageOfThoughtExpr(*x))
343 .collect(),
344 ),
345 root: crate::lambda::LambdaExprRef(value.start.0),
346 }
347 }
348}
349
350#[derive(Debug, Copy, Clone, PartialEq, Eq)]
351pub(super) enum AssociativityData {
352 Lambda,
353 App,
354 Binom(BinOp),
355 Monop,
356}
357
358#[derive(Debug, Clone, Error, PartialEq, Eq)]
360pub enum ConjoiningError {
361 #[error("Can't conjoin {0} and {1}")]
363 MismatchingTypes(LambdaType, LambdaType),
364
365 #[error("Lambda type, {0} doesn't return a truth value")]
367 DoesntReturnT(LambdaType),
368
369 #[error("One of the operands causes problems in reduction: {0})")]
371 ReductionError(#[from] ReductionError),
372}
373
374fn who_raises_who<'a>(
375 a: RootedLambdaPool<'a, Expr<'a>>,
376 b: RootedLambdaPool<'a, Expr<'a>>,
377) -> Result<
378 (
379 RootedLambdaPool<'a, Expr<'a>>,
380 RootedLambdaPool<'a, Expr<'a>>,
381 ),
382 ConjoiningError,
383> {
384 let a_type = a.get_type().unwrap();
385 let b_type = b.get_type().unwrap();
386
387 let Ok(a_rhs) = a_type.rhs() else {
388 return Err(ConjoiningError::DoesntReturnT(a_type));
389 };
390 let Ok(b_rhs) = b_type.rhs() else {
391 return Err(ConjoiningError::DoesntReturnT(b_type));
392 };
393 if b_rhs != &LambdaType::T && a_rhs != &LambdaType::T {
394 return Err(ConjoiningError::DoesntReturnT(a_type));
395 }
396
397 if a_rhs != &b_type && b_rhs != &a_type {
398 Err(ConjoiningError::MismatchingTypes(a_type, b_type))
399 } else if a_rhs == &b_type {
400 Ok((a, b))
401 } else {
402 Ok((b, a))
403 }
404}
405
406impl<'a> RootedLambdaPool<'a, Expr<'a>> {
407 pub fn conjoin(self, other: Self) -> Result<Self, ConjoiningError> {
410 let self_type = self.get_type().unwrap();
411 let other_type = other.get_type().unwrap();
412 if self_type != other_type {
413 return Err(ConjoiningError::MismatchingTypes(self_type, other_type));
414 }
415
416 let Ok((lhs, rhs)) = self_type.split() else {
417 return Err(ConjoiningError::DoesntReturnT(self_type));
418 };
419
420 if rhs != &LambdaType::T {
421 return Err(ConjoiningError::DoesntReturnT(self_type));
422 }
423 let lhs = lhs.clone();
424
425 let combinator = RootedLambdaPool {
426 pool: LambdaPool(vec![
427 LambdaExpr::Lambda(LambdaExprRef(1), self_type.clone()),
428 LambdaExpr::Lambda(LambdaExprRef(2), other_type.clone()),
429 LambdaExpr::Lambda(LambdaExprRef(3), lhs.clone()),
430 LambdaExpr::LanguageOfThoughtExpr(Expr::Binary(BinOp::And, ExprRef(4), ExprRef(7))),
431 LambdaExpr::Application {
432 subformula: LambdaExprRef(5),
433 argument: LambdaExprRef(6),
434 },
435 LambdaExpr::BoundVariable(2, self_type),
436 LambdaExpr::BoundVariable(0, lhs.clone()),
437 LambdaExpr::Application {
438 subformula: LambdaExprRef(8),
439 argument: LambdaExprRef(9),
440 },
441 LambdaExpr::BoundVariable(1, other_type),
442 LambdaExpr::BoundVariable(0, lhs),
443 ]),
444 root: LambdaExprRef(0),
445 };
446
447 let mut conjoined = combinator.merge(self).unwrap().merge(other).unwrap();
448 conjoined.reduce()?;
449 Ok(conjoined)
450 }
451
452 pub fn raised_conjoin(self, other: Self) -> Result<Self, ConjoiningError> {
459 let (a, b) = who_raises_who(self, other)?;
460 let a_type = a.get_type().unwrap();
461 let b_type = b.get_type().unwrap();
462
463 let Ok(event) = a_type.lhs() else {
464 return Err(ConjoiningError::DoesntReturnT(a_type));
465 };
466
467 let Ok(e) = b_type.lhs() else {
468 return Err(ConjoiningError::DoesntReturnT(b_type));
469 };
470 let e = e.clone();
471 let event = event.clone();
472
473 let combinator = RootedLambdaPool {
474 pool: LambdaPool(vec![
475 LambdaExpr::Lambda(LambdaExprRef(1), a_type.clone()),
476 LambdaExpr::Lambda(LambdaExprRef(2), b_type.clone()),
477 LambdaExpr::Lambda(LambdaExprRef(3), event.clone()),
478 LambdaExpr::Lambda(LambdaExprRef(4), e.clone()),
479 LambdaExpr::LanguageOfThoughtExpr(Expr::Binary(
480 BinOp::And,
481 ExprRef(5),
482 ExprRef(10),
483 )),
484 LambdaExpr::Application {
485 subformula: LambdaExprRef(6),
486 argument: LambdaExprRef(9),
487 },
488 LambdaExpr::Application {
489 subformula: LambdaExprRef(7),
490 argument: LambdaExprRef(8),
491 },
492 LambdaExpr::BoundVariable(3, a_type),
493 LambdaExpr::BoundVariable(1, event),
494 LambdaExpr::BoundVariable(0, e.clone()),
495 LambdaExpr::Application {
496 subformula: LambdaExprRef(11),
497 argument: LambdaExprRef(12),
498 },
499 LambdaExpr::BoundVariable(2, b_type),
500 LambdaExpr::BoundVariable(0, e),
501 ]),
502 root: LambdaExprRef(0),
503 };
504
505 let mut conjoined = combinator.merge(a).unwrap().merge(b).unwrap();
506 conjoined.reduce()?;
507 Ok(conjoined)
508 }
509
510 pub fn parse(s: &'a str) -> Result<Self, LambdaParseError> {
512 parse_lot(s)
513 }
514
515 fn string(
516 &self,
517 expr: LambdaExprRef,
518 c: VarContext,
519 parent_is_app: bool,
520 ) -> (String, AssociativityData) {
521 match self.get(expr) {
522 LambdaExpr::Lambda(child, lambda_type) => {
523 let (c, var) = c.inc_depth(lambda_type);
524 (
525 format!(
526 "lambda {} {} {}",
527 lambda_type,
528 var,
529 self.string(*child, c, false).0
530 ),
531 AssociativityData::Lambda,
532 )
533 }
534 LambdaExpr::Application {
535 subformula,
536 argument,
537 } => {
538 let (sub, associative) = self.string(*subformula, c.clone(), true);
539 let (arg, _) = self.string(*argument, c, false); let mut s = match associative {
543 AssociativityData::Lambda | AssociativityData::Binom(_) => {
544 format!("({sub})({arg}")
545 }
546 AssociativityData::Monop => format!("{sub}({arg}"),
547 AssociativityData::App => format!("{sub}{arg}"),
548 };
549
550 if parent_is_app {
551 s.push_str(", ");
552 } else {
553 s.push(')');
554 }
555
556 (s, AssociativityData::App)
557 }
558 LambdaExpr::BoundVariable(bvar, lambda_type) => {
559 (c.lambda_var(*bvar, lambda_type), AssociativityData::Monop)
560 }
561 LambdaExpr::FreeVariable(fvar, t) => (format!("{fvar}#{t}"), AssociativityData::Monop),
562 LambdaExpr::LanguageOfThoughtExpr(x) => match x {
563 Expr::Variable(variable) => (
564 c.lambda_var(variable.id() as usize, variable.as_lambda_type()),
565 AssociativityData::Monop,
566 ),
567 Expr::Quantifier {
568 quantifier,
569 var_type,
570 restrictor,
571 subformula,
572 } => {
573 let (c, var_string) = c.inc_depth_q(*var_type);
574 let (restrictor, _) =
575 self.string(LambdaExprRef(restrictor.0), c.clone(), false);
576 let (subformula, _) = self.string(LambdaExprRef(subformula.0), c, false);
577 (
578 format!(
579 "{}{}({}, {restrictor}, {subformula})",
580 quantifier,
581 match var_type {
582 ActorOrEvent::Actor => "",
583 ActorOrEvent::Event => "_e",
584 },
585 var_string,
586 ),
587 AssociativityData::Monop,
588 )
589 }
590 Expr::Unary(MonOp::Iota(var_type), arg) => {
591 let (c, var_string) = c.inc_depth_q(*var_type);
592 let (arg, _) = self.string(LambdaExprRef(arg.0), c, false);
593 (
594 format!(
595 "iota{}({}, {arg})",
596 match var_type {
597 ActorOrEvent::Actor => "",
598 ActorOrEvent::Event => "_e",
599 },
600 var_string,
601 ),
602 AssociativityData::Monop,
603 )
604 }
605 Expr::Actor(a) => (format!("a_{a}"), AssociativityData::Monop),
606 Expr::Event(e) => (format!("e_{e}"), AssociativityData::Monop),
607 Expr::Binary(bin_op, x, y) => {
608 let (x, x_a) = self.string(LambdaExprRef(x.0), c.clone(), false);
609 let (y, y_a) = self.string(LambdaExprRef(y.0), c, false);
610 match bin_op {
611 BinOp::AgentOf | BinOp::PatientOf => {
612 (format!("{bin_op}({x}, {y})",), AssociativityData::Monop)
613 }
614
615 BinOp::And | BinOp::Or => (
616 {
617 let mut s = String::default();
618 if add_parenthesis_for_bin_op(*bin_op, x_a) {
619 write!(s, "({x})").unwrap();
620 } else {
621 s.push_str(&x);
622 }
623 write!(s, " {bin_op} ").unwrap();
624 if add_parenthesis_for_bin_op(*bin_op, y_a) {
625 write!(s, "({y})").unwrap();
626 } else {
627 s.push_str(&y);
628 }
629 s
630 },
631 AssociativityData::Binom(*bin_op),
632 ),
633 }
634 }
635 Expr::Unary(mon_op, arg) => {
636 let (arg, arg_binom) = self.string(LambdaExprRef(arg.0), c, false);
637 (
638 match mon_op {
639 MonOp::Not => match arg_binom {
640 AssociativityData::Binom(BinOp::And | BinOp::Or) => {
641 format!("{mon_op}({arg})")
642 }
643 AssociativityData::Binom(_)
644 | AssociativityData::Lambda
645 | AssociativityData::App
646 | AssociativityData::Monop => {
647 format!("{mon_op}{arg}")
648 }
649 },
650 _ => format!("{mon_op}({arg})"),
651 },
652 AssociativityData::Monop,
653 )
654 }
655 Expr::Constant(constant) => (format!("{constant}"), AssociativityData::Monop),
656 },
657 }
658 }
659}
660
661pub(super) fn add_parenthesis_for_bin_op(x: BinOp, data: AssociativityData) -> bool {
662 match data {
663 AssociativityData::Binom(b) => match b {
664 BinOp::AgentOf | BinOp::PatientOf => false,
665 BinOp::And | BinOp::Or if b == x => false,
666 BinOp::And | BinOp::Or => true,
667 },
668 AssociativityData::Lambda => true,
669 AssociativityData::App | AssociativityData::Monop => false,
670 }
671}
672
673#[cfg(test)]
674mod test {
675 use super::to_var;
676
677 use crate::lambda::{FreeVar, types::LambdaType};
678 use crate::{Entity, Scenario, ThetaRoles, lambda::RootedLambdaPool, parse_executable};
679
680 #[test]
681 fn fancy_printing() -> anyhow::Result<()> {
682 for statement in [
683 "~AgentOf(a_John, e_0)",
684 "pa_Red(a_John) & ~pa_Red(a_Mary)",
685 "every(x, all_a, pa_Blue(x))",
686 "every(x, pa_Blue, pa_Blue(x))",
687 "every(x, pa_5, pa_10(a_59))",
688 "every_e(x, all_e, PatientOf(a_Mary, x))",
689 ] {
690 println!("{statement}");
691 let expression = parse_executable(statement)?;
692 assert_eq!(expression.to_string(), statement);
693 }
694 for s in [
695 "cool#<a,t>(a_John)",
696 "bad#<a,t>(man#a)",
697 "woah#<<e,t>,t>(lambda e x pe_wow(x))",
698 "lambda <a,t> P lambda a x P(x)",
699 "lambda <a,t> P P(a_man) & ~P(a_woman)",
700 "loves#<a,<a,t>>(a_john, a_mary)",
701 "gives#<a,<a,<a,t>>>(a_john, a_mary, a_present)",
702 "lambda e x lambda a y loves#<e,<a,t>>(x, y)",
703 ] {
704 println!("{s}");
705 let p = RootedLambdaPool::parse(s)?;
706 assert_eq!(p.to_string(), s);
707 }
708
709 Ok(())
710 }
711
712 #[test]
713 fn type_checking() -> anyhow::Result<()> {
714 let john = RootedLambdaPool::parse("a_John")?;
715 let likes = RootedLambdaPool::parse(
716 "lambda a x ((lambda a y (some_e(e, all_e, AgentOf(x, e) & PatientOf(y, e) & pe_likes(e)))))",
717 )?;
718
719 let mary = RootedLambdaPool::parse("a_Mary")?;
720 let phi = mary.clone().merge(likes.clone()).unwrap();
721 let mut phi = phi.merge(john.clone()).unwrap();
722 phi.reduce()?;
723 let pool = phi.into_pool()?;
724 assert_eq!(
725 "some_e(x, all_e, AgentOf(a_Mary, x) & PatientOf(a_John, x) & pe_likes(x))",
726 pool.to_string()
727 );
728 let phi = likes.merge(mary).unwrap();
729 let mut phi = john.merge(phi).unwrap();
730 phi.reduce()?;
731 let pool = phi.into_pool()?;
732 assert_eq!(
733 "some_e(x, all_e, AgentOf(a_Mary, x) & PatientOf(a_John, x) & pe_likes(x))",
734 pool.to_string()
735 );
736 Ok(())
737 }
738
739 #[test]
740 fn var_name_assigner() {
741 assert_eq!(to_var(0, None), "x");
742 assert_eq!(to_var(1, None), "y");
743 assert_eq!(to_var(2, None), "z");
744 assert_eq!(to_var(26, None), "x1");
745 assert_eq!(to_var(27, None), "y1");
746 assert_eq!(to_var(28, None), "z1");
747 assert_eq!(to_var(26 * 300, None), "x300");
748 }
749
750 #[test]
751 fn printing() -> anyhow::Result<()> {
752 let pool = RootedLambdaPool::parse(
753 "some_e(x0, all_e, AgentOf(a_1, x0) & PatientOf(a_0, x0) & pe_0(x0))",
754 )?;
755 assert_eq!(
756 pool.to_string(),
757 "some_e(x, all_e, AgentOf(a_1, x) & PatientOf(a_0, x) & pe_0(x))"
758 );
759 let likes = RootedLambdaPool::parse(
760 "lambda e x lambda e y (some(e, all_a, AgentOf(e, x) & PatientOf(e, y) & pe_likes(y)))",
761 )?;
762
763 let s =
764 "lambda e x lambda e y some(z, all_a, AgentOf(z, x) & PatientOf(z, y) & pe_likes(y))";
765 assert_eq!(likes.to_string(), s,);
766 let likes2 = RootedLambdaPool::parse(s)?;
767 assert_eq!(likes, likes2);
768
769 Ok(())
770 }
771
772 #[test]
773 fn fancy_quantification_reduction() -> anyhow::Result<()> {
774 let pool = RootedLambdaPool::parse("every_e(x0,pe_0(x0) & pe_1(x0), pe_2(x0))")?;
775 let scenario = Scenario::new(
776 vec![],
777 vec![ThetaRoles::default(); 5],
778 [
779 ("0", vec![Entity::Event(1), Entity::Event(2)]),
780 ("1", vec![Entity::Event(0), Entity::Event(1)]),
781 ("2", vec![Entity::Event(1)]),
782 ]
783 .into_iter()
784 .collect(),
785 );
786
787 dbg!(&pool);
788 assert!(pool.into_pool()?.run(&scenario, None)?.try_into()?);
789
790 let pool = RootedLambdaPool::parse("every_e(x0, pe_0(x0) & pe_1(x0), pe_2(x0))")?;
791
792 let scenario = Scenario::new(
793 vec![],
794 vec![ThetaRoles::default(); 5],
795 [
796 ("0", vec![Entity::Event(1), Entity::Event(2)]),
797 ("1", vec![Entity::Event(0), Entity::Event(1)]),
798 ("2", vec![Entity::Event(1)]),
799 ]
800 .into_iter()
801 .collect(),
802 );
803
804 dbg!(&pool);
805 assert!(pool.into_pool()?.run(&scenario, None)?.try_into()?);
806
807 let pool =
808 RootedLambdaPool::parse("every_e(x, pe_laughs, every(y, pe_sleeps(x), pa_woman(y)))")?;
809 println!("{}", pool.into_pool()?);
810 Ok(())
811 }
812
813 #[test]
814 fn conjoining_check() -> anyhow::Result<()> {
815 let tall = RootedLambdaPool::parse("lambda a x pa_tall(x)")?;
816 let man = RootedLambdaPool::parse("lambda a x pa_man(x)")?;
817
818 let mut tall_man = tall.conjoin(man)?;
819 tall_man.reduce()?;
820 let weird = RootedLambdaPool::parse("weird#<a,t>")?;
821 let man = RootedLambdaPool::parse("lambda a x pa_man(x)")?;
822 let weird_man = weird.conjoin(man)?;
823 assert_eq!(format!("{tall_man}"), "lambda a x pa_tall(x) & pa_man(x)");
824 assert_eq!(
825 format!("{weird_man}"),
826 "lambda a x weird#<a,t>(x) & pa_man(x)"
827 );
828
829 let voice = RootedLambdaPool::parse("lambda a x lambda e y AgentOf(x, y)")?;
830 let run = RootedLambdaPool::parse("lambda e x pe_run(x)")?;
831
832 let mut agent_run = voice.raised_conjoin(run)?;
833 agent_run.reduce()?;
834 assert_eq!(
835 format!("{agent_run}"),
836 "lambda a x lambda e y AgentOf(x, y) & pe_run(y)"
837 );
838 let voice = RootedLambdaPool::parse("lambda a x lambda e y AgentOf(x, y)")?;
839 let run = RootedLambdaPool::parse("lambda e x pe_run(x)")?;
840
841 let mut agent_run = run.raised_conjoin(voice)?;
842 agent_run.reduce()?;
843 assert_eq!(
844 format!("{agent_run}"),
845 "lambda a x lambda e y AgentOf(x, y) & pe_run(y)"
846 );
847 Ok(())
848 }
849
850 #[test]
851 fn alpha_check() -> anyhow::Result<()> {
852 let everyone = RootedLambdaPool::parse("lambda <a,t> P (every(x, all_a, P(x)))")?;
853 let someone = RootedLambdaPool::parse("lambda <a,t> P (some(x, all_a, P(x)))")?;
854 let mut likes = RootedLambdaPool::parse(
855 "lambda a x (lambda a y (some_e(e, all_e, AgentOf(y, e)&pe_likes(e)&PatientOf(x, e))))",
856 )?;
857
858 likes.apply_new_free_variable(FreeVar::Anonymous(0))?;
859 let mut sentence = likes.merge(someone).unwrap();
860 sentence.lambda_abstract_free_variable(FreeVar::Anonymous(0), LambdaType::A, true)?;
861 let mut sentence = sentence.merge(everyone).unwrap();
862 sentence.reduce()?;
863
864 assert_eq!(
865 sentence.to_string(),
866 "every(x, all_a, some(y, all_a, some_e(z, all_e, AgentOf(y, z) & pe_likes(z) & PatientOf(x, z))))"
867 );
868
869 assert_eq!(
870 sentence,
871 RootedLambdaPool::parse(
872 "every(x, all_a, some(y, all_a, some_e(z, all_e, AgentOf(y, z) & pe_likes(z) & PatientOf(x, z))))"
873 )?
874 );
875
876 let everyone = RootedLambdaPool::parse("lambda <a,t> P (every(x, all_a, P(x)))")?;
877 let someone = RootedLambdaPool::parse("lambda <a,t> P (some(x, all_a, P(x)))")?;
878 let mut likes = RootedLambdaPool::parse(
879 "lambda a x (lambda a y ( some_e(e, all_e, AgentOf(y, e)&pe_likes(e)&PatientOf(x, e)) | some(w, all_a, every_e(e, all_e, AgentOf(y, e)&pe_likes(e)&PatientOf(x, e)))))",
880 )?;
881
882 likes.apply_new_free_variable(FreeVar::Anonymous(0))?;
883 let mut sentence = likes.merge(someone).unwrap();
884 sentence.lambda_abstract_free_variable(FreeVar::Anonymous(0), LambdaType::A, true)?;
885 let mut sentence = sentence.merge(everyone).unwrap();
886 sentence.reduce()?;
887 assert_eq!(
888 sentence,
889 RootedLambdaPool::parse(
890 "every(x, all_a, some(y, all_a, some_e(z, all_e, AgentOf(y, z) & pe_likes(z) & PatientOf(x, z)) | some(z, all_a, every_e(a, all_e, AgentOf(y, a) & pe_likes(a) & PatientOf(x, a)))))"
891 )?
892 );
893 Ok(())
894 }
895}