1use crate::utils::ArgumentIterator;
5use std::{
6 collections::{HashSet, VecDeque},
7 fmt::{Debug, Display},
8 hash::Hash,
9 iter::empty,
10 marker::PhantomData,
11};
12use thiserror::Error;
13
14pub mod types;
15use types::{LambdaType, TypeError};
16
17pub(crate) type Bvar = usize;
18
19#[derive(Debug, Clone, Error, PartialEq, Eq)]
21pub enum LambdaError {
22 #[error("The free variable has type {free_var} while the argument is {arg}")]
24 BadFreeVariableApp {
25 free_var: LambdaType,
27 arg: LambdaType,
29 },
30 #[error("The free variable has type {free_var} while its lambda takes {lambda}")]
32 BadFreeVariable {
33 free_var: LambdaType,
35 lambda: LambdaType,
37 },
38
39 #[error(
41 "A bound variable {var:?} cannot have a DeBruijn index higher than its lambda depth ({depth})"
42 )]
43 BadBoundVariable {
44 var: LambdaExprRef,
46 depth: usize,
48 },
49
50 #[error("Expression has type error ({0})")]
52 TypeError(#[from] TypeError),
53
54 #[error("Failed reduction: {0}")]
56 ReductionError(#[from] ReductionError),
57}
58
59#[derive(Debug, Clone, Error, PartialEq, Eq)]
61pub enum LambdaTryFromError {
62 #[error("The vec contains None")]
64 HasNone,
65}
66
67#[derive(Debug, Clone, Error, PartialEq, Eq)]
69pub enum ReductionError {
70 #[error("{0:?} is not a valid ref!")]
72 NotValidRef(LambdaExprRef),
73 #[error("{0:?} is not an application!")]
75 NotApplication(LambdaExprRef),
76
77 #[error("The left hand side of the application ({app:?}), {lhs:?} is not a lambda expression!")]
79 NotLambdaInApplication {
80 app: LambdaExprRef,
82 lhs: LambdaExprRef,
84 },
85
86 #[error("Incorrect types: {0}")]
88 TypeError(#[from] TypeError),
89}
90
91#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord)]
93pub struct LambdaExprRef(pub u32);
94
95pub trait LambdaLanguageOfThought {
98 type Pool;
100 type ConversionError;
102
103 fn get_children(&self) -> impl Iterator<Item = LambdaExprRef>;
105
106 fn remap_refs(&mut self, remap: &[usize]);
109
110 fn inc_depth(&self) -> bool;
113
114 fn var_type(&self) -> Option<&LambdaType>;
116
117 fn change_children(&mut self, new_children: impl Iterator<Item = LambdaExprRef>);
119
120 fn n_children(&self) -> usize;
122
123 fn get_type(&self) -> &LambdaType;
125
126 fn get_arguments(&self) -> impl Iterator<Item = LambdaType>;
128
129 fn commutative(&self) -> bool {
131 false
132 }
133
134 fn same_expr(&self, other: &Self) -> bool;
137
138 fn to_pool(pool: RootedLambdaPool<Self>) -> Result<Self::Pool, Self::ConversionError>
142 where
143 Self: Sized;
144}
145
146impl LambdaLanguageOfThought for () {
147 type Pool = ();
148 type ConversionError = ();
149 fn get_children(&self) -> impl Iterator<Item = LambdaExprRef> {
150 std::iter::empty()
151 }
152
153 fn n_children(&self) -> usize {
154 0
155 }
156
157 fn var_type(&self) -> Option<&LambdaType> {
158 None
159 }
160
161 fn same_expr(&self, _other: &Self) -> bool {
162 true
163 }
164
165 fn remap_refs(&mut self, _: &[usize]) {}
166
167 fn change_children(&mut self, _: impl Iterator<Item = LambdaExprRef>) {}
168
169 fn get_type(&self) -> &LambdaType {
170 unimplemented!()
171 }
172
173 fn inc_depth(&self) -> bool {
174 false
175 }
176
177 fn get_arguments(&self) -> impl Iterator<Item = LambdaType> {
178 empty()
179 }
180
181 fn to_pool(_: RootedLambdaPool<Self>) -> Result<Self::Pool, ()> {
182 Ok(())
183 }
184}
185
186#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord)]
188pub enum FreeVar<'a> {
189 Named(&'a str),
191 Anonymous(usize),
193}
194
195impl Display for FreeVar<'_> {
196 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
197 match self {
198 FreeVar::Named(s) => write!(f, "{s}"),
199 FreeVar::Anonymous(t) => write!(f, "{t}"),
200 }
201 }
202}
203
204impl<'a> From<&'a str> for FreeVar<'a> {
205 fn from(value: &'a str) -> Self {
206 FreeVar::Named(value)
207 }
208}
209
210impl From<usize> for FreeVar<'_> {
211 fn from(value: usize) -> Self {
212 FreeVar::Anonymous(value)
213 }
214}
215
216#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
217pub enum LambdaExpr<'a, T> {
219 Lambda(LambdaExprRef, LambdaType),
221 BoundVariable(Bvar, LambdaType),
223 FreeVariable(FreeVar<'a>, LambdaType),
225 Application {
227 subformula: LambdaExprRef,
229
230 argument: LambdaExprRef,
232 },
233 LanguageOfThoughtExpr(T),
236}
237
238impl<T: LambdaLanguageOfThought> LambdaExpr<'_, T> {
239 pub(crate) fn var_type(&self) -> Option<&LambdaType> {
240 match self {
241 LambdaExpr::Lambda(_, lambda_type) => Some(lambda_type),
242 LambdaExpr::LanguageOfThoughtExpr(e) => e.var_type(),
243 LambdaExpr::BoundVariable(..)
244 | LambdaExpr::FreeVariable(..)
245 | LambdaExpr::Application { .. } => None,
246 }
247 }
248 pub(crate) fn inc_depth(&self) -> bool {
249 match self {
250 LambdaExpr::Lambda(..) => true,
251 LambdaExpr::LanguageOfThoughtExpr(e) => e.inc_depth(),
252 LambdaExpr::BoundVariable(..)
253 | LambdaExpr::FreeVariable(..)
254 | LambdaExpr::Application { .. } => false,
255 }
256 }
257
258 pub(crate) fn commutative(&self) -> bool {
259 match self {
260 LambdaExpr::LanguageOfThoughtExpr(e) => e.commutative(),
261 LambdaExpr::Lambda(..)
262 | LambdaExpr::BoundVariable(..)
263 | LambdaExpr::FreeVariable(..)
264 | LambdaExpr::Application { .. } => false,
265 }
266 }
267}
268
269#[derive(Debug, Clone)]
270pub struct RootedLambdaPool<'src, T: LambdaLanguageOfThought> {
272 pub(crate) pool: LambdaPool<'src, T>,
273 pub(crate) root: LambdaExprRef,
274}
275
276impl<T: PartialEq + LambdaLanguageOfThought> PartialEq for RootedLambdaPool<'_, T> {
277 fn eq(&self, other: &Self) -> bool {
278 let mut bfs = self.pool.bfs_from(self.root).map(|(x, _)| self.pool.get(x));
279 let mut o_bfs = other
280 .pool
281 .bfs_from(other.root)
282 .map(|(x, _)| other.pool.get(x));
283 loop {
284 let x = bfs.next();
285 let y = o_bfs.next();
286 match (x, y) {
287 (None, None) => return true,
288 (None, Some(_)) | (Some(_), None) => return false,
289 (Some(a), Some(b)) => {
290 if !a.same_expr(b) {
291 return false;
292 }
293 }
294 }
295 }
296 }
297}
298
299impl<T: LambdaLanguageOfThought + HashLambda> Hash for RootedLambdaPool<'_, T> {
300 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
301 for x in self.pool.bfs_from(self.root).map(|(x, _)| self.pool.get(x)) {
302 match x {
303 LambdaExpr::Lambda(_, lambda_type) => {
304 0.hash(state);
305 lambda_type.hash(state);
306 }
307 LambdaExpr::BoundVariable(a, lambda_type) => {
308 1.hash(state);
309 a.hash(state);
310 lambda_type.hash(state);
311 }
312 LambdaExpr::FreeVariable(free_var, lambda_type) => {
313 2.hash(state);
314 free_var.hash(state);
315 lambda_type.hash(state);
316 }
317 LambdaExpr::Application { .. } => {
318 3.hash(state);
319 }
320 LambdaExpr::LanguageOfThoughtExpr(x) => {
321 4.hash(state);
322 x.hash_expr(state);
323 }
324 }
325 }
326 }
327}
328
329pub trait HashLambda {
333 fn hash_expr<H: std::hash::Hasher>(&self, state: &mut H);
336}
337
338impl<T: PartialEq + Eq + LambdaLanguageOfThought> Eq for RootedLambdaPool<'_, T> {}
339
340impl<T: LambdaLanguageOfThought> LambdaExpr<'_, T> {
341 fn same_expr(&self, other: &Self) -> bool {
342 match self {
343 LambdaExpr::Lambda(_, lambda_type) => {
344 matches!(other, LambdaExpr::Lambda(_, other_type) if lambda_type == other_type)
345 }
346 LambdaExpr::BoundVariable(x, a) => {
347 matches!(other, LambdaExpr::BoundVariable(y, b) if x==y && a==b)
348 }
349 LambdaExpr::FreeVariable(free_var, lambda_type) => {
350 matches!(other, LambdaExpr::FreeVariable(o_var, o_type) if o_var == free_var && o_type == lambda_type)
351 }
352 LambdaExpr::Application { .. } => matches!(self, LambdaExpr::Application { .. }),
353 LambdaExpr::LanguageOfThoughtExpr(x) => {
354 matches!(other, LambdaExpr::LanguageOfThoughtExpr(y) if x.same_expr(y))
355 }
356 }
357 }
358}
359
360impl<'src, T: LambdaLanguageOfThought> RootedLambdaPool<'src, T> {
361 #[must_use]
363 pub fn new_free_variable(index: usize, t: LambdaType) -> RootedLambdaPool<'src, T> {
364 RootedLambdaPool {
365 pool: LambdaPool(vec![LambdaExpr::FreeVariable(FreeVar::Anonymous(index), t)]),
366 root: LambdaExprRef(0),
367 }
368 }
369
370 pub fn free_variables(&self) -> impl Iterator<Item = (&FreeVar<'src>, &LambdaType)> {
372 self.pool.0.iter().filter_map(|x| {
373 if let LambdaExpr::FreeVariable(free_var, lambda_type) = x {
374 Some((free_var, lambda_type))
375 } else {
376 None
377 }
378 })
379 }
380
381 pub(crate) fn root(&self) -> LambdaExprRef {
382 self.root
383 }
384
385 pub(crate) fn get(&self, x: LambdaExprRef) -> &LambdaExpr<'src, T> {
387 self.pool.get(x)
388 }
389
390 #[allow(clippy::len_without_is_empty)]
392 #[must_use]
393 pub fn len(&self) -> usize {
394 self.pool.0.len()
395 }
396}
397
398impl<'src, T: LambdaLanguageOfThought + Clone> RootedLambdaPool<'src, T> {
399 pub fn cleanup(&mut self) {
401 self.root = self.pool.cleanup(self.root);
402 }
403
404 pub fn get_type(&self) -> Result<LambdaType, TypeError> {
406 self.pool.get_type(self.root)
407 }
408
409 pub(crate) fn new(pool: LambdaPool<'src, T>, root: LambdaExprRef) -> Self {
411 RootedLambdaPool { pool, root }
412 }
413
414 pub(crate) fn split(self) -> (LambdaPool<'src, T>, LambdaExprRef) {
416 (self.pool, self.root)
417 }
418
419 #[must_use]
422 pub fn merge(mut self, other: Self) -> Option<Self> {
423 let self_type = self.pool.get_type(self.root).expect("malformed type");
424 let other_type = other.pool.get_type(other.root).expect("malformed type");
425
426 let self_subformula = if self_type.can_apply(&other_type) {
427 true
428 } else if other_type.can_apply(&self_type) {
429 false
430 } else {
431 return None;
432 };
433
434 let (other_pool, other_root) = other.split();
435 let other_root = self.pool.extend_pool(other_root, other_pool);
436
437 self.root = self.pool.add(if self_subformula {
438 LambdaExpr::Application {
439 subformula: self.root,
440 argument: other_root,
441 }
442 } else {
443 LambdaExpr::Application {
444 subformula: other_root,
445 argument: self.root,
446 }
447 });
448
449 Some(self)
450 }
451
452 pub fn reduce(&mut self) -> Result<(), ReductionError> {
454 self.pool.reduce(self.root)?;
455 Ok(())
456 }
457
458 pub fn into_pool(mut self) -> Result<T::Pool, T::ConversionError> {
461 self.cleanup();
462 T::to_pool(self)
463 }
464
465 pub fn bind_free_variable(
467 &mut self,
468 fvar: FreeVar<'src>,
469 replacement: RootedLambdaPool<'src, T>,
470 ) -> Result<(), LambdaError> {
471 let (other_pool, other_root) = replacement.split();
472 let other_root = self.pool.extend_pool(other_root, other_pool);
473 self.pool.bind_free_variable(self.root, fvar, other_root)?;
474 Ok(())
476 }
477
478 pub fn lambda_abstract_free_variable(
480 &mut self,
481 fvar: FreeVar<'src>,
482 lambda_type: LambdaType,
483 always_abstract: bool,
484 ) -> Result<(), LambdaError> {
485 self.reduce()?;
486 let vars = self
487 .pool
488 .bfs_from(self.root)
489 .filter_map(|(x, d)| match self.pool.get(x) {
490 LambdaExpr::FreeVariable(var, var_type) if *var == fvar => {
491 if &lambda_type == var_type {
492 Some(Ok((x, d)))
493 } else {
494 Some(Err(LambdaError::BadFreeVariable {
495 free_var: var_type.clone(),
496 lambda: lambda_type.clone(),
497 }))
498 }
499 }
500 _ => None,
501 })
502 .collect::<Result<Vec<_>, LambdaError>>()?;
503
504 if !vars.is_empty() || always_abstract {
505 for (x, lambda_depth) in vars {
506 *self.pool.get_mut(x) =
507 LambdaExpr::BoundVariable(lambda_depth, lambda_type.clone());
508 }
509 self.root = self.pool.add(LambdaExpr::Lambda(self.root, lambda_type));
510 }
511 Ok(())
512 }
513
514 pub fn apply_new_free_variable(
516 &mut self,
517 fvar: FreeVar<'src>,
518 ) -> Result<LambdaType, LambdaError> {
519 let pool_type = self.pool.get_type(self.root)?;
520 let var_type = pool_type.lhs()?;
521 let argument = self
522 .pool
523 .add(LambdaExpr::FreeVariable(fvar, var_type.clone()));
524 self.root = self.pool.add(LambdaExpr::Application {
525 subformula: self.root,
526 argument,
527 });
528 self.reduce()?;
529 Ok(var_type.clone())
530 }
531}
532
533#[derive(Default, Debug, Clone, Eq, PartialEq, Hash)]
534pub(crate) struct LambdaPool<'a, T: LambdaLanguageOfThought>(pub(crate) Vec<LambdaExpr<'a, T>>);
535
536impl<'src, T: LambdaLanguageOfThought + Sized> LambdaPool<'src, T> {
537 pub(crate) fn extend_pool(
538 &mut self,
539 mut other_root: LambdaExprRef,
540 mut other_pool: LambdaPool<'src, T>,
541 ) -> LambdaExprRef {
542 let shift_n = self.0.len();
543 let remap: Vec<_> = (0..other_pool.0.len()).map(|x| x + shift_n).collect();
544 other_pool.0.iter_mut().for_each(|x| x.remap_refs(&remap));
545 other_root.0 += shift_n as u32;
546 self.0.append(&mut other_pool.0);
547 other_root
548 }
549
550 pub fn from(x: Vec<LambdaExpr<'src, T>>) -> Self {
552 LambdaPool(x)
553 }
554
555 pub fn new<'c>() -> LambdaPool<'c, T> {
557 LambdaPool(vec![])
558 }
559
560 fn checked_get(&self, expr: LambdaExprRef) -> Option<&LambdaExpr<'src, T>> {
561 self.0.get(expr.0 as usize)
562 }
563
564 pub fn get(&self, expr: LambdaExprRef) -> &LambdaExpr<'src, T> {
566 &self.0[expr.0 as usize]
567 }
568
569 pub fn get_mut<'a>(&'a mut self, expr: LambdaExprRef) -> &'a mut LambdaExpr<'src, T> {
570 &mut self.0[expr.0 as usize]
571 }
572
573 pub fn add(&mut self, expr: LambdaExpr<'src, T>) -> LambdaExprRef {
574 let idx = self.0.len();
575 self.0.push(expr);
576 LambdaExprRef(idx.try_into().expect("Too many exprs in the pool"))
577 }
578}
579
580pub(crate) struct LambdaPoolBFSIterator<'a, 'src, T: LambdaLanguageOfThought> {
582 pool: &'a LambdaPool<'src, T>,
583 queue: VecDeque<(LambdaExprRef, Bvar)>,
584}
585
586impl<T: LambdaLanguageOfThought> LambdaExpr<'_, T> {
587 pub(crate) fn n_children(&self) -> usize {
588 match self {
589 LambdaExpr::BoundVariable(..) | LambdaExpr::FreeVariable(..) => 0,
590 LambdaExpr::Lambda(..) => 1,
591 LambdaExpr::Application { .. } => 2,
592 LambdaExpr::LanguageOfThoughtExpr(e) => e.n_children(),
593 }
594 }
595
596 pub(crate) fn get_children(&self) -> impl Iterator<Item = LambdaExprRef> {
597 match self {
598 LambdaExpr::Lambda(x, _) => ArgumentIterator::A([x].into_iter().copied()),
599 LambdaExpr::Application {
600 subformula,
601 argument,
602 } => ArgumentIterator::B([subformula, argument].into_iter().copied()),
603 LambdaExpr::BoundVariable(..) | LambdaExpr::FreeVariable(..) => {
604 ArgumentIterator::C(std::iter::empty())
605 }
606 LambdaExpr::LanguageOfThoughtExpr(x) => ArgumentIterator::D(x.get_children()),
607 }
608 }
609}
610
611impl<T: LambdaLanguageOfThought> Iterator for LambdaPoolBFSIterator<'_, '_, T> {
612 type Item = (LambdaExprRef, Bvar);
613
614 fn next(&mut self) -> Option<Self::Item> {
615 if let Some((x, lambda_depth)) = self.queue.pop_front() {
616 match self.pool.get(x) {
617 LambdaExpr::Lambda(x, _) => self.queue.push_back((*x, lambda_depth + 1)),
618 LambdaExpr::Application {
619 subformula,
620 argument,
621 } => {
622 self.queue.push_back((*subformula, lambda_depth));
623 self.queue.push_back((*argument, lambda_depth));
624 }
625 LambdaExpr::BoundVariable(..) | LambdaExpr::FreeVariable(..) => (),
626 LambdaExpr::LanguageOfThoughtExpr(x) => {
627 let depth = lambda_depth + usize::from(x.inc_depth());
628
629 x.get_children()
630 .for_each(|x| self.queue.push_back((x, depth)));
631 }
632 }
633 Some((x, lambda_depth))
634 } else {
635 None
636 }
637 }
638}
639
640pub(crate) struct MutableLambdaPoolBFSIterator<'a, 'src: 'a, T: LambdaLanguageOfThought + 'a> {
642 pool: *mut LambdaPool<'src, T>,
643 queue: VecDeque<(LambdaExprRef, Bvar)>,
644 phantom: PhantomData<&'a ()>,
645}
646
647impl<'a, 'src: 'a, T: LambdaLanguageOfThought + 'a> MutableLambdaPoolBFSIterator<'a, 'src, T> {
648 fn new(pool: &mut LambdaPool<'src, T>, x: LambdaExprRef) -> Self {
649 Self {
650 pool: std::ptr::from_mut::<LambdaPool<'src, T>>(pool),
651 queue: VecDeque::from([(x, 0)]),
652 phantom: PhantomData,
653 }
654 }
655}
656
657impl<'a, 'src, T: LambdaLanguageOfThought> Iterator for MutableLambdaPoolBFSIterator<'a, 'src, T> {
658 type Item = (&'a mut LambdaExpr<'src, T>, usize, LambdaExprRef);
659
660 fn next(&mut self) -> Option<Self::Item> {
661 if let Some((x, lambda_depth)) = self.queue.pop_front() {
662 let expr = unsafe { self.pool.as_ref().unwrap() };
663 match expr.get(x) {
664 LambdaExpr::Lambda(x, _) => self.queue.push_back((*x, lambda_depth + 1)),
665 LambdaExpr::Application {
666 subformula,
667 argument,
668 } => {
669 self.queue.push_back((*subformula, lambda_depth));
670 self.queue.push_back((*argument, lambda_depth));
671 }
672 LambdaExpr::BoundVariable(..) | LambdaExpr::FreeVariable(..) => (),
673 LambdaExpr::LanguageOfThoughtExpr(x) => {
674 let depth = lambda_depth + usize::from(x.inc_depth());
675
676 x.get_children()
677 .for_each(|x| self.queue.push_back((x, depth)));
678 }
679 }
680 Some((
681 unsafe { self.pool.as_mut().unwrap().get_mut(x) },
682 lambda_depth,
683 x,
684 ))
685 } else {
686 None
687 }
688 }
689}
690
691impl<'src, T: LambdaLanguageOfThought> LambdaPool<'src, T> {
692 pub(crate) fn bfs_from(&self, x: LambdaExprRef) -> LambdaPoolBFSIterator<'_, 'src, T> {
693 LambdaPoolBFSIterator {
694 pool: self,
695 queue: VecDeque::from([(x, 0)]),
696 }
697 }
698}
699impl<'src, T: LambdaLanguageOfThought> LambdaPool<'src, T> {
700 pub fn get_type(&self, x: LambdaExprRef) -> Result<LambdaType, TypeError> {
701 match self.get(x) {
702 LambdaExpr::BoundVariable(_, x) | LambdaExpr::FreeVariable(_, x) => Ok(x.clone()),
703 LambdaExpr::Lambda(s, x) => {
704 let result = self.get_type(*s);
705 Ok(LambdaType::compose(x.clone(), result?))
706 }
707 LambdaExpr::Application { subformula, .. } => {
708 let subformula_type = self.get_type(*subformula)?;
709 Ok(subformula_type.rhs()?.clone())
710 }
711 LambdaExpr::LanguageOfThoughtExpr(x) => Ok(x.get_type().clone()),
712 }
713 }
714
715 fn check_type_clash(&self, x: LambdaExprRef) -> Result<LambdaType, ReductionError> {
716 if let LambdaExpr::Application {
717 subformula,
718 argument,
719 } = self.get(x)
720 {
721 let argument_type = self.get_type(*argument)?;
722 let subformula_type = self.get_type(*subformula)?;
723 Ok(subformula_type.apply(&argument_type)?.clone())
724 } else {
725 Err(ReductionError::NotApplication(x))
726 }
727 }
728
729 pub(crate) fn bfs_from_mut<'a>(
730 &'a mut self,
731 x: LambdaExprRef,
732 ) -> MutableLambdaPoolBFSIterator<'a, 'src, T> {
733 MutableLambdaPoolBFSIterator::new(self, x)
734 }
735
736 fn get_next_app(&self, root: LambdaExprRef) -> Option<LambdaExprRef> {
737 self.bfs_from(root)
738 .map(|(x, _)| x)
739 .find(|x| match self.get(*x) {
740 LambdaExpr::Application { subformula, .. } => {
741 matches!(self.get(*subformula), LambdaExpr::Lambda(..))
742 }
743 _ => false,
744 })
745 }
746}
747
748impl<'src, T: LambdaLanguageOfThought> LambdaPool<'src, T>
749where
750 T: Clone,
751{
752 fn bind_free_variable(
753 &mut self,
754 root: LambdaExprRef,
755 fvar: FreeVar<'src>,
756 replacement_root: LambdaExprRef,
757 ) -> Result<(), LambdaError> {
758 let arg_t = self.get_type(replacement_root)?;
759
760 let to_replace = self
761 .bfs_from(root)
762 .filter_map(|(x, d)| match self.get(x) {
763 LambdaExpr::FreeVariable(var, t) if *var == fvar => {
764 if t == &arg_t {
765 Some(Ok((x, d)))
766 } else {
767 Some(Err(LambdaError::BadFreeVariableApp {
768 free_var: t.clone(),
769 arg: arg_t.clone(),
770 }))
771 }
772 }
773 _ => None,
774 })
775 .collect::<Result<Vec<_>, LambdaError>>()?;
776
777 self.replace_section(&to_replace, replacement_root);
778 Ok(())
779 }
780
781 fn replace_section(&mut self, to_replace: &[(LambdaExprRef, usize)], to_copy: LambdaExprRef) {
782 let n = to_replace.len();
783 for (i, (x, depth)) in to_replace.iter().enumerate() {
784 if i == n - 1 {
785 for (x, d, _) in self.bfs_from_mut(to_copy) {
786 if let LambdaExpr::BoundVariable(bound_depth, _) = x
787 && *bound_depth >= d
788 {
789 *bound_depth += depth;
790 }
791 }
792 *self.get_mut(*x) = self.get(to_copy).clone();
794 } else {
795 let mut len = self.0.len();
796 let mut first = true;
797 let mut head = None;
798 self.0.extend(
799 self.bfs_from(to_copy)
800 .filter_map(|(x, d)| {
801 let mut expr = self.get(x).clone();
802 if let LambdaExpr::BoundVariable(bound_depth, _) = &mut expr
803 && *bound_depth >= d
804 {
805 *bound_depth += depth;
806 }
807
808 let old_len = len;
809 len += expr.n_children();
810 expr.change_children((old_len..len).map(|x| LambdaExprRef(x as u32)));
811 if first {
812 head = Some(expr);
813 first = false;
814 None
815 } else {
816 Some(expr)
817 }
818 })
819 .collect::<Vec<_>>(),
820 );
821
822 *self.get_mut(*x) = head.unwrap();
823 }
824 }
825 }
826
827 fn beta_reduce(&mut self, app: LambdaExprRef) -> Result<(), ReductionError> {
828 let Some(expr) = self.checked_get(app) else {
835 return Err(ReductionError::NotValidRef(app));
836 };
837
838 let (inner_term, argument, subformula_vars) = if let LambdaExpr::Application {
839 argument,
840 subformula,
841 } = expr
842 {
843 let inner_term = match self.get(*subformula) {
844 LambdaExpr::Lambda(x, ..) => {
845 self.check_type_clash(app)?;
846 *x
847 }
848 _ => {
849 return Err(ReductionError::NotLambdaInApplication {
850 app,
851 lhs: *subformula,
852 });
853 }
854 };
855
856 (
857 inner_term,
858 *argument,
859 self.bfs_from_mut(inner_term)
860 .filter_map(|(expr, d, expr_ref)| {
861 if let LambdaExpr::BoundVariable(b_d, _) = expr {
862 if *b_d > d {
863 *b_d -= 1;
865 None
866 } else if *b_d == d {
867 Some((expr_ref, *b_d))
868 } else {
869 None
870 }
871 } else {
872 None
873 }
874 })
875 .collect::<Vec<_>>(),
876 )
877 } else {
878 return Err(ReductionError::NotApplication(app));
879 };
880
881 self.replace_section(&subformula_vars, argument);
885 self.0[app.0 as usize] = self.0[inner_term.0 as usize].clone();
886 Ok(())
889 }
890
891 pub(crate) fn cleanup(&mut self, root: LambdaExprRef) -> LambdaExprRef {
894 let findable: HashSet<_> = self.bfs_from(root).map(|(x, _)| x.0 as usize).collect();
895 let mut remap = (0..self.0.len()).collect::<Vec<_>>();
896 let mut adjustment = 0;
897
898 for i in &mut remap {
899 if findable.contains(i) {
900 *i -= adjustment;
901 } else {
902 adjustment += 1;
903 }
904 }
905
906 let mut i = 0;
907 self.0.retain(|_| {
908 i += 1;
909 findable.contains(&(i - 1))
910 });
911 for x in &mut self.0 {
912 x.remap_refs(&remap);
913 }
914 LambdaExprRef(remap[root.0 as usize] as u32)
915 }
916
917 pub fn reduce(&mut self, root: LambdaExprRef) -> Result<(), ReductionError> {
918 while let Some(x) = self.get_next_app(root) {
919 self.beta_reduce(x)?;
920 }
921 Ok(())
922 }
923}
924
925impl<T: LambdaLanguageOfThought> LambdaExpr<'_, T> {
926 pub(crate) fn change_children(&mut self, mut children: impl Iterator<Item = LambdaExprRef>) {
927 match self {
928 LambdaExpr::Lambda(lambda_expr_ref, _) => *lambda_expr_ref = children.next().unwrap(),
929 LambdaExpr::BoundVariable(..) | LambdaExpr::FreeVariable(..) => (),
930 LambdaExpr::Application {
931 subformula,
932 argument,
933 } => {
934 *subformula = children.next().unwrap();
935 *argument = children.next().unwrap();
936 }
937 LambdaExpr::LanguageOfThoughtExpr(x) => x.change_children(children),
938 }
939 }
940
941 fn remap_refs(&mut self, remap: &[usize]) {
942 match self {
943 LambdaExpr::Lambda(x, _) => {
944 *x = LambdaExprRef(remap[x.0 as usize] as u32);
945 }
946 LambdaExpr::Application {
947 subformula,
948 argument,
949 } => {
950 *subformula = LambdaExprRef(remap[subformula.0 as usize] as u32);
951 *argument = LambdaExprRef(remap[argument.0 as usize] as u32);
952 }
953 LambdaExpr::BoundVariable(..) | LambdaExpr::FreeVariable(..) => (),
954 LambdaExpr::LanguageOfThoughtExpr(x) => x.remap_refs(remap),
955 }
956 }
957}
958
959#[derive(Debug, Clone, PartialEq, Eq, Hash)]
961pub enum LambdaSummaryStats {
962 WellFormed {
964 lambda_type: LambdaType,
966
967 constant_function: bool,
969
970 n_nodes: usize,
972 },
973
974 Malformed,
976}
977
978impl<T: LambdaLanguageOfThought + Clone + std::fmt::Debug> RootedLambdaPool<'_, T> {
979 pub fn lift(&mut self) -> Result<(), TypeError> {
981 let t =
982 LambdaType::Composition(Box::new(self.get_type()?.clone()), Box::new(LambdaType::T));
983
984 let p = self.pool.add(LambdaExpr::BoundVariable(0, t.clone()));
985 let apply = self.pool.add(LambdaExpr::Application {
986 subformula: p,
987 argument: self.root,
988 });
989 let lambda = self.pool.add(LambdaExpr::Lambda(apply, t));
990 self.root = lambda;
991
992 Ok(())
993 }
994
995 #[must_use]
997 pub fn stats(&self) -> LambdaSummaryStats {
998 let lambda_type = self.get_type();
999 if lambda_type.is_err() {
1000 return LambdaSummaryStats::Malformed;
1001 }
1002 let lambda_type = lambda_type.unwrap();
1003 let n_nodes = self.pool.0.len();
1004
1005 match self.all_lambda_has_variable(self.root) {
1006 Ok(has_variable) => LambdaSummaryStats::WellFormed {
1007 lambda_type,
1008 constant_function: !has_variable,
1009 n_nodes,
1010 },
1011
1012 Err(_) => LambdaSummaryStats::Malformed,
1013 }
1014 }
1015
1016 fn all_lambda_has_variable(&self, i: LambdaExprRef) -> Result<bool, LambdaError> {
1017 let mut found = vec![];
1018 let mut stack = vec![(i, vec![])];
1019 while let Some((expr_ref, mut lambdas)) = stack.pop() {
1020 match self.get(expr_ref) {
1021 LambdaExpr::Lambda(lambda_expr_ref, _) => {
1022 found.push(false);
1023 lambdas.push(found.len() - 1);
1024 stack.push((*lambda_expr_ref, lambdas));
1025 }
1026 LambdaExpr::BoundVariable(d, _) => {
1027 if let Some(index) = lambdas.len().checked_sub(d + 1) {
1028 if let Some(found_index) = lambdas.get(index) {
1029 if let Some(found) = found.get_mut(*found_index) {
1030 *found = true;
1031 } else {
1032 return Err(LambdaError::BadBoundVariable {
1033 var: expr_ref,
1034 depth: lambdas.len(),
1035 });
1036 }
1037 } else {
1038 return Err(LambdaError::BadBoundVariable {
1039 var: expr_ref,
1040 depth: lambdas.len(),
1041 });
1042 }
1043 } else {
1044 return Err(LambdaError::BadBoundVariable {
1045 var: expr_ref,
1046 depth: lambdas.len(),
1047 });
1048 }
1049 }
1050 LambdaExpr::FreeVariable(..) => (),
1051 LambdaExpr::Application {
1052 subformula,
1053 argument,
1054 } => {
1055 stack.push((*subformula, lambdas.clone()));
1056 stack.push((*argument, lambdas));
1057 }
1058
1059 LambdaExpr::LanguageOfThoughtExpr(x) => {
1060 if x.inc_depth() {
1061 found.push(false);
1062 lambdas.push(found.len() - 1);
1063 }
1064 stack.extend(x.get_children().map(|x| (x, lambdas.clone())));
1065 }
1066 }
1067 }
1068
1069 Ok(found.iter().all(|x| *x))
1070 }
1071}
1072
1073impl<'a, T: LambdaLanguageOfThought> From<LambdaPool<'a, T>> for Vec<Option<LambdaExpr<'a, T>>> {
1074 fn from(value: LambdaPool<'a, T>) -> Self {
1075 value.0.into_iter().map(Some).collect()
1076 }
1077}
1078
1079impl<'a, T: LambdaLanguageOfThought> TryFrom<Vec<Option<LambdaExpr<'a, T>>>> for LambdaPool<'a, T> {
1080 type Error = LambdaTryFromError;
1081
1082 fn try_from(value: Vec<Option<LambdaExpr<'a, T>>>) -> Result<Self, Self::Error> {
1083 match value.into_iter().collect::<Option<Vec<_>>>() {
1084 Some(x) => Ok(LambdaPool(x)),
1085 None => Err(LambdaTryFromError::HasNone),
1086 }
1087 }
1088}
1089
1090#[cfg(test)]
1091mod test {
1092
1093 use std::hash::{DefaultHasher, Hasher};
1094
1095 use super::*;
1096 use crate::language::{
1097 ActorOrEvent, BinOp, Expr, ExprPool, ExprRef, LanguageExpression, MonOp,
1098 };
1099
1100 #[test]
1101 fn stats() -> anyhow::Result<()> {
1102 for (expr, constant_lambda) in [
1103 ("a_0", false),
1104 ("lambda a x (pa_man(x))", false),
1105 ("lambda a x (pa_man(a_m))", true),
1106 (
1107 "lambda a x (((lambda a y (pa_woman(y)))(a_m)) & pa_man(x))",
1108 false,
1109 ),
1110 (
1111 "lambda a x (((lambda a y (pa_woman(a_m)))(a_m)) & pa_man(x))",
1112 true,
1113 ),
1114 ("lambda a y (pa_woman(a_m))", true),
1115 ("lambda a y (lambda a x (y))", true),
1116 ("some(x, pa_man(x), True)", false),
1117 ("some(x, pa_man(x), pa_man(x))", false),
1118 ("some(x, True, pa_man(x))", false),
1119 ("some(x, True, True)", true),
1120 ] {
1121 let expr = RootedLambdaPool::parse(expr)?;
1122 match expr.stats() {
1123 LambdaSummaryStats::WellFormed {
1124 constant_function, ..
1125 } => assert_eq!(constant_function, constant_lambda),
1126 LambdaSummaryStats::Malformed => panic!("{expr} should be well-formed!"),
1127 }
1128 }
1129 Ok(())
1130 }
1131
1132 fn k<'a, T: Default>(pos: u32) -> anyhow::Result<[LambdaExpr<'a, T>; 3]> {
1133 Ok([
1134 LambdaExpr::Lambda(LambdaExprRef(pos + 1), LambdaType::e().clone()),
1135 LambdaExpr::Lambda(LambdaExprRef(pos + 2), LambdaType::e().clone()),
1136 LambdaExpr::BoundVariable(1, LambdaType::e().clone()),
1137 ])
1138 }
1139
1140 #[test]
1141 fn complicated_lambda_language_of_thought() -> anyhow::Result<()> {
1142 let mut pool = LambdaPool::<Expr>(vec![
1143 LambdaExpr::Application {
1144 subformula: LambdaExprRef(1),
1146 argument: LambdaExprRef(4),
1147 },
1148 LambdaExpr::Lambda(LambdaExprRef(2), LambdaType::a().clone()),
1149 LambdaExpr::LanguageOfThoughtExpr(Expr::Unary(
1150 MonOp::Property("32", ActorOrEvent::Actor),
1151 ExprRef(3),
1152 )),
1153 LambdaExpr::BoundVariable(0, LambdaType::a().clone()),
1154 LambdaExpr::LanguageOfThoughtExpr(Expr::Actor("3")),
1155 ]);
1156 pool.reduce(LambdaExprRef(0))?;
1157 pool.cleanup(LambdaExprRef(0));
1158
1159 assert_eq!(
1160 pool.clone(),
1161 LambdaPool(vec![
1162 LambdaExpr::LanguageOfThoughtExpr(Expr::Unary(
1163 MonOp::Property("32", ActorOrEvent::Actor),
1164 ExprRef(1)
1165 )),
1166 LambdaExpr::LanguageOfThoughtExpr(Expr::Actor("3"))
1167 ]),
1168 );
1169
1170 let mut pool = LambdaPool(vec![
1171 LambdaExpr::Application {
1172 subformula: LambdaExprRef(1),
1173 argument: LambdaExprRef(5),
1174 },
1175 LambdaExpr::Lambda(LambdaExprRef(2), LambdaType::from_string("<a, t>")?),
1176 LambdaExpr::Application {
1177 subformula: LambdaExprRef(3),
1178 argument: LambdaExprRef(4),
1179 },
1180 LambdaExpr::BoundVariable(0, LambdaType::et().clone()),
1181 LambdaExpr::LanguageOfThoughtExpr(Expr::Actor("2")),
1182 LambdaExpr::Lambda(LambdaExprRef(6), LambdaType::a().clone()),
1183 LambdaExpr::LanguageOfThoughtExpr(Expr::Unary(
1184 MonOp::Property("36", ActorOrEvent::Actor),
1185 ExprRef(7),
1186 )),
1187 LambdaExpr::BoundVariable(0, LambdaType::a().clone()),
1188 ]);
1189 pool.reduce(LambdaExprRef(0))?;
1190 pool.cleanup(LambdaExprRef(0));
1191 assert_eq!(
1192 pool,
1193 LambdaPool(vec![
1194 LambdaExpr::LanguageOfThoughtExpr(Expr::Unary(
1195 MonOp::Property("36", ActorOrEvent::Actor),
1196 ExprRef(1)
1197 )),
1198 LambdaExpr::LanguageOfThoughtExpr(Expr::Actor("2")),
1199 ])
1200 );
1201
1202 let mut pool = LambdaPool(vec![
1203 LambdaExpr::Application {
1204 subformula: LambdaExprRef(1),
1205 argument: LambdaExprRef(6),
1206 },
1207 LambdaExpr::Lambda(LambdaExprRef(2), LambdaType::t().clone()),
1208 LambdaExpr::Lambda(LambdaExprRef(3), LambdaType::t().clone()),
1209 LambdaExpr::LanguageOfThoughtExpr(Expr::Binary(BinOp::And, ExprRef(4), ExprRef(5))), LambdaExpr::BoundVariable(1, LambdaType::t().clone()),
1211 LambdaExpr::BoundVariable(0, LambdaType::t().clone()),
1212 LambdaExpr::Application {
1213 subformula: LambdaExprRef(7),
1215 argument: LambdaExprRef(10),
1216 },
1217 LambdaExpr::Lambda(LambdaExprRef(8), LambdaType::a().clone()),
1218 LambdaExpr::LanguageOfThoughtExpr(Expr::Unary(
1219 MonOp::Property("36", ActorOrEvent::Actor),
1220 ExprRef(9),
1221 )),
1222 LambdaExpr::BoundVariable(0, LambdaType::a().clone()),
1223 LambdaExpr::LanguageOfThoughtExpr(Expr::Actor("2")),
1224 ]);
1225 pool.reduce(LambdaExprRef(0))?;
1226 pool.cleanup(LambdaExprRef(0));
1227
1228 assert_eq!(
1229 pool,
1230 LambdaPool(vec![
1231 LambdaExpr::Lambda(LambdaExprRef(1), LambdaType::t().clone()),
1232 LambdaExpr::LanguageOfThoughtExpr(Expr::Binary(BinOp::And, ExprRef(2), ExprRef(3))),
1233 LambdaExpr::LanguageOfThoughtExpr(Expr::Unary(
1234 MonOp::Property("36", ActorOrEvent::Actor),
1235 ExprRef(4)
1236 )),
1237 LambdaExpr::BoundVariable(0, LambdaType::t().clone()),
1238 LambdaExpr::LanguageOfThoughtExpr(Expr::Actor("2")),
1239 ])
1240 );
1241
1242 let mut pool = LambdaPool::<Expr>(vec![
1244 LambdaExpr::Application {
1245 subformula: LambdaExprRef(6),
1246 argument: LambdaExprRef(1),
1247 },
1248 LambdaExpr::Application {
1249 subformula: LambdaExprRef(2),
1251 argument: LambdaExprRef(5),
1252 },
1253 LambdaExpr::Lambda(LambdaExprRef(3), LambdaType::a().clone()),
1254 LambdaExpr::LanguageOfThoughtExpr(Expr::Unary(
1255 MonOp::Property("32", ActorOrEvent::Actor),
1256 ExprRef(4),
1257 )),
1258 LambdaExpr::BoundVariable(0, LambdaType::a().clone()),
1259 LambdaExpr::LanguageOfThoughtExpr(Expr::Actor("3")),
1260 LambdaExpr::Application {
1263 subformula: LambdaExprRef(7),
1264 argument: LambdaExprRef(12),
1265 },
1266 LambdaExpr::Lambda(LambdaExprRef(8), LambdaType::t().clone()),
1267 LambdaExpr::Lambda(LambdaExprRef(9), LambdaType::t().clone()),
1268 LambdaExpr::LanguageOfThoughtExpr(Expr::Binary(BinOp::And, ExprRef(10), ExprRef(11))), LambdaExpr::BoundVariable(1, LambdaType::t().clone()),
1270 LambdaExpr::BoundVariable(0, LambdaType::t().clone()),
1271 LambdaExpr::Application {
1272 subformula: LambdaExprRef(13),
1274 argument: LambdaExprRef(16),
1275 },
1276 LambdaExpr::Lambda(LambdaExprRef(14), LambdaType::a().clone()),
1277 LambdaExpr::LanguageOfThoughtExpr(Expr::Unary(
1278 MonOp::Property("36", ActorOrEvent::Actor),
1279 ExprRef(15),
1280 )),
1281 LambdaExpr::BoundVariable(0, LambdaType::a().clone()),
1282 LambdaExpr::LanguageOfThoughtExpr(Expr::Actor("2")),
1283 ]);
1284 pool.reduce(LambdaExprRef(0))?;
1285 let root = pool.cleanup(LambdaExprRef(0));
1286 assert_eq!(
1287 pool,
1288 LambdaPool(vec![
1289 LambdaExpr::LanguageOfThoughtExpr(Expr::Binary(BinOp::And, ExprRef(2), ExprRef(3))),
1290 LambdaExpr::LanguageOfThoughtExpr(Expr::Actor("3")),
1291 LambdaExpr::LanguageOfThoughtExpr(Expr::Unary(
1292 MonOp::Property("36", ActorOrEvent::Actor),
1293 ExprRef(4)
1294 )),
1295 LambdaExpr::LanguageOfThoughtExpr(Expr::Unary(
1296 MonOp::Property("32", ActorOrEvent::Actor),
1297 ExprRef(1)
1298 )),
1299 LambdaExpr::LanguageOfThoughtExpr(Expr::Actor("2"))
1300 ])
1301 );
1302
1303 assert_eq!(
1304 RootedLambdaPool::new(pool, root).into_pool()?,
1305 LanguageExpression::new(
1306 ExprPool::from(vec![
1307 Expr::Binary(BinOp::And, ExprRef(2), ExprRef(3)),
1308 Expr::Actor("3"),
1309 Expr::Unary(MonOp::Property("36", ActorOrEvent::Actor), ExprRef(4)),
1310 Expr::Unary(MonOp::Property("32", ActorOrEvent::Actor), ExprRef(1)),
1311 Expr::Actor("2")
1312 ]),
1313 ExprRef(root.0)
1314 )
1315 );
1316 Ok(())
1317 }
1318 #[test]
1319 fn type_check() -> anyhow::Result<()> {
1320 let mut pool = LambdaPool::<()>(vec![
1322 LambdaExpr::Application {
1323 subformula: LambdaExprRef(1),
1324 argument: LambdaExprRef(3),
1325 },
1326 LambdaExpr::Lambda(LambdaExprRef(2), LambdaType::a().clone()),
1327 LambdaExpr::BoundVariable(0, LambdaType::t().clone()),
1328 LambdaExpr::FreeVariable("0".into(), LambdaType::t().clone()),
1329 ]);
1330 assert_eq!(
1331 pool.reduce(LambdaExprRef(0)).unwrap_err(),
1332 ReductionError::TypeError(TypeError::CantApply(
1333 LambdaType::t().clone(),
1334 LambdaType::at().clone()
1335 ))
1336 );
1337
1338 let mut pool = LambdaPool::<()>(vec![
1339 LambdaExpr::Application {
1340 subformula: LambdaExprRef(1),
1341 argument: LambdaExprRef(3),
1342 },
1343 LambdaExpr::Lambda(LambdaExprRef(2), LambdaType::a().clone()),
1344 LambdaExpr::BoundVariable(0, LambdaType::t().clone()),
1345 LambdaExpr::FreeVariable("0".into(), LambdaType::a().clone()),
1346 ]);
1347 assert!(pool.reduce(LambdaExprRef(0)).is_ok());
1348 Ok(())
1349 }
1350
1351 #[test]
1352 fn complicated_lambda() -> anyhow::Result<()> {
1353 let mut pool = LambdaPool::<()>(vec![
1355 LambdaExpr::Application {
1356 subformula: LambdaExprRef(5),
1357 argument: LambdaExprRef(1),
1358 },
1359 LambdaExpr::Application {
1360 subformula: LambdaExprRef(2),
1362 argument: LambdaExprRef(4),
1363 },
1364 LambdaExpr::Lambda(LambdaExprRef(3), LambdaType::e().clone()),
1365 LambdaExpr::FreeVariable("0".into(), LambdaType::t().clone()),
1366 LambdaExpr::FreeVariable("2".into(), LambdaType::t().clone()),
1367 LambdaExpr::Application {
1370 subformula: LambdaExprRef(6),
1371 argument: LambdaExprRef(9),
1372 },
1373 LambdaExpr::Lambda(LambdaExprRef(7), LambdaType::t().clone()),
1374 LambdaExpr::Lambda(LambdaExprRef(8), LambdaType::t().clone()),
1375 LambdaExpr::BoundVariable(1, LambdaType::t().clone()),
1376 LambdaExpr::Application {
1377 subformula: LambdaExprRef(10),
1379 argument: LambdaExprRef(12),
1380 },
1381 LambdaExpr::Lambda(LambdaExprRef(11), LambdaType::e().clone()),
1382 LambdaExpr::FreeVariable("1337".into(), LambdaType::t().clone()),
1383 LambdaExpr::FreeVariable("5".into(), LambdaType::e().clone()),
1384 ]);
1385 pool.reduce(LambdaExprRef(0))?;
1386 pool.cleanup(LambdaExprRef(0));
1387 assert_eq!(
1388 pool,
1389 LambdaPool(vec![LambdaExpr::FreeVariable(
1390 "1337".into(),
1391 LambdaType::t().clone()
1392 )])
1393 );
1394 Ok(())
1395 }
1396
1397 #[test]
1398 fn test_lambda_calculus() -> anyhow::Result<()> {
1399 let mut pool = LambdaPool::<()>(
1400 k(0)?
1401 .into_iter()
1402 .chain([
1403 LambdaExpr::FreeVariable("32".into(), LambdaType::e().clone()),
1404 LambdaExpr::Application {
1405 subformula: LambdaExprRef(0),
1406 argument: LambdaExprRef(3),
1407 },
1408 ])
1409 .collect(),
1410 );
1411 let root = LambdaExprRef(4);
1412 pool.beta_reduce(root)?;
1413 pool.cleanup(root);
1414
1415 assert_eq!(
1416 pool,
1417 LambdaPool(vec![
1418 LambdaExpr::FreeVariable("32".into(), LambdaType::e().clone()),
1419 LambdaExpr::Lambda(LambdaExprRef(0), LambdaType::e().clone())
1420 ])
1421 );
1422 Ok(())
1423 }
1424
1425 #[test]
1426 fn test_root_and_merger() -> anyhow::Result<()> {
1427 let man = RootedLambdaPool::parse("lambda a x (pa_man(x))")?;
1428
1429 let sleeps =
1430 RootedLambdaPool::parse("lambda a x (some_e(y, all_e, AgentOf(x, y) & pe_sleep(y)))")?;
1431 let every =
1432 RootedLambdaPool::parse("lambda <a,t> p (lambda <a,t> q every(x, p(x), q(x)))")?;
1433
1434 let phi = every.clone().merge(man.clone()).unwrap();
1435 let mut phi = phi.merge(sleeps.clone()).unwrap();
1436 println!("{phi}");
1437 phi.reduce()?;
1438 println!("{phi}");
1439 assert_eq!(
1440 phi,
1441 RootedLambdaPool::parse(
1442 "every(x, pa_man(x), some_e(y, all_e, AgentOf(x, y) & pe_sleep(y)))"
1443 )?
1444 );
1445 assert!(check_hashes(
1446 &phi,
1447 &RootedLambdaPool::parse(
1448 "every(x, pa_man(x), some_e(y, all_e, AgentOf(x, y) & pe_sleep(y)))",
1449 )?,
1450 ));
1451 let pool = phi.into_pool()?;
1452 assert_eq!(
1453 "every(x, pa_man(x), some_e(y, all_e, AgentOf(x, y) & pe_sleep(y)))",
1454 pool.to_string()
1455 );
1456 let phi = man.merge(every).unwrap();
1457 let mut phi = sleeps.merge(phi).unwrap();
1458 phi.reduce()?;
1459 assert_eq!(
1460 phi,
1461 RootedLambdaPool::parse(
1462 "every(x, pa_man(x), some_e(y, all_e, AgentOf(x, y) & pe_sleep(y)))",
1463 )?
1464 );
1465
1466 assert!(check_hashes(
1467 &phi,
1468 &RootedLambdaPool::parse(
1469 "every(x, pa_man(x), some_e(y, all_e, AgentOf(x, y) & pe_sleep(y)))",
1470 )?,
1471 ));
1472
1473 let pool = phi.into_pool()?;
1474 assert_eq!(
1475 "every(x, pa_man(x), some_e(y, all_e, AgentOf(x, y) & pe_sleep(y)))",
1476 pool.to_string()
1477 );
1478 Ok(())
1479 }
1480
1481 fn check_hashes<'src>(
1482 phi: &RootedLambdaPool<'src, Expr<'src>>,
1483 psi: &RootedLambdaPool<'src, Expr<'src>>,
1484 ) -> bool {
1485 let mut hasher1 = DefaultHasher::new();
1486 let mut hasher2 = DefaultHasher::new();
1487
1488 phi.hash(&mut hasher1);
1489 psi.hash(&mut hasher2);
1490
1491 hasher1.finish() == hasher2.finish()
1492 }
1493
1494 #[test]
1495 fn bind_free_variable() -> anyhow::Result<()> {
1496 let mut pool = RootedLambdaPool::parse("phi#t & True")?;
1497
1498 pool.bind_free_variable("phi".into(), RootedLambdaPool::parse("False")?)?;
1499 assert_eq!("False & True", pool.into_pool()?.to_string());
1500
1501 let input = RootedLambdaPool::parse("lambda a x every_e(y,pe_4,AgentOf(x,y))")?;
1502 let mut a = RootedLambdaPool::parse("(P#<a,t>(a_3) & ~P#<a,t>(a_1))")?;
1503
1504 a.bind_free_variable("P".into(), input)?;
1505 a.reduce()?;
1506 assert_eq!(
1507 a.to_string(),
1508 "every_e(x, pe_4, AgentOf(a_3, x)) & ~every_e(x, pe_4, AgentOf(a_1, x))"
1509 );
1510 Ok(())
1511 }
1512
1513 #[test]
1514 fn apply_new_free_variable() -> anyhow::Result<()> {
1515 let mut pool =
1516 RootedLambdaPool::parse("lambda <e,t> P (lambda <e,t> Q (lambda e x (P(x) & Q(x))))")?;
1517
1518 pool.apply_new_free_variable("X".into())?;
1519
1520 let gold_pool = RootedLambdaPool {
1521 pool: LambdaPool(vec![
1522 LambdaExpr::FreeVariable("X".into(), LambdaType::et().clone()),
1523 LambdaExpr::BoundVariable(0, LambdaType::e().clone()),
1524 LambdaExpr::Application {
1525 subformula: LambdaExprRef(0),
1526 argument: LambdaExprRef(1),
1527 },
1528 LambdaExpr::BoundVariable(1, LambdaType::et().clone()),
1529 LambdaExpr::BoundVariable(0, LambdaType::e().clone()),
1530 LambdaExpr::Application {
1531 subformula: LambdaExprRef(3),
1532 argument: LambdaExprRef(4),
1533 },
1534 LambdaExpr::LanguageOfThoughtExpr(Expr::Binary(BinOp::And, ExprRef(2), ExprRef(5))),
1535 LambdaExpr::Lambda(LambdaExprRef(6), LambdaType::e().clone()),
1536 LambdaExpr::Lambda(LambdaExprRef(7), LambdaType::et().clone()),
1537 ]),
1538 root: LambdaExprRef(8),
1539 };
1540 pool.cleanup();
1541 assert_eq!(pool, gold_pool);
1542 Ok(())
1543 }
1544
1545 #[test]
1546 fn lambda_abstraction() -> anyhow::Result<()> {
1547 let mut pool = RootedLambdaPool::parse(
1548 "lambda <e,t> P lambda <e,t> Q lambda e x Z#<e,t>(x) & P(x) & Q(x)",
1549 )?;
1550
1551 pool.lambda_abstract_free_variable("Z".into(), LambdaType::et().clone(), false)?;
1552
1553 let gold_pool = RootedLambdaPool {
1554 pool: LambdaPool(vec![
1555 LambdaExpr::BoundVariable(3, LambdaType::et().clone()),
1556 LambdaExpr::BoundVariable(0, LambdaType::e().clone()),
1557 LambdaExpr::Application {
1558 subformula: LambdaExprRef(0),
1559 argument: LambdaExprRef(1),
1560 },
1561 LambdaExpr::BoundVariable(2, LambdaType::et().clone()),
1562 LambdaExpr::BoundVariable(0, LambdaType::e().clone()),
1563 LambdaExpr::Application {
1564 subformula: LambdaExprRef(3),
1565 argument: LambdaExprRef(4),
1566 },
1567 LambdaExpr::LanguageOfThoughtExpr(Expr::Binary(BinOp::And, ExprRef(2), ExprRef(5))),
1568 LambdaExpr::BoundVariable(1, LambdaType::et().clone()),
1569 LambdaExpr::BoundVariable(0, LambdaType::e().clone()),
1570 LambdaExpr::Application {
1571 subformula: LambdaExprRef(7),
1572 argument: LambdaExprRef(8),
1573 },
1574 LambdaExpr::LanguageOfThoughtExpr(Expr::Binary(BinOp::And, ExprRef(6), ExprRef(9))),
1575 LambdaExpr::Lambda(LambdaExprRef(10), LambdaType::e().clone()),
1576 LambdaExpr::Lambda(LambdaExprRef(11), LambdaType::et().clone()),
1577 LambdaExpr::Lambda(LambdaExprRef(12), LambdaType::et().clone()),
1578 LambdaExpr::Lambda(LambdaExprRef(13), LambdaType::et().clone()),
1579 ]),
1580 root: LambdaExprRef(14),
1581 };
1582
1583 assert_eq!(pool, gold_pool);
1584 Ok(())
1585 }
1586
1587 #[test]
1588 fn could_time_out_if_swapping_instead_of_cloning() -> anyhow::Result<()> {
1589 let mut x = RootedLambdaPool::parse(
1590 "(lambda a x (PatientOf(x,e_0) & AgentOf(x, e_0)))((lambda a x (a_1))(a_0))",
1591 )?;
1592
1593 println!("{x}");
1594 x.reduce()?;
1595 println!("{x}");
1596 Ok(())
1597 }
1598
1599 #[test]
1600 fn lambda_abstraction_reduction() -> anyhow::Result<()> {
1601 let mut a = RootedLambdaPool::parse("a_1")?;
1602 let mut b = RootedLambdaPool::parse("(lambda t x (a_1))(pa_0(freeVar#a))")?;
1603
1604 a.lambda_abstract_free_variable("freeVar".into(), LambdaType::a().clone(), false)?;
1605 b.lambda_abstract_free_variable("freeVar".into(), LambdaType::a().clone(), false)?;
1606 println!("A:\t{a}");
1607 println!("B:\t{b}");
1608
1609 a.cleanup();
1610 b.cleanup();
1611 assert_eq!(a, b);
1612 Ok(())
1613 }
1614
1615 #[test]
1616 fn reduction_test() -> anyhow::Result<()> {
1617 let mut a = RootedLambdaPool::parse(
1618 "lambda a x (every_e(z, all_e, AgentOf(a_0, (lambda e y ((lambda e w (w))(y)))(z))))",
1619 )?;
1620 a.reduce()?;
1621
1622 let mut a = RootedLambdaPool::parse(
1623 "(lambda <a,t> P (P(a_3) & ~P(a_1)))(lambda a x (every_e(y,pe_4,AgentOf(x,y))))",
1624 )?;
1625
1626 a.pool.beta_reduce(a.root)?;
1627 a.root = a.pool.cleanup(a.root);
1628 println!("{a}");
1629 dbg!(&a);
1630
1631 let mut a = RootedLambdaPool::parse(
1632 "(lambda <a,t> P (P(a_3) & ~P(a_1)))(lambda a x (every_e(y,pe_4,AgentOf(x,y))))",
1633 )?;
1634
1635 a.reduce()?;
1636 assert_eq!(
1637 a.to_string(),
1638 "every_e(x, pe_4, AgentOf(a_3, x)) & ~every_e(x, pe_4, AgentOf(a_1, x))"
1639 );
1640
1641 Ok(())
1642 }
1643
1644 #[test]
1645 fn lift() -> anyhow::Result<()> {
1646 let mut e = RootedLambdaPool::parse("a_john")?;
1647 e.lift()?;
1648 assert_eq!(e.to_string(), "lambda <a,t> P P(a_john)");
1649
1650 Ok(())
1651 }
1652
1653 #[test]
1654 fn lambda_abstractions() -> anyhow::Result<()> {
1655 let mut e = RootedLambdaPool::parse(
1656 "(lambda t phi phi)(some_e(x, all_e, AgentOf(a_m, x) & PatientOf(blarg#a, x) & pe_likes(x)))",
1657 )?;
1658 e.reduce()?;
1659 e.lambda_abstract_free_variable(FreeVar::Named("blarg"), LambdaType::A, false)
1660 .unwrap();
1661 assert_eq!(
1662 e.to_string(),
1663 "lambda a x some_e(y, all_e, AgentOf(a_m, y) & PatientOf(x, y) & pe_likes(y))"
1664 );
1665 Ok(())
1666 }
1667
1668 #[test]
1669 fn is_constant_function() -> anyhow::Result<()> {
1670 let constants = [
1671 "lambda a x a_John",
1672 "lambda a x lambda a y pa_man(x)",
1673 "lambda a x some_e(y, all_e, pe_runs(y))",
1674 ];
1675 for s in constants {
1676 println!("{s}");
1677 let LambdaSummaryStats::WellFormed {
1678 lambda_type: _,
1679 constant_function,
1680 n_nodes: _,
1681 } = RootedLambdaPool::parse(s).unwrap().stats()
1682 else {
1683 panic!("{s} is poorly formed")
1684 };
1685 assert!(constant_function);
1686 }
1687
1688 let not_constants = [
1689 "lambda a x x",
1690 "lambda a x lambda a y pa_man(x) & pa_woman(y)",
1691 ];
1692 for s in not_constants {
1693 println!("{s}");
1694 let LambdaSummaryStats::WellFormed {
1695 lambda_type: _,
1696 constant_function,
1697 n_nodes: _,
1698 } = RootedLambdaPool::parse(s).unwrap().stats()
1699 else {
1700 panic!("{s} is poorly formed")
1701 };
1702 assert!(!constant_function);
1703 }
1704 Ok(())
1705 }
1706}