1use ahash::HashMap;
2use std::{
3 borrow::Cow,
4 collections::{BTreeMap, btree_map::Entry as BTEntry, hash_map::Entry},
5};
6
7use super::{
8 ActorOrEvent, BinOp, Context, Debug, Expr, ExprRef, LambdaExpr, LambdaExprRef,
9 LambdaLanguageOfThought, MonOp, Quantifier,
10};
11use crate::{Actor, PropertyLabel, lambda::types::LambdaType};
12
13#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct PossibleExpressions<'src, T> {
19 expressions: HashMap<LambdaType, BTreeMap<Vec<LambdaType>, Vec<LambdaExpr<'src, T>>>>,
20}
21
22impl<'src, T> From<HashMap<LambdaType, BTreeMap<Vec<LambdaType>, Vec<LambdaExpr<'src, T>>>>>
23 for PossibleExpressions<'src, T>
24{
25 fn from(
26 value: HashMap<LambdaType, BTreeMap<Vec<LambdaType>, Vec<LambdaExpr<'src, T>>>>,
27 ) -> Self {
28 PossibleExpressions { expressions: value }
29 }
30}
31
32impl<'src> PossibleExpressions<'src, Expr<'src>> {
33 #[must_use]
35 pub fn new(
36 actors: &[Actor<'src>],
37 actor_properties: &[PropertyLabel<'src>],
38 event_properties: &[PropertyLabel<'src>],
39 ) -> Self {
40 let bad_ref = ExprRef(0);
41 let mut all_expressions: Vec<_> = [
42 Expr::Unary(MonOp::Not, bad_ref),
43 Expr::Binary(BinOp::And, bad_ref, bad_ref),
44 Expr::Binary(BinOp::Or, bad_ref, bad_ref),
45 Expr::Quantifier {
46 quantifier: Quantifier::Existential,
47 var_type: ActorOrEvent::Actor,
48 subformula: bad_ref,
49 restrictor: bad_ref,
50 },
51 Expr::Quantifier {
52 quantifier: Quantifier::Universal,
53 var_type: ActorOrEvent::Actor,
54 subformula: bad_ref,
55 restrictor: bad_ref,
56 },
57 Expr::Quantifier {
58 quantifier: Quantifier::Existential,
59 var_type: ActorOrEvent::Event,
60 subformula: bad_ref,
61 restrictor: bad_ref,
62 },
63 Expr::Quantifier {
64 quantifier: Quantifier::Universal,
65 var_type: ActorOrEvent::Event,
66 subformula: bad_ref,
67 restrictor: bad_ref,
68 },
69 Expr::Binary(BinOp::AgentOf, bad_ref, bad_ref),
70 Expr::Binary(BinOp::PatientOf, bad_ref, bad_ref),
71 Expr::Unary(MonOp::Iota(ActorOrEvent::Actor), bad_ref),
72 Expr::Unary(MonOp::Iota(ActorOrEvent::Event), bad_ref),
73 ]
74 .to_vec();
75
76 all_expressions.extend(actors.iter().map(|x| Expr::Actor(x)));
77
78 all_expressions.extend(actor_properties.iter().flat_map(|i| {
79 [Expr::Unary(
80 MonOp::Property(i, ActorOrEvent::Actor),
81 bad_ref,
82 )]
83 }));
84 all_expressions.extend(event_properties.iter().flat_map(|i| {
85 [Expr::Unary(
86 MonOp::Property(i, ActorOrEvent::Event),
87 bad_ref,
88 )]
89 }));
90
91 let mut expressions: HashMap<LambdaType, BTreeMap<_, Vec<_>>> = HashMap::default();
92 for expr in all_expressions {
93 let output = expr.get_type();
94 let arguments = expr.get_arguments().collect();
95 let expr = LambdaExpr::LanguageOfThoughtExpr(expr);
96 match expressions.entry(output.clone()) {
98 Entry::Occupied(mut occupied) => {
99 let inner_h: &mut BTreeMap<_, _> = occupied.get_mut();
100 match inner_h.entry(arguments) {
101 BTEntry::Occupied(mut occupied) => occupied.get_mut().push(expr),
102 BTEntry::Vacant(vacant) => {
103 vacant.insert(vec![expr]);
104 }
105 }
106 }
107 Entry::Vacant(vacant) => {
108 vacant.insert([(arguments, vec![expr])].into_iter().collect());
109 }
110 }
111 }
112
113 PossibleExpressions { expressions }
114 }
115}
116
117#[derive(Debug, Clone, PartialEq, Eq)]
118pub(crate) struct PossibleExpr<'a, 'src, T: LambdaLanguageOfThought + Clone> {
119 expr: Cow<'a, LambdaExpr<'src, T>>,
120 app_details: Option<(LambdaType, LambdaType)>,
121}
122
123impl<'a, 'src, T: LambdaLanguageOfThought + Clone> PossibleExpr<'a, 'src, T> {
124 pub fn into_expr(self) -> (LambdaExpr<'src, T>, Option<(LambdaType, LambdaType)>) {
125 (self.expr.into_owned(), self.app_details)
126 }
127
128 pub fn expr(&self) -> &LambdaExpr<'src, T> {
129 &self.expr
130 }
131
132 pub fn new_borrowed(expr: &'a LambdaExpr<'src, T>) -> Self {
133 PossibleExpr {
134 expr: Cow::Borrowed(expr),
135 app_details: None,
136 }
137 }
138
139 fn new_owned(expr: LambdaExpr<'src, T>) -> Self {
140 PossibleExpr {
141 expr: Cow::Owned(expr),
142 app_details: None,
143 }
144 }
145
146 fn new_application(subformula: LambdaType, argument: LambdaType) -> Self {
147 PossibleExpr {
148 expr: Cow::Owned(LambdaExpr::Application {
149 subformula: LambdaExprRef(0),
150 argument: LambdaExprRef(0),
151 }),
152 app_details: Some((subformula, argument)),
153 }
154 }
155}
156impl<'src, T: LambdaLanguageOfThought + Clone> PossibleExpressions<'src, T> {
157 pub(crate) fn terms<'a>(
158 &'a self,
159 lambda_type: &LambdaType,
160 include_lambdas: bool,
161 variables: impl Iterator<Item = LambdaExpr<'src, T>>,
162 applications: impl Iterator<Item = (LambdaType, LambdaType)>,
163 ) -> Vec<PossibleExpr<'a, 'src, T>> {
164 let mut possibilities = vec![];
165 if let Some(x) = self.expressions.get(lambda_type).map(|x| {
166 x.iter()
167 .flat_map(|(_, v)| v.iter().map(PossibleExpr::new_borrowed))
168 }) {
169 possibilities.extend(x);
170 }
171 if include_lambdas && let Ok((lhs, _)) = lambda_type.split() {
172 let e = PossibleExpr::new_owned(LambdaExpr::Lambda(LambdaExprRef(0), lhs.clone()));
173 possibilities.push(e);
174 }
175 possibilities.extend(variables.map(PossibleExpr::new_owned));
176 possibilities.extend(
177 applications
178 .map(|(subformula, argument)| PossibleExpr::new_application(subformula, argument)),
179 );
180
181 possibilities
182 }
183}
184
185impl<'src, T: LambdaLanguageOfThought + Clone + Debug> PossibleExpressions<'src, T> {
186 pub(super) fn possibilities<'a>(
187 &'a self,
188 lambda_type: &LambdaType,
189 is_subformula: bool,
190 context: &Context,
191 ) -> Vec<PossibleExpr<'a, 'src, T>> {
192 let mut possibilities = vec![];
193 if !is_subformula {
194 if let Some(x) = self.expressions.get(lambda_type).map(|x| {
195 x.iter()
196 .flat_map(|(_, v)| v.iter().map(PossibleExpr::new_borrowed))
197 }) {
198 possibilities.extend(x);
199 }
200
201 if let Ok((lhs, _)) = lambda_type.split() {
202 let e = PossibleExpr::new_owned(LambdaExpr::Lambda(LambdaExprRef(0), lhs.clone()));
203 possibilities.push(e);
204 }
205 }
206 possibilities.extend(context.variables(lambda_type).map(PossibleExpr::new_owned));
207 possibilities.extend(
208 context
209 .applications(lambda_type)
210 .map(|(subformula, argument)| PossibleExpr::new_application(subformula, argument)),
211 );
212
213 possibilities
214 }
215
216 pub(super) fn possiblities_fixed_children<'a>(
217 &'a self,
218 lambda_type: &LambdaType,
219 arguments: &[LambdaType],
220 var_type: Option<&LambdaType>,
221 context: &Context,
222 ) -> Vec<Cow<'a, LambdaExpr<'src, T>>> {
223 let mut possibilities: Vec<Cow<'a, LambdaExpr<'src, T>>> = self
224 .expressions
225 .get(lambda_type)
226 .map(|x| {
227 x.get(arguments)
228 .map(|x| x.iter().map(Cow::Borrowed).collect::<Vec<_>>())
229 .unwrap_or_default()
230 })
231 .unwrap_or_default();
232
233 if arguments.len() == 2
234 && let Ok((arg_type, return_type)) = arguments.first().unwrap().split()
235 && return_type == lambda_type
236 && arg_type == arguments.last().unwrap()
237 {
238 possibilities.push(Cow::Owned(LambdaExpr::Application {
239 subformula: LambdaExprRef(0),
240 argument: LambdaExprRef(0),
241 }));
242 } else if arguments.len() == 1
243 && let Ok((lhs, rhs)) = lambda_type.split()
244 && rhs == arguments.first().unwrap()
245 {
246 possibilities.push(Cow::Owned(LambdaExpr::Lambda(
247 LambdaExprRef(0),
248 lhs.clone(),
249 )));
250 } else if arguments.is_empty() {
251 possibilities.extend(context.variables(lambda_type).map(Cow::Owned));
252 }
253
254 possibilities.retain(|x| x.var_type() == var_type);
255
256 possibilities
257 }
258}