dypdl/
transition.rs

1use crate::effect::Effect;
2use crate::expression::{
3    Condition, ContinuousExpression, ElementExpression, IntegerExpression, ReferenceExpression,
4    SetCondition, SetExpression, VectorExpression,
5};
6use crate::grounded_condition;
7use crate::state::{
8    ContinuousResourceVariable, ContinuousVariable, ElementResourceVariable, ElementVariable,
9    IntegerResourceVariable, IntegerVariable, SetVariable, State, StateInterface, VectorVariable,
10};
11use crate::state_functions::{StateFunctionCache, StateFunctions};
12use crate::table_registry;
13use crate::util::ModelErr;
14use crate::variable_type::{Continuous, Element, FromNumeric, Numeric};
15use std::fmt::Debug;
16
17/// Wrapper for an integer expression or a continuous expression.
18#[derive(Debug, PartialEq, Clone)]
19pub enum CostExpression {
20    /// Integer numeric expression.
21    Integer(IntegerExpression),
22    /// Continuous numeric expression.
23    Continuous(ContinuousExpression),
24}
25
26impl Default for CostExpression {
27    /// Returns `CostExpression::Integer(IntegerExpression::Cost)`.
28    fn default() -> Self {
29        Self::Integer(IntegerExpression::Cost)
30    }
31}
32
33impl<T> From<T> for CostExpression
34where
35    IntegerExpression: From<T>,
36{
37    fn from(cost: T) -> Self {
38        Self::Integer(IntegerExpression::from(cost))
39    }
40}
41
42impl From<ContinuousExpression> for CostExpression {
43    fn from(cost: ContinuousExpression) -> Self {
44        Self::Continuous(cost)
45    }
46}
47
48impl From<Continuous> for CostExpression {
49    fn from(cost: Continuous) -> Self {
50        Self::from(ContinuousExpression::from(cost))
51    }
52}
53
54impl From<ContinuousVariable> for CostExpression {
55    fn from(cost: ContinuousVariable) -> Self {
56        Self::from(ContinuousExpression::from(cost))
57    }
58}
59
60impl From<ContinuousResourceVariable> for CostExpression {
61    fn from(cost: ContinuousResourceVariable) -> Self {
62        Self::from(ContinuousExpression::from(cost))
63    }
64}
65
66impl CostExpression {
67    /// Returns the evaluation result.
68    ///
69    /// # Panics
70    ///
71    /// Panics if the cost of the transition state is used or a min/max reduce operation is performed on an empty set or vector.
72    ///
73    /// # Examples
74    ///
75    /// ```
76    /// use dypdl::prelude::*;
77    ///
78    /// let mut model = Model::default();
79    /// let variable = model.add_integer_variable("x", 2).unwrap();
80    /// let state = model.target.clone();
81    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
82    ///
83    /// let expression = CostExpression::from(IntegerExpression::from(variable));
84    /// assert_eq!(
85    ///     expression.eval::<Integer, _>(
86    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry
87    ///     ),
88    ///     2,
89    /// );
90    /// ```
91    #[inline]
92    pub fn eval<T: Numeric, U: StateInterface>(
93        &self,
94        state: &U,
95        function_cache: &mut StateFunctionCache,
96        state_functions: &StateFunctions,
97        registry: &table_registry::TableRegistry,
98    ) -> T {
99        match self {
100            Self::Integer(expression) => {
101                T::from(expression.eval(state, function_cache, state_functions, registry))
102            }
103            Self::Continuous(expression) => {
104                T::from(expression.eval(state, function_cache, state_functions, registry))
105            }
106        }
107    }
108
109    /// Returns the evaluation result.
110    ///
111    /// # Panics
112    ///
113    /// Panics if a min/max reduce operation is performed on an empty set or vector.
114    /// # Examples
115    ///
116    /// ```
117    /// use dypdl::prelude::*;
118    ///
119    /// let mut model = Model::default();
120    /// let variable = model.add_integer_variable("x", 2).unwrap();
121    /// let state = model.target.clone();
122    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
123    ///
124    /// let expression = CostExpression::from(variable + IntegerExpression::Cost);
125    /// assert_eq!(
126    ///     expression.eval_cost(
127    ///         1, &state, &mut function_cache, &model.state_functions, &model.table_registry
128    ///     ),
129    ///     3,
130    /// );
131    /// ```
132    pub fn eval_cost<T: Numeric, U: StateInterface>(
133        &self,
134        cost: T,
135        state: &U,
136        function_cache: &mut StateFunctionCache,
137        state_functions: &StateFunctions,
138        registry: &table_registry::TableRegistry,
139    ) -> T {
140        match self {
141            Self::Integer(expression) => T::from(expression.eval_cost(
142                FromNumeric::from(cost),
143                state,
144                function_cache,
145                state_functions,
146                registry,
147            )),
148            Self::Continuous(expression) => T::from(expression.eval_cost(
149                FromNumeric::from(cost),
150                state,
151                function_cache,
152                state_functions,
153                registry,
154            )),
155        }
156    }
157
158    /// Returns a simplified version by precomputation.
159    ///
160    /// # Panics
161    ///
162    /// Panics if a min/max reduce operation is performed on an empty set or vector.
163    pub fn simplify(&self, registry: &table_registry::TableRegistry) -> CostExpression {
164        match self {
165            Self::Integer(expression) => Self::Integer(expression.simplify(registry)),
166            Self::Continuous(expression) => Self::Continuous(expression.simplify(registry)),
167        }
168    }
169}
170
171/// Trait representing a transition.
172pub trait TransitionInterface {
173    /// Returns true if the transition is applicable and false otherwise.
174    fn is_applicable<T: StateInterface>(
175        &self,
176        state: &T,
177        function_cache: &mut StateFunctionCache,
178        state_functions: &StateFunctions,
179        registry: &table_registry::TableRegistry,
180    ) -> bool;
181
182    /// Returns the transitioned state.
183    fn apply<S: StateInterface, T: From<State>>(
184        &self,
185        state: &S,
186        function_cache: &mut StateFunctionCache,
187        state_functions: &StateFunctions,
188        registry: &table_registry::TableRegistry,
189    ) -> T;
190
191    /// Returns the evaluation result of the cost expression.
192    fn eval_cost<U: Numeric, T: StateInterface>(
193        &self,
194        cost: U,
195        state: &T,
196        function_cache: &mut StateFunctionCache,
197        state_functions: &StateFunctions,
198        registry: &table_registry::TableRegistry,
199    ) -> U;
200}
201
202/// Transition.
203#[derive(Debug, PartialEq, Clone, Default)]
204pub struct Transition {
205    /// Name of the transition.
206    pub name: String,
207    //// Names of parameters.
208    pub parameter_names: Vec<String>,
209    /// The values of parameters.
210    pub parameter_values: Vec<Element>,
211    /// Pairs of an index of a set variable and a parameter.
212    /// A parameter must be included in the corresponding variable to be applicable.
213    pub elements_in_set_variable: Vec<(usize, Element)>,
214    /// Triplets of an index of a vector variable, a parameter, and the capacity.
215    /// A parameter must be included in the corresponding variable to be applicable.
216    pub elements_in_vector_variable: Vec<(usize, Element, usize)>,
217    /// Preconditions.
218    pub preconditions: Vec<grounded_condition::GroundedCondition>,
219    /// Effect.
220    pub effect: Effect,
221    /// Cost expression.
222    pub cost: CostExpression,
223}
224
225impl TransitionInterface for Transition {
226    /// Returns true if the transition is applicable and false otherwise.
227    ///
228    /// # Panics
229    ///
230    /// Panics if the cost of the transition state is used or a min/max reduce operation is performed on an empty set or vector.
231    ///
232    /// # Examples
233    ///
234    /// ```
235    /// use dypdl::prelude::*;
236    ///
237    /// let mut model = Model::default();
238    /// let variable = model.add_integer_variable("x", 2).unwrap();
239    /// let state = model.target.clone();
240    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
241    ///
242    /// let mut transition = Transition::new("transition");
243    /// assert!(
244    ///     transition.is_applicable(
245    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
246    ///     ),
247    /// );
248    ///
249    /// let condition = Condition::comparison_i(ComparisonOperator::Ge, variable, 0);;
250    /// transition.add_precondition(condition);
251    /// assert!(
252    ///     transition.is_applicable(
253    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
254    ///     ),
255    /// );
256    ///
257    /// let condition = Condition::comparison_i(ComparisonOperator::Le, variable, 1);;
258    /// transition.add_precondition(condition);
259    /// assert!(
260    ///     !transition.is_applicable(
261    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
262    ///     ),
263    /// );
264    /// ```
265    fn is_applicable<S: StateInterface>(
266        &self,
267        state: &S,
268        function_cache: &mut StateFunctionCache,
269        state_functions: &StateFunctions,
270        registry: &table_registry::TableRegistry,
271    ) -> bool {
272        for (i, v) in &self.elements_in_set_variable {
273            if !state.get_set_variable(*i).contains(*v) {
274                return false;
275            }
276        }
277        for (i, v, _) in &self.elements_in_vector_variable {
278            if !state.get_vector_variable(*i).contains(v) {
279                return false;
280            }
281        }
282        self.preconditions
283            .iter()
284            .all(|c| c.is_satisfied(state, function_cache, state_functions, registry))
285    }
286
287    /// Returns the transitioned state.
288    ///
289    /// # Panics
290    ///
291    /// Panics if the cost of the transition state is used or a min/max reduce operation is performed on an empty set or vector.
292    ///
293    /// # Examples
294    ///
295    /// ```
296    /// use dypdl::prelude::*;
297    ///
298    /// let mut model = Model::default();
299    /// let variable = model.add_integer_variable("x", 2).unwrap();
300    /// let state = model.target.clone();
301    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
302    ///
303    /// let mut transition = Transition::new("transition");
304    /// transition.add_effect(variable, variable + 1);
305    /// let state: State = transition.apply(
306    ///     &state, &mut function_cache, &model.state_functions, &model.table_registry,
307    /// );
308    /// assert_eq!(state.get_integer_variable(variable.id()), 3);
309    /// ```
310    #[inline]
311    fn apply<S: StateInterface, T: From<State>>(
312        &self,
313        state: &S,
314        function_cache: &mut StateFunctionCache,
315        state_functions: &StateFunctions,
316        registry: &table_registry::TableRegistry,
317    ) -> T {
318        state.apply_effect(&self.effect, function_cache, state_functions, registry)
319    }
320
321    /// Returns the evaluation result of the cost expression.
322    ///
323    /// # Panics
324    ///
325    /// Panics if a min/max reduce operation is performed on an empty set or vector.
326    ///
327    /// # Examples
328    ///
329    /// ```
330    /// use dypdl::prelude::*;
331    ///
332    /// let mut model = Model::default();
333    /// let variable = model.add_integer_variable("x", 2).unwrap();
334    /// let state = model.target.clone();
335    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
336    ///
337    /// let mut transition = Transition::new("transition");
338    /// transition.set_cost(IntegerExpression::Cost + variable);
339    /// assert_eq!(
340    ///     transition.eval_cost(
341    ///         1, &state, &mut function_cache, &model.state_functions, &model.table_registry,
342    ///     ),
343    ///     3,
344    /// );
345    /// ```
346    #[inline]
347    fn eval_cost<T: Numeric, S: StateInterface>(
348        &self,
349        cost: T,
350        state: &S,
351        function_cache: &mut StateFunctionCache,
352        state_functions: &StateFunctions,
353        registry: &table_registry::TableRegistry,
354    ) -> T {
355        self.cost
356            .eval_cost(cost, state, function_cache, state_functions, registry)
357    }
358}
359
360impl Transition {
361    /// Returns the name of transition considering parameters.
362    ///
363    /// # Examples
364    ///
365    /// ```
366    /// use dypdl::prelude::*;
367    ///
368    /// let transition = Transition::new("transition");
369    /// assert_eq!(transition.get_full_name(), String::from("transition"));
370    /// ```
371    pub fn get_full_name(&self) -> String {
372        let mut full_name = self.name.clone();
373        for (name, value) in self
374            .parameter_names
375            .iter()
376            .zip(self.parameter_values.iter())
377        {
378            full_name += format!(" {name}:{value}").as_str();
379        }
380        full_name
381    }
382
383    /// Returns a new transition with the name.
384    pub fn new<T>(name: T) -> Transition
385    where
386        String: From<T>,
387    {
388        Transition {
389            name: String::from(name),
390            ..Default::default()
391        }
392    }
393
394    /// Sets the cost expression;
395    /// # Examples
396    ///
397    /// ```
398    /// use dypdl::prelude::*;
399    ///
400    /// let mut transition = Transition::new("transition");
401    /// transition.set_cost(IntegerExpression::Cost + 1);
402    /// ```
403    pub fn set_cost<T>(&mut self, cost: T)
404    where
405        CostExpression: From<T>,
406    {
407        self.cost = CostExpression::from(cost)
408    }
409
410    /// Gets preconditions.
411    ///
412    /// Note that the preconditions and their order might be changed due to internal optimizations.
413    ///
414    /// # Examples
415    ///
416    /// ```
417    /// use dypdl::prelude::*;
418    ///
419    /// let mut model = Model::default();
420    /// let variable = model.add_integer_variable("x", 2).unwrap();
421    /// let state = model.target.clone();
422    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
423    ///
424    /// let mut transition = Transition::new("transition");
425    /// let condition = Condition::comparison_i(ComparisonOperator::Ge, variable, 0);;
426    /// transition.add_precondition(condition.clone());
427    ///
428    /// let preconditions = transition.get_preconditions();
429    /// assert_eq!(preconditions.len(), 1);
430    /// assert!(
431    ///     preconditions[0].eval(
432    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
433    ///     )
434    /// );
435    /// ```
436    pub fn get_preconditions(&self) -> Vec<Condition> {
437        let mut result = Vec::with_capacity(
438            self.elements_in_set_variable.len()
439                + self.elements_in_vector_variable.len()
440                + self.preconditions.len(),
441        );
442
443        for (i, e) in &self.elements_in_set_variable {
444            result.push(Condition::Set(Box::new(SetCondition::IsIn(
445                ElementExpression::Constant(*e),
446                SetExpression::Reference(ReferenceExpression::Variable(*i)),
447            ))));
448        }
449
450        for (i, e, capacity) in &self.elements_in_vector_variable {
451            result.push(Condition::Set(Box::new(SetCondition::IsIn(
452                ElementExpression::Constant(*e),
453                SetExpression::FromVector(
454                    *capacity,
455                    Box::new(VectorExpression::Reference(ReferenceExpression::Variable(
456                        *i,
457                    ))),
458                ),
459            ))));
460        }
461
462        for condition in &self.preconditions {
463            result.push(Condition::from(condition.clone()));
464        }
465
466        result
467    }
468
469    /// Adds a precondition;
470    ///
471    /// # Examples
472    ///
473    /// ```
474    /// use dypdl::prelude::*;
475    ///
476    /// let mut model = Model::default();
477    /// let variable = model.add_integer_variable("x", 2).unwrap();
478    /// let state = model.target.clone();
479    ///
480    /// let mut transition = Transition::new("transition");
481    /// let condition = Condition::comparison_i(ComparisonOperator::Ge, variable, 0);;
482    /// transition.add_precondition(condition);
483    /// ```
484    pub fn add_precondition(&mut self, condition: Condition) {
485        match &condition {
486            Condition::Set(condition) => match condition.as_ref() {
487                SetCondition::IsIn(
488                    ElementExpression::Constant(e),
489                    SetExpression::Reference(ReferenceExpression::Variable(i)),
490                ) => {
491                    self.elements_in_set_variable.push((*i, *e));
492                    return;
493                }
494                SetCondition::IsIn(
495                    ElementExpression::Constant(e),
496                    SetExpression::FromVector(capacity, v),
497                ) => {
498                    if let VectorExpression::Reference(ReferenceExpression::Variable(i)) =
499                        v.as_ref()
500                    {
501                        self.elements_in_vector_variable.push((*i, *e, *capacity));
502                        return;
503                    }
504                }
505                _ => {}
506            },
507            Condition::Constant(true) => {
508                eprintln!("a precondition is always satisfied");
509            }
510            Condition::Constant(false) => {
511                eprintln!("a precondition is never satisfied");
512            }
513            _ => {}
514        }
515        self.preconditions
516            .push(grounded_condition::GroundedCondition::from(condition))
517    }
518}
519
520/// Trait for adding an effect.
521///
522/// # Examples
523///
524/// ```
525/// use dypdl::prelude::*;
526///
527/// let mut model = Model::default();
528/// let variable = model.add_integer_variable("variable", 0).unwrap();
529///
530/// let mut transition = Transition::new("transition");
531/// assert!(transition.add_effect(variable, variable + 1).is_ok());
532/// ```
533pub trait AddEffect<T, U> {
534    /// Adds an effect.
535    ///
536    /// # Errors
537    ///
538    /// If an effect is already defined for the variable.
539    fn add_effect<V>(&mut self, v: T, expression: V) -> Result<(), ModelErr>
540    where
541        U: From<V>;
542}
543
544macro_rules! impl_add_effect {
545    ($T:ty,$U:ty,$x:ident) => {
546        impl AddEffect<$T, $U> for Transition {
547            fn add_effect<V>(&mut self, v: $T, expression: V) -> Result<(), ModelErr>
548            where
549                $U: From<V>,
550            {
551                let expression = <$U>::from(expression);
552                let mut index = None;
553                for (j, (i, _)) in self.effect.$x.iter().enumerate() {
554                    if *i == v.id() {
555                        return Err(ModelErr::new(format!(
556                            "the transition already has an effect on variable id {i}",
557                        )));
558                    }
559
560                    if *i > v.id() {
561                        index = Some(j);
562                        break;
563                    }
564                }
565
566                if let Some(index) = index {
567                    self.effect.$x.insert(index, (v.id(), expression));
568                } else {
569                    self.effect.$x.push((v.id(), expression));
570                }
571
572                Ok(())
573            }
574        }
575    };
576}
577
578impl_add_effect!(SetVariable, SetExpression, set_effects);
579impl_add_effect!(VectorVariable, VectorExpression, vector_effects);
580impl_add_effect!(ElementVariable, ElementExpression, element_effects);
581impl_add_effect!(
582    ElementResourceVariable,
583    ElementExpression,
584    element_resource_effects
585);
586impl_add_effect!(IntegerVariable, IntegerExpression, integer_effects);
587impl_add_effect!(
588    IntegerResourceVariable,
589    IntegerExpression,
590    integer_resource_effects
591);
592impl_add_effect!(ContinuousVariable, ContinuousExpression, continuous_effects);
593impl_add_effect!(
594    ContinuousResourceVariable,
595    ContinuousExpression,
596    continuous_resource_effects
597);
598
599#[cfg(test)]
600mod tests {
601    use super::*;
602    use crate::expression::*;
603    use crate::state;
604    use crate::table;
605    use crate::table_data;
606    use crate::variable_type::*;
607    use crate::StateMetadata;
608    use rustc_hash::FxHashMap;
609
610    fn generate_registry() -> table_registry::TableRegistry {
611        let tables_1d = vec![table::Table1D::new(vec![10, 20, 30])];
612        let mut name_to_table_1d = FxHashMap::default();
613        name_to_table_1d.insert(String::from("f1"), 0);
614
615        let tables_2d = vec![table::Table2D::new(vec![
616            vec![10, 20, 30],
617            vec![40, 50, 60],
618        ])];
619        let mut name_to_table_2d = FxHashMap::default();
620        name_to_table_2d.insert(String::from("f2"), 0);
621
622        table_registry::TableRegistry {
623            integer_tables: table_data::TableData {
624                tables_1d,
625                name_to_table_1d,
626                tables_2d,
627                name_to_table_2d,
628                ..Default::default()
629            },
630            ..Default::default()
631        }
632    }
633
634    fn generate_state() -> state::State {
635        let mut set1 = Set::with_capacity(3);
636        set1.insert(0);
637        set1.insert(2);
638        let mut set2 = Set::with_capacity(3);
639        set2.insert(0);
640        set2.insert(1);
641        state::State {
642            signature_variables: state::SignatureVariables {
643                set_variables: vec![set1, set2],
644                vector_variables: vec![vec![0, 2], vec![1, 2]],
645                element_variables: vec![1, 2],
646                integer_variables: vec![1, 2, 3],
647                continuous_variables: vec![1.0, 2.0, 3.0],
648            },
649            resource_variables: state::ResourceVariables {
650                element_variables: vec![0, 1],
651                integer_variables: vec![4, 5, 6],
652                continuous_variables: vec![4.0, 5.0, 6.0],
653            },
654        }
655    }
656
657    #[test]
658    fn cost_expression_default() {
659        let expression = CostExpression::default();
660        assert_eq!(expression, CostExpression::Integer(IntegerExpression::Cost));
661    }
662
663    #[test]
664    fn cost_expression_from_integer() {
665        let expression = CostExpression::from(IntegerExpression::Cost);
666        assert_eq!(expression, CostExpression::Integer(IntegerExpression::Cost));
667    }
668
669    #[test]
670    fn cost_expression_from_continuous_expression() {
671        let expression = CostExpression::from(ContinuousExpression::Cost);
672        assert_eq!(
673            expression,
674            CostExpression::Continuous(ContinuousExpression::Cost)
675        );
676    }
677
678    #[test]
679    fn cost_expression_from_continuous() {
680        let expression = CostExpression::from(1.0);
681        assert_eq!(
682            expression,
683            CostExpression::Continuous(ContinuousExpression::Constant(1.0))
684        );
685    }
686
687    #[test]
688    fn cost_expression_from_continuous_variable() {
689        let mut metadata = StateMetadata::default();
690        let var = metadata.add_continuous_variable("var");
691        assert!(var.is_ok());
692        let var = var.unwrap();
693        let expression = CostExpression::from(var);
694        assert_eq!(
695            expression,
696            CostExpression::Continuous(ContinuousExpression::Variable(0))
697        );
698    }
699
700    #[test]
701    fn cost_expression_from_continuous_resource_variable() {
702        let mut metadata = StateMetadata::default();
703        let var = metadata.add_continuous_resource_variable("var", false);
704        assert!(var.is_ok());
705        let var = var.unwrap();
706        let expression = CostExpression::from(var);
707        assert_eq!(
708            expression,
709            CostExpression::Continuous(ContinuousExpression::ResourceVariable(0))
710        );
711    }
712
713    #[test]
714    fn cost_expression_eval() {
715        let state = generate_state();
716        let state_functions = StateFunctions::default();
717        let mut function_cache = StateFunctionCache::new(&state_functions);
718        let registry = generate_registry();
719
720        let expression = CostExpression::Integer(IntegerExpression::BinaryOperation(
721            BinaryOperator::Add,
722            Box::new(IntegerExpression::Constant(1)),
723            Box::new(IntegerExpression::Constant(1)),
724        ));
725        assert_eq!(
726            expression.eval_cost(0, &state, &mut function_cache, &state_functions, &registry),
727            2
728        );
729
730        let expression = CostExpression::Continuous(ContinuousExpression::BinaryOperation(
731            BinaryOperator::Add,
732            Box::new(ContinuousExpression::Constant(1.0)),
733            Box::new(ContinuousExpression::Constant(1.0)),
734        ));
735        assert_eq!(
736            expression.eval_cost(
737                0.0,
738                &state,
739                &mut function_cache,
740                &state_functions,
741                &registry
742            ),
743            2.0
744        );
745    }
746
747    #[test]
748    fn cost_expression_eval_cost() {
749        let state = generate_state();
750        let state_functions = StateFunctions::default();
751        let mut function_cache = StateFunctionCache::new(&state_functions);
752        let registry = generate_registry();
753
754        let expression = CostExpression::Integer(IntegerExpression::BinaryOperation(
755            BinaryOperator::Add,
756            Box::new(IntegerExpression::Cost),
757            Box::new(IntegerExpression::Constant(1)),
758        ));
759        assert_eq!(
760            expression.eval_cost(0, &state, &mut function_cache, &state_functions, &registry),
761            1
762        );
763
764        let expression = CostExpression::Continuous(ContinuousExpression::BinaryOperation(
765            BinaryOperator::Add,
766            Box::new(ContinuousExpression::Cost),
767            Box::new(ContinuousExpression::Constant(1.0)),
768        ));
769        assert_eq!(
770            expression.eval_cost(
771                0.0,
772                &state,
773                &mut function_cache,
774                &state_functions,
775                &registry
776            ),
777            1.0
778        );
779    }
780
781    #[test]
782    fn cost_expression_simplify_integer() {
783        let registry = generate_registry();
784        let expression = CostExpression::Integer(IntegerExpression::BinaryOperation(
785            BinaryOperator::Add,
786            Box::new(IntegerExpression::Constant(1)),
787            Box::new(IntegerExpression::Constant(1)),
788        ));
789        assert_eq!(
790            expression.simplify(&registry),
791            CostExpression::Integer(IntegerExpression::Constant(2))
792        )
793    }
794
795    #[test]
796    fn cost_expression_simplify_continuous() {
797        let registry = generate_registry();
798        let expression = CostExpression::Continuous(ContinuousExpression::BinaryOperation(
799            BinaryOperator::Add,
800            Box::new(ContinuousExpression::Constant(1.0)),
801            Box::new(ContinuousExpression::Constant(1.0)),
802        ));
803        assert_eq!(
804            expression.simplify(&registry),
805            CostExpression::Continuous(ContinuousExpression::Constant(2.0))
806        )
807    }
808
809    #[test]
810    fn applicable() {
811        let state = generate_state();
812        let state_functions = StateFunctions::default();
813        let mut function_cache = StateFunctionCache::new(&state_functions);
814        let registry = generate_registry();
815        let set_condition = grounded_condition::GroundedCondition {
816            condition: Condition::Set(Box::new(SetCondition::IsIn(
817                ElementExpression::Constant(0),
818                SetExpression::Reference(ReferenceExpression::Variable(0)),
819            ))),
820            ..Default::default()
821        };
822        let numeric_condition = grounded_condition::GroundedCondition {
823            condition: Condition::ComparisonI(
824                ComparisonOperator::Ge,
825                Box::new(IntegerExpression::Variable(0)),
826                Box::new(IntegerExpression::Constant(1)),
827            ),
828            ..Default::default()
829        };
830
831        let transition = Transition {
832            name: String::from(""),
833            preconditions: vec![set_condition, numeric_condition],
834            cost: CostExpression::Integer(IntegerExpression::Constant(0)),
835            ..Default::default()
836        };
837        assert!(transition.is_applicable(&state, &mut function_cache, &state_functions, &registry));
838
839        let transition = Transition {
840            name: String::from(""),
841            elements_in_set_variable: vec![(0, 0), (1, 1)],
842            elements_in_vector_variable: vec![(0, 0, 3), (1, 2, 3)],
843            cost: CostExpression::Integer(IntegerExpression::Constant(0)),
844            ..Default::default()
845        };
846        assert!(transition.is_applicable(&state, &mut function_cache, &state_functions, &registry));
847    }
848
849    #[test]
850    fn not_applicable() {
851        let state = generate_state();
852        let registry = generate_registry();
853        let state_functions = StateFunctions::default();
854        let mut function_cache = StateFunctionCache::new(&state_functions);
855        let set_condition = grounded_condition::GroundedCondition {
856            condition: Condition::Set(Box::new(SetCondition::IsIn(
857                ElementExpression::Constant(0),
858                SetExpression::Reference(ReferenceExpression::Variable(0)),
859            ))),
860            ..Default::default()
861        };
862        let numeric_condition = grounded_condition::GroundedCondition {
863            condition: Condition::ComparisonI(
864                ComparisonOperator::Le,
865                Box::new(IntegerExpression::Variable(0)),
866                Box::new(IntegerExpression::Constant(1)),
867            ),
868            ..Default::default()
869        };
870
871        let transition = Transition {
872            name: String::from(""),
873            preconditions: vec![set_condition, numeric_condition],
874            cost: CostExpression::Integer(IntegerExpression::Constant(0)),
875            ..Default::default()
876        };
877        assert!(transition.is_applicable(&state, &mut function_cache, &state_functions, &registry));
878
879        let transition = Transition {
880            name: String::from(""),
881            elements_in_set_variable: vec![(0, 1), (1, 1)],
882            elements_in_vector_variable: vec![(0, 0, 3), (1, 2, 3)],
883            cost: CostExpression::Integer(IntegerExpression::Constant(0)),
884            ..Default::default()
885        };
886        assert!(!transition.is_applicable(
887            &state,
888            &mut function_cache,
889            &state_functions,
890            &registry
891        ));
892
893        let transition = Transition {
894            name: String::from(""),
895            elements_in_set_variable: vec![(0, 1), (1, 1)],
896            elements_in_vector_variable: vec![(0, 1, 3), (1, 2, 3)],
897            cost: CostExpression::Integer(IntegerExpression::Constant(0)),
898            ..Default::default()
899        };
900        assert!(!transition.is_applicable(
901            &state,
902            &mut function_cache,
903            &state_functions,
904            &registry
905        ));
906    }
907
908    #[test]
909    fn apply_effects() {
910        let state = generate_state();
911        let state_functions = StateFunctions::default();
912        let mut function_cache = StateFunctionCache::new(&state_functions);
913        let registry = generate_registry();
914        let set_effect1 = SetExpression::SetElementOperation(
915            SetElementOperator::Add,
916            ElementExpression::Constant(1),
917            Box::new(SetExpression::Reference(ReferenceExpression::Variable(0))),
918        );
919        let set_effect2 = SetExpression::SetElementOperation(
920            SetElementOperator::Remove,
921            ElementExpression::Constant(0),
922            Box::new(SetExpression::Reference(ReferenceExpression::Variable(1))),
923        );
924        let vector_effect1 = VectorExpression::Push(
925            ElementExpression::Constant(1),
926            Box::new(VectorExpression::Reference(ReferenceExpression::Variable(
927                0,
928            ))),
929        );
930        let vector_effect2 = VectorExpression::Push(
931            ElementExpression::Constant(0),
932            Box::new(VectorExpression::Reference(ReferenceExpression::Variable(
933                1,
934            ))),
935        );
936        let element_effect1 = ElementExpression::Constant(2);
937        let element_effect2 = ElementExpression::Constant(1);
938        let integer_effect1 = IntegerExpression::BinaryOperation(
939            BinaryOperator::Sub,
940            Box::new(IntegerExpression::Variable(0)),
941            Box::new(IntegerExpression::Constant(1)),
942        );
943        let integer_effect2 = IntegerExpression::BinaryOperation(
944            BinaryOperator::Mul,
945            Box::new(IntegerExpression::Variable(1)),
946            Box::new(IntegerExpression::Constant(2)),
947        );
948        let continuous_effect1 = ContinuousExpression::BinaryOperation(
949            BinaryOperator::Sub,
950            Box::new(ContinuousExpression::Variable(0)),
951            Box::new(ContinuousExpression::Constant(1.0)),
952        );
953        let continuous_effect2 = ContinuousExpression::BinaryOperation(
954            BinaryOperator::Mul,
955            Box::new(ContinuousExpression::Variable(1)),
956            Box::new(ContinuousExpression::Constant(2.0)),
957        );
958        let element_resource_effect1 = ElementExpression::Constant(1);
959        let element_resource_effect2 = ElementExpression::Constant(0);
960        let integer_resource_effect1 = IntegerExpression::BinaryOperation(
961            BinaryOperator::Add,
962            Box::new(IntegerExpression::ResourceVariable(0)),
963            Box::new(IntegerExpression::Constant(1)),
964        );
965        let integer_resource_effect2 = IntegerExpression::BinaryOperation(
966            BinaryOperator::Div,
967            Box::new(IntegerExpression::ResourceVariable(1)),
968            Box::new(IntegerExpression::Constant(2)),
969        );
970        let continuous_resource_effect1 = ContinuousExpression::BinaryOperation(
971            BinaryOperator::Add,
972            Box::new(ContinuousExpression::ResourceVariable(0)),
973            Box::new(ContinuousExpression::Constant(1.0)),
974        );
975        let continuous_resource_effect2 = ContinuousExpression::BinaryOperation(
976            BinaryOperator::Div,
977            Box::new(ContinuousExpression::ResourceVariable(1)),
978            Box::new(ContinuousExpression::Constant(2.0)),
979        );
980        let transition = Transition {
981            name: String::from(""),
982            effect: Effect {
983                set_effects: vec![(0, set_effect1), (1, set_effect2)],
984                vector_effects: vec![(0, vector_effect1), (1, vector_effect2)],
985                element_effects: vec![(0, element_effect1), (1, element_effect2)],
986                integer_effects: vec![(0, integer_effect1), (1, integer_effect2)],
987                continuous_effects: vec![(0, continuous_effect1), (1, continuous_effect2)],
988                element_resource_effects: vec![
989                    (0, element_resource_effect1),
990                    (1, element_resource_effect2),
991                ],
992                integer_resource_effects: vec![
993                    (0, integer_resource_effect1),
994                    (1, integer_resource_effect2),
995                ],
996                continuous_resource_effects: vec![
997                    (0, continuous_resource_effect1),
998                    (1, continuous_resource_effect2),
999                ],
1000            },
1001            cost: CostExpression::Integer(IntegerExpression::BinaryOperation(
1002                BinaryOperator::Add,
1003                Box::new(IntegerExpression::Cost),
1004                Box::new(IntegerExpression::Constant(1)),
1005            )),
1006            ..Default::default()
1007        };
1008
1009        let mut set1 = Set::with_capacity(3);
1010        set1.insert(0);
1011        set1.insert(1);
1012        set1.insert(2);
1013        let mut set2 = Set::with_capacity(3);
1014        set2.insert(1);
1015        let expected = state::State {
1016            signature_variables: state::SignatureVariables {
1017                set_variables: vec![set1, set2],
1018                vector_variables: vec![vec![0, 2, 1], vec![1, 2, 0]],
1019                element_variables: vec![2, 1],
1020                integer_variables: vec![0, 4, 3],
1021                continuous_variables: vec![0.0, 4.0, 3.0],
1022            },
1023            resource_variables: state::ResourceVariables {
1024                element_variables: vec![1, 0],
1025                integer_variables: vec![5, 2, 6],
1026                continuous_variables: vec![5.0, 2.5, 6.0],
1027            },
1028        };
1029        let successor: State =
1030            transition.apply(&state, &mut function_cache, &state_functions, &registry);
1031        assert_eq!(successor, expected);
1032    }
1033
1034    #[test]
1035    fn eval_cost() {
1036        let state = generate_state();
1037        let state_functions = StateFunctions::default();
1038        let mut function_cache = StateFunctionCache::new(&state_functions);
1039        let registry = generate_registry();
1040
1041        let transition = Transition {
1042            cost: CostExpression::Integer(IntegerExpression::BinaryOperation(
1043                BinaryOperator::Add,
1044                Box::new(IntegerExpression::Cost),
1045                Box::new(IntegerExpression::Constant(1)),
1046            )),
1047            ..Default::default()
1048        };
1049        assert_eq!(
1050            transition.eval_cost(0, &state, &mut function_cache, &state_functions, &registry),
1051            1
1052        );
1053
1054        let transition = Transition {
1055            cost: CostExpression::Continuous(ContinuousExpression::BinaryOperation(
1056                BinaryOperator::Add,
1057                Box::new(ContinuousExpression::Cost),
1058                Box::new(ContinuousExpression::Constant(1.0)),
1059            )),
1060            ..Default::default()
1061        };
1062        assert_eq!(
1063            transition.eval_cost(
1064                0.0,
1065                &state,
1066                &mut function_cache,
1067                &state_functions,
1068                &registry
1069            ),
1070            1.0
1071        );
1072    }
1073
1074    #[test]
1075    fn get_full_name() {
1076        let transition = Transition {
1077            name: String::from("transition"),
1078            parameter_names: vec![String::from("param1"), String::from("param2")],
1079            parameter_values: vec![0, 1],
1080            ..Default::default()
1081        };
1082        assert_eq!(
1083            transition.get_full_name(),
1084            String::from("transition param1:0 param2:1")
1085        );
1086    }
1087
1088    #[test]
1089    fn new() {
1090        let transition = Transition::new("t");
1091        assert_eq!(
1092            transition,
1093            Transition {
1094                name: String::from("t"),
1095                ..Default::default()
1096            }
1097        );
1098    }
1099
1100    #[test]
1101    fn set_cost() {
1102        let mut transition = Transition::default();
1103        transition.set_cost(ContinuousExpression::Cost);
1104        assert_eq!(
1105            transition,
1106            Transition {
1107                cost: CostExpression::Continuous(ContinuousExpression::Cost),
1108                ..Default::default()
1109            }
1110        );
1111    }
1112
1113    #[test]
1114    fn get_preconditions() {
1115        let transition = Transition {
1116            elements_in_set_variable: vec![(0, 1), (1, 2)],
1117            elements_in_vector_variable: vec![(2, 3, 4), (3, 4, 5)],
1118            preconditions: vec![
1119                grounded_condition::GroundedCondition {
1120                    condition: Condition::Set(Box::new(SetCondition::IsIn(
1121                        ElementExpression::Variable(0),
1122                        SetExpression::Reference(ReferenceExpression::Variable(0)),
1123                    ))),
1124                    ..Default::default()
1125                },
1126                grounded_condition::GroundedCondition {
1127                    condition: Condition::Set(Box::new(SetCondition::IsIn(
1128                        ElementExpression::Variable(1),
1129                        SetExpression::Reference(ReferenceExpression::Variable(1)),
1130                    ))),
1131                    ..Default::default()
1132                },
1133            ],
1134            ..Default::default()
1135        };
1136        assert_eq!(
1137            transition.get_preconditions(),
1138            vec![
1139                Condition::Set(Box::new(SetCondition::IsIn(
1140                    ElementExpression::Constant(1),
1141                    SetExpression::Reference(ReferenceExpression::Variable(0)),
1142                ))),
1143                Condition::Set(Box::new(SetCondition::IsIn(
1144                    ElementExpression::Constant(2),
1145                    SetExpression::Reference(ReferenceExpression::Variable(1)),
1146                ))),
1147                Condition::Set(Box::new(SetCondition::IsIn(
1148                    ElementExpression::Constant(3),
1149                    SetExpression::FromVector(
1150                        4,
1151                        Box::new(VectorExpression::Reference(ReferenceExpression::Variable(
1152                            2
1153                        )))
1154                    ),
1155                ))),
1156                Condition::Set(Box::new(SetCondition::IsIn(
1157                    ElementExpression::Constant(4),
1158                    SetExpression::FromVector(
1159                        5,
1160                        Box::new(VectorExpression::Reference(ReferenceExpression::Variable(
1161                            3
1162                        )))
1163                    ),
1164                ))),
1165                Condition::Set(Box::new(SetCondition::IsIn(
1166                    ElementExpression::Variable(0),
1167                    SetExpression::Reference(ReferenceExpression::Variable(0)),
1168                ))),
1169                Condition::Set(Box::new(SetCondition::IsIn(
1170                    ElementExpression::Variable(1),
1171                    SetExpression::Reference(ReferenceExpression::Variable(1)),
1172                ))),
1173            ]
1174        );
1175    }
1176
1177    #[test]
1178    fn add_precondition() {
1179        let mut transition = Transition::default();
1180        transition.add_precondition(Condition::Set(Box::new(SetCondition::IsIn(
1181            ElementExpression::Constant(0),
1182            SetExpression::Reference(ReferenceExpression::Variable(0)),
1183        ))));
1184        assert_eq!(
1185            transition,
1186            Transition {
1187                elements_in_set_variable: vec![(0, 0)],
1188                ..Default::default()
1189            }
1190        );
1191        transition.add_precondition(Condition::Set(Box::new(SetCondition::IsIn(
1192            ElementExpression::Constant(1),
1193            SetExpression::Reference(ReferenceExpression::Variable(1)),
1194        ))));
1195        assert_eq!(
1196            transition,
1197            Transition {
1198                elements_in_set_variable: vec![(0, 0), (1, 1)],
1199                ..Default::default()
1200            }
1201        );
1202        transition.add_precondition(Condition::Set(Box::new(SetCondition::IsIn(
1203            ElementExpression::Constant(0),
1204            SetExpression::FromVector(
1205                10,
1206                Box::new(VectorExpression::Reference(ReferenceExpression::Variable(
1207                    0,
1208                ))),
1209            ),
1210        ))));
1211        assert_eq!(
1212            transition,
1213            Transition {
1214                elements_in_set_variable: vec![(0, 0), (1, 1)],
1215                elements_in_vector_variable: vec![(0, 0, 10)],
1216                ..Default::default()
1217            }
1218        );
1219        transition.add_precondition(Condition::Set(Box::new(SetCondition::IsIn(
1220            ElementExpression::Constant(1),
1221            SetExpression::FromVector(
1222                10,
1223                Box::new(VectorExpression::Reference(ReferenceExpression::Variable(
1224                    1,
1225                ))),
1226            ),
1227        ))));
1228        assert_eq!(
1229            transition,
1230            Transition {
1231                elements_in_set_variable: vec![(0, 0), (1, 1)],
1232                elements_in_vector_variable: vec![(0, 0, 10), (1, 1, 10)],
1233                ..Default::default()
1234            }
1235        );
1236        transition.add_precondition(Condition::ComparisonE(
1237            ComparisonOperator::Eq,
1238            Box::new(ElementExpression::Variable(0)),
1239            Box::new(ElementExpression::Constant(0)),
1240        ));
1241        assert_eq!(
1242            transition,
1243            Transition {
1244                elements_in_set_variable: vec![(0, 0), (1, 1)],
1245                elements_in_vector_variable: vec![(0, 0, 10), (1, 1, 10)],
1246                preconditions: vec![grounded_condition::GroundedCondition {
1247                    condition: Condition::ComparisonE(
1248                        ComparisonOperator::Eq,
1249                        Box::new(ElementExpression::Variable(0)),
1250                        Box::new(ElementExpression::Constant(0))
1251                    ),
1252                    ..Default::default()
1253                }],
1254                ..Default::default()
1255            }
1256        );
1257        transition.add_precondition(Condition::ComparisonE(
1258            ComparisonOperator::Eq,
1259            Box::new(ElementExpression::Variable(1)),
1260            Box::new(ElementExpression::Constant(1)),
1261        ));
1262        assert_eq!(
1263            transition,
1264            Transition {
1265                elements_in_set_variable: vec![(0, 0), (1, 1)],
1266                elements_in_vector_variable: vec![(0, 0, 10), (1, 1, 10)],
1267                preconditions: vec![
1268                    grounded_condition::GroundedCondition {
1269                        condition: Condition::ComparisonE(
1270                            ComparisonOperator::Eq,
1271                            Box::new(ElementExpression::Variable(0)),
1272                            Box::new(ElementExpression::Constant(0))
1273                        ),
1274                        ..Default::default()
1275                    },
1276                    grounded_condition::GroundedCondition {
1277                        condition: Condition::ComparisonE(
1278                            ComparisonOperator::Eq,
1279                            Box::new(ElementExpression::Variable(1)),
1280                            Box::new(ElementExpression::Constant(1))
1281                        ),
1282                        ..Default::default()
1283                    },
1284                ],
1285                ..Default::default()
1286            }
1287        );
1288    }
1289
1290    #[test]
1291    fn add_set_effect_ok() {
1292        let mut metadata = state::StateMetadata::default();
1293        let ob = metadata.add_object_type(String::from("something"), 10);
1294        assert!(ob.is_ok());
1295        let ob = ob.unwrap();
1296        let v1 = metadata.add_set_variable(String::from("v1"), ob);
1297        assert!(v1.is_ok());
1298        let v1 = v1.unwrap();
1299        let v2 = metadata.add_set_variable(String::from("v2"), ob);
1300        assert!(v2.is_ok());
1301        let v2 = v2.unwrap();
1302        let v3 = metadata.add_set_variable(String::from("v3"), ob);
1303        assert!(v3.is_ok());
1304        let v3 = v3.unwrap();
1305        let v4 = metadata.add_set_variable(String::from("v4"), ob);
1306        assert!(v4.is_ok());
1307        let v4 = v4.unwrap();
1308
1309        let mut transition = Transition::default();
1310        let mut effect = Set::with_capacity(10);
1311        effect.insert(1);
1312        let result = transition.add_effect(v3, effect);
1313        assert!(result.is_ok());
1314        assert_eq!(
1315            transition,
1316            Transition {
1317                effect: Effect {
1318                    set_effects: vec![(
1319                        v3.id(),
1320                        SetExpression::Reference(ReferenceExpression::Constant({
1321                            let mut set = Set::with_capacity(10);
1322                            set.insert(1);
1323                            set
1324                        }))
1325                    )],
1326                    ..Default::default()
1327                },
1328                ..Default::default()
1329            },
1330        );
1331        let result = transition.add_effect(v1, Set::with_capacity(10));
1332        assert!(result.is_ok());
1333        assert_eq!(
1334            transition,
1335            Transition {
1336                effect: Effect {
1337                    set_effects: vec![
1338                        (
1339                            v1.id(),
1340                            SetExpression::Reference(ReferenceExpression::Constant(
1341                                Set::with_capacity(10)
1342                            ))
1343                        ),
1344                        (
1345                            v3.id(),
1346                            SetExpression::Reference(ReferenceExpression::Constant({
1347                                let mut set = Set::with_capacity(10);
1348                                set.insert(1);
1349                                set
1350                            }))
1351                        )
1352                    ],
1353                    ..Default::default()
1354                },
1355                ..Default::default()
1356            },
1357        );
1358        let result = transition.add_effect(v2, v1);
1359        assert!(result.is_ok());
1360        assert_eq!(
1361            transition,
1362            Transition {
1363                effect: Effect {
1364                    set_effects: vec![
1365                        (
1366                            v1.id(),
1367                            SetExpression::Reference(ReferenceExpression::Constant(
1368                                Set::with_capacity(10)
1369                            ))
1370                        ),
1371                        (
1372                            v2.id(),
1373                            SetExpression::Reference(ReferenceExpression::Variable(v1.id()))
1374                        ),
1375                        (
1376                            v3.id(),
1377                            SetExpression::Reference(ReferenceExpression::Constant({
1378                                let mut set = Set::with_capacity(10);
1379                                set.insert(1);
1380                                set
1381                            }))
1382                        )
1383                    ],
1384                    ..Default::default()
1385                },
1386                ..Default::default()
1387            },
1388        );
1389        let result = transition.add_effect(v4, v2);
1390        assert!(result.is_ok());
1391        assert_eq!(
1392            transition,
1393            Transition {
1394                effect: Effect {
1395                    set_effects: vec![
1396                        (
1397                            v1.id(),
1398                            SetExpression::Reference(ReferenceExpression::Constant(
1399                                Set::with_capacity(10)
1400                            ))
1401                        ),
1402                        (
1403                            v2.id(),
1404                            SetExpression::Reference(ReferenceExpression::Variable(v1.id()))
1405                        ),
1406                        (
1407                            v3.id(),
1408                            SetExpression::Reference(ReferenceExpression::Constant({
1409                                let mut set = Set::with_capacity(10);
1410                                set.insert(1);
1411                                set
1412                            }))
1413                        ),
1414                        (
1415                            v4.id(),
1416                            SetExpression::Reference(ReferenceExpression::Variable(v2.id()))
1417                        ),
1418                    ],
1419                    ..Default::default()
1420                },
1421                ..Default::default()
1422            },
1423        );
1424    }
1425
1426    #[test]
1427    fn add_set_effect_err() {
1428        let mut metadata = state::StateMetadata::default();
1429        let ob = metadata.add_object_type(String::from("something"), 10);
1430        assert!(ob.is_ok());
1431        let ob = ob.unwrap();
1432        let v = metadata.add_set_variable(String::from("v"), ob);
1433        assert!(v.is_ok());
1434        let v = v.unwrap();
1435
1436        let mut transition = Transition::default();
1437        let result = transition.add_effect(v, Set::with_capacity(10));
1438        assert!(result.is_ok());
1439        let result = transition.add_effect(v, Set::with_capacity(10));
1440        assert!(result.is_err());
1441    }
1442
1443    #[test]
1444    fn add_vector_effect_ok() {
1445        let mut metadata = state::StateMetadata::default();
1446        let ob = metadata.add_object_type(String::from("something"), 10);
1447        assert!(ob.is_ok());
1448        let ob = ob.unwrap();
1449        let v1 = metadata.add_vector_variable(String::from("v1"), ob);
1450        assert!(v1.is_ok());
1451        let v1 = v1.unwrap();
1452        let v2 = metadata.add_vector_variable(String::from("v2"), ob);
1453        assert!(v2.is_ok());
1454        let v2 = v2.unwrap();
1455        let v3 = metadata.add_vector_variable(String::from("v3"), ob);
1456        assert!(v3.is_ok());
1457        let v3 = v3.unwrap();
1458        let v4 = metadata.add_vector_variable(String::from("v4"), ob);
1459        assert!(v4.is_ok());
1460        let v4 = v4.unwrap();
1461
1462        let mut transition = Transition::default();
1463        let result = transition.add_effect(
1464            v3,
1465            VectorExpression::Reference(ReferenceExpression::Constant(vec![])),
1466        );
1467        assert!(result.is_ok());
1468        assert_eq!(
1469            transition,
1470            Transition {
1471                effect: Effect {
1472                    vector_effects: vec![(
1473                        v3.id(),
1474                        VectorExpression::Reference(ReferenceExpression::Constant(vec![]))
1475                    )],
1476                    ..Default::default()
1477                },
1478                ..Default::default()
1479            },
1480        );
1481        let result = transition.add_effect(
1482            v1,
1483            VectorExpression::Reference(ReferenceExpression::Constant(vec![1, 2])),
1484        );
1485        assert!(result.is_ok());
1486        assert_eq!(
1487            transition,
1488            Transition {
1489                effect: Effect {
1490                    vector_effects: vec![
1491                        (
1492                            v1.id(),
1493                            VectorExpression::Reference(ReferenceExpression::Constant(vec![1, 2]))
1494                        ),
1495                        (
1496                            v3.id(),
1497                            VectorExpression::Reference(ReferenceExpression::Constant(vec![]))
1498                        )
1499                    ],
1500                    ..Default::default()
1501                },
1502                ..Default::default()
1503            },
1504        );
1505        let result = transition.add_effect(
1506            v2,
1507            VectorExpression::Reference(ReferenceExpression::Variable(v1.id())),
1508        );
1509        assert!(result.is_ok());
1510        assert_eq!(
1511            transition,
1512            Transition {
1513                effect: Effect {
1514                    vector_effects: vec![
1515                        (
1516                            v1.id(),
1517                            VectorExpression::Reference(ReferenceExpression::Constant(vec![1, 2]))
1518                        ),
1519                        (
1520                            v2.id(),
1521                            VectorExpression::Reference(ReferenceExpression::Variable(v1.id()))
1522                        ),
1523                        (
1524                            v3.id(),
1525                            VectorExpression::Reference(ReferenceExpression::Constant(vec![]))
1526                        )
1527                    ],
1528                    ..Default::default()
1529                },
1530                ..Default::default()
1531            },
1532        );
1533        let result = transition.add_effect(
1534            v4,
1535            VectorExpression::Reference(ReferenceExpression::Variable(v2.id())),
1536        );
1537        assert!(result.is_ok());
1538        assert_eq!(
1539            transition,
1540            Transition {
1541                effect: Effect {
1542                    vector_effects: vec![
1543                        (
1544                            v1.id(),
1545                            VectorExpression::Reference(ReferenceExpression::Constant(vec![1, 2]))
1546                        ),
1547                        (
1548                            v2.id(),
1549                            VectorExpression::Reference(ReferenceExpression::Variable(v1.id()))
1550                        ),
1551                        (
1552                            v3.id(),
1553                            VectorExpression::Reference(ReferenceExpression::Constant(vec![]))
1554                        ),
1555                        (
1556                            v4.id(),
1557                            VectorExpression::Reference(ReferenceExpression::Variable(v2.id()))
1558                        ),
1559                    ],
1560                    ..Default::default()
1561                },
1562                ..Default::default()
1563            },
1564        );
1565    }
1566
1567    #[test]
1568    fn add_vector_effect_err() {
1569        let mut metadata = state::StateMetadata::default();
1570        let ob = metadata.add_object_type(String::from("something"), 10);
1571        assert!(ob.is_ok());
1572        let ob = ob.unwrap();
1573        let v = metadata.add_vector_variable(String::from("v"), ob);
1574        assert!(v.is_ok());
1575        let v = v.unwrap();
1576
1577        let mut transition = Transition::default();
1578        let result = transition.add_effect(
1579            v,
1580            VectorExpression::Reference(ReferenceExpression::Constant(vec![1, 2])),
1581        );
1582        assert!(result.is_ok());
1583        let result = transition.add_effect(
1584            v,
1585            VectorExpression::Reference(ReferenceExpression::Constant(vec![1, 2])),
1586        );
1587        assert!(result.is_err());
1588    }
1589
1590    #[test]
1591    fn add_element_effect_ok() {
1592        let mut metadata = state::StateMetadata::default();
1593        let ob = metadata.add_object_type(String::from("something"), 10);
1594        assert!(ob.is_ok());
1595        let ob = ob.unwrap();
1596        let v1 = metadata.add_element_variable(String::from("v1"), ob);
1597        assert!(v1.is_ok());
1598        let v1 = v1.unwrap();
1599        let v2 = metadata.add_element_variable(String::from("v2"), ob);
1600        assert!(v2.is_ok());
1601        let v2 = v2.unwrap();
1602
1603        let mut transition = Transition::default();
1604        let result = transition.add_effect(v1, 0);
1605        assert!(result.is_ok());
1606        assert_eq!(
1607            transition,
1608            Transition {
1609                effect: Effect {
1610                    element_effects: vec![(v1.id(), ElementExpression::Constant(0))],
1611                    ..Default::default()
1612                },
1613                ..Default::default()
1614            },
1615        );
1616        let result = transition.add_effect(v2, v1);
1617        assert!(result.is_ok());
1618        assert_eq!(
1619            transition,
1620            Transition {
1621                effect: Effect {
1622                    element_effects: vec![
1623                        (v1.id(), ElementExpression::Constant(0)),
1624                        (v2.id(), ElementExpression::Variable(v1.id()))
1625                    ],
1626                    ..Default::default()
1627                },
1628                ..Default::default()
1629            },
1630        );
1631    }
1632
1633    #[test]
1634    fn add_element_effect_err() {
1635        let mut metadata = state::StateMetadata::default();
1636        let ob = metadata.add_object_type(String::from("something"), 10);
1637        assert!(ob.is_ok());
1638        let ob = ob.unwrap();
1639        let v = metadata.add_element_variable(String::from("v"), ob);
1640        assert!(v.is_ok());
1641        let v = v.unwrap();
1642
1643        let mut transition = Transition::default();
1644        let result = transition.add_effect(v, 0);
1645        assert!(result.is_ok());
1646        let result = transition.add_effect(v, 0);
1647        assert!(result.is_err());
1648    }
1649
1650    #[test]
1651    fn add_element_resource_effect_ok() {
1652        let mut metadata = state::StateMetadata::default();
1653        let ob = metadata.add_object_type(String::from("something"), 10);
1654        assert!(ob.is_ok());
1655        let ob = ob.unwrap();
1656        let v1 = metadata.add_element_resource_variable(String::from("v1"), ob, false);
1657        assert!(v1.is_ok());
1658        let v1 = v1.unwrap();
1659        let v2 = metadata.add_element_resource_variable(String::from("v2"), ob, true);
1660        assert!(v2.is_ok());
1661        let v2 = v2.unwrap();
1662
1663        let mut transition = Transition::default();
1664        let result = transition.add_effect(v1, 0);
1665        assert!(result.is_ok());
1666        assert_eq!(
1667            transition,
1668            Transition {
1669                effect: Effect {
1670                    element_resource_effects: vec![(v1.id(), ElementExpression::Constant(0))],
1671                    ..Default::default()
1672                },
1673                ..Default::default()
1674            },
1675        );
1676        let result = transition.add_effect(v2, v1);
1677        assert!(result.is_ok());
1678        assert_eq!(
1679            transition,
1680            Transition {
1681                effect: Effect {
1682                    element_resource_effects: vec![
1683                        (v1.id(), ElementExpression::Constant(0)),
1684                        (v2.id(), ElementExpression::ResourceVariable(v1.id()))
1685                    ],
1686                    ..Default::default()
1687                },
1688                ..Default::default()
1689            },
1690        );
1691    }
1692
1693    #[test]
1694    fn add_element_resource_effect_err() {
1695        let mut metadata = state::StateMetadata::default();
1696        let ob = metadata.add_object_type(String::from("something"), 10);
1697        assert!(ob.is_ok());
1698        let ob = ob.unwrap();
1699        let v = metadata.add_element_resource_variable(String::from("v"), ob, false);
1700        assert!(v.is_ok());
1701        let v = v.unwrap();
1702
1703        let mut transition = Transition::default();
1704        let result = transition.add_effect(v, 0);
1705        assert!(result.is_ok());
1706        let result = transition.add_effect(v, 0);
1707        assert!(result.is_err());
1708    }
1709
1710    #[test]
1711    fn add_integer_effect_ok() {
1712        let mut metadata = state::StateMetadata::default();
1713        let v1 = metadata.add_integer_variable(String::from("v1"));
1714        assert!(v1.is_ok());
1715        let v1 = v1.unwrap();
1716        let v2 = metadata.add_integer_variable(String::from("v2"));
1717        assert!(v2.is_ok());
1718        let v2 = v2.unwrap();
1719
1720        let mut transition = Transition::default();
1721        let result = transition.add_effect(v1, 0);
1722        assert!(result.is_ok());
1723        assert_eq!(
1724            transition,
1725            Transition {
1726                effect: Effect {
1727                    integer_effects: vec![(v1.id(), IntegerExpression::Constant(0))],
1728                    ..Default::default()
1729                },
1730                ..Default::default()
1731            },
1732        );
1733        let result = transition.add_effect(v2, v1);
1734        assert!(result.is_ok());
1735        assert_eq!(
1736            transition,
1737            Transition {
1738                effect: Effect {
1739                    integer_effects: vec![
1740                        (v1.id(), IntegerExpression::Constant(0)),
1741                        (v2.id(), IntegerExpression::Variable(v1.id()))
1742                    ],
1743                    ..Default::default()
1744                },
1745                ..Default::default()
1746            },
1747        );
1748    }
1749
1750    #[test]
1751    fn add_integer_effect_err() {
1752        let mut metadata = state::StateMetadata::default();
1753        let v = metadata.add_integer_variable(String::from("v"));
1754        assert!(v.is_ok());
1755        let v = v.unwrap();
1756
1757        let mut transition = Transition::default();
1758        let result = transition.add_effect(v, 0);
1759        assert!(result.is_ok());
1760        let result = transition.add_effect(v, 0);
1761        assert!(result.is_err());
1762    }
1763
1764    #[test]
1765    fn add_integer_resource_effect_ok() {
1766        let mut metadata = state::StateMetadata::default();
1767        let v1 = metadata.add_integer_resource_variable(String::from("v1"), false);
1768        assert!(v1.is_ok());
1769        let v1 = v1.unwrap();
1770        let v2 = metadata.add_integer_resource_variable(String::from("v2"), true);
1771        assert!(v2.is_ok());
1772        let v2 = v2.unwrap();
1773
1774        let mut transition = Transition::default();
1775        let result = transition.add_effect(v1, 0);
1776        assert!(result.is_ok());
1777        assert_eq!(
1778            transition,
1779            Transition {
1780                effect: Effect {
1781                    integer_resource_effects: vec![(v1.id(), IntegerExpression::Constant(0))],
1782                    ..Default::default()
1783                },
1784                ..Default::default()
1785            },
1786        );
1787        let result = transition.add_effect(v2, v1);
1788        assert!(result.is_ok());
1789        assert_eq!(
1790            transition,
1791            Transition {
1792                effect: Effect {
1793                    integer_resource_effects: vec![
1794                        (v1.id(), IntegerExpression::Constant(0)),
1795                        (v2.id(), IntegerExpression::ResourceVariable(v1.id()))
1796                    ],
1797                    ..Default::default()
1798                },
1799                ..Default::default()
1800            },
1801        );
1802    }
1803
1804    #[test]
1805    fn add_integer_resource_effect_err() {
1806        let mut metadata = state::StateMetadata::default();
1807        let v = metadata.add_integer_resource_variable(String::from("v"), false);
1808        assert!(v.is_ok());
1809        let v = v.unwrap();
1810
1811        let mut transition = Transition::default();
1812        let result = transition.add_effect(v, 0);
1813        assert!(result.is_ok());
1814        let result = transition.add_effect(v, 0);
1815        assert!(result.is_err());
1816    }
1817
1818    #[test]
1819    fn add_continuous_effect_ok() {
1820        let mut metadata = state::StateMetadata::default();
1821        let v1 = metadata.add_continuous_variable(String::from("v1"));
1822        assert!(v1.is_ok());
1823        let v1 = v1.unwrap();
1824        let v2 = metadata.add_continuous_variable(String::from("v2"));
1825        assert!(v2.is_ok());
1826        let v2 = v2.unwrap();
1827
1828        let mut transition = Transition::default();
1829        let result = transition.add_effect(v1, 0.0);
1830        assert!(result.is_ok());
1831        assert_eq!(
1832            transition,
1833            Transition {
1834                effect: Effect {
1835                    continuous_effects: vec![(v1.id(), ContinuousExpression::Constant(0.0))],
1836                    ..Default::default()
1837                },
1838                ..Default::default()
1839            },
1840        );
1841        let result = transition.add_effect(v2, v1);
1842        assert!(result.is_ok());
1843        assert_eq!(
1844            transition,
1845            Transition {
1846                effect: Effect {
1847                    continuous_effects: vec![
1848                        (v1.id(), ContinuousExpression::Constant(0.0)),
1849                        (v2.id(), ContinuousExpression::Variable(v1.id()))
1850                    ],
1851                    ..Default::default()
1852                },
1853                ..Default::default()
1854            },
1855        );
1856    }
1857
1858    #[test]
1859    fn add_continuous_effect_err() {
1860        let mut metadata = state::StateMetadata::default();
1861        let v = metadata.add_continuous_variable(String::from("v"));
1862        assert!(v.is_ok());
1863        let v = v.unwrap();
1864
1865        let mut transition = Transition::default();
1866        let result = transition.add_effect(v, 0.0);
1867        assert!(result.is_ok());
1868        let result = transition.add_effect(v, 0.0);
1869        assert!(result.is_err());
1870    }
1871
1872    #[test]
1873    fn add_continuous_resource_effect() {
1874        let mut metadata = state::StateMetadata::default();
1875        let v1 = metadata.add_continuous_resource_variable(String::from("v1"), false);
1876        assert!(v1.is_ok());
1877        let v1 = v1.unwrap();
1878        let v2 = metadata.add_continuous_resource_variable(String::from("v2"), true);
1879        assert!(v2.is_ok());
1880        let v2 = v2.unwrap();
1881
1882        let mut transition = Transition::default();
1883        let result = transition.add_effect(v1, 0.0);
1884        assert!(result.is_ok());
1885        assert_eq!(
1886            transition,
1887            Transition {
1888                effect: Effect {
1889                    continuous_resource_effects: vec![(
1890                        v1.id(),
1891                        ContinuousExpression::Constant(0.0)
1892                    )],
1893                    ..Default::default()
1894                },
1895                ..Default::default()
1896            },
1897        );
1898        let result = transition.add_effect(v2, v1);
1899        assert!(result.is_ok());
1900        assert_eq!(
1901            transition,
1902            Transition {
1903                effect: Effect {
1904                    continuous_resource_effects: vec![
1905                        (v1.id(), ContinuousExpression::Constant(0.0)),
1906                        (v2.id(), ContinuousExpression::ResourceVariable(v1.id()))
1907                    ],
1908                    ..Default::default()
1909                },
1910                ..Default::default()
1911            },
1912        );
1913    }
1914
1915    #[test]
1916    fn add_continuous_resource_effect_err() {
1917        let mut metadata = state::StateMetadata::default();
1918        let v = metadata.add_continuous_resource_variable(String::from("v"), false);
1919        assert!(v.is_ok());
1920        let v = v.unwrap();
1921
1922        let mut transition = Transition::default();
1923        let result = transition.add_effect(v, 0.0);
1924        assert!(result.is_ok());
1925        let result = transition.add_effect(v, 0.0);
1926        assert!(result.is_err());
1927    }
1928}