simple_semantics/language/mutations/
samplers.rs

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