dypdl/expression/
continuous_expression.rs

1use super::argument_expression::ArgumentExpression;
2use super::condition::{Condition, IfThenElse};
3use super::continuous_vector_expression::ContinuousVectorExpression;
4use super::element_expression::ElementExpression;
5use super::integer_expression::IntegerExpression;
6use super::numeric_operator::{
7    BinaryOperator, CastOperator, ContinuousBinaryOperation, ContinuousBinaryOperator,
8    ContinuousUnaryOperator, MaxMin, ReduceOperator, UnaryOperator,
9};
10use super::numeric_table_expression::NumericTableExpression;
11use super::reference_expression::ReferenceExpression;
12use super::set_expression::SetExpression;
13use super::vector_expression::VectorExpression;
14use crate::state::{
15    ContinuousResourceVariable, ContinuousVariable, IntegerResourceVariable, IntegerVariable,
16    SetVariable, StateInterface,
17};
18use crate::state_functions::{StateFunctionCache, StateFunctions};
19use crate::table_data::{Table1DHandle, Table2DHandle, Table3DHandle, TableHandle};
20use crate::table_registry::TableRegistry;
21use crate::variable_type::{Continuous, Integer};
22use std::boxed::Box;
23use std::ops;
24
25/// Continuous numeric expression.
26#[derive(Debug, PartialEq, Clone)]
27pub enum ContinuousExpression {
28    /// Constant.
29    Constant(Continuous),
30    /// Variable index.
31    Variable(usize),
32    /// Resource variable index.
33    ResourceVariable(usize),
34    /// State function index.
35    StateFunction(usize),
36    /// The cost of the transitioned state.
37    Cost,
38    /// Unary arithmetic operation.
39    UnaryOperation(UnaryOperator, Box<ContinuousExpression>),
40    /// Unary arithmetic operation specific to continuous values.
41    ContinuousUnaryOperation(ContinuousUnaryOperator, Box<ContinuousExpression>),
42    /// Rounding operation.
43    Round(CastOperator, Box<ContinuousExpression>),
44    /// Binary arithmetic operation.
45    BinaryOperation(
46        BinaryOperator,
47        Box<ContinuousExpression>,
48        Box<ContinuousExpression>,
49    ),
50    /// Binary arithmetic operation specific to continuous values.
51    ContinuousBinaryOperation(
52        ContinuousBinaryOperator,
53        Box<ContinuousExpression>,
54        Box<ContinuousExpression>,
55    ),
56    /// Cardinality of a set expression.
57    Cardinality(SetExpression),
58    /// Length of a vector expression.
59    Length(VectorExpression),
60    /// A constant in a continuous table.
61    Table(Box<NumericTableExpression<Continuous>>),
62    /// If-then-else expression, which returns the first one if the condition holds and the second one otherwise.
63    If(
64        Box<Condition>,
65        Box<ContinuousExpression>,
66        Box<ContinuousExpression>,
67    ),
68    /// Conversion from an integer expression.
69    FromInteger(Box<IntegerExpression>),
70    /// The last element of a continuosu vector expression.
71    Last(Box<ContinuousVectorExpression>),
72    /// An item of a continuosu vector expression.
73    At(Box<ContinuousVectorExpression>, ElementExpression),
74    /// Reduce operation on a continuous vector expression.
75    Reduce(ReduceOperator, Box<ContinuousVectorExpression>),
76}
77
78impl Default for ContinuousExpression {
79    /// Returns an expression representing a constant zero.
80    #[inline]
81    fn default() -> Self {
82        Self::Constant(0.0)
83    }
84}
85
86impl From<Integer> for ContinuousExpression {
87    #[inline]
88    fn from(v: Integer) -> Self {
89        Self::Constant(v as Continuous)
90    }
91}
92
93impl From<Continuous> for ContinuousExpression {
94    #[inline]
95    fn from(v: Continuous) -> Self {
96        Self::Constant(v)
97    }
98}
99
100impl From<ContinuousVariable> for ContinuousExpression {
101    #[inline]
102    fn from(v: ContinuousVariable) -> Self {
103        Self::Variable(v.id())
104    }
105}
106
107impl From<ContinuousResourceVariable> for ContinuousExpression {
108    #[inline]
109    fn from(v: ContinuousResourceVariable) -> Self {
110        Self::ResourceVariable(v.id())
111    }
112}
113
114impl From<IntegerExpression> for ContinuousExpression {
115    #[inline]
116    fn from(v: IntegerExpression) -> Self {
117        Self::FromInteger(Box::new(v))
118    }
119}
120
121impl From<IntegerVariable> for ContinuousExpression {
122    #[inline]
123    fn from(v: IntegerVariable) -> Self {
124        Self::FromInteger(Box::new(IntegerExpression::from(v)))
125    }
126}
127
128impl From<IntegerResourceVariable> for ContinuousExpression {
129    #[inline]
130    fn from(v: IntegerResourceVariable) -> Self {
131        Self::FromInteger(Box::new(IntegerExpression::from(v)))
132    }
133}
134
135impl ContinuousExpression {
136    /// Returns an expression representing the abstract value.
137    ///
138    /// # Examples
139    ///
140    /// ```
141    /// use dypdl::prelude::*;
142    /// use approx::assert_relative_eq;
143    ///
144    /// let model = Model::default();
145    /// let state = model.target.clone();
146    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
147    /// let expression = ContinuousExpression::from(-1.5);
148    /// let expression = expression.abs();
149    ///
150    /// assert_relative_eq!(
151    ///     expression.eval(
152    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
153    ///     ),
154    ///     1.5,
155    /// );
156    /// ```
157    #[inline]
158    pub fn abs(self) -> ContinuousExpression {
159        Self::UnaryOperation(UnaryOperator::Abs, Box::new(self))
160    }
161
162    /// Returns an expression representing the square root.
163    ///
164    /// # Examples
165    ///
166    /// ```
167    /// use dypdl::prelude::*;
168    /// use approx::assert_relative_eq;
169    ///
170    /// let model = Model::default();
171    /// let state = model.target.clone();
172    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
173    /// let expression = ContinuousExpression::from(4.0);
174    /// let expression = expression.sqrt();
175    ///
176    /// assert_relative_eq!(
177    ///     expression.eval(
178    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
179    ///     ),
180    ///     2.0,
181    /// );
182    /// ```
183    #[inline]
184    pub fn sqrt(self) -> ContinuousExpression {
185        Self::ContinuousUnaryOperation(ContinuousUnaryOperator::Sqrt, Box::new(self))
186    }
187
188    /// Returns an expression representing the floor.
189    ///
190    /// # Examples
191    ///
192    /// ```
193    /// use dypdl::prelude::*;
194    /// use approx::assert_relative_eq;
195    ///
196    /// let model = Model::default();
197    /// let state = model.target.clone();
198    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
199    /// let expression = ContinuousExpression::from(1.5);
200    /// let expression = expression.floor();
201    ///
202    /// assert_relative_eq!(
203    ///     expression.eval(
204    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
205    ///     ),
206    ///     1.0,
207    /// );
208    /// ```
209    #[inline]
210    pub fn floor(self) -> ContinuousExpression {
211        Self::Round(CastOperator::Floor, Box::new(self))
212    }
213
214    /// Returns an expression representing the ceiling.
215    ///
216    /// # Examples
217    ///
218    /// ```
219    /// use dypdl::prelude::*;
220    /// use approx::assert_relative_eq;
221    ///
222    /// let model = Model::default();
223    /// let state = model.target.clone();
224    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
225    /// let expression = ContinuousExpression::from(1.5);
226    /// let expression = expression.ceil();
227    ///
228    /// assert_relative_eq!(
229    ///     expression.eval(
230    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
231    ///     ),
232    ///     2.0,
233    /// );
234    /// ```
235    #[inline]
236    pub fn ceil(self) -> ContinuousExpression {
237        Self::Round(CastOperator::Ceil, Box::new(self))
238    }
239
240    /// Returns an expression representing the rounded value.
241    ///
242    /// # Examples
243    ///
244    /// ```
245    /// use dypdl::prelude::*;
246    /// use approx::assert_relative_eq;
247    ///
248    /// let model = Model::default();
249    /// let state = model.target.clone();
250    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
251    /// let expression = ContinuousExpression::from(1.5);
252    /// let expression = expression.round();
253    ///
254    /// assert_relative_eq!(
255    ///     expression.eval(
256    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
257    ///     ),
258    ///     2.0,
259    /// );
260    /// ```
261    #[inline]
262    pub fn round(self) -> ContinuousExpression {
263        Self::Round(CastOperator::Round, Box::new(self))
264    }
265
266    /// Returns an expression representing the truncated value.
267    ///
268    /// # Examples
269    ///
270    /// ```
271    /// use dypdl::prelude::*;
272    /// use approx::assert_relative_eq;
273    ///
274    /// let model = Model::default();
275    /// let state = model.target.clone();
276    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
277    /// let expression = ContinuousExpression::from(1.5);
278    /// let expression = expression.trunc();
279    ///
280    /// assert_relative_eq!(
281    ///     expression.eval(
282    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
283    ///     ),
284    ///     1.0,
285    /// );
286    /// ```
287    #[inline]
288    pub fn trunc(self) -> ContinuousExpression {
289        Self::Round(CastOperator::Trunc, Box::new(self))
290    }
291}
292
293impl ops::Neg for ContinuousExpression {
294    type Output = ContinuousExpression;
295
296    /// Returns an expression representing the negative value.
297    ///
298    /// # Examples
299    ///
300    /// ```
301    /// use dypdl::prelude::*;
302    /// use approx::assert_relative_eq;
303    ///
304    /// let model = Model::default();
305    /// let state = model.target.clone();
306    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
307    /// let expression = ContinuousExpression::from(1.5);
308    /// let expression = -expression;
309    ///
310    /// assert_relative_eq!(
311    ///     expression.eval(
312    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
313    ///     ),
314    ///     -1.5,
315    /// );
316    /// ```
317    #[inline]
318    fn neg(self) -> Self::Output {
319        Self::UnaryOperation(UnaryOperator::Neg, Box::new(self))
320    }
321}
322
323impl ops::Add for ContinuousExpression {
324    type Output = ContinuousExpression;
325
326    /// Returns an expression representing the addition.
327    ///
328    /// # Examples
329    ///
330    /// ```
331    /// use dypdl::prelude::*;
332    /// use approx::assert_relative_eq;
333    ///
334    /// let model = Model::default();
335    /// let state = model.target.clone();
336    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
337    /// let a = ContinuousExpression::from(0.2);
338    /// let b = ContinuousExpression::from(0.3);
339    /// let expression = a + b;
340    ///
341    /// assert_relative_eq!(
342    ///     expression.eval(
343    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
344    ///     ),
345    ///     0.5,
346    /// );
347    /// ```
348    #[inline]
349    fn add(self, rhs: Self) -> Self::Output {
350        ContinuousExpression::BinaryOperation(BinaryOperator::Add, Box::new(self), Box::new(rhs))
351    }
352}
353
354impl ops::Sub for ContinuousExpression {
355    type Output = ContinuousExpression;
356
357    /// Returns an expression representing the subtraction.
358    ///
359    /// # Examples
360    ///
361    /// ```
362    /// use dypdl::prelude::*;
363    /// use approx::assert_relative_eq;
364    ///
365    /// let model = Model::default();
366    /// let state = model.target.clone();
367    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
368    /// let a = ContinuousExpression::from(0.2);
369    /// let b = ContinuousExpression::from(0.3);
370    /// let expression = a - b;
371    ///
372    /// assert_relative_eq!(
373    ///     expression.eval(
374    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
375    ///     ),
376    ///     -0.1,
377    /// );
378    /// ```
379    #[inline]
380    fn sub(self, rhs: Self) -> Self::Output {
381        ContinuousExpression::BinaryOperation(BinaryOperator::Sub, Box::new(self), Box::new(rhs))
382    }
383}
384
385impl ops::Mul for ContinuousExpression {
386    type Output = ContinuousExpression;
387
388    /// Returns an expression representing the multiplication.
389    ///
390    /// # Examples
391    ///
392    /// ```
393    /// use dypdl::prelude::*;
394    /// use approx::assert_relative_eq;
395    ///
396    /// let model = Model::default();
397    /// let state = model.target.clone();
398    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
399    /// let a = ContinuousExpression::from(0.2);
400    /// let b = ContinuousExpression::from(0.3);
401    /// let expression = a * b;
402    ///
403    /// assert_relative_eq!(
404    ///     expression.eval(    
405    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
406    ///     ),
407    ///     0.06,
408    /// );
409    /// ```
410    #[inline]
411    fn mul(self, rhs: Self) -> Self::Output {
412        ContinuousExpression::BinaryOperation(BinaryOperator::Mul, Box::new(self), Box::new(rhs))
413    }
414}
415
416impl ops::Div for ContinuousExpression {
417    type Output = ContinuousExpression;
418
419    /// Returns an expression representing the division.
420    ///
421    /// # Examples
422    ///
423    /// ```
424    /// use dypdl::prelude::*;
425    /// use approx::assert_relative_eq;
426    ///
427    /// let model = Model::default();
428    /// let state = model.target.clone();
429    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
430    /// let a = ContinuousExpression::from(0.2);
431    /// let b = ContinuousExpression::from(0.3);
432    /// let expression = a / b;
433    ///
434    /// assert_relative_eq!(
435    ///     expression.eval(
436    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
437    ///     ),
438    ///     2.0 / 3.0,
439    /// );
440    /// ```
441    #[inline]
442    fn div(self, rhs: Self) -> Self::Output {
443        ContinuousExpression::BinaryOperation(BinaryOperator::Div, Box::new(self), Box::new(rhs))
444    }
445}
446
447impl ops::Rem for ContinuousExpression {
448    type Output = ContinuousExpression;
449
450    /// Returns an expression representing the remainder.
451    ///
452    /// # Examples
453    ///
454    /// ```
455    /// use dypdl::prelude::*;
456    /// use approx::assert_relative_eq;
457    ///
458    /// let model = Model::default();
459    /// let state = model.target.clone();
460    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
461    /// let a = ContinuousExpression::from(0.2);
462    /// let b = ContinuousExpression::from(0.3);
463    /// let expression = a % b;
464    ///
465    /// assert_relative_eq!(
466    ///     expression.eval(
467    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
468    ///     ),
469    ///     0.2,
470    /// );
471    /// ```
472    #[inline]
473    fn rem(self, rhs: Self) -> Self::Output {
474        ContinuousExpression::BinaryOperation(BinaryOperator::Rem, Box::new(self), Box::new(rhs))
475    }
476}
477
478impl MaxMin for ContinuousExpression {
479    type Output = ContinuousExpression;
480
481    /// Returns an expression representing the maximum.
482    ///
483    /// # Examples
484    ///
485    /// ```
486    /// use dypdl::prelude::*;
487    /// use approx::assert_relative_eq;
488    ///
489    /// let model = Model::default();
490    /// let state = model.target.clone();
491    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
492    /// let a = ContinuousExpression::from(0.2);
493    /// let b = ContinuousExpression::from(0.3);
494    /// let expression = a.max(b);
495    ///
496    /// assert_relative_eq!(
497    ///     expression.eval(
498    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry
499    ///     ),
500    ///     0.3,
501    /// );
502    /// ```
503    #[inline]
504    fn max(self, rhs: Self) -> Self::Output {
505        ContinuousExpression::BinaryOperation(BinaryOperator::Max, Box::new(self), Box::new(rhs))
506    }
507
508    /// Returns an expression representing the minimum.
509    ///
510    /// # Examples
511    ///
512    /// ```
513    /// use dypdl::prelude::*;
514    /// use approx::assert_relative_eq;
515    ///
516    /// let model = Model::default();
517    /// let state = model.target.clone();
518    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
519    /// let a = ContinuousExpression::from(0.2);
520    /// let b = ContinuousExpression::from(0.3);
521    /// let expression = a.min(b);
522    ///
523    /// assert_relative_eq!(
524    ///     expression.eval(
525    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
526    ///     ),
527    ///     0.2,
528    /// );
529    /// ```
530    #[inline]
531    fn min(self, rhs: Self) -> Self::Output {
532        ContinuousExpression::BinaryOperation(BinaryOperator::Min, Box::new(self), Box::new(rhs))
533    }
534}
535
536impl ContinuousBinaryOperation for ContinuousExpression {
537    type Output = ContinuousExpression;
538
539    /// Returns an expression representing the power.
540    ///
541    /// # Examples
542    ///
543    /// ```
544    /// use dypdl::prelude::*;
545    /// use approx::assert_relative_eq;
546    ///
547    /// let model = Model::default();
548    /// let state = model.target.clone();
549    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
550    /// let a = ContinuousExpression::from(2.0);
551    /// let b = ContinuousExpression::from(-1.0);
552    /// let expression = a.pow(b);
553    ///
554    /// assert_relative_eq!(
555    ///     expression.eval(
556    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
557    ///     ),
558    ///     0.5,
559    /// );
560    /// ```
561    #[inline]
562    fn pow(self, rhs: Self) -> Self::Output {
563        ContinuousExpression::ContinuousBinaryOperation(
564            ContinuousBinaryOperator::Pow,
565            Box::new(self),
566            Box::new(rhs),
567        )
568    }
569
570    /// Returns an expression representing the logarithm.
571    ///
572    /// # Examples
573    ///
574    /// ```
575    /// use dypdl::prelude::*;
576    /// use approx::assert_relative_eq;
577    ///
578    /// let model = Model::default();
579    /// let state = model.target.clone();
580    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
581    /// let a = ContinuousExpression::from(4.0);
582    /// let b = ContinuousExpression::from(2.0);
583    /// let expression = a.log(b);
584    ///
585    /// assert_relative_eq!(
586    ///     expression.eval(
587    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
588    ///     ),
589    ///     2.0,
590    /// );
591    /// ```
592    #[inline]
593    fn log(self, rhs: Self) -> Self::Output {
594        ContinuousExpression::ContinuousBinaryOperation(
595            ContinuousBinaryOperator::Log,
596            Box::new(self),
597            Box::new(rhs),
598        )
599    }
600}
601
602impl SetExpression {
603    /// Returns an expression representing the cardinality of a set.
604    ///
605    /// # Examples
606    ///
607    /// ```
608    /// use dypdl::prelude::*;
609    /// use approx::assert_relative_eq;
610    ///
611    /// let mut model = Model::default();
612    /// let object_type = model.add_object_type("object", 4).unwrap();
613    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
614    /// let state = model.target.clone();
615    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
616    ///
617    /// let expression = SetExpression::from(set);
618    /// let expression = expression.len_continuous();
619    ///
620    /// assert_relative_eq!(
621    ///     expression.eval(
622    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
623    ///     ),
624    ///     2.0,
625    /// );
626    /// ```
627    #[inline]
628    pub fn len_continuous(self) -> ContinuousExpression {
629        ContinuousExpression::Cardinality(self)
630    }
631}
632
633impl SetVariable {
634    /// Returns an expression representing the cardinality of a set.
635    ///
636    /// # Examples
637    ///
638    /// ```
639    /// use dypdl::prelude::*;
640    /// use approx::assert_relative_eq;
641    ///
642    /// let mut model = Model::default();
643    /// let object_type = model.add_object_type("object", 4).unwrap();
644    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
645    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
646    /// let variable = model.add_set_variable("variable", object_type, set).unwrap();
647    /// let state = model.target.clone();
648    ///
649    /// let expression = variable.len_continuous();
650    ///
651    /// assert_relative_eq!(
652    ///     expression.eval(
653    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
654    ///     ),
655    ///     2.0
656    /// );
657    /// ```
658    #[inline]
659    pub fn len_continuous(self) -> ContinuousExpression {
660        ContinuousExpression::Cardinality(SetExpression::from(self))
661    }
662}
663
664impl Table1DHandle<Continuous> {
665    /// Returns a constant in a 1D continuous table.
666    ///
667    /// # Examples
668    ///
669    /// ```
670    /// use dypdl::prelude::*;
671    /// use approx::assert_relative_eq;
672    ///
673    /// let mut model = Model::default();
674    /// let table = model.add_table_1d("table", vec![0.2, 0.3]).unwrap();
675    /// let object_type = model.add_object_type("object", 2).unwrap();
676    /// let variable = model.add_element_variable("variable", object_type, 0).unwrap();
677    /// let state = model.target.clone();
678    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
679    ///
680    /// let expression = table.element(variable);
681    /// assert_relative_eq!(
682    ///     expression.eval(
683    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
684    ///     ),
685    ///     0.2
686    /// );
687    /// ```
688    #[inline]
689    pub fn element<T>(&self, x: T) -> ContinuousExpression
690    where
691        ElementExpression: From<T>,
692    {
693        ContinuousExpression::Table(Box::new(NumericTableExpression::Table1D(
694            self.id(),
695            ElementExpression::from(x),
696        )))
697    }
698
699    /// Returns the sum of constants over a set expression in a 1D continuous table.
700    ///
701    /// ```
702    /// use dypdl::prelude::*;
703    /// use approx::assert_relative_eq;
704    ///
705    /// let mut model = Model::default();
706    /// let table = model.add_table_1d("table", vec![0.2, 0.3]).unwrap();
707    /// let object_type = model.add_object_type("object", 2).unwrap();
708    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
709    /// let variable = model.add_set_variable("variable", object_type, set).unwrap();
710    /// let state = model.target.clone();
711    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
712    ///
713    /// let expression = table.sum(variable);
714    /// assert_relative_eq!(
715    ///     expression.eval(
716    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
717    ///     ),
718    ///     0.5
719    /// );
720    /// ```
721    #[inline]
722    pub fn sum<T>(&self, x: T) -> ContinuousExpression
723    where
724        SetExpression: From<T>,
725    {
726        ContinuousExpression::Table(Box::new(NumericTableExpression::Table1DReduce(
727            ReduceOperator::Sum,
728            self.id(),
729            SetExpression::from(x),
730        )))
731    }
732
733    /// Returns the product of constants over a set expression in a 1D continuous table.
734    ///
735    /// # Examples
736    ///
737    /// ```
738    /// use dypdl::prelude::*;
739    /// use approx::assert_relative_eq;
740    ///
741    /// let mut model = Model::default();
742    /// let table = model.add_table_1d("table", vec![0.2, 0.3]).unwrap();
743    /// let object_type = model.add_object_type("object", 2).unwrap();
744    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
745    /// let variable = model.add_set_variable("variable", object_type, set).unwrap();
746    /// let state = model.target.clone();
747    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
748    ///
749    /// let expression = table.product(variable);
750    /// assert_relative_eq!(
751    ///     expression.eval(
752    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
753    ///     ),
754    ///     0.06,
755    /// );
756    /// ```
757    #[inline]
758    pub fn product<T>(&self, x: T) -> ContinuousExpression
759    where
760        SetExpression: From<T>,
761    {
762        ContinuousExpression::Table(Box::new(NumericTableExpression::Table1DReduce(
763            ReduceOperator::Product,
764            self.id(),
765            SetExpression::from(x),
766        )))
767    }
768
769    /// Returns the maximum of constants over a set expression in a 1D continuous table.
770    ///
771    /// # Examples
772    ///
773    /// ```
774    /// use dypdl::prelude::*;
775    /// use approx::assert_relative_eq;
776    ///
777    /// let mut model = Model::default();
778    /// let table = model.add_table_1d("table", vec![0.2, 0.3]).unwrap();
779    /// let object_type = model.add_object_type("object", 2).unwrap();
780    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
781    /// let variable = model.add_set_variable("variable", object_type, set).unwrap();
782    /// let state = model.target.clone();
783    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
784    ///
785    /// let expression = table.max(variable);
786    /// assert_relative_eq!(
787    ///     expression.eval(
788    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
789    ///     ),
790    ///     0.3,
791    /// );
792    /// ```
793    #[inline]
794    pub fn max<T>(&self, x: T) -> ContinuousExpression
795    where
796        SetExpression: From<T>,
797    {
798        ContinuousExpression::Table(Box::new(NumericTableExpression::Table1DReduce(
799            ReduceOperator::Max,
800            self.id(),
801            SetExpression::from(x),
802        )))
803    }
804
805    /// Returns the minimum of constants over a set expression in a 1D continuous table.
806    ///
807    /// # Examples
808    ///
809    /// ```
810    /// use dypdl::prelude::*;
811    /// use approx::assert_relative_eq;
812    ///
813    /// let mut model = Model::default();
814    /// let table = model.add_table_1d("table", vec![0.2, 0.3]).unwrap();
815    /// let object_type = model.add_object_type("object", 2).unwrap();
816    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
817    /// let variable = model.add_set_variable("variable", object_type, set).unwrap();
818    /// let state = model.target.clone();
819    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
820    ///
821    /// let expression = table.min(variable);
822    /// assert_relative_eq!(
823    ///     expression.eval(
824    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
825    ///     ),
826    ///     0.2,
827    /// );
828    /// ```
829    #[inline]
830    pub fn min<T>(&self, x: T) -> ContinuousExpression
831    where
832        SetExpression: From<T>,
833    {
834        ContinuousExpression::Table(Box::new(NumericTableExpression::Table1DReduce(
835            ReduceOperator::Min,
836            self.id(),
837            SetExpression::from(x),
838        )))
839    }
840}
841
842impl Table2DHandle<Continuous> {
843    /// Returns a constant in a 2D continuous table.
844    ///
845    /// # Examples
846    ///
847    /// ```
848    /// use dypdl::prelude::*;
849    /// use approx::assert_relative_eq;
850    ///
851    /// let mut model = Model::default();
852    /// let table = model.add_table_2d("table", vec![vec![0.2, 0.3], vec![0.4, 0.5]]).unwrap();
853    /// let object_type = model.add_object_type("object", 2).unwrap();
854    /// let variable = model.add_element_variable("variable", object_type, 0).unwrap();
855    /// let state = model.target.clone();
856    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
857    ///
858    /// let expression = table.element(variable, 1);
859    /// assert_relative_eq!(
860    ///     expression.eval(
861    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
862    ///     ),
863    ///     0.3,
864    /// );
865    /// ```
866    #[inline]
867    pub fn element<T, U>(&self, x: T, y: U) -> ContinuousExpression
868    where
869        ElementExpression: From<T>,
870        ElementExpression: From<U>,
871    {
872        ContinuousExpression::Table(Box::new(NumericTableExpression::Table2D(
873            self.id(),
874            ElementExpression::from(x),
875            ElementExpression::from(y),
876        )))
877    }
878
879    /// Returns the sum of constants over a set expression in a 2D continuous table.
880    ///
881    /// # Examples
882    ///
883    /// ```
884    /// use dypdl::prelude::*;
885    /// use approx::assert_relative_eq;
886    ///
887    /// let mut model = Model::default();
888    /// let table = model.add_table_2d("table", vec![vec![0.2, 0.3], vec![0.4, 0.5]]).unwrap();
889    /// let object_type = model.add_object_type("object", 2).unwrap();
890    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
891    /// let x = model.add_set_variable("x", object_type, set).unwrap();
892    /// let y = model.add_element_variable("y", object_type, 0).unwrap();
893    /// let state = model.target.clone();
894    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
895    ///
896    /// let expression = table.sum_x(x, y);
897    /// assert_relative_eq!(
898    ///     expression.eval(
899    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
900    ///     ),
901    ///     0.6,
902    /// );
903    /// ```
904    #[inline]
905    pub fn sum_x<T, U>(&self, x: T, y: U) -> ContinuousExpression
906    where
907        SetExpression: From<T>,
908        ElementExpression: From<U>,
909    {
910        ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduceX(
911            ReduceOperator::Sum,
912            self.id(),
913            SetExpression::from(x),
914            ElementExpression::from(y),
915        )))
916    }
917
918    /// Returns the sum of constants over a set expression in a 2D continuous table.
919    ///
920    /// # Examples
921    ///
922    /// ```
923    /// use dypdl::prelude::*;
924    /// use approx::assert_relative_eq;
925    ///
926    /// let mut model = Model::default();
927    /// let table = model.add_table_2d("table", vec![vec![0.2, 0.3], vec![0.4, 0.5]]).unwrap();
928    /// let object_type = model.add_object_type("object", 2).unwrap();
929    /// let x = model.add_element_variable("x", object_type, 0).unwrap();
930    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
931    /// let y = model.add_set_variable("y", object_type, set).unwrap();
932    /// let state = model.target.clone();
933    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
934    ///
935    /// let expression = table.sum_y(x, y);
936    /// assert_relative_eq!(    
937    ///     expression.eval(
938    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
939    ///     ),
940    ///     0.5,
941    /// );
942    /// ```
943    #[inline]
944    pub fn sum_y<T, U>(&self, x: T, y: U) -> ContinuousExpression
945    where
946        ElementExpression: From<T>,
947        SetExpression: From<U>,
948    {
949        ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduceY(
950            ReduceOperator::Sum,
951            self.id(),
952            ElementExpression::from(x),
953            SetExpression::from(y),
954        )))
955    }
956
957    /// Returns the sum of constants over two set expressions in a 2D continuous table.
958    ///
959    /// # Examples
960    ///
961    /// ```
962    /// use dypdl::prelude::*;
963    /// use approx::assert_relative_eq;
964    ///
965    /// let mut model = Model::default();
966    /// let table = model.add_table_2d("table", vec![vec![0.2, 0.3], vec![0.4, 0.5]]).unwrap();
967    /// let object_type = model.add_object_type("object", 2).unwrap();
968    /// let x = model.create_set(object_type, &[0, 1]).unwrap();
969    /// let y = model.add_set_variable("y", object_type, x.clone()).unwrap();
970    /// let state = model.target.clone();
971    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
972    ///
973    /// let expression = table.sum(x, y);
974    /// assert_relative_eq!(
975    ///     expression.eval(
976    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
977    ///     ),
978    ///     1.4,
979    /// );
980    /// ```
981    #[inline]
982    pub fn sum<T, U>(&self, x: T, y: U) -> ContinuousExpression
983    where
984        SetExpression: From<T>,
985        SetExpression: From<U>,
986    {
987        ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduce(
988            ReduceOperator::Sum,
989            self.id(),
990            SetExpression::from(x),
991            SetExpression::from(y),
992        )))
993    }
994
995    /// Returns the product of constants over a set expression in a 2D continuous table.
996    ///
997    /// # Examples
998    ///
999    /// ```
1000    /// use dypdl::prelude::*;
1001    /// use approx::assert_relative_eq;
1002    ///
1003    /// let mut model = Model::default();
1004    /// let table = model.add_table_2d("table", vec![vec![0.2, 0.3], vec![0.4, 0.5]]).unwrap();
1005    /// let object_type = model.add_object_type("object", 2).unwrap();
1006    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
1007    /// let x = model.add_set_variable("x", object_type, set).unwrap();
1008    /// let y = model.add_element_variable("y", object_type, 0).unwrap();
1009    /// let state = model.target.clone();
1010    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
1011    ///
1012    /// let expression = table.product_x(x, y);
1013    /// assert_relative_eq!(
1014    ///     expression.eval(
1015    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1016    ///     ),
1017    ///     0.08,
1018    /// );
1019    /// ```
1020    #[inline]
1021    pub fn product_x<T, U>(&self, x: T, y: U) -> ContinuousExpression
1022    where
1023        SetExpression: From<T>,
1024        ElementExpression: From<U>,
1025    {
1026        ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduceX(
1027            ReduceOperator::Product,
1028            self.id(),
1029            SetExpression::from(x),
1030            ElementExpression::from(y),
1031        )))
1032    }
1033
1034    /// Returns the product of constants over a set expression in a 2D continuous table.
1035    ///
1036    /// # Examples
1037    ///
1038    /// ```
1039    /// use dypdl::prelude::*;
1040    /// use approx::assert_relative_eq;
1041    ///
1042    /// let mut model = Model::default();
1043    /// let table = model.add_table_2d("table", vec![vec![0.2, 0.3], vec![0.4, 0.5]]).unwrap();
1044    /// let object_type = model.add_object_type("object", 2).unwrap();
1045    /// let x = model.add_element_variable("x", object_type, 0).unwrap();
1046    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
1047    /// let y = model.add_set_variable("y", object_type, set).unwrap();
1048    /// let state = model.target.clone();
1049    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
1050    ///
1051    /// let expression = table.product_y(x, y);
1052    /// assert_relative_eq!(
1053    ///     expression.eval(
1054    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1055    ///     ),
1056    ///     0.06,
1057    /// );
1058    /// ```
1059    #[inline]
1060    pub fn product_y<T, U>(&self, x: T, y: U) -> ContinuousExpression
1061    where
1062        ElementExpression: From<T>,
1063        SetExpression: From<U>,
1064    {
1065        ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduceY(
1066            ReduceOperator::Product,
1067            self.id(),
1068            ElementExpression::from(x),
1069            SetExpression::from(y),
1070        )))
1071    }
1072
1073    /// Returns the product of constants over two set expressions in a 2D continuous table.
1074    ///
1075    /// # Examples
1076    ///
1077    /// ```
1078    /// use dypdl::prelude::*;
1079    /// use approx::assert_relative_eq;
1080    ///
1081    /// let mut model = Model::default();
1082    /// let table = model.add_table_2d("table", vec![vec![0.2, 0.3], vec![0.4, 0.5]]).unwrap();
1083    /// let object_type = model.add_object_type("object", 2).unwrap();
1084    /// let x = model.create_set(object_type, &[0, 1]).unwrap();
1085    /// let y = model.add_set_variable("y", object_type, x.clone()).unwrap();
1086    /// let state = model.target.clone();
1087    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
1088    ///
1089    /// let expression = table.product(x, y);
1090    /// assert_relative_eq!(
1091    ///     expression.eval(
1092    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1093    ///     ),
1094    ///     0.012,
1095    /// );
1096    /// ```
1097    #[inline]
1098    pub fn product<T, U>(&self, x: T, y: U) -> ContinuousExpression
1099    where
1100        SetExpression: From<T>,
1101        SetExpression: From<U>,
1102    {
1103        ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduce(
1104            ReduceOperator::Product,
1105            self.id(),
1106            SetExpression::from(x),
1107            SetExpression::from(y),
1108        )))
1109    }
1110
1111    /// Returns the maximum of constants over a set expression in a 2D continuous table.
1112    ///
1113    /// # Examples
1114    ///
1115    /// ```
1116    /// use dypdl::prelude::*;
1117    /// use approx::assert_relative_eq;
1118    ///
1119    /// let mut model = Model::default();
1120    /// let table = model.add_table_2d("table", vec![vec![0.2, 0.3], vec![0.4, 0.5]]).unwrap();
1121    /// let object_type = model.add_object_type("object", 2).unwrap();
1122    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
1123    /// let x = model.add_set_variable("x", object_type, set).unwrap();
1124    /// let y = model.add_element_variable("y", object_type, 0).unwrap();
1125    /// let state = model.target.clone();
1126    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
1127    ///
1128    /// let expression = table.max_x(x, y);
1129    /// assert_relative_eq!(
1130    ///     expression.eval(
1131    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1132    ///     ),
1133    ///     0.4,
1134    /// );
1135    /// ```
1136    #[inline]
1137    pub fn max_x<T, U>(&self, x: T, y: U) -> ContinuousExpression
1138    where
1139        SetExpression: From<T>,
1140        ElementExpression: From<U>,
1141    {
1142        ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduceX(
1143            ReduceOperator::Max,
1144            self.id(),
1145            SetExpression::from(x),
1146            ElementExpression::from(y),
1147        )))
1148    }
1149
1150    /// Returns the maximum of constants over a set expression in a 2D continuous table.
1151    ///
1152    /// # Examples
1153    ///
1154    /// ```
1155    /// use dypdl::prelude::*;
1156    /// use approx::assert_relative_eq;
1157    ///
1158    /// let mut model = Model::default();
1159    /// let table = model.add_table_2d("table", vec![vec![0.2, 0.3], vec![0.4, 0.5]]).unwrap();
1160    /// let object_type = model.add_object_type("object", 2).unwrap();
1161    /// let x = model.add_element_variable("x", object_type, 0).unwrap();
1162    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
1163    /// let y = model.add_set_variable("y", object_type, set).unwrap();
1164    /// let state = model.target.clone();
1165    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
1166    ///
1167    /// let expression = table.max_y(x, y);
1168    /// assert_relative_eq!(
1169    ///     expression.eval(
1170    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1171    ///     ),
1172    ///     0.3,
1173    /// );
1174    /// ```
1175    #[inline]
1176    pub fn max_y<T, U>(&self, x: T, y: U) -> ContinuousExpression
1177    where
1178        ElementExpression: From<T>,
1179        SetExpression: From<U>,
1180    {
1181        ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduceY(
1182            ReduceOperator::Max,
1183            self.id(),
1184            ElementExpression::from(x),
1185            SetExpression::from(y),
1186        )))
1187    }
1188
1189    /// Returns the maximum of constants over two set expressions in a 2D continuous table.
1190    ///
1191    /// # Examples
1192    ///
1193    /// ```
1194    /// use dypdl::prelude::*;
1195    /// use approx::assert_relative_eq;
1196    ///
1197    /// let mut model = Model::default();
1198    /// let table = model.add_table_2d("table", vec![vec![0.2, 0.3], vec![0.4, 0.5]]).unwrap();
1199    /// let object_type = model.add_object_type("object", 2).unwrap();
1200    /// let x = model.create_set(object_type, &[0, 1]).unwrap();
1201    /// let y = model.add_set_variable("y", object_type, x.clone()).unwrap();
1202    /// let state = model.target.clone();
1203    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
1204    ///
1205    /// let expression = table.max(x, y);
1206    /// assert_relative_eq!(
1207    ///     expression.eval(
1208    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1209    ///     ),
1210    ///     0.5,
1211    /// );
1212    /// ```
1213    #[inline]
1214    pub fn max<T, U>(&self, x: T, y: U) -> ContinuousExpression
1215    where
1216        SetExpression: From<T>,
1217        SetExpression: From<U>,
1218    {
1219        ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduce(
1220            ReduceOperator::Max,
1221            self.id(),
1222            SetExpression::from(x),
1223            SetExpression::from(y),
1224        )))
1225    }
1226
1227    /// Returns the minimum of constants over a set expression in a 2D continuous table.
1228    ///
1229    /// # Examples
1230    ///
1231    /// ```
1232    /// use dypdl::prelude::*;
1233    /// use approx::assert_relative_eq;
1234    ///
1235    /// let mut model = Model::default();
1236    /// let table = model.add_table_2d("table", vec![vec![0.2, 0.3], vec![0.4, 0.5]]).unwrap();
1237    /// let object_type = model.add_object_type("object", 2).unwrap();
1238    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
1239    /// let x = model.add_set_variable("x", object_type, set).unwrap();
1240    /// let y = model.add_element_variable("y", object_type, 0).unwrap();
1241    /// let state = model.target.clone();
1242    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
1243    ///
1244    /// let expression = table.min_x(x, y);
1245    /// assert_relative_eq!(
1246    ///     expression.eval(
1247    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1248    ///     ),
1249    ///     0.2,
1250    /// );
1251    /// ```
1252    #[inline]
1253    pub fn min_x<T, U>(&self, x: T, y: U) -> ContinuousExpression
1254    where
1255        SetExpression: From<T>,
1256        ElementExpression: From<U>,
1257    {
1258        ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduceX(
1259            ReduceOperator::Min,
1260            self.id(),
1261            SetExpression::from(x),
1262            ElementExpression::from(y),
1263        )))
1264    }
1265
1266    /// Returns the minimum of constants over a set expression in a 2D continuous table.
1267    ///
1268    /// # Examples
1269    ///
1270    /// ```
1271    /// use dypdl::prelude::*;
1272    /// use approx::assert_relative_eq;
1273    ///
1274    /// let mut model = Model::default();
1275    /// let table = model.add_table_2d("table", vec![vec![0.2, 0.3], vec![0.4, 0.5]]).unwrap();
1276    /// let object_type = model.add_object_type("object", 2).unwrap();
1277    /// let x = model.add_element_variable("x", object_type, 0).unwrap();
1278    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
1279    /// let y = model.add_set_variable("y", object_type, set).unwrap();
1280    /// let state = model.target.clone();
1281    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
1282    ///
1283    /// let expression = table.min_y(x, y);
1284    /// assert_relative_eq!(
1285    ///     expression.eval(
1286    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1287    ///     ),
1288    ///     0.2,
1289    /// );
1290    /// ```
1291    #[inline]
1292    pub fn min_y<T, U>(&self, x: T, y: U) -> ContinuousExpression
1293    where
1294        ElementExpression: From<T>,
1295        SetExpression: From<U>,
1296    {
1297        ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduceY(
1298            ReduceOperator::Min,
1299            self.id(),
1300            ElementExpression::from(x),
1301            SetExpression::from(y),
1302        )))
1303    }
1304
1305    /// Returns the minimum of constants over two set expressions in a 2D continuous table.
1306    ///
1307    /// # Examples
1308    ///
1309    /// ```
1310    /// use dypdl::prelude::*;
1311    /// use approx::assert_relative_eq;
1312    ///
1313    /// let mut model = Model::default();
1314    /// let table = model.add_table_2d("table", vec![vec![0.2, 0.3], vec![0.4, 0.5]]).unwrap();
1315    /// let object_type = model.add_object_type("object", 2).unwrap();
1316    /// let x = model.create_set(object_type, &[0, 1]).unwrap();
1317    /// let y = model.add_set_variable("y", object_type, x.clone()).unwrap();
1318    /// let state = model.target.clone();
1319    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
1320    ///
1321    /// let expression = table.min(x, y);
1322    /// assert_relative_eq!(
1323    ///     expression.eval(
1324    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1325    ///     ),
1326    ///     0.2,
1327    /// );
1328    /// ```
1329    #[inline]
1330    pub fn min<T, U>(&self, x: T, y: U) -> ContinuousExpression
1331    where
1332        SetExpression: From<T>,
1333        SetExpression: From<U>,
1334    {
1335        ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduce(
1336            ReduceOperator::Min,
1337            self.id(),
1338            SetExpression::from(x),
1339            SetExpression::from(y),
1340        )))
1341    }
1342}
1343
1344impl Table3DHandle<Continuous> {
1345    /// Returns a constant in a 3D continuous table.
1346    ///
1347    /// # Examples
1348    ///
1349    /// ```
1350    /// use dypdl::prelude::*;
1351    /// use approx::assert_relative_eq;
1352    ///
1353    /// let mut model = Model::default();
1354    /// let table = model.add_table_3d(
1355    ///     "table",
1356    ///     vec![
1357    ///         vec![vec![0.2, 0.3], vec![0.4, 0.5]],
1358    ///         vec![vec![0.6, 0.7], vec![0.8, 0.9]]
1359    ///     ]
1360    /// ).unwrap();
1361    /// let object_type = model.add_object_type("object", 2).unwrap();
1362    /// let variable = model.add_element_variable("variable", object_type, 0).unwrap();
1363    /// let state = model.target.clone();
1364    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
1365    ///
1366    /// let expression = table.element(variable, variable + 1, 1);
1367    /// assert_relative_eq!(
1368    ///     expression.eval(
1369    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1370    ///     ),
1371    ///     0.5,
1372    /// );
1373    /// ```
1374    #[inline]
1375    pub fn element<T, U, V>(&self, x: T, y: U, z: V) -> ContinuousExpression
1376    where
1377        ElementExpression: From<T>,
1378        ElementExpression: From<U>,
1379        ElementExpression: From<V>,
1380    {
1381        ContinuousExpression::Table(Box::new(NumericTableExpression::Table3D(
1382            self.id(),
1383            ElementExpression::from(x),
1384            ElementExpression::from(y),
1385            ElementExpression::from(z),
1386        )))
1387    }
1388
1389    /// Returns the sum of constants over set expressions in a 3D continuous table.
1390    ///
1391    /// # Examples
1392    ///
1393    /// ```
1394    /// use dypdl::prelude::*;
1395    /// use approx::assert_relative_eq;
1396    ///
1397    /// let mut model = Model::default();
1398    /// let table = model.add_table_3d(
1399    ///     "table",
1400    ///     vec![
1401    ///         vec![vec![0.2, 0.3], vec![0.4, 0.5]],
1402    ///         vec![vec![0.6, 0.7], vec![0.8, 0.9]]
1403    ///     ]
1404    /// ).unwrap();
1405    /// let object_type = model.add_object_type("object", 2).unwrap();
1406    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
1407    /// let set_variable = model.add_set_variable("set", object_type, set.clone()).unwrap();
1408    /// let element_variable = model.add_element_variable("element", object_type, 0).unwrap();
1409    /// let state = model.target.clone();
1410    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
1411    ///
1412    /// let expression = table.sum(set_variable, element_variable, 1);
1413    /// assert_relative_eq!(
1414    ///     expression.eval(
1415    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1416    ///     ),
1417    ///     1.0,
1418    /// );
1419    ///
1420    /// let expression = table.sum(set, set_variable, set_variable);
1421    /// assert_relative_eq!(
1422    ///     expression.eval(
1423    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1424    ///     ),
1425    ///     4.4,
1426    /// );
1427    /// ```
1428    #[inline]
1429    pub fn sum<T, U, V>(&self, x: T, y: U, z: V) -> ContinuousExpression
1430    where
1431        ArgumentExpression: From<T>,
1432        ArgumentExpression: From<U>,
1433        ArgumentExpression: From<V>,
1434    {
1435        ContinuousExpression::Table(Box::new(NumericTableExpression::Table3DReduce(
1436            ReduceOperator::Sum,
1437            self.id(),
1438            ArgumentExpression::from(x),
1439            ArgumentExpression::from(y),
1440            ArgumentExpression::from(z),
1441        )))
1442    }
1443
1444    /// Returns the product of constants over set expressions in a 3D continuous table.
1445    ///
1446    /// # Examples
1447    ///
1448    /// ```
1449    /// use dypdl::prelude::*;
1450    /// use approx::assert_relative_eq;
1451    ///
1452    /// let mut model = Model::default();
1453    /// let table = model.add_table_3d(
1454    ///     "table",
1455    ///     vec![
1456    ///         vec![vec![0.2, 0.3], vec![0.4, 0.5]],
1457    ///         vec![vec![0.6, 0.7], vec![0.8, 0.9]]
1458    ///     ]
1459    /// ).unwrap();
1460    /// let object_type = model.add_object_type("object", 2).unwrap();
1461    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
1462    /// let set_variable = model.add_set_variable("set", object_type, set.clone()).unwrap();
1463    /// let element_variable = model.add_element_variable("element", object_type, 0).unwrap();
1464    /// let state = model.target.clone();
1465    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
1466    ///
1467    /// let expression = table.product(set_variable, element_variable, 1);
1468    /// assert_relative_eq!(
1469    ///     expression.eval(
1470    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1471    ///     ),
1472    ///     0.21,
1473    /// );
1474    ///
1475    /// let expression = table.product(set, set_variable, set_variable);
1476    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
1477    /// assert_relative_eq!(
1478    ///     expression.eval(
1479    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1480    ///     ),
1481    ///     0.0036288,
1482    /// );
1483    /// ```
1484    #[inline]
1485    pub fn product<T, U, V>(&self, x: T, y: U, z: V) -> ContinuousExpression
1486    where
1487        ArgumentExpression: From<T>,
1488        ArgumentExpression: From<U>,
1489        ArgumentExpression: From<V>,
1490    {
1491        ContinuousExpression::Table(Box::new(NumericTableExpression::Table3DReduce(
1492            ReduceOperator::Product,
1493            self.id(),
1494            ArgumentExpression::from(x),
1495            ArgumentExpression::from(y),
1496            ArgumentExpression::from(z),
1497        )))
1498    }
1499
1500    /// Returns the maximum of constants over set expressions in a 3D continuous table.
1501    ///
1502    /// # Examples
1503    ///
1504    /// ```
1505    /// use dypdl::prelude::*;
1506    /// use approx::assert_relative_eq;
1507    ///
1508    /// let mut model = Model::default();
1509    /// let table = model.add_table_3d(
1510    ///     "table",
1511    ///     vec![
1512    ///         vec![vec![0.2, 0.3], vec![0.4, 0.5]],
1513    ///         vec![vec![0.6, 0.7], vec![0.8, 0.9]]
1514    ///     ]
1515    /// ).unwrap();
1516    /// let object_type = model.add_object_type("object", 2).unwrap();
1517    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
1518    /// let set_variable = model.add_set_variable("set", object_type, set.clone()).unwrap();
1519    /// let element_variable = model.add_element_variable("element", object_type, 0).unwrap();
1520    /// let state = model.target.clone();
1521    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
1522    ///
1523    /// let expression = table.max(set_variable, element_variable, 1);
1524    /// assert_relative_eq!(
1525    ///     expression.eval(
1526    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1527    ///     ),
1528    ///     0.7,
1529    /// );
1530    ///
1531    /// let expression = table.max(set, set_variable, set_variable);
1532    /// assert_relative_eq!(
1533    ///     expression.eval(
1534    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1535    ///     ),
1536    ///     0.9,
1537    /// );
1538    /// ```
1539    #[inline]
1540    pub fn max<T, U, V>(&self, x: T, y: U, z: V) -> ContinuousExpression
1541    where
1542        ArgumentExpression: From<T>,
1543        ArgumentExpression: From<U>,
1544        ArgumentExpression: From<V>,
1545    {
1546        ContinuousExpression::Table(Box::new(NumericTableExpression::Table3DReduce(
1547            ReduceOperator::Max,
1548            self.id(),
1549            ArgumentExpression::from(x),
1550            ArgumentExpression::from(y),
1551            ArgumentExpression::from(z),
1552        )))
1553    }
1554
1555    /// Returns the minimum of constants over set expressions in a 3D continuous table.
1556    ///
1557    /// # Examples
1558    ///
1559    /// ```
1560    /// use dypdl::prelude::*;
1561    /// use approx::assert_relative_eq;
1562    ///
1563    /// let mut model = Model::default();
1564    /// let table = model.add_table_3d(
1565    ///     "table",
1566    ///     vec![
1567    ///         vec![vec![0.2, 0.3], vec![0.4, 0.5]],
1568    ///         vec![vec![0.6, 0.7], vec![0.8, 0.9]]
1569    ///     ]
1570    /// ).unwrap();
1571    /// let object_type = model.add_object_type("object", 2).unwrap();
1572    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
1573    /// let set_variable = model.add_set_variable("set", object_type, set.clone()).unwrap();
1574    /// let element_variable = model.add_element_variable("element", object_type, 0).unwrap();
1575    /// let state = model.target.clone();
1576    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
1577    ///
1578    /// let expression = table.min(set_variable, element_variable, 1);
1579    /// assert_relative_eq!(
1580    ///     expression.eval(
1581    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1582    ///     ),
1583    ///     0.3,
1584    /// );
1585    ///
1586    /// let expression = table.min(set, set_variable, set_variable);
1587    /// assert_relative_eq!(
1588    ///     expression.eval(
1589    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1590    ///     ),
1591    ///     0.2,
1592    /// );
1593    /// ```
1594    #[inline]
1595    pub fn min<T, U, V>(&self, x: T, y: U, z: V) -> ContinuousExpression
1596    where
1597        ArgumentExpression: From<T>,
1598        ArgumentExpression: From<U>,
1599        ArgumentExpression: From<V>,
1600    {
1601        ContinuousExpression::Table(Box::new(NumericTableExpression::Table3DReduce(
1602            ReduceOperator::Min,
1603            self.id(),
1604            ArgumentExpression::from(x),
1605            ArgumentExpression::from(y),
1606            ArgumentExpression::from(z),
1607        )))
1608    }
1609}
1610
1611impl TableHandle<Continuous> {
1612    /// Returns a constant in a continuous table.
1613    ///
1614    /// # Examples
1615    ///
1616    /// ```
1617    /// use dypdl::prelude::*;
1618    /// use rustc_hash::FxHashMap;
1619    ///
1620    /// let mut model = Model::default();
1621    /// let map = FxHashMap::from_iter(vec![(vec![0, 0, 0, 0], 0.1), (vec![1, 1, 1, 1], 0.2)]);
1622    /// let table = model.add_table("table", map, 0.0).unwrap();
1623    /// let object_type = model.add_object_type("object", 2).unwrap();
1624    /// let variable = model.add_element_variable("variable", object_type, 0).unwrap();
1625    /// let state = model.target.clone();
1626    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
1627    ///
1628    /// let indices = vec![
1629    ///     ElementExpression::from(variable),
1630    ///     ElementExpression::from(0),
1631    ///     ElementExpression::from(0),
1632    ///     ElementExpression::from(0),
1633    /// ];
1634    /// let expression = table.element(indices);
1635    /// assert_eq!(
1636    ///     expression.eval(
1637    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1638    ///     ),
1639    ///     0.1,
1640    /// );
1641    /// ```
1642    #[inline]
1643    pub fn element<T>(&self, index: Vec<T>) -> ContinuousExpression
1644    where
1645        ElementExpression: From<T>,
1646    {
1647        let indices = index.into_iter().map(ElementExpression::from).collect();
1648        ContinuousExpression::Table(Box::new(NumericTableExpression::Table(self.id(), indices)))
1649    }
1650
1651    /// Returns the sum of constants over set expressions in a continuous table.
1652    ///
1653    /// # Examples
1654    ///
1655    /// ```
1656    /// use dypdl::prelude::*;
1657    /// use dypdl::expression::*;
1658    /// use rustc_hash::FxHashMap;
1659    ///
1660    /// let mut model = Model::default();
1661    /// let map = FxHashMap::from_iter(vec![(vec![0, 0, 0, 0], 0.1), (vec![1, 1, 1, 1], 0.2)]);
1662    /// let table = model.add_table("table", map, 0.0).unwrap();
1663    /// let object_type = model.add_object_type("object", 2).unwrap();
1664    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
1665    /// let set_variable = model.add_set_variable("set", object_type, set.clone()).unwrap();
1666    /// let element_variable = model.add_element_variable("element", object_type, 0).unwrap();
1667    /// let state = model.target.clone();
1668    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
1669    ///
1670    /// let indices = vec![
1671    ///     ArgumentExpression::from(set),
1672    ///     ArgumentExpression::from(set_variable),
1673    ///     ArgumentExpression::from(element_variable),
1674    ///     ArgumentExpression::from(0),
1675    /// ];
1676    /// let expression = table.sum(indices);
1677    /// assert_eq!(
1678    ///     expression.eval(
1679    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry
1680    ///     ),
1681    ///     0.1,
1682    /// );
1683    /// ```
1684    #[inline]
1685    pub fn sum<T>(&self, index: Vec<T>) -> ContinuousExpression
1686    where
1687        ArgumentExpression: From<T>,
1688    {
1689        let indices = index.into_iter().map(ArgumentExpression::from).collect();
1690        ContinuousExpression::Table(Box::new(NumericTableExpression::TableReduce(
1691            ReduceOperator::Sum,
1692            self.id(),
1693            indices,
1694        )))
1695    }
1696
1697    /// Returns the product of constants over set expressions in a continuous table.
1698    ///
1699    /// # Examples
1700    ///
1701    /// ```
1702    /// use dypdl::prelude::*;
1703    /// use dypdl::expression::*;
1704    /// use rustc_hash::FxHashMap;
1705    ///
1706    /// let mut model = Model::default();
1707    /// let map = FxHashMap::from_iter(vec![(vec![0, 0, 0, 0], 0.1), (vec![1, 1, 1, 1], 0.2)]);
1708    /// let table = model.add_table("table", map, 0.0).unwrap();
1709    /// let object_type = model.add_object_type("object", 2).unwrap();
1710    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
1711    /// let set_variable = model.add_set_variable("set", object_type, set.clone()).unwrap();
1712    /// let element_variable = model.add_element_variable("element", object_type, 0).unwrap();
1713    /// let state = model.target.clone();
1714    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
1715    ///
1716    /// let indices = vec![
1717    ///     ArgumentExpression::from(set),
1718    ///     ArgumentExpression::from(set_variable),
1719    ///     ArgumentExpression::from(element_variable),
1720    ///     ArgumentExpression::from(0),
1721    /// ];
1722    /// let expression = table.product(indices);
1723    /// assert_eq!(
1724    ///     expression.eval(
1725    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1726    ///     ),
1727    ///     0.0,
1728    /// );
1729    /// ```
1730    #[inline]
1731    pub fn product<T>(&self, index: Vec<T>) -> ContinuousExpression
1732    where
1733        ArgumentExpression: From<T>,
1734    {
1735        let indices = index.into_iter().map(ArgumentExpression::from).collect();
1736        ContinuousExpression::Table(Box::new(NumericTableExpression::TableReduce(
1737            ReduceOperator::Product,
1738            self.id(),
1739            indices,
1740        )))
1741    }
1742
1743    /// Returns the maximum of constants over set expressions in a continuous table.
1744    ///
1745    /// # Examples
1746    ///
1747    /// ```
1748    /// use dypdl::prelude::*;
1749    /// use dypdl::expression::*;
1750    /// use rustc_hash::FxHashMap;
1751    ///
1752    /// let mut model = Model::default();
1753    /// let map = FxHashMap::from_iter(vec![(vec![0, 0, 0, 0], 0.1), (vec![1, 1, 1, 1], 0.2)]);
1754    /// let table = model.add_table("table", map, 0.0).unwrap();
1755    /// let object_type = model.add_object_type("object", 2).unwrap();
1756    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
1757    /// let set_variable = model.add_set_variable("set", object_type, set.clone()).unwrap();
1758    /// let element_variable = model.add_element_variable("element", object_type, 0).unwrap();
1759    /// let state = model.target.clone();
1760    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
1761    ///
1762    /// let indices = vec![
1763    ///     ArgumentExpression::from(set),
1764    ///     ArgumentExpression::from(set_variable),
1765    ///     ArgumentExpression::from(element_variable),
1766    ///     ArgumentExpression::from(0),
1767    /// ];
1768    /// let expression = table.max(indices);
1769    /// assert_eq!(
1770    ///     expression.eval(
1771    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1772    ///     ),
1773    ///     0.1,
1774    /// );
1775    /// ```
1776    #[inline]
1777    pub fn max<T>(&self, index: Vec<T>) -> ContinuousExpression
1778    where
1779        ArgumentExpression: From<T>,
1780    {
1781        let indices = index.into_iter().map(ArgumentExpression::from).collect();
1782        ContinuousExpression::Table(Box::new(NumericTableExpression::TableReduce(
1783            ReduceOperator::Max,
1784            self.id(),
1785            indices,
1786        )))
1787    }
1788
1789    /// Returns the minimum of constants over set expressions in a continuous table.
1790    ///
1791    /// # Examples
1792    ///
1793    /// ```
1794    /// use dypdl::prelude::*;
1795    /// use dypdl::expression::*;
1796    /// use rustc_hash::FxHashMap;
1797    ///
1798    /// let mut model = Model::default();
1799    /// let map = FxHashMap::from_iter(vec![(vec![0, 0, 0, 0], 0.1), (vec![1, 1, 1, 1], 0.2)]);
1800    /// let table = model.add_table("table", map, 0.0).unwrap();
1801    /// let object_type = model.add_object_type("object", 2).unwrap();
1802    /// let set = model.create_set(object_type, &[0, 1]).unwrap();
1803    /// let set_variable = model.add_set_variable("set", object_type, set.clone()).unwrap();
1804    /// let element_variable = model.add_element_variable("element", object_type, 0).unwrap();
1805    /// let state = model.target.clone();
1806    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
1807    ///
1808    /// let indices = vec![
1809    ///     ArgumentExpression::from(set),
1810    ///     ArgumentExpression::from(set_variable),
1811    ///     ArgumentExpression::from(element_variable),
1812    ///     ArgumentExpression::from(0),
1813    /// ];
1814    /// let expression = table.min(indices);
1815    /// assert_eq!(
1816    ///     expression.eval(
1817    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
1818    ///     ),
1819    ///     0.0,
1820    /// );
1821    /// ```
1822    #[inline]
1823    pub fn min<T>(&self, index: Vec<T>) -> ContinuousExpression
1824    where
1825        ArgumentExpression: From<T>,
1826    {
1827        let indices = index.into_iter().map(ArgumentExpression::from).collect();
1828        ContinuousExpression::Table(Box::new(NumericTableExpression::TableReduce(
1829            ReduceOperator::Min,
1830            self.id(),
1831            indices,
1832        )))
1833    }
1834}
1835
1836impl IfThenElse<ContinuousExpression> for Condition {
1837    #[inline]
1838    fn if_then_else<U, V>(self, lhs: U, rhs: V) -> ContinuousExpression
1839    where
1840        ContinuousExpression: From<U> + From<V>,
1841    {
1842        ContinuousExpression::If(
1843            Box::new(self),
1844            Box::new(ContinuousExpression::from(lhs)),
1845            Box::new(ContinuousExpression::from(rhs)),
1846        )
1847    }
1848}
1849
1850macro_rules! impl_unary_ops {
1851    ($T:ty) => {
1852        impl $T {
1853            /// Returns an expression representing the absolute value
1854            #[inline]
1855            pub fn abs(self) -> ContinuousExpression {
1856                ContinuousExpression::from(self).abs()
1857            }
1858
1859            /// Returns an expression representing the square root.
1860            #[inline]
1861            pub fn sqrt(self) -> ContinuousExpression {
1862                ContinuousExpression::from(self).sqrt()
1863            }
1864
1865            /// Returns an expression representing the floor.
1866            #[inline]
1867            pub fn floor(self) -> ContinuousExpression {
1868                ContinuousExpression::from(self).floor()
1869            }
1870
1871            /// Returns an expression representing the ceiling.
1872            #[inline]
1873            pub fn ceil(self) -> ContinuousExpression {
1874                ContinuousExpression::from(self).ceil()
1875            }
1876
1877            /// Returns an expression representing the rounded value.
1878            #[inline]
1879            pub fn round(self) -> ContinuousExpression {
1880                ContinuousExpression::from(self).round()
1881            }
1882
1883            /// Returns an expression representing the truncated value.
1884            #[inline]
1885            pub fn trunc(self) -> ContinuousExpression {
1886                ContinuousExpression::from(self).trunc()
1887            }
1888        }
1889
1890        impl ops::Neg for $T {
1891            type Output = ContinuousExpression;
1892
1893            /// Returns an expression representing the negative value.
1894            #[inline]
1895            fn neg(self) -> Self::Output {
1896                -ContinuousExpression::from(self)
1897            }
1898        }
1899    };
1900}
1901
1902macro_rules! impl_binary_ops {
1903    ($T:ty,$U:ty) => {
1904        impl ops::Add<$U> for $T {
1905            type Output = ContinuousExpression;
1906
1907            /// Returns an expression representing the addition.
1908            #[inline]
1909            fn add(self, rhs: $U) -> ContinuousExpression {
1910                ContinuousExpression::from(self) + ContinuousExpression::from(rhs)
1911            }
1912        }
1913
1914        impl ops::Sub<$U> for $T {
1915            type Output = ContinuousExpression;
1916
1917            /// Returns an expression representing the subtraction.
1918            #[inline]
1919            fn sub(self, rhs: $U) -> ContinuousExpression {
1920                ContinuousExpression::from(self) - ContinuousExpression::from(rhs)
1921            }
1922        }
1923
1924        impl ops::Mul<$U> for $T {
1925            type Output = ContinuousExpression;
1926
1927            /// Returns an expression representing the multiplication.
1928            #[inline]
1929            fn mul(self, rhs: $U) -> ContinuousExpression {
1930                ContinuousExpression::from(self) * ContinuousExpression::from(rhs)
1931            }
1932        }
1933
1934        impl ops::Div<$U> for $T {
1935            type Output = ContinuousExpression;
1936
1937            /// Returns an expression representing the division.
1938            #[inline]
1939            fn div(self, rhs: $U) -> ContinuousExpression {
1940                ContinuousExpression::from(self) / ContinuousExpression::from(rhs)
1941            }
1942        }
1943
1944        impl ops::Rem<$U> for $T {
1945            type Output = ContinuousExpression;
1946
1947            /// Returns an expression representing the remainder.
1948            #[inline]
1949            fn rem(self, rhs: $U) -> ContinuousExpression {
1950                ContinuousExpression::from(self) % ContinuousExpression::from(rhs)
1951            }
1952        }
1953
1954        impl MaxMin<$U> for $T {
1955            type Output = ContinuousExpression;
1956
1957            #[inline]
1958            fn max(self, rhs: $U) -> ContinuousExpression {
1959                ContinuousExpression::from(self).max(ContinuousExpression::from(rhs))
1960            }
1961
1962            #[inline]
1963            fn min(self, rhs: $U) -> ContinuousExpression {
1964                ContinuousExpression::from(self).min(ContinuousExpression::from(rhs))
1965            }
1966        }
1967
1968        impl ContinuousBinaryOperation<$U> for $T {
1969            type Output = ContinuousExpression;
1970
1971            #[inline]
1972            fn pow(self, rhs: $U) -> ContinuousExpression {
1973                ContinuousExpression::from(self).pow(ContinuousExpression::from(rhs))
1974            }
1975
1976            #[inline]
1977            fn log(self, rhs: $U) -> ContinuousExpression {
1978                ContinuousExpression::from(self).log(ContinuousExpression::from(rhs))
1979            }
1980        }
1981    };
1982}
1983
1984impl_binary_ops!(ContinuousExpression, Continuous);
1985impl_binary_ops!(ContinuousExpression, ContinuousVariable);
1986impl_binary_ops!(ContinuousExpression, ContinuousResourceVariable);
1987impl_binary_ops!(ContinuousExpression, IntegerExpression);
1988impl_binary_ops!(ContinuousExpression, Integer);
1989impl_binary_ops!(ContinuousExpression, IntegerVariable);
1990impl_binary_ops!(ContinuousExpression, IntegerResourceVariable);
1991impl_binary_ops!(Continuous, ContinuousExpression);
1992impl_binary_ops!(Continuous, ContinuousVariable);
1993impl_binary_ops!(Continuous, ContinuousResourceVariable);
1994impl_binary_ops!(Continuous, IntegerExpression);
1995impl_binary_ops!(Continuous, IntegerVariable);
1996impl_binary_ops!(Continuous, IntegerResourceVariable);
1997impl_unary_ops!(ContinuousVariable);
1998impl_binary_ops!(ContinuousVariable, ContinuousExpression);
1999impl_binary_ops!(ContinuousVariable, Continuous);
2000impl_binary_ops!(ContinuousVariable, ContinuousVariable);
2001impl_binary_ops!(ContinuousVariable, ContinuousResourceVariable);
2002impl_binary_ops!(ContinuousVariable, IntegerExpression);
2003impl_binary_ops!(ContinuousVariable, IntegerVariable);
2004impl_binary_ops!(ContinuousVariable, IntegerResourceVariable);
2005impl_binary_ops!(ContinuousVariable, Integer);
2006impl_unary_ops!(ContinuousResourceVariable);
2007impl_binary_ops!(ContinuousResourceVariable, ContinuousExpression);
2008impl_binary_ops!(ContinuousResourceVariable, Continuous);
2009impl_binary_ops!(ContinuousResourceVariable, ContinuousVariable);
2010impl_binary_ops!(ContinuousResourceVariable, ContinuousResourceVariable);
2011impl_binary_ops!(ContinuousResourceVariable, IntegerExpression);
2012impl_binary_ops!(ContinuousResourceVariable, IntegerVariable);
2013impl_binary_ops!(ContinuousResourceVariable, IntegerResourceVariable);
2014impl_binary_ops!(ContinuousResourceVariable, Integer);
2015impl_binary_ops!(IntegerExpression, ContinuousExpression);
2016impl_binary_ops!(IntegerExpression, Continuous);
2017impl_binary_ops!(IntegerExpression, ContinuousVariable);
2018impl_binary_ops!(IntegerExpression, ContinuousResourceVariable);
2019impl_binary_ops!(IntegerVariable, ContinuousExpression);
2020impl_binary_ops!(IntegerVariable, Continuous);
2021impl_binary_ops!(IntegerVariable, ContinuousVariable);
2022impl_binary_ops!(IntegerVariable, ContinuousResourceVariable);
2023impl_binary_ops!(IntegerResourceVariable, ContinuousExpression);
2024impl_binary_ops!(IntegerResourceVariable, Continuous);
2025impl_binary_ops!(IntegerResourceVariable, ContinuousVariable);
2026impl_binary_ops!(IntegerResourceVariable, ContinuousResourceVariable);
2027impl_binary_ops!(Integer, ContinuousExpression);
2028impl_binary_ops!(Integer, ContinuousVariable);
2029impl_binary_ops!(Integer, ContinuousResourceVariable);
2030
2031impl ContinuousExpression {
2032    /// Returns the evaluation result.
2033    ///
2034    /// # Panics
2035    ///
2036    /// Panics if the cost of the transition state is used or a min/max reduce operation is performed on an empty set or vector.
2037    ///
2038    /// # Examples
2039    ///
2040    /// ```
2041    /// use dypdl::prelude::*;
2042    /// use approx::assert_relative_eq;
2043    ///
2044    /// let mut model = Model::default();
2045    /// let variable = model.add_continuous_variable("variable", 0.1).unwrap();
2046    /// let state = model.target.clone();
2047    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
2048    ///
2049    /// let expression = ContinuousExpression::from(variable);
2050    /// assert_relative_eq!(
2051    ///     expression.eval(
2052    ///         &state, &mut function_cache, &model.state_functions, &model.table_registry,
2053    ///     ),
2054    ///     0.1,
2055    /// );
2056    /// ```
2057    #[inline]
2058    pub fn eval<U: StateInterface>(
2059        &self,
2060        state: &U,
2061        function_cache: &mut StateFunctionCache,
2062        state_functions: &StateFunctions,
2063        registry: &TableRegistry,
2064    ) -> Continuous {
2065        self.eval_inner(None, state, function_cache, state_functions, registry)
2066    }
2067
2068    /// Returns the evaluation result of a cost expression.
2069    ///
2070    /// # Panics
2071    ///
2072    /// Panics if a min/max reduce operation is performed on an empty set or vector.
2073    ///
2074    /// # Examples
2075    ///
2076    /// ```
2077    /// use dypdl::prelude::*;
2078    /// use approx::assert_relative_eq;
2079    ///
2080    /// let model = Model::default();
2081    /// let state = model.target.clone();
2082    /// let mut function_cache = StateFunctionCache::new(&model.state_functions);
2083    ///
2084    /// let expression = ContinuousExpression::Cost + 0.1;
2085    /// assert_relative_eq!(
2086    ///     expression.eval_cost(
2087    ///         0.1,
2088    ///         &state,
2089    ///         &mut function_cache,
2090    ///         &model.state_functions,
2091    ///         &model.table_registry,
2092    ///     ),
2093    ///     0.2,
2094    /// );
2095    /// ```
2096    #[inline]
2097    pub fn eval_cost<U: StateInterface>(
2098        &self,
2099        cost: Continuous,
2100        state: &U,
2101        function_cache: &mut StateFunctionCache,
2102        state_functions: &StateFunctions,
2103        registry: &TableRegistry,
2104    ) -> Continuous {
2105        self.eval_inner(Some(cost), state, function_cache, state_functions, registry)
2106    }
2107
2108    fn eval_inner<U: StateInterface>(
2109        &self,
2110        cost: Option<Continuous>,
2111        state: &U,
2112        function_cache: &mut StateFunctionCache,
2113        state_functions: &StateFunctions,
2114        registry: &TableRegistry,
2115    ) -> Continuous {
2116        match self {
2117            Self::Constant(x) => *x,
2118            Self::Variable(i) => state.get_continuous_variable(*i),
2119            Self::ResourceVariable(i) => state.get_continuous_resource_variable(*i),
2120            Self::StateFunction(i) => {
2121                function_cache.get_continuous_value(*i, state, state_functions, registry)
2122            }
2123            Self::Cost => cost.unwrap(),
2124            Self::UnaryOperation(op, x) => {
2125                op.eval(x.eval_inner(cost, state, function_cache, state_functions, registry))
2126            }
2127            Self::ContinuousUnaryOperation(op, x) => {
2128                op.eval(x.eval_inner(cost, state, function_cache, state_functions, registry))
2129            }
2130            Self::Round(op, x) => {
2131                op.eval(x.eval_inner(cost, state, function_cache, state_functions, registry))
2132            }
2133            Self::BinaryOperation(op, a, b) => {
2134                let a = a.eval_inner(cost, state, function_cache, state_functions, registry);
2135                let b = b.eval_inner(cost, state, function_cache, state_functions, registry);
2136                op.eval(a, b)
2137            }
2138            Self::ContinuousBinaryOperation(op, a, b) => {
2139                let a = a.eval_inner(cost, state, function_cache, state_functions, registry);
2140                let b = b.eval_inner(cost, state, function_cache, state_functions, registry);
2141                op.eval(a, b)
2142            }
2143            Self::Cardinality(SetExpression::Reference(expression)) => {
2144                let set = expression.eval(state, function_cache, state_functions, registry);
2145                set.count_ones(..) as Continuous
2146            }
2147            Self::Cardinality(SetExpression::StateFunction(i)) => {
2148                let set = function_cache.get_set_value(*i, state, state_functions, registry);
2149                set.count_ones(..) as Continuous
2150            }
2151            Self::Cardinality(set) => set
2152                .eval(state, function_cache, state_functions, registry)
2153                .count_ones(..) as Continuous,
2154            Self::Table(t) => t.eval(
2155                state,
2156                function_cache,
2157                state_functions,
2158                registry,
2159                &registry.continuous_tables,
2160            ),
2161            Self::If(condition, x, y) => {
2162                if condition.eval(state, function_cache, state_functions, registry) {
2163                    x.eval_inner(cost, state, function_cache, state_functions, registry)
2164                } else {
2165                    y.eval_inner(cost, state, function_cache, state_functions, registry)
2166                }
2167            }
2168            Self::FromInteger(x) => Continuous::from(if let Some(cost) = cost {
2169                x.eval_cost(
2170                    cost as Integer,
2171                    state,
2172                    function_cache,
2173                    state_functions,
2174                    registry,
2175                )
2176            } else {
2177                x.eval(state, function_cache, state_functions, registry)
2178            }),
2179            Self::Length(VectorExpression::Reference(expression)) => {
2180                let vector = expression.eval(state, function_cache, state_functions, registry);
2181                vector.len() as Continuous
2182            }
2183            Self::Length(vector) => vector
2184                .eval(state, function_cache, state_functions, registry)
2185                .len() as Continuous,
2186            Self::Last(vector) => match vector.as_ref() {
2187                ContinuousVectorExpression::Constant(vector) => *vector.last().unwrap(),
2188                vector => *vector
2189                    .eval_inner(cost, state, function_cache, state_functions, registry)
2190                    .last()
2191                    .unwrap(),
2192            },
2193            Self::At(vector, i) => match vector.as_ref() {
2194                ContinuousVectorExpression::Constant(vector) => {
2195                    vector[i.eval(state, function_cache, state_functions, registry)]
2196                }
2197                vector => vector.eval_inner(cost, state, function_cache, state_functions, registry)
2198                    [i.eval(state, function_cache, state_functions, registry)],
2199            },
2200            Self::Reduce(op, vector) => match vector.as_ref() {
2201                ContinuousVectorExpression::Constant(vector) => op.eval(vector),
2202                vector => op.eval(&vector.eval_inner(
2203                    cost,
2204                    state,
2205                    function_cache,
2206                    state_functions,
2207                    registry,
2208                )),
2209            },
2210        }
2211    }
2212
2213    /// Returns a simplified version by precomputation.
2214    ///
2215    /// # Panics
2216    ///
2217    /// Panics if a min/max reduce operation is performed on an empty set or vector.
2218    pub fn simplify(&self, registry: &TableRegistry) -> ContinuousExpression {
2219        match self {
2220            Self::UnaryOperation(op, x) => match x.simplify(registry) {
2221                Self::Constant(x) => Self::Constant(op.eval(x)),
2222                x => Self::UnaryOperation(op.clone(), Box::new(x)),
2223            },
2224            Self::ContinuousUnaryOperation(op, x) => match x.simplify(registry) {
2225                Self::Constant(x) => Self::Constant(op.eval(x)),
2226                x => Self::ContinuousUnaryOperation(op.clone(), Box::new(x)),
2227            },
2228            Self::Round(op, x) => match x.simplify(registry) {
2229                Self::Constant(x) => Self::Constant(op.eval(x)),
2230                x => Self::Round(op.clone(), Box::new(x)),
2231            },
2232            Self::BinaryOperation(op, a, b) => match (a.simplify(registry), b.simplify(registry)) {
2233                (Self::Constant(a), Self::Constant(b)) => Self::Constant(op.eval(a, b)),
2234                (a, b) => Self::BinaryOperation(op.clone(), Box::new(a), Box::new(b)),
2235            },
2236            Self::ContinuousBinaryOperation(op, a, b) => {
2237                match (a.simplify(registry), b.simplify(registry)) {
2238                    (Self::Constant(a), Self::Constant(b)) => Self::Constant(op.eval(a, b)),
2239                    (a, b) => Self::ContinuousBinaryOperation(op.clone(), Box::new(a), Box::new(b)),
2240                }
2241            }
2242            Self::Cardinality(expression) => match expression.simplify(registry) {
2243                SetExpression::Reference(ReferenceExpression::Constant(set)) => {
2244                    Self::Constant(set.count_ones(..) as Continuous)
2245                }
2246                expression => Self::Cardinality(expression),
2247            },
2248            Self::Length(expression) => match expression.simplify(registry) {
2249                VectorExpression::Reference(ReferenceExpression::Constant(vector)) => {
2250                    Self::Constant(vector.len() as Continuous)
2251                }
2252                expression => Self::Length(expression),
2253            },
2254            Self::Table(expression) => {
2255                match expression.simplify(registry, &registry.continuous_tables) {
2256                    NumericTableExpression::Constant(value) => Self::Constant(value),
2257                    expression => Self::Table(Box::new(expression)),
2258                }
2259            }
2260            Self::If(condition, x, y) => match condition.simplify(registry) {
2261                Condition::Constant(true) => x.simplify(registry),
2262                Condition::Constant(false) => y.simplify(registry),
2263                condition => Self::If(
2264                    Box::new(condition),
2265                    Box::new(x.simplify(registry)),
2266                    Box::new(y.simplify(registry)),
2267                ),
2268            },
2269            Self::FromInteger(x) => match x.simplify(registry) {
2270                IntegerExpression::Constant(x) => Self::Constant(x as Continuous),
2271                x => Self::FromInteger(Box::new(x)),
2272            },
2273            Self::Last(vector) => match vector.simplify(registry) {
2274                ContinuousVectorExpression::Constant(vector) => {
2275                    Self::Constant(*vector.last().unwrap())
2276                }
2277                vector => Self::Last(Box::new(vector)),
2278            },
2279            Self::At(vector, i) => match (vector.simplify(registry), i.simplify(registry)) {
2280                (ContinuousVectorExpression::Constant(vector), ElementExpression::Constant(i)) => {
2281                    Self::Constant(vector[i])
2282                }
2283                (vector, i) => Self::At(Box::new(vector), i),
2284            },
2285            Self::Reduce(op, vector) => match vector.simplify(registry) {
2286                ContinuousVectorExpression::Constant(vector) => Self::Constant(op.eval(&vector)),
2287                vector => Self::Reduce(op.clone(), Box::new(vector)),
2288            },
2289            _ => self.clone(),
2290        }
2291    }
2292}
2293
2294#[cfg(test)]
2295mod tests {
2296    use super::super::table_expression::TableExpression;
2297    use super::super::table_vector_expression::TableVectorExpression;
2298    use super::*;
2299    use crate::state::*;
2300    use crate::table_data::TableInterface;
2301    use crate::variable_type::*;
2302    use approx::assert_relative_eq;
2303    use rustc_hash::FxHashMap;
2304
2305    #[test]
2306    fn default() {
2307        assert_eq!(
2308            ContinuousExpression::default(),
2309            ContinuousExpression::Constant(0.0)
2310        );
2311    }
2312
2313    #[test]
2314    fn from() {
2315        assert_eq!(
2316            ContinuousExpression::from(1),
2317            ContinuousExpression::Constant(1.0)
2318        );
2319
2320        assert_eq!(
2321            ContinuousExpression::from(1.0),
2322            ContinuousExpression::Constant(1.0)
2323        );
2324
2325        let mut metadata = StateMetadata::default();
2326
2327        let v = metadata.add_continuous_variable(String::from("cv"));
2328        assert!(v.is_ok());
2329        let v = v.unwrap();
2330        assert_eq!(
2331            ContinuousExpression::from(v),
2332            ContinuousExpression::Variable(v.id())
2333        );
2334
2335        let v = metadata.add_continuous_resource_variable(String::from("crv"), true);
2336        assert!(v.is_ok());
2337        let v = v.unwrap();
2338        assert_eq!(
2339            ContinuousExpression::from(v),
2340            ContinuousExpression::ResourceVariable(v.id())
2341        );
2342
2343        assert_eq!(
2344            ContinuousExpression::from(IntegerExpression::Constant(1)),
2345            ContinuousExpression::FromInteger(Box::new(IntegerExpression::Constant(1)))
2346        );
2347
2348        let v = metadata.add_integer_variable(String::from("iv"));
2349        assert!(v.is_ok());
2350        let v = v.unwrap();
2351        assert_eq!(
2352            ContinuousExpression::from(v),
2353            ContinuousExpression::FromInteger(Box::new(IntegerExpression::Variable(v.id())))
2354        );
2355
2356        let v = metadata.add_integer_resource_variable(String::from("irv"), true);
2357        assert!(v.is_ok());
2358        let v = v.unwrap();
2359        assert_eq!(
2360            ContinuousExpression::from(v),
2361            ContinuousExpression::FromInteger(Box::new(IntegerExpression::ResourceVariable(
2362                v.id()
2363            )))
2364        );
2365    }
2366
2367    #[test]
2368    fn abs() {
2369        let expression = ContinuousExpression::Constant(1.0);
2370        assert_eq!(
2371            expression.abs(),
2372            ContinuousExpression::UnaryOperation(
2373                UnaryOperator::Abs,
2374                Box::new(ContinuousExpression::Constant(1.0))
2375            )
2376        );
2377
2378        let mut metadata = StateMetadata::default();
2379
2380        let v = metadata.add_continuous_variable(String::from("iv"));
2381        assert!(v.is_ok());
2382        let v = v.unwrap();
2383        assert_eq!(
2384            v.abs(),
2385            ContinuousExpression::UnaryOperation(
2386                UnaryOperator::Abs,
2387                Box::new(ContinuousExpression::Variable(0))
2388            )
2389        );
2390
2391        let v = metadata.add_continuous_resource_variable(String::from("irv"), true);
2392        assert!(v.is_ok());
2393        let v = v.unwrap();
2394        assert_eq!(
2395            v.abs(),
2396            ContinuousExpression::UnaryOperation(
2397                UnaryOperator::Abs,
2398                Box::new(ContinuousExpression::ResourceVariable(0))
2399            )
2400        );
2401    }
2402
2403    #[test]
2404    fn sqrt() {
2405        let expression = ContinuousExpression::Constant(1.0);
2406        assert_eq!(
2407            expression.sqrt(),
2408            ContinuousExpression::ContinuousUnaryOperation(
2409                ContinuousUnaryOperator::Sqrt,
2410                Box::new(ContinuousExpression::Constant(1.0))
2411            )
2412        );
2413
2414        let mut metadata = StateMetadata::default();
2415
2416        let v = metadata.add_continuous_variable(String::from("iv"));
2417        assert!(v.is_ok());
2418        let v = v.unwrap();
2419        assert_eq!(
2420            v.sqrt(),
2421            ContinuousExpression::ContinuousUnaryOperation(
2422                ContinuousUnaryOperator::Sqrt,
2423                Box::new(ContinuousExpression::Variable(0))
2424            )
2425        );
2426
2427        let v = metadata.add_continuous_resource_variable(String::from("irv"), true);
2428        assert!(v.is_ok());
2429        let v = v.unwrap();
2430        assert_eq!(
2431            v.sqrt(),
2432            ContinuousExpression::ContinuousUnaryOperation(
2433                ContinuousUnaryOperator::Sqrt,
2434                Box::new(ContinuousExpression::ResourceVariable(0))
2435            )
2436        );
2437    }
2438
2439    #[test]
2440    fn floor() {
2441        let expression = ContinuousExpression::Constant(1.0);
2442        assert_eq!(
2443            expression.floor(),
2444            ContinuousExpression::Round(
2445                CastOperator::Floor,
2446                Box::new(ContinuousExpression::Constant(1.0))
2447            )
2448        );
2449
2450        let mut metadata = StateMetadata::default();
2451
2452        let v = metadata.add_continuous_variable(String::from("iv"));
2453        assert!(v.is_ok());
2454        let v = v.unwrap();
2455        assert_eq!(
2456            v.floor(),
2457            ContinuousExpression::Round(
2458                CastOperator::Floor,
2459                Box::new(ContinuousExpression::Variable(0))
2460            )
2461        );
2462
2463        let v = metadata.add_continuous_resource_variable(String::from("irv"), true);
2464        assert!(v.is_ok());
2465        let v = v.unwrap();
2466        assert_eq!(
2467            v.floor(),
2468            ContinuousExpression::Round(
2469                CastOperator::Floor,
2470                Box::new(ContinuousExpression::ResourceVariable(0))
2471            )
2472        );
2473    }
2474
2475    #[test]
2476    fn ceil() {
2477        let expression = ContinuousExpression::Constant(1.0);
2478        assert_eq!(
2479            expression.ceil(),
2480            ContinuousExpression::Round(
2481                CastOperator::Ceil,
2482                Box::new(ContinuousExpression::Constant(1.0))
2483            )
2484        );
2485
2486        let mut metadata = StateMetadata::default();
2487
2488        let v = metadata.add_continuous_variable(String::from("iv"));
2489        assert!(v.is_ok());
2490        let v = v.unwrap();
2491        assert_eq!(
2492            v.ceil(),
2493            ContinuousExpression::Round(
2494                CastOperator::Ceil,
2495                Box::new(ContinuousExpression::Variable(0))
2496            )
2497        );
2498
2499        let v = metadata.add_continuous_resource_variable(String::from("irv"), true);
2500        assert!(v.is_ok());
2501        let v = v.unwrap();
2502        assert_eq!(
2503            v.ceil(),
2504            ContinuousExpression::Round(
2505                CastOperator::Ceil,
2506                Box::new(ContinuousExpression::ResourceVariable(0))
2507            )
2508        );
2509    }
2510
2511    #[test]
2512    fn round() {
2513        let expression = ContinuousExpression::Constant(1.0);
2514        assert_eq!(
2515            expression.round(),
2516            ContinuousExpression::Round(
2517                CastOperator::Round,
2518                Box::new(ContinuousExpression::Constant(1.0))
2519            )
2520        );
2521
2522        let mut metadata = StateMetadata::default();
2523
2524        let v = metadata.add_continuous_variable(String::from("iv"));
2525        assert!(v.is_ok());
2526        let v = v.unwrap();
2527        assert_eq!(
2528            v.round(),
2529            ContinuousExpression::Round(
2530                CastOperator::Round,
2531                Box::new(ContinuousExpression::Variable(0))
2532            )
2533        );
2534
2535        let v = metadata.add_continuous_resource_variable(String::from("irv"), true);
2536        assert!(v.is_ok());
2537        let v = v.unwrap();
2538        assert_eq!(
2539            v.round(),
2540            ContinuousExpression::Round(
2541                CastOperator::Round,
2542                Box::new(ContinuousExpression::ResourceVariable(0))
2543            )
2544        );
2545    }
2546
2547    #[test]
2548    fn trunc() {
2549        let expression = ContinuousExpression::Constant(1.0);
2550        assert_eq!(
2551            expression.trunc(),
2552            ContinuousExpression::Round(
2553                CastOperator::Trunc,
2554                Box::new(ContinuousExpression::Constant(1.0))
2555            )
2556        );
2557
2558        let mut metadata = StateMetadata::default();
2559
2560        let v = metadata.add_continuous_variable(String::from("iv"));
2561        assert!(v.is_ok());
2562        let v = v.unwrap();
2563        assert_eq!(
2564            v.trunc(),
2565            ContinuousExpression::Round(
2566                CastOperator::Trunc,
2567                Box::new(ContinuousExpression::Variable(0))
2568            )
2569        );
2570
2571        let v = metadata.add_continuous_resource_variable(String::from("irv"), true);
2572        assert!(v.is_ok());
2573        let v = v.unwrap();
2574        assert_eq!(
2575            v.trunc(),
2576            ContinuousExpression::Round(
2577                CastOperator::Trunc,
2578                Box::new(ContinuousExpression::ResourceVariable(0))
2579            )
2580        );
2581    }
2582
2583    #[test]
2584    fn neg() {
2585        let expression = ContinuousExpression::Constant(1.0);
2586        assert_eq!(
2587            -expression,
2588            ContinuousExpression::UnaryOperation(
2589                UnaryOperator::Neg,
2590                Box::new(ContinuousExpression::Constant(1.0))
2591            )
2592        );
2593
2594        let mut metadata = StateMetadata::default();
2595
2596        let v = metadata.add_continuous_variable(String::from("iv"));
2597        assert!(v.is_ok());
2598        let v = v.unwrap();
2599        assert_eq!(
2600            -v,
2601            ContinuousExpression::UnaryOperation(
2602                UnaryOperator::Neg,
2603                Box::new(ContinuousExpression::Variable(0))
2604            )
2605        );
2606
2607        let v = metadata.add_continuous_resource_variable(String::from("irv"), true);
2608        assert!(v.is_ok());
2609        let v = v.unwrap();
2610        assert_eq!(
2611            -v,
2612            ContinuousExpression::UnaryOperation(
2613                UnaryOperator::Neg,
2614                Box::new(ContinuousExpression::ResourceVariable(0))
2615            )
2616        );
2617    }
2618
2619    #[test]
2620    fn add() {
2621        let mut metadata = StateMetadata::default();
2622        let iv1 = metadata.add_integer_variable(String::from("iv1"));
2623        assert!(iv1.is_ok());
2624        let iv1 = iv1.unwrap();
2625        let iv2 = metadata.add_integer_variable(String::from("iv2"));
2626        assert!(iv2.is_ok());
2627        let iv2 = iv2.unwrap();
2628        let irv1 = metadata.add_integer_resource_variable(String::from("irv1"), true);
2629        assert!(irv1.is_ok());
2630        let irv1 = irv1.unwrap();
2631        let irv2 = metadata.add_integer_resource_variable(String::from("irv2"), false);
2632        assert!(irv2.is_ok());
2633        let irv2 = irv2.unwrap();
2634        let cv1 = metadata.add_continuous_variable(String::from("cv1"));
2635        assert!(cv1.is_ok());
2636        let cv1 = cv1.unwrap();
2637        let cv2 = metadata.add_continuous_variable(String::from("cv2"));
2638        assert!(cv2.is_ok());
2639        let cv2 = cv2.unwrap();
2640        let crv1 = metadata.add_continuous_resource_variable(String::from("crv1"), true);
2641        assert!(crv1.is_ok());
2642        let crv1 = crv1.unwrap();
2643        let crv2 = metadata.add_continuous_resource_variable(String::from("crv2"), false);
2644        assert!(crv2.is_ok());
2645        let crv2 = crv2.unwrap();
2646
2647        let expression1 = ContinuousExpression::Constant(1.0);
2648        let expression2 = ContinuousExpression::Constant(2.0);
2649        assert_eq!(
2650            expression1 + expression2,
2651            ContinuousExpression::BinaryOperation(
2652                BinaryOperator::Add,
2653                Box::new(ContinuousExpression::Constant(1.0)),
2654                Box::new(ContinuousExpression::Constant(2.0))
2655            )
2656        );
2657
2658        let expression1 = ContinuousExpression::Constant(1.0);
2659        assert_eq!(
2660            expression1 + 2.0,
2661            ContinuousExpression::BinaryOperation(
2662                BinaryOperator::Add,
2663                Box::new(ContinuousExpression::Constant(1.0)),
2664                Box::new(ContinuousExpression::Constant(2.0))
2665            )
2666        );
2667
2668        let expression1 = ContinuousExpression::Constant(1.0);
2669        assert_eq!(
2670            expression1 + cv2,
2671            ContinuousExpression::BinaryOperation(
2672                BinaryOperator::Add,
2673                Box::new(ContinuousExpression::Constant(1.0)),
2674                Box::new(ContinuousExpression::Variable(cv2.id()))
2675            )
2676        );
2677
2678        let expression1 = ContinuousExpression::Constant(1.0);
2679        assert_eq!(
2680            expression1 + crv2,
2681            ContinuousExpression::BinaryOperation(
2682                BinaryOperator::Add,
2683                Box::new(ContinuousExpression::Constant(1.0)),
2684                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
2685            )
2686        );
2687
2688        let expression1 = ContinuousExpression::Constant(1.0);
2689        let expression2 = IntegerExpression::Constant(2);
2690        assert_eq!(
2691            expression1 + expression2,
2692            ContinuousExpression::BinaryOperation(
2693                BinaryOperator::Add,
2694                Box::new(ContinuousExpression::Constant(1.0)),
2695                Box::new(ContinuousExpression::FromInteger(Box::new(
2696                    IntegerExpression::Constant(2)
2697                )))
2698            )
2699        );
2700
2701        let expression1 = ContinuousExpression::Constant(1.0);
2702        assert_eq!(
2703            expression1 + iv2,
2704            ContinuousExpression::BinaryOperation(
2705                BinaryOperator::Add,
2706                Box::new(ContinuousExpression::Constant(1.0)),
2707                Box::new(ContinuousExpression::FromInteger(Box::new(
2708                    IntegerExpression::Variable(iv2.id())
2709                )))
2710            )
2711        );
2712
2713        let expression1 = ContinuousExpression::Constant(1.0);
2714        assert_eq!(
2715            expression1 + irv2,
2716            ContinuousExpression::BinaryOperation(
2717                BinaryOperator::Add,
2718                Box::new(ContinuousExpression::Constant(1.0)),
2719                Box::new(ContinuousExpression::FromInteger(Box::new(
2720                    IntegerExpression::ResourceVariable(irv2.id())
2721                )))
2722            )
2723        );
2724
2725        let expression2 = ContinuousExpression::Constant(2.0);
2726        assert_eq!(
2727            1.0 + expression2,
2728            ContinuousExpression::BinaryOperation(
2729                BinaryOperator::Add,
2730                Box::new(ContinuousExpression::Constant(1.0)),
2731                Box::new(ContinuousExpression::Constant(2.0))
2732            )
2733        );
2734
2735        assert_eq!(
2736            1.0 + cv2,
2737            ContinuousExpression::BinaryOperation(
2738                BinaryOperator::Add,
2739                Box::new(ContinuousExpression::Constant(1.0)),
2740                Box::new(ContinuousExpression::Variable(cv2.id()))
2741            )
2742        );
2743
2744        assert_eq!(
2745            1.0 + crv2,
2746            ContinuousExpression::BinaryOperation(
2747                BinaryOperator::Add,
2748                Box::new(ContinuousExpression::Constant(1.0)),
2749                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
2750            )
2751        );
2752
2753        let expression2 = IntegerExpression::Constant(2);
2754        assert_eq!(
2755            1.0 + expression2,
2756            ContinuousExpression::BinaryOperation(
2757                BinaryOperator::Add,
2758                Box::new(ContinuousExpression::Constant(1.0)),
2759                Box::new(ContinuousExpression::FromInteger(Box::new(
2760                    IntegerExpression::Constant(2)
2761                )))
2762            )
2763        );
2764
2765        assert_eq!(
2766            1.0 + iv2,
2767            ContinuousExpression::BinaryOperation(
2768                BinaryOperator::Add,
2769                Box::new(ContinuousExpression::Constant(1.0)),
2770                Box::new(ContinuousExpression::FromInteger(Box::new(
2771                    IntegerExpression::Variable(iv2.id())
2772                )))
2773            )
2774        );
2775
2776        assert_eq!(
2777            1.0 + irv2,
2778            ContinuousExpression::BinaryOperation(
2779                BinaryOperator::Add,
2780                Box::new(ContinuousExpression::Constant(1.0)),
2781                Box::new(ContinuousExpression::FromInteger(Box::new(
2782                    IntegerExpression::ResourceVariable(irv2.id())
2783                )))
2784            )
2785        );
2786
2787        let expression2 = ContinuousExpression::Constant(2.0);
2788        assert_eq!(
2789            cv1 + expression2,
2790            ContinuousExpression::BinaryOperation(
2791                BinaryOperator::Add,
2792                Box::new(ContinuousExpression::Variable(cv1.id())),
2793                Box::new(ContinuousExpression::Constant(2.0))
2794            )
2795        );
2796
2797        assert_eq!(
2798            cv1 + 2.0,
2799            ContinuousExpression::BinaryOperation(
2800                BinaryOperator::Add,
2801                Box::new(ContinuousExpression::Variable(cv1.id())),
2802                Box::new(ContinuousExpression::Constant(2.0))
2803            )
2804        );
2805
2806        assert_eq!(
2807            cv1 + cv2,
2808            ContinuousExpression::BinaryOperation(
2809                BinaryOperator::Add,
2810                Box::new(ContinuousExpression::Variable(cv1.id())),
2811                Box::new(ContinuousExpression::Variable(cv2.id()))
2812            )
2813        );
2814
2815        assert_eq!(
2816            cv1 + crv2,
2817            ContinuousExpression::BinaryOperation(
2818                BinaryOperator::Add,
2819                Box::new(ContinuousExpression::Variable(cv1.id())),
2820                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
2821            )
2822        );
2823
2824        let expression2 = IntegerExpression::Constant(2);
2825        assert_eq!(
2826            cv1 + expression2,
2827            ContinuousExpression::BinaryOperation(
2828                BinaryOperator::Add,
2829                Box::new(ContinuousExpression::Variable(cv1.id())),
2830                Box::new(ContinuousExpression::FromInteger(Box::new(
2831                    IntegerExpression::Constant(2)
2832                )))
2833            )
2834        );
2835
2836        assert_eq!(
2837            cv1 + iv2,
2838            ContinuousExpression::BinaryOperation(
2839                BinaryOperator::Add,
2840                Box::new(ContinuousExpression::Variable(cv1.id())),
2841                Box::new(ContinuousExpression::FromInteger(Box::new(
2842                    IntegerExpression::Variable(iv2.id())
2843                )))
2844            )
2845        );
2846
2847        assert_eq!(
2848            cv1 + irv2,
2849            ContinuousExpression::BinaryOperation(
2850                BinaryOperator::Add,
2851                Box::new(ContinuousExpression::Variable(cv1.id())),
2852                Box::new(ContinuousExpression::FromInteger(Box::new(
2853                    IntegerExpression::ResourceVariable(irv2.id())
2854                )))
2855            )
2856        );
2857
2858        let expression2 = ContinuousExpression::Constant(2.0);
2859        assert_eq!(
2860            crv1 + expression2,
2861            ContinuousExpression::BinaryOperation(
2862                BinaryOperator::Add,
2863                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
2864                Box::new(ContinuousExpression::Constant(2.0))
2865            )
2866        );
2867
2868        assert_eq!(
2869            crv1 + 2.0,
2870            ContinuousExpression::BinaryOperation(
2871                BinaryOperator::Add,
2872                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
2873                Box::new(ContinuousExpression::Constant(2.0))
2874            )
2875        );
2876
2877        assert_eq!(
2878            crv1 + cv2,
2879            ContinuousExpression::BinaryOperation(
2880                BinaryOperator::Add,
2881                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
2882                Box::new(ContinuousExpression::Variable(cv2.id()))
2883            )
2884        );
2885
2886        assert_eq!(
2887            crv1 + crv2,
2888            ContinuousExpression::BinaryOperation(
2889                BinaryOperator::Add,
2890                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
2891                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
2892            )
2893        );
2894
2895        let expression2 = IntegerExpression::Constant(2);
2896        assert_eq!(
2897            crv1 + expression2,
2898            ContinuousExpression::BinaryOperation(
2899                BinaryOperator::Add,
2900                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
2901                Box::new(ContinuousExpression::FromInteger(Box::new(
2902                    IntegerExpression::Constant(2)
2903                )))
2904            )
2905        );
2906
2907        assert_eq!(
2908            crv1 + iv2,
2909            ContinuousExpression::BinaryOperation(
2910                BinaryOperator::Add,
2911                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
2912                Box::new(ContinuousExpression::FromInteger(Box::new(
2913                    IntegerExpression::Variable(iv2.id())
2914                )))
2915            )
2916        );
2917
2918        assert_eq!(
2919            crv1 + irv2,
2920            ContinuousExpression::BinaryOperation(
2921                BinaryOperator::Add,
2922                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
2923                Box::new(ContinuousExpression::FromInteger(Box::new(
2924                    IntegerExpression::ResourceVariable(irv2.id())
2925                )))
2926            )
2927        );
2928
2929        let expression1 = IntegerExpression::Constant(1);
2930        let expression2 = ContinuousExpression::Constant(2.0);
2931        assert_eq!(
2932            expression1 + expression2,
2933            ContinuousExpression::BinaryOperation(
2934                BinaryOperator::Add,
2935                Box::new(ContinuousExpression::FromInteger(Box::new(
2936                    IntegerExpression::Constant(1)
2937                ))),
2938                Box::new(ContinuousExpression::Constant(2.0))
2939            )
2940        );
2941
2942        let expression1 = IntegerExpression::Constant(1);
2943        assert_eq!(
2944            expression1 + 2.0,
2945            ContinuousExpression::BinaryOperation(
2946                BinaryOperator::Add,
2947                Box::new(ContinuousExpression::FromInteger(Box::new(
2948                    IntegerExpression::Constant(1)
2949                ))),
2950                Box::new(ContinuousExpression::Constant(2.0))
2951            )
2952        );
2953
2954        let expression1 = IntegerExpression::Constant(1);
2955        assert_eq!(
2956            expression1 + cv2,
2957            ContinuousExpression::BinaryOperation(
2958                BinaryOperator::Add,
2959                Box::new(ContinuousExpression::FromInteger(Box::new(
2960                    IntegerExpression::Constant(1)
2961                ))),
2962                Box::new(ContinuousExpression::Variable(cv2.id()))
2963            )
2964        );
2965
2966        let expression1 = IntegerExpression::Constant(1);
2967        assert_eq!(
2968            expression1 + crv2,
2969            ContinuousExpression::BinaryOperation(
2970                BinaryOperator::Add,
2971                Box::new(ContinuousExpression::FromInteger(Box::new(
2972                    IntegerExpression::Constant(1)
2973                ))),
2974                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
2975            )
2976        );
2977
2978        let expression2 = ContinuousExpression::Constant(2.0);
2979        assert_eq!(
2980            iv1 + expression2,
2981            ContinuousExpression::BinaryOperation(
2982                BinaryOperator::Add,
2983                Box::new(ContinuousExpression::FromInteger(Box::new(
2984                    IntegerExpression::Variable(iv1.id())
2985                ))),
2986                Box::new(ContinuousExpression::Constant(2.0))
2987            )
2988        );
2989
2990        assert_eq!(
2991            iv1 + 2.0,
2992            ContinuousExpression::BinaryOperation(
2993                BinaryOperator::Add,
2994                Box::new(ContinuousExpression::FromInteger(Box::new(
2995                    IntegerExpression::Variable(iv1.id())
2996                ))),
2997                Box::new(ContinuousExpression::Constant(2.0))
2998            )
2999        );
3000
3001        assert_eq!(
3002            iv1 + cv2,
3003            ContinuousExpression::BinaryOperation(
3004                BinaryOperator::Add,
3005                Box::new(ContinuousExpression::FromInteger(Box::new(
3006                    IntegerExpression::Variable(iv1.id())
3007                ))),
3008                Box::new(ContinuousExpression::Variable(cv2.id()))
3009            )
3010        );
3011
3012        assert_eq!(
3013            iv1 + crv2,
3014            ContinuousExpression::BinaryOperation(
3015                BinaryOperator::Add,
3016                Box::new(ContinuousExpression::FromInteger(Box::new(
3017                    IntegerExpression::Variable(iv1.id())
3018                ))),
3019                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
3020            )
3021        );
3022
3023        let expression2 = ContinuousExpression::Constant(2.0);
3024        assert_eq!(
3025            irv1 + expression2,
3026            ContinuousExpression::BinaryOperation(
3027                BinaryOperator::Add,
3028                Box::new(ContinuousExpression::FromInteger(Box::new(
3029                    IntegerExpression::ResourceVariable(irv1.id())
3030                ))),
3031                Box::new(ContinuousExpression::Constant(2.0))
3032            )
3033        );
3034
3035        assert_eq!(
3036            irv1 + 2.0,
3037            ContinuousExpression::BinaryOperation(
3038                BinaryOperator::Add,
3039                Box::new(ContinuousExpression::FromInteger(Box::new(
3040                    IntegerExpression::ResourceVariable(irv1.id())
3041                ))),
3042                Box::new(ContinuousExpression::Constant(2.0))
3043            )
3044        );
3045
3046        assert_eq!(
3047            irv1 + cv2,
3048            ContinuousExpression::BinaryOperation(
3049                BinaryOperator::Add,
3050                Box::new(ContinuousExpression::FromInteger(Box::new(
3051                    IntegerExpression::ResourceVariable(irv1.id())
3052                ))),
3053                Box::new(ContinuousExpression::Variable(cv2.id()))
3054            )
3055        );
3056
3057        assert_eq!(
3058            irv1 + crv2,
3059            ContinuousExpression::BinaryOperation(
3060                BinaryOperator::Add,
3061                Box::new(ContinuousExpression::FromInteger(Box::new(
3062                    IntegerExpression::ResourceVariable(irv1.id())
3063                ))),
3064                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
3065            )
3066        );
3067
3068        let expression2 = ContinuousExpression::Constant(2.0);
3069        assert_eq!(
3070            1 + expression2,
3071            ContinuousExpression::BinaryOperation(
3072                BinaryOperator::Add,
3073                Box::new(ContinuousExpression::Constant(1.0)),
3074                Box::new(ContinuousExpression::Constant(2.0))
3075            )
3076        );
3077
3078        assert_eq!(
3079            1 + cv2,
3080            ContinuousExpression::BinaryOperation(
3081                BinaryOperator::Add,
3082                Box::new(ContinuousExpression::Constant(1.0)),
3083                Box::new(ContinuousExpression::Variable(cv2.id()))
3084            )
3085        );
3086
3087        assert_eq!(
3088            1 + crv2,
3089            ContinuousExpression::BinaryOperation(
3090                BinaryOperator::Add,
3091                Box::new(ContinuousExpression::Constant(1.0)),
3092                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
3093            )
3094        );
3095    }
3096
3097    #[test]
3098    fn sub() {
3099        let mut metadata = StateMetadata::default();
3100        let iv1 = metadata.add_integer_variable(String::from("iv1"));
3101        assert!(iv1.is_ok());
3102        let iv1 = iv1.unwrap();
3103        let iv2 = metadata.add_integer_variable(String::from("iv2"));
3104        assert!(iv2.is_ok());
3105        let iv2 = iv2.unwrap();
3106        let irv1 = metadata.add_integer_resource_variable(String::from("irv1"), true);
3107        assert!(irv1.is_ok());
3108        let irv1 = irv1.unwrap();
3109        let irv2 = metadata.add_integer_resource_variable(String::from("irv2"), false);
3110        assert!(irv2.is_ok());
3111        let irv2 = irv2.unwrap();
3112        let cv1 = metadata.add_continuous_variable(String::from("cv1"));
3113        assert!(cv1.is_ok());
3114        let cv1 = cv1.unwrap();
3115        let cv2 = metadata.add_continuous_variable(String::from("cv2"));
3116        assert!(cv2.is_ok());
3117        let cv2 = cv2.unwrap();
3118        let crv1 = metadata.add_continuous_resource_variable(String::from("crv1"), true);
3119        assert!(crv1.is_ok());
3120        let crv1 = crv1.unwrap();
3121        let crv2 = metadata.add_continuous_resource_variable(String::from("crv2"), false);
3122        assert!(crv2.is_ok());
3123        let crv2 = crv2.unwrap();
3124
3125        let expression1 = ContinuousExpression::Constant(1.0);
3126        let expression2 = ContinuousExpression::Constant(2.0);
3127        assert_eq!(
3128            expression1 - expression2,
3129            ContinuousExpression::BinaryOperation(
3130                BinaryOperator::Sub,
3131                Box::new(ContinuousExpression::Constant(1.0)),
3132                Box::new(ContinuousExpression::Constant(2.0))
3133            )
3134        );
3135
3136        let expression1 = ContinuousExpression::Constant(1.0);
3137        assert_eq!(
3138            expression1 - 2.0,
3139            ContinuousExpression::BinaryOperation(
3140                BinaryOperator::Sub,
3141                Box::new(ContinuousExpression::Constant(1.0)),
3142                Box::new(ContinuousExpression::Constant(2.0))
3143            )
3144        );
3145
3146        let expression1 = ContinuousExpression::Constant(1.0);
3147        assert_eq!(
3148            expression1 - cv2,
3149            ContinuousExpression::BinaryOperation(
3150                BinaryOperator::Sub,
3151                Box::new(ContinuousExpression::Constant(1.0)),
3152                Box::new(ContinuousExpression::Variable(cv2.id()))
3153            )
3154        );
3155
3156        let expression1 = ContinuousExpression::Constant(1.0);
3157        assert_eq!(
3158            expression1 - crv2,
3159            ContinuousExpression::BinaryOperation(
3160                BinaryOperator::Sub,
3161                Box::new(ContinuousExpression::Constant(1.0)),
3162                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
3163            )
3164        );
3165
3166        let expression1 = ContinuousExpression::Constant(1.0);
3167        let expression2 = IntegerExpression::Constant(2);
3168        assert_eq!(
3169            expression1 - expression2,
3170            ContinuousExpression::BinaryOperation(
3171                BinaryOperator::Sub,
3172                Box::new(ContinuousExpression::Constant(1.0)),
3173                Box::new(ContinuousExpression::FromInteger(Box::new(
3174                    IntegerExpression::Constant(2)
3175                )))
3176            )
3177        );
3178
3179        let expression1 = ContinuousExpression::Constant(1.0);
3180        assert_eq!(
3181            expression1 - iv2,
3182            ContinuousExpression::BinaryOperation(
3183                BinaryOperator::Sub,
3184                Box::new(ContinuousExpression::Constant(1.0)),
3185                Box::new(ContinuousExpression::FromInteger(Box::new(
3186                    IntegerExpression::Variable(iv2.id())
3187                )))
3188            )
3189        );
3190
3191        let expression1 = ContinuousExpression::Constant(1.0);
3192        assert_eq!(
3193            expression1 - irv2,
3194            ContinuousExpression::BinaryOperation(
3195                BinaryOperator::Sub,
3196                Box::new(ContinuousExpression::Constant(1.0)),
3197                Box::new(ContinuousExpression::FromInteger(Box::new(
3198                    IntegerExpression::ResourceVariable(irv2.id())
3199                )))
3200            )
3201        );
3202
3203        let expression2 = ContinuousExpression::Constant(2.0);
3204        assert_eq!(
3205            1.0 - expression2,
3206            ContinuousExpression::BinaryOperation(
3207                BinaryOperator::Sub,
3208                Box::new(ContinuousExpression::Constant(1.0)),
3209                Box::new(ContinuousExpression::Constant(2.0))
3210            )
3211        );
3212
3213        assert_eq!(
3214            1.0 - cv2,
3215            ContinuousExpression::BinaryOperation(
3216                BinaryOperator::Sub,
3217                Box::new(ContinuousExpression::Constant(1.0)),
3218                Box::new(ContinuousExpression::Variable(cv2.id()))
3219            )
3220        );
3221
3222        assert_eq!(
3223            1.0 - crv2,
3224            ContinuousExpression::BinaryOperation(
3225                BinaryOperator::Sub,
3226                Box::new(ContinuousExpression::Constant(1.0)),
3227                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
3228            )
3229        );
3230
3231        let expression2 = IntegerExpression::Constant(2);
3232        assert_eq!(
3233            1.0 - expression2,
3234            ContinuousExpression::BinaryOperation(
3235                BinaryOperator::Sub,
3236                Box::new(ContinuousExpression::Constant(1.0)),
3237                Box::new(ContinuousExpression::FromInteger(Box::new(
3238                    IntegerExpression::Constant(2)
3239                )))
3240            )
3241        );
3242
3243        assert_eq!(
3244            1.0 - iv2,
3245            ContinuousExpression::BinaryOperation(
3246                BinaryOperator::Sub,
3247                Box::new(ContinuousExpression::Constant(1.0)),
3248                Box::new(ContinuousExpression::FromInteger(Box::new(
3249                    IntegerExpression::Variable(iv2.id())
3250                )))
3251            )
3252        );
3253
3254        assert_eq!(
3255            1.0 - irv2,
3256            ContinuousExpression::BinaryOperation(
3257                BinaryOperator::Sub,
3258                Box::new(ContinuousExpression::Constant(1.0)),
3259                Box::new(ContinuousExpression::FromInteger(Box::new(
3260                    IntegerExpression::ResourceVariable(irv2.id())
3261                )))
3262            )
3263        );
3264
3265        let expression2 = ContinuousExpression::Constant(2.0);
3266        assert_eq!(
3267            cv1 - expression2,
3268            ContinuousExpression::BinaryOperation(
3269                BinaryOperator::Sub,
3270                Box::new(ContinuousExpression::Variable(cv1.id())),
3271                Box::new(ContinuousExpression::Constant(2.0))
3272            )
3273        );
3274
3275        assert_eq!(
3276            cv1 - 2.0,
3277            ContinuousExpression::BinaryOperation(
3278                BinaryOperator::Sub,
3279                Box::new(ContinuousExpression::Variable(cv1.id())),
3280                Box::new(ContinuousExpression::Constant(2.0))
3281            )
3282        );
3283
3284        assert_eq!(
3285            cv1 - cv2,
3286            ContinuousExpression::BinaryOperation(
3287                BinaryOperator::Sub,
3288                Box::new(ContinuousExpression::Variable(cv1.id())),
3289                Box::new(ContinuousExpression::Variable(cv2.id()))
3290            )
3291        );
3292
3293        assert_eq!(
3294            cv1 - crv2,
3295            ContinuousExpression::BinaryOperation(
3296                BinaryOperator::Sub,
3297                Box::new(ContinuousExpression::Variable(cv1.id())),
3298                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
3299            )
3300        );
3301
3302        let expression2 = IntegerExpression::Constant(2);
3303        assert_eq!(
3304            cv1 - expression2,
3305            ContinuousExpression::BinaryOperation(
3306                BinaryOperator::Sub,
3307                Box::new(ContinuousExpression::Variable(cv1.id())),
3308                Box::new(ContinuousExpression::FromInteger(Box::new(
3309                    IntegerExpression::Constant(2)
3310                )))
3311            )
3312        );
3313
3314        assert_eq!(
3315            cv1 - iv2,
3316            ContinuousExpression::BinaryOperation(
3317                BinaryOperator::Sub,
3318                Box::new(ContinuousExpression::Variable(cv1.id())),
3319                Box::new(ContinuousExpression::FromInteger(Box::new(
3320                    IntegerExpression::Variable(iv2.id())
3321                )))
3322            )
3323        );
3324
3325        assert_eq!(
3326            cv1 - irv2,
3327            ContinuousExpression::BinaryOperation(
3328                BinaryOperator::Sub,
3329                Box::new(ContinuousExpression::Variable(cv1.id())),
3330                Box::new(ContinuousExpression::FromInteger(Box::new(
3331                    IntegerExpression::ResourceVariable(irv2.id())
3332                )))
3333            )
3334        );
3335
3336        let expression2 = ContinuousExpression::Constant(2.0);
3337        assert_eq!(
3338            crv1 - expression2,
3339            ContinuousExpression::BinaryOperation(
3340                BinaryOperator::Sub,
3341                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
3342                Box::new(ContinuousExpression::Constant(2.0))
3343            )
3344        );
3345
3346        assert_eq!(
3347            crv1 - 2.0,
3348            ContinuousExpression::BinaryOperation(
3349                BinaryOperator::Sub,
3350                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
3351                Box::new(ContinuousExpression::Constant(2.0))
3352            )
3353        );
3354
3355        assert_eq!(
3356            crv1 - cv2,
3357            ContinuousExpression::BinaryOperation(
3358                BinaryOperator::Sub,
3359                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
3360                Box::new(ContinuousExpression::Variable(cv2.id()))
3361            )
3362        );
3363
3364        assert_eq!(
3365            crv1 - crv2,
3366            ContinuousExpression::BinaryOperation(
3367                BinaryOperator::Sub,
3368                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
3369                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
3370            )
3371        );
3372
3373        let expression2 = IntegerExpression::Constant(2);
3374        assert_eq!(
3375            crv1 - expression2,
3376            ContinuousExpression::BinaryOperation(
3377                BinaryOperator::Sub,
3378                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
3379                Box::new(ContinuousExpression::FromInteger(Box::new(
3380                    IntegerExpression::Constant(2)
3381                )))
3382            )
3383        );
3384
3385        assert_eq!(
3386            crv1 - iv2,
3387            ContinuousExpression::BinaryOperation(
3388                BinaryOperator::Sub,
3389                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
3390                Box::new(ContinuousExpression::FromInteger(Box::new(
3391                    IntegerExpression::Variable(iv2.id())
3392                )))
3393            )
3394        );
3395
3396        assert_eq!(
3397            crv1 - irv2,
3398            ContinuousExpression::BinaryOperation(
3399                BinaryOperator::Sub,
3400                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
3401                Box::new(ContinuousExpression::FromInteger(Box::new(
3402                    IntegerExpression::ResourceVariable(irv2.id())
3403                )))
3404            )
3405        );
3406
3407        let expression1 = IntegerExpression::Constant(1);
3408        let expression2 = ContinuousExpression::Constant(2.0);
3409        assert_eq!(
3410            expression1 - expression2,
3411            ContinuousExpression::BinaryOperation(
3412                BinaryOperator::Sub,
3413                Box::new(ContinuousExpression::FromInteger(Box::new(
3414                    IntegerExpression::Constant(1)
3415                ))),
3416                Box::new(ContinuousExpression::Constant(2.0))
3417            )
3418        );
3419
3420        let expression1 = IntegerExpression::Constant(1);
3421        assert_eq!(
3422            expression1 - 2.0,
3423            ContinuousExpression::BinaryOperation(
3424                BinaryOperator::Sub,
3425                Box::new(ContinuousExpression::FromInteger(Box::new(
3426                    IntegerExpression::Constant(1)
3427                ))),
3428                Box::new(ContinuousExpression::Constant(2.0))
3429            )
3430        );
3431
3432        let expression1 = IntegerExpression::Constant(1);
3433        assert_eq!(
3434            expression1 - cv2,
3435            ContinuousExpression::BinaryOperation(
3436                BinaryOperator::Sub,
3437                Box::new(ContinuousExpression::FromInteger(Box::new(
3438                    IntegerExpression::Constant(1)
3439                ))),
3440                Box::new(ContinuousExpression::Variable(cv2.id()))
3441            )
3442        );
3443
3444        let expression1 = IntegerExpression::Constant(1);
3445        assert_eq!(
3446            expression1 - crv2,
3447            ContinuousExpression::BinaryOperation(
3448                BinaryOperator::Sub,
3449                Box::new(ContinuousExpression::FromInteger(Box::new(
3450                    IntegerExpression::Constant(1)
3451                ))),
3452                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
3453            )
3454        );
3455
3456        let expression2 = ContinuousExpression::Constant(2.0);
3457        assert_eq!(
3458            iv1 - expression2,
3459            ContinuousExpression::BinaryOperation(
3460                BinaryOperator::Sub,
3461                Box::new(ContinuousExpression::FromInteger(Box::new(
3462                    IntegerExpression::Variable(iv1.id())
3463                ))),
3464                Box::new(ContinuousExpression::Constant(2.0))
3465            )
3466        );
3467
3468        assert_eq!(
3469            iv1 - 2.0,
3470            ContinuousExpression::BinaryOperation(
3471                BinaryOperator::Sub,
3472                Box::new(ContinuousExpression::FromInteger(Box::new(
3473                    IntegerExpression::Variable(iv1.id())
3474                ))),
3475                Box::new(ContinuousExpression::Constant(2.0))
3476            )
3477        );
3478
3479        assert_eq!(
3480            iv1 - cv2,
3481            ContinuousExpression::BinaryOperation(
3482                BinaryOperator::Sub,
3483                Box::new(ContinuousExpression::FromInteger(Box::new(
3484                    IntegerExpression::Variable(iv1.id())
3485                ))),
3486                Box::new(ContinuousExpression::Variable(cv2.id()))
3487            )
3488        );
3489
3490        assert_eq!(
3491            iv1 - crv2,
3492            ContinuousExpression::BinaryOperation(
3493                BinaryOperator::Sub,
3494                Box::new(ContinuousExpression::FromInteger(Box::new(
3495                    IntegerExpression::Variable(iv1.id())
3496                ))),
3497                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
3498            )
3499        );
3500
3501        let expression2 = ContinuousExpression::Constant(2.0);
3502        assert_eq!(
3503            irv1 - expression2,
3504            ContinuousExpression::BinaryOperation(
3505                BinaryOperator::Sub,
3506                Box::new(ContinuousExpression::FromInteger(Box::new(
3507                    IntegerExpression::ResourceVariable(irv1.id())
3508                ))),
3509                Box::new(ContinuousExpression::Constant(2.0))
3510            )
3511        );
3512
3513        assert_eq!(
3514            irv1 - 2.0,
3515            ContinuousExpression::BinaryOperation(
3516                BinaryOperator::Sub,
3517                Box::new(ContinuousExpression::FromInteger(Box::new(
3518                    IntegerExpression::ResourceVariable(irv1.id())
3519                ))),
3520                Box::new(ContinuousExpression::Constant(2.0))
3521            )
3522        );
3523
3524        assert_eq!(
3525            irv1 - cv2,
3526            ContinuousExpression::BinaryOperation(
3527                BinaryOperator::Sub,
3528                Box::new(ContinuousExpression::FromInteger(Box::new(
3529                    IntegerExpression::ResourceVariable(irv1.id())
3530                ))),
3531                Box::new(ContinuousExpression::Variable(cv2.id()))
3532            )
3533        );
3534
3535        assert_eq!(
3536            irv1 - crv2,
3537            ContinuousExpression::BinaryOperation(
3538                BinaryOperator::Sub,
3539                Box::new(ContinuousExpression::FromInteger(Box::new(
3540                    IntegerExpression::ResourceVariable(irv1.id())
3541                ))),
3542                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
3543            )
3544        );
3545
3546        let expression2 = ContinuousExpression::Constant(2.0);
3547        assert_eq!(
3548            1 - expression2,
3549            ContinuousExpression::BinaryOperation(
3550                BinaryOperator::Sub,
3551                Box::new(ContinuousExpression::Constant(1.0)),
3552                Box::new(ContinuousExpression::Constant(2.0))
3553            )
3554        );
3555
3556        assert_eq!(
3557            1 - cv2,
3558            ContinuousExpression::BinaryOperation(
3559                BinaryOperator::Sub,
3560                Box::new(ContinuousExpression::Constant(1.0)),
3561                Box::new(ContinuousExpression::Variable(cv2.id()))
3562            )
3563        );
3564
3565        assert_eq!(
3566            1 - crv2,
3567            ContinuousExpression::BinaryOperation(
3568                BinaryOperator::Sub,
3569                Box::new(ContinuousExpression::Constant(1.0)),
3570                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
3571            )
3572        );
3573    }
3574
3575    #[test]
3576    fn mul() {
3577        let mut metadata = StateMetadata::default();
3578        let iv1 = metadata.add_integer_variable(String::from("iv1"));
3579        assert!(iv1.is_ok());
3580        let iv1 = iv1.unwrap();
3581        let iv2 = metadata.add_integer_variable(String::from("iv2"));
3582        assert!(iv2.is_ok());
3583        let iv2 = iv2.unwrap();
3584        let irv1 = metadata.add_integer_resource_variable(String::from("irv1"), true);
3585        assert!(irv1.is_ok());
3586        let irv1 = irv1.unwrap();
3587        let irv2 = metadata.add_integer_resource_variable(String::from("irv2"), false);
3588        assert!(irv2.is_ok());
3589        let irv2 = irv2.unwrap();
3590        let cv1 = metadata.add_continuous_variable(String::from("cv1"));
3591        assert!(cv1.is_ok());
3592        let cv1 = cv1.unwrap();
3593        let cv2 = metadata.add_continuous_variable(String::from("cv2"));
3594        assert!(cv2.is_ok());
3595        let cv2 = cv2.unwrap();
3596        let crv1 = metadata.add_continuous_resource_variable(String::from("crv1"), true);
3597        assert!(crv1.is_ok());
3598        let crv1 = crv1.unwrap();
3599        let crv2 = metadata.add_continuous_resource_variable(String::from("crv2"), false);
3600        assert!(crv2.is_ok());
3601        let crv2 = crv2.unwrap();
3602
3603        let expression1 = ContinuousExpression::Constant(1.0);
3604        let expression2 = ContinuousExpression::Constant(2.0);
3605        assert_eq!(
3606            expression1 * expression2,
3607            ContinuousExpression::BinaryOperation(
3608                BinaryOperator::Mul,
3609                Box::new(ContinuousExpression::Constant(1.0)),
3610                Box::new(ContinuousExpression::Constant(2.0))
3611            )
3612        );
3613
3614        let expression1 = ContinuousExpression::Constant(1.0);
3615        assert_eq!(
3616            expression1 * 2.0,
3617            ContinuousExpression::BinaryOperation(
3618                BinaryOperator::Mul,
3619                Box::new(ContinuousExpression::Constant(1.0)),
3620                Box::new(ContinuousExpression::Constant(2.0))
3621            )
3622        );
3623
3624        let expression1 = ContinuousExpression::Constant(1.0);
3625        assert_eq!(
3626            expression1 * cv2,
3627            ContinuousExpression::BinaryOperation(
3628                BinaryOperator::Mul,
3629                Box::new(ContinuousExpression::Constant(1.0)),
3630                Box::new(ContinuousExpression::Variable(cv2.id()))
3631            )
3632        );
3633
3634        let expression1 = ContinuousExpression::Constant(1.0);
3635        assert_eq!(
3636            expression1 * crv2,
3637            ContinuousExpression::BinaryOperation(
3638                BinaryOperator::Mul,
3639                Box::new(ContinuousExpression::Constant(1.0)),
3640                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
3641            )
3642        );
3643
3644        let expression1 = ContinuousExpression::Constant(1.0);
3645        let expression2 = IntegerExpression::Constant(2);
3646        assert_eq!(
3647            expression1 * expression2,
3648            ContinuousExpression::BinaryOperation(
3649                BinaryOperator::Mul,
3650                Box::new(ContinuousExpression::Constant(1.0)),
3651                Box::new(ContinuousExpression::FromInteger(Box::new(
3652                    IntegerExpression::Constant(2)
3653                )))
3654            )
3655        );
3656
3657        let expression1 = ContinuousExpression::Constant(1.0);
3658        assert_eq!(
3659            expression1 * iv2,
3660            ContinuousExpression::BinaryOperation(
3661                BinaryOperator::Mul,
3662                Box::new(ContinuousExpression::Constant(1.0)),
3663                Box::new(ContinuousExpression::FromInteger(Box::new(
3664                    IntegerExpression::Variable(iv2.id())
3665                )))
3666            )
3667        );
3668
3669        let expression1 = ContinuousExpression::Constant(1.0);
3670        assert_eq!(
3671            expression1 * irv2,
3672            ContinuousExpression::BinaryOperation(
3673                BinaryOperator::Mul,
3674                Box::new(ContinuousExpression::Constant(1.0)),
3675                Box::new(ContinuousExpression::FromInteger(Box::new(
3676                    IntegerExpression::ResourceVariable(irv2.id())
3677                )))
3678            )
3679        );
3680
3681        let expression2 = ContinuousExpression::Constant(2.0);
3682        assert_eq!(
3683            1.0 * expression2,
3684            ContinuousExpression::BinaryOperation(
3685                BinaryOperator::Mul,
3686                Box::new(ContinuousExpression::Constant(1.0)),
3687                Box::new(ContinuousExpression::Constant(2.0))
3688            )
3689        );
3690
3691        assert_eq!(
3692            1.0 * cv2,
3693            ContinuousExpression::BinaryOperation(
3694                BinaryOperator::Mul,
3695                Box::new(ContinuousExpression::Constant(1.0)),
3696                Box::new(ContinuousExpression::Variable(cv2.id()))
3697            )
3698        );
3699
3700        assert_eq!(
3701            1.0 * crv2,
3702            ContinuousExpression::BinaryOperation(
3703                BinaryOperator::Mul,
3704                Box::new(ContinuousExpression::Constant(1.0)),
3705                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
3706            )
3707        );
3708
3709        let expression2 = IntegerExpression::Constant(2);
3710        assert_eq!(
3711            1.0 * expression2,
3712            ContinuousExpression::BinaryOperation(
3713                BinaryOperator::Mul,
3714                Box::new(ContinuousExpression::Constant(1.0)),
3715                Box::new(ContinuousExpression::FromInteger(Box::new(
3716                    IntegerExpression::Constant(2)
3717                )))
3718            )
3719        );
3720
3721        assert_eq!(
3722            1.0 * iv2,
3723            ContinuousExpression::BinaryOperation(
3724                BinaryOperator::Mul,
3725                Box::new(ContinuousExpression::Constant(1.0)),
3726                Box::new(ContinuousExpression::FromInteger(Box::new(
3727                    IntegerExpression::Variable(iv2.id())
3728                )))
3729            )
3730        );
3731
3732        assert_eq!(
3733            1.0 * irv2,
3734            ContinuousExpression::BinaryOperation(
3735                BinaryOperator::Mul,
3736                Box::new(ContinuousExpression::Constant(1.0)),
3737                Box::new(ContinuousExpression::FromInteger(Box::new(
3738                    IntegerExpression::ResourceVariable(irv2.id())
3739                )))
3740            )
3741        );
3742
3743        let expression2 = ContinuousExpression::Constant(2.0);
3744        assert_eq!(
3745            cv1 * expression2,
3746            ContinuousExpression::BinaryOperation(
3747                BinaryOperator::Mul,
3748                Box::new(ContinuousExpression::Variable(cv1.id())),
3749                Box::new(ContinuousExpression::Constant(2.0))
3750            )
3751        );
3752
3753        assert_eq!(
3754            cv1 * 2.0,
3755            ContinuousExpression::BinaryOperation(
3756                BinaryOperator::Mul,
3757                Box::new(ContinuousExpression::Variable(cv1.id())),
3758                Box::new(ContinuousExpression::Constant(2.0))
3759            )
3760        );
3761
3762        assert_eq!(
3763            cv1 * cv2,
3764            ContinuousExpression::BinaryOperation(
3765                BinaryOperator::Mul,
3766                Box::new(ContinuousExpression::Variable(cv1.id())),
3767                Box::new(ContinuousExpression::Variable(cv2.id()))
3768            )
3769        );
3770
3771        assert_eq!(
3772            cv1 * crv2,
3773            ContinuousExpression::BinaryOperation(
3774                BinaryOperator::Mul,
3775                Box::new(ContinuousExpression::Variable(cv1.id())),
3776                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
3777            )
3778        );
3779
3780        let expression2 = IntegerExpression::Constant(2);
3781        assert_eq!(
3782            cv1 * expression2,
3783            ContinuousExpression::BinaryOperation(
3784                BinaryOperator::Mul,
3785                Box::new(ContinuousExpression::Variable(cv1.id())),
3786                Box::new(ContinuousExpression::FromInteger(Box::new(
3787                    IntegerExpression::Constant(2)
3788                )))
3789            )
3790        );
3791
3792        assert_eq!(
3793            cv1 * iv2,
3794            ContinuousExpression::BinaryOperation(
3795                BinaryOperator::Mul,
3796                Box::new(ContinuousExpression::Variable(cv1.id())),
3797                Box::new(ContinuousExpression::FromInteger(Box::new(
3798                    IntegerExpression::Variable(iv2.id())
3799                )))
3800            )
3801        );
3802
3803        assert_eq!(
3804            cv1 * irv2,
3805            ContinuousExpression::BinaryOperation(
3806                BinaryOperator::Mul,
3807                Box::new(ContinuousExpression::Variable(cv1.id())),
3808                Box::new(ContinuousExpression::FromInteger(Box::new(
3809                    IntegerExpression::ResourceVariable(irv2.id())
3810                )))
3811            )
3812        );
3813
3814        let expression2 = ContinuousExpression::Constant(2.0);
3815        assert_eq!(
3816            crv1 * expression2,
3817            ContinuousExpression::BinaryOperation(
3818                BinaryOperator::Mul,
3819                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
3820                Box::new(ContinuousExpression::Constant(2.0))
3821            )
3822        );
3823
3824        assert_eq!(
3825            crv1 * 2.0,
3826            ContinuousExpression::BinaryOperation(
3827                BinaryOperator::Mul,
3828                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
3829                Box::new(ContinuousExpression::Constant(2.0))
3830            )
3831        );
3832
3833        assert_eq!(
3834            crv1 * cv2,
3835            ContinuousExpression::BinaryOperation(
3836                BinaryOperator::Mul,
3837                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
3838                Box::new(ContinuousExpression::Variable(cv2.id()))
3839            )
3840        );
3841
3842        assert_eq!(
3843            crv1 * crv2,
3844            ContinuousExpression::BinaryOperation(
3845                BinaryOperator::Mul,
3846                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
3847                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
3848            )
3849        );
3850
3851        let expression2 = IntegerExpression::Constant(2);
3852        assert_eq!(
3853            crv1 * expression2,
3854            ContinuousExpression::BinaryOperation(
3855                BinaryOperator::Mul,
3856                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
3857                Box::new(ContinuousExpression::FromInteger(Box::new(
3858                    IntegerExpression::Constant(2)
3859                )))
3860            )
3861        );
3862
3863        assert_eq!(
3864            crv1 * iv2,
3865            ContinuousExpression::BinaryOperation(
3866                BinaryOperator::Mul,
3867                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
3868                Box::new(ContinuousExpression::FromInteger(Box::new(
3869                    IntegerExpression::Variable(iv2.id())
3870                )))
3871            )
3872        );
3873
3874        assert_eq!(
3875            crv1 * irv2,
3876            ContinuousExpression::BinaryOperation(
3877                BinaryOperator::Mul,
3878                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
3879                Box::new(ContinuousExpression::FromInteger(Box::new(
3880                    IntegerExpression::ResourceVariable(irv2.id())
3881                )))
3882            )
3883        );
3884
3885        let expression1 = IntegerExpression::Constant(1);
3886        let expression2 = ContinuousExpression::Constant(2.0);
3887        assert_eq!(
3888            expression1 * expression2,
3889            ContinuousExpression::BinaryOperation(
3890                BinaryOperator::Mul,
3891                Box::new(ContinuousExpression::FromInteger(Box::new(
3892                    IntegerExpression::Constant(1)
3893                ))),
3894                Box::new(ContinuousExpression::Constant(2.0))
3895            )
3896        );
3897
3898        let expression1 = IntegerExpression::Constant(1);
3899        assert_eq!(
3900            expression1 * 2.0,
3901            ContinuousExpression::BinaryOperation(
3902                BinaryOperator::Mul,
3903                Box::new(ContinuousExpression::FromInteger(Box::new(
3904                    IntegerExpression::Constant(1)
3905                ))),
3906                Box::new(ContinuousExpression::Constant(2.0))
3907            )
3908        );
3909
3910        let expression1 = IntegerExpression::Constant(1);
3911        assert_eq!(
3912            expression1 * cv2,
3913            ContinuousExpression::BinaryOperation(
3914                BinaryOperator::Mul,
3915                Box::new(ContinuousExpression::FromInteger(Box::new(
3916                    IntegerExpression::Constant(1)
3917                ))),
3918                Box::new(ContinuousExpression::Variable(cv2.id()))
3919            )
3920        );
3921
3922        let expression1 = IntegerExpression::Constant(1);
3923        assert_eq!(
3924            expression1 * crv2,
3925            ContinuousExpression::BinaryOperation(
3926                BinaryOperator::Mul,
3927                Box::new(ContinuousExpression::FromInteger(Box::new(
3928                    IntegerExpression::Constant(1)
3929                ))),
3930                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
3931            )
3932        );
3933
3934        let expression2 = ContinuousExpression::Constant(2.0);
3935        assert_eq!(
3936            iv1 * expression2,
3937            ContinuousExpression::BinaryOperation(
3938                BinaryOperator::Mul,
3939                Box::new(ContinuousExpression::FromInteger(Box::new(
3940                    IntegerExpression::Variable(iv1.id())
3941                ))),
3942                Box::new(ContinuousExpression::Constant(2.0))
3943            )
3944        );
3945
3946        assert_eq!(
3947            iv1 * 2.0,
3948            ContinuousExpression::BinaryOperation(
3949                BinaryOperator::Mul,
3950                Box::new(ContinuousExpression::FromInteger(Box::new(
3951                    IntegerExpression::Variable(iv1.id())
3952                ))),
3953                Box::new(ContinuousExpression::Constant(2.0))
3954            )
3955        );
3956
3957        assert_eq!(
3958            iv1 * cv2,
3959            ContinuousExpression::BinaryOperation(
3960                BinaryOperator::Mul,
3961                Box::new(ContinuousExpression::FromInteger(Box::new(
3962                    IntegerExpression::Variable(iv1.id())
3963                ))),
3964                Box::new(ContinuousExpression::Variable(cv2.id()))
3965            )
3966        );
3967
3968        assert_eq!(
3969            iv1 * crv2,
3970            ContinuousExpression::BinaryOperation(
3971                BinaryOperator::Mul,
3972                Box::new(ContinuousExpression::FromInteger(Box::new(
3973                    IntegerExpression::Variable(iv1.id())
3974                ))),
3975                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
3976            )
3977        );
3978
3979        let expression2 = ContinuousExpression::Constant(2.0);
3980        assert_eq!(
3981            irv1 * expression2,
3982            ContinuousExpression::BinaryOperation(
3983                BinaryOperator::Mul,
3984                Box::new(ContinuousExpression::FromInteger(Box::new(
3985                    IntegerExpression::ResourceVariable(irv1.id())
3986                ))),
3987                Box::new(ContinuousExpression::Constant(2.0))
3988            )
3989        );
3990
3991        assert_eq!(
3992            irv1 * 2.0,
3993            ContinuousExpression::BinaryOperation(
3994                BinaryOperator::Mul,
3995                Box::new(ContinuousExpression::FromInteger(Box::new(
3996                    IntegerExpression::ResourceVariable(irv1.id())
3997                ))),
3998                Box::new(ContinuousExpression::Constant(2.0))
3999            )
4000        );
4001
4002        assert_eq!(
4003            irv1 * cv2,
4004            ContinuousExpression::BinaryOperation(
4005                BinaryOperator::Mul,
4006                Box::new(ContinuousExpression::FromInteger(Box::new(
4007                    IntegerExpression::ResourceVariable(irv1.id())
4008                ))),
4009                Box::new(ContinuousExpression::Variable(cv2.id()))
4010            )
4011        );
4012
4013        assert_eq!(
4014            irv1 * crv2,
4015            ContinuousExpression::BinaryOperation(
4016                BinaryOperator::Mul,
4017                Box::new(ContinuousExpression::FromInteger(Box::new(
4018                    IntegerExpression::ResourceVariable(irv1.id())
4019                ))),
4020                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
4021            )
4022        );
4023
4024        let expression2 = ContinuousExpression::Constant(2.0);
4025        assert_eq!(
4026            1 * expression2,
4027            ContinuousExpression::BinaryOperation(
4028                BinaryOperator::Mul,
4029                Box::new(ContinuousExpression::Constant(1.0)),
4030                Box::new(ContinuousExpression::Constant(2.0))
4031            )
4032        );
4033
4034        assert_eq!(
4035            1 * cv2,
4036            ContinuousExpression::BinaryOperation(
4037                BinaryOperator::Mul,
4038                Box::new(ContinuousExpression::Constant(1.0)),
4039                Box::new(ContinuousExpression::Variable(cv2.id()))
4040            )
4041        );
4042
4043        assert_eq!(
4044            1 * crv2,
4045            ContinuousExpression::BinaryOperation(
4046                BinaryOperator::Mul,
4047                Box::new(ContinuousExpression::Constant(1.0)),
4048                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
4049            )
4050        );
4051    }
4052
4053    #[test]
4054    fn div() {
4055        let mut metadata = StateMetadata::default();
4056        let iv1 = metadata.add_integer_variable(String::from("iv1"));
4057        assert!(iv1.is_ok());
4058        let iv1 = iv1.unwrap();
4059        let iv2 = metadata.add_integer_variable(String::from("iv2"));
4060        assert!(iv2.is_ok());
4061        let iv2 = iv2.unwrap();
4062        let irv1 = metadata.add_integer_resource_variable(String::from("irv1"), true);
4063        assert!(irv1.is_ok());
4064        let irv1 = irv1.unwrap();
4065        let irv2 = metadata.add_integer_resource_variable(String::from("irv2"), false);
4066        assert!(irv2.is_ok());
4067        let irv2 = irv2.unwrap();
4068        let cv1 = metadata.add_continuous_variable(String::from("cv1"));
4069        assert!(cv1.is_ok());
4070        let cv1 = cv1.unwrap();
4071        let cv2 = metadata.add_continuous_variable(String::from("cv2"));
4072        assert!(cv2.is_ok());
4073        let cv2 = cv2.unwrap();
4074        let crv1 = metadata.add_continuous_resource_variable(String::from("crv1"), true);
4075        assert!(crv1.is_ok());
4076        let crv1 = crv1.unwrap();
4077        let crv2 = metadata.add_continuous_resource_variable(String::from("crv2"), false);
4078        assert!(crv2.is_ok());
4079        let crv2 = crv2.unwrap();
4080
4081        let expression1 = ContinuousExpression::Constant(1.0);
4082        let expression2 = ContinuousExpression::Constant(2.0);
4083        assert_eq!(
4084            expression1 / expression2,
4085            ContinuousExpression::BinaryOperation(
4086                BinaryOperator::Div,
4087                Box::new(ContinuousExpression::Constant(1.0)),
4088                Box::new(ContinuousExpression::Constant(2.0))
4089            )
4090        );
4091
4092        let expression1 = ContinuousExpression::Constant(1.0);
4093        assert_eq!(
4094            expression1 / 2.0,
4095            ContinuousExpression::BinaryOperation(
4096                BinaryOperator::Div,
4097                Box::new(ContinuousExpression::Constant(1.0)),
4098                Box::new(ContinuousExpression::Constant(2.0))
4099            )
4100        );
4101
4102        let expression1 = ContinuousExpression::Constant(1.0);
4103        assert_eq!(
4104            expression1 / cv2,
4105            ContinuousExpression::BinaryOperation(
4106                BinaryOperator::Div,
4107                Box::new(ContinuousExpression::Constant(1.0)),
4108                Box::new(ContinuousExpression::Variable(cv2.id()))
4109            )
4110        );
4111
4112        let expression1 = ContinuousExpression::Constant(1.0);
4113        assert_eq!(
4114            expression1 / crv2,
4115            ContinuousExpression::BinaryOperation(
4116                BinaryOperator::Div,
4117                Box::new(ContinuousExpression::Constant(1.0)),
4118                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
4119            )
4120        );
4121
4122        let expression1 = ContinuousExpression::Constant(1.0);
4123        let expression2 = IntegerExpression::Constant(2);
4124        assert_eq!(
4125            expression1 / expression2,
4126            ContinuousExpression::BinaryOperation(
4127                BinaryOperator::Div,
4128                Box::new(ContinuousExpression::Constant(1.0)),
4129                Box::new(ContinuousExpression::FromInteger(Box::new(
4130                    IntegerExpression::Constant(2)
4131                )))
4132            )
4133        );
4134
4135        let expression1 = ContinuousExpression::Constant(1.0);
4136        assert_eq!(
4137            expression1 / iv2,
4138            ContinuousExpression::BinaryOperation(
4139                BinaryOperator::Div,
4140                Box::new(ContinuousExpression::Constant(1.0)),
4141                Box::new(ContinuousExpression::FromInteger(Box::new(
4142                    IntegerExpression::Variable(iv2.id())
4143                )))
4144            )
4145        );
4146
4147        let expression1 = ContinuousExpression::Constant(1.0);
4148        assert_eq!(
4149            expression1 / irv2,
4150            ContinuousExpression::BinaryOperation(
4151                BinaryOperator::Div,
4152                Box::new(ContinuousExpression::Constant(1.0)),
4153                Box::new(ContinuousExpression::FromInteger(Box::new(
4154                    IntegerExpression::ResourceVariable(irv2.id())
4155                )))
4156            )
4157        );
4158
4159        let expression2 = ContinuousExpression::Constant(2.0);
4160        assert_eq!(
4161            1.0 / expression2,
4162            ContinuousExpression::BinaryOperation(
4163                BinaryOperator::Div,
4164                Box::new(ContinuousExpression::Constant(1.0)),
4165                Box::new(ContinuousExpression::Constant(2.0))
4166            )
4167        );
4168
4169        assert_eq!(
4170            1.0 / cv2,
4171            ContinuousExpression::BinaryOperation(
4172                BinaryOperator::Div,
4173                Box::new(ContinuousExpression::Constant(1.0)),
4174                Box::new(ContinuousExpression::Variable(cv2.id()))
4175            )
4176        );
4177
4178        assert_eq!(
4179            1.0 / crv2,
4180            ContinuousExpression::BinaryOperation(
4181                BinaryOperator::Div,
4182                Box::new(ContinuousExpression::Constant(1.0)),
4183                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
4184            )
4185        );
4186
4187        let expression2 = IntegerExpression::Constant(2);
4188        assert_eq!(
4189            1.0 / expression2,
4190            ContinuousExpression::BinaryOperation(
4191                BinaryOperator::Div,
4192                Box::new(ContinuousExpression::Constant(1.0)),
4193                Box::new(ContinuousExpression::FromInteger(Box::new(
4194                    IntegerExpression::Constant(2)
4195                )))
4196            )
4197        );
4198
4199        assert_eq!(
4200            1.0 / iv2,
4201            ContinuousExpression::BinaryOperation(
4202                BinaryOperator::Div,
4203                Box::new(ContinuousExpression::Constant(1.0)),
4204                Box::new(ContinuousExpression::FromInteger(Box::new(
4205                    IntegerExpression::Variable(iv2.id())
4206                )))
4207            )
4208        );
4209
4210        assert_eq!(
4211            1.0 / irv2,
4212            ContinuousExpression::BinaryOperation(
4213                BinaryOperator::Div,
4214                Box::new(ContinuousExpression::Constant(1.0)),
4215                Box::new(ContinuousExpression::FromInteger(Box::new(
4216                    IntegerExpression::ResourceVariable(irv2.id())
4217                )))
4218            )
4219        );
4220
4221        let expression2 = ContinuousExpression::Constant(2.0);
4222        assert_eq!(
4223            cv1 / expression2,
4224            ContinuousExpression::BinaryOperation(
4225                BinaryOperator::Div,
4226                Box::new(ContinuousExpression::Variable(cv1.id())),
4227                Box::new(ContinuousExpression::Constant(2.0))
4228            )
4229        );
4230
4231        assert_eq!(
4232            cv1 / 2.0,
4233            ContinuousExpression::BinaryOperation(
4234                BinaryOperator::Div,
4235                Box::new(ContinuousExpression::Variable(cv1.id())),
4236                Box::new(ContinuousExpression::Constant(2.0))
4237            )
4238        );
4239
4240        assert_eq!(
4241            cv1 / cv2,
4242            ContinuousExpression::BinaryOperation(
4243                BinaryOperator::Div,
4244                Box::new(ContinuousExpression::Variable(cv1.id())),
4245                Box::new(ContinuousExpression::Variable(cv2.id()))
4246            )
4247        );
4248
4249        assert_eq!(
4250            cv1 / crv2,
4251            ContinuousExpression::BinaryOperation(
4252                BinaryOperator::Div,
4253                Box::new(ContinuousExpression::Variable(cv1.id())),
4254                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
4255            )
4256        );
4257
4258        let expression2 = IntegerExpression::Constant(2);
4259        assert_eq!(
4260            cv1 / expression2,
4261            ContinuousExpression::BinaryOperation(
4262                BinaryOperator::Div,
4263                Box::new(ContinuousExpression::Variable(cv1.id())),
4264                Box::new(ContinuousExpression::FromInteger(Box::new(
4265                    IntegerExpression::Constant(2)
4266                )))
4267            )
4268        );
4269
4270        assert_eq!(
4271            cv1 / iv2,
4272            ContinuousExpression::BinaryOperation(
4273                BinaryOperator::Div,
4274                Box::new(ContinuousExpression::Variable(cv1.id())),
4275                Box::new(ContinuousExpression::FromInteger(Box::new(
4276                    IntegerExpression::Variable(iv2.id())
4277                )))
4278            )
4279        );
4280
4281        assert_eq!(
4282            cv1 / irv2,
4283            ContinuousExpression::BinaryOperation(
4284                BinaryOperator::Div,
4285                Box::new(ContinuousExpression::Variable(cv1.id())),
4286                Box::new(ContinuousExpression::FromInteger(Box::new(
4287                    IntegerExpression::ResourceVariable(irv2.id())
4288                )))
4289            )
4290        );
4291
4292        let expression2 = ContinuousExpression::Constant(2.0);
4293        assert_eq!(
4294            crv1 / expression2,
4295            ContinuousExpression::BinaryOperation(
4296                BinaryOperator::Div,
4297                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
4298                Box::new(ContinuousExpression::Constant(2.0))
4299            )
4300        );
4301
4302        assert_eq!(
4303            crv1 / 2.0,
4304            ContinuousExpression::BinaryOperation(
4305                BinaryOperator::Div,
4306                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
4307                Box::new(ContinuousExpression::Constant(2.0))
4308            )
4309        );
4310
4311        assert_eq!(
4312            crv1 / cv2,
4313            ContinuousExpression::BinaryOperation(
4314                BinaryOperator::Div,
4315                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
4316                Box::new(ContinuousExpression::Variable(cv2.id()))
4317            )
4318        );
4319
4320        assert_eq!(
4321            crv1 / crv2,
4322            ContinuousExpression::BinaryOperation(
4323                BinaryOperator::Div,
4324                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
4325                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
4326            )
4327        );
4328
4329        let expression2 = IntegerExpression::Constant(2);
4330        assert_eq!(
4331            crv1 / expression2,
4332            ContinuousExpression::BinaryOperation(
4333                BinaryOperator::Div,
4334                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
4335                Box::new(ContinuousExpression::FromInteger(Box::new(
4336                    IntegerExpression::Constant(2)
4337                )))
4338            )
4339        );
4340
4341        assert_eq!(
4342            crv1 / iv2,
4343            ContinuousExpression::BinaryOperation(
4344                BinaryOperator::Div,
4345                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
4346                Box::new(ContinuousExpression::FromInteger(Box::new(
4347                    IntegerExpression::Variable(iv2.id())
4348                )))
4349            )
4350        );
4351
4352        assert_eq!(
4353            crv1 / irv2,
4354            ContinuousExpression::BinaryOperation(
4355                BinaryOperator::Div,
4356                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
4357                Box::new(ContinuousExpression::FromInteger(Box::new(
4358                    IntegerExpression::ResourceVariable(irv2.id())
4359                )))
4360            )
4361        );
4362
4363        let expression1 = IntegerExpression::Constant(1);
4364        let expression2 = ContinuousExpression::Constant(2.0);
4365        assert_eq!(
4366            expression1 / expression2,
4367            ContinuousExpression::BinaryOperation(
4368                BinaryOperator::Div,
4369                Box::new(ContinuousExpression::FromInteger(Box::new(
4370                    IntegerExpression::Constant(1)
4371                ))),
4372                Box::new(ContinuousExpression::Constant(2.0))
4373            )
4374        );
4375
4376        let expression1 = IntegerExpression::Constant(1);
4377        assert_eq!(
4378            expression1 / 2.0,
4379            ContinuousExpression::BinaryOperation(
4380                BinaryOperator::Div,
4381                Box::new(ContinuousExpression::FromInteger(Box::new(
4382                    IntegerExpression::Constant(1)
4383                ))),
4384                Box::new(ContinuousExpression::Constant(2.0))
4385            )
4386        );
4387
4388        let expression1 = IntegerExpression::Constant(1);
4389        assert_eq!(
4390            expression1 / cv2,
4391            ContinuousExpression::BinaryOperation(
4392                BinaryOperator::Div,
4393                Box::new(ContinuousExpression::FromInteger(Box::new(
4394                    IntegerExpression::Constant(1)
4395                ))),
4396                Box::new(ContinuousExpression::Variable(cv2.id()))
4397            )
4398        );
4399
4400        let expression1 = IntegerExpression::Constant(1);
4401        assert_eq!(
4402            expression1 / crv2,
4403            ContinuousExpression::BinaryOperation(
4404                BinaryOperator::Div,
4405                Box::new(ContinuousExpression::FromInteger(Box::new(
4406                    IntegerExpression::Constant(1)
4407                ))),
4408                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
4409            )
4410        );
4411
4412        let expression2 = ContinuousExpression::Constant(2.0);
4413        assert_eq!(
4414            iv1 / expression2,
4415            ContinuousExpression::BinaryOperation(
4416                BinaryOperator::Div,
4417                Box::new(ContinuousExpression::FromInteger(Box::new(
4418                    IntegerExpression::Variable(iv1.id())
4419                ))),
4420                Box::new(ContinuousExpression::Constant(2.0))
4421            )
4422        );
4423
4424        assert_eq!(
4425            iv1 / 2.0,
4426            ContinuousExpression::BinaryOperation(
4427                BinaryOperator::Div,
4428                Box::new(ContinuousExpression::FromInteger(Box::new(
4429                    IntegerExpression::Variable(iv1.id())
4430                ))),
4431                Box::new(ContinuousExpression::Constant(2.0))
4432            )
4433        );
4434
4435        assert_eq!(
4436            iv1 / cv2,
4437            ContinuousExpression::BinaryOperation(
4438                BinaryOperator::Div,
4439                Box::new(ContinuousExpression::FromInteger(Box::new(
4440                    IntegerExpression::Variable(iv1.id())
4441                ))),
4442                Box::new(ContinuousExpression::Variable(cv2.id()))
4443            )
4444        );
4445
4446        assert_eq!(
4447            iv1 / crv2,
4448            ContinuousExpression::BinaryOperation(
4449                BinaryOperator::Div,
4450                Box::new(ContinuousExpression::FromInteger(Box::new(
4451                    IntegerExpression::Variable(iv1.id())
4452                ))),
4453                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
4454            )
4455        );
4456
4457        let expression2 = ContinuousExpression::Constant(2.0);
4458        assert_eq!(
4459            irv1 / expression2,
4460            ContinuousExpression::BinaryOperation(
4461                BinaryOperator::Div,
4462                Box::new(ContinuousExpression::FromInteger(Box::new(
4463                    IntegerExpression::ResourceVariable(irv1.id())
4464                ))),
4465                Box::new(ContinuousExpression::Constant(2.0))
4466            )
4467        );
4468
4469        assert_eq!(
4470            irv1 / 2.0,
4471            ContinuousExpression::BinaryOperation(
4472                BinaryOperator::Div,
4473                Box::new(ContinuousExpression::FromInteger(Box::new(
4474                    IntegerExpression::ResourceVariable(irv1.id())
4475                ))),
4476                Box::new(ContinuousExpression::Constant(2.0))
4477            )
4478        );
4479
4480        assert_eq!(
4481            irv1 / cv2,
4482            ContinuousExpression::BinaryOperation(
4483                BinaryOperator::Div,
4484                Box::new(ContinuousExpression::FromInteger(Box::new(
4485                    IntegerExpression::ResourceVariable(irv1.id())
4486                ))),
4487                Box::new(ContinuousExpression::Variable(cv2.id()))
4488            )
4489        );
4490
4491        assert_eq!(
4492            irv1 / crv2,
4493            ContinuousExpression::BinaryOperation(
4494                BinaryOperator::Div,
4495                Box::new(ContinuousExpression::FromInteger(Box::new(
4496                    IntegerExpression::ResourceVariable(irv1.id())
4497                ))),
4498                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
4499            )
4500        );
4501
4502        let expression2 = ContinuousExpression::Constant(2.0);
4503        assert_eq!(
4504            1 / expression2,
4505            ContinuousExpression::BinaryOperation(
4506                BinaryOperator::Div,
4507                Box::new(ContinuousExpression::Constant(1.0)),
4508                Box::new(ContinuousExpression::Constant(2.0))
4509            )
4510        );
4511
4512        assert_eq!(
4513            1 / cv2,
4514            ContinuousExpression::BinaryOperation(
4515                BinaryOperator::Div,
4516                Box::new(ContinuousExpression::Constant(1.0)),
4517                Box::new(ContinuousExpression::Variable(cv2.id()))
4518            )
4519        );
4520
4521        assert_eq!(
4522            1 / crv2,
4523            ContinuousExpression::BinaryOperation(
4524                BinaryOperator::Div,
4525                Box::new(ContinuousExpression::Constant(1.0)),
4526                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
4527            )
4528        );
4529    }
4530
4531    #[test]
4532    fn rem() {
4533        let mut metadata = StateMetadata::default();
4534        let iv1 = metadata.add_integer_variable(String::from("iv1"));
4535        assert!(iv1.is_ok());
4536        let iv1 = iv1.unwrap();
4537        let iv2 = metadata.add_integer_variable(String::from("iv2"));
4538        assert!(iv2.is_ok());
4539        let iv2 = iv2.unwrap();
4540        let irv1 = metadata.add_integer_resource_variable(String::from("irv1"), true);
4541        assert!(irv1.is_ok());
4542        let irv1 = irv1.unwrap();
4543        let irv2 = metadata.add_integer_resource_variable(String::from("irv2"), false);
4544        assert!(irv2.is_ok());
4545        let irv2 = irv2.unwrap();
4546        let cv1 = metadata.add_continuous_variable(String::from("cv1"));
4547        assert!(cv1.is_ok());
4548        let cv1 = cv1.unwrap();
4549        let cv2 = metadata.add_continuous_variable(String::from("cv2"));
4550        assert!(cv2.is_ok());
4551        let cv2 = cv2.unwrap();
4552        let crv1 = metadata.add_continuous_resource_variable(String::from("crv1"), true);
4553        assert!(crv1.is_ok());
4554        let crv1 = crv1.unwrap();
4555        let crv2 = metadata.add_continuous_resource_variable(String::from("crv2"), false);
4556        assert!(crv2.is_ok());
4557        let crv2 = crv2.unwrap();
4558
4559        let expression1 = ContinuousExpression::Constant(1.0);
4560        let expression2 = ContinuousExpression::Constant(2.0);
4561        assert_eq!(
4562            expression1 % expression2,
4563            ContinuousExpression::BinaryOperation(
4564                BinaryOperator::Rem,
4565                Box::new(ContinuousExpression::Constant(1.0)),
4566                Box::new(ContinuousExpression::Constant(2.0))
4567            )
4568        );
4569
4570        let expression1 = ContinuousExpression::Constant(1.0);
4571        assert_eq!(
4572            expression1 % 2.0,
4573            ContinuousExpression::BinaryOperation(
4574                BinaryOperator::Rem,
4575                Box::new(ContinuousExpression::Constant(1.0)),
4576                Box::new(ContinuousExpression::Constant(2.0))
4577            )
4578        );
4579
4580        let expression1 = ContinuousExpression::Constant(1.0);
4581        assert_eq!(
4582            expression1 % cv2,
4583            ContinuousExpression::BinaryOperation(
4584                BinaryOperator::Rem,
4585                Box::new(ContinuousExpression::Constant(1.0)),
4586                Box::new(ContinuousExpression::Variable(cv2.id()))
4587            )
4588        );
4589
4590        let expression1 = ContinuousExpression::Constant(1.0);
4591        assert_eq!(
4592            expression1 % crv2,
4593            ContinuousExpression::BinaryOperation(
4594                BinaryOperator::Rem,
4595                Box::new(ContinuousExpression::Constant(1.0)),
4596                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
4597            )
4598        );
4599
4600        let expression1 = ContinuousExpression::Constant(1.0);
4601        let expression2 = IntegerExpression::Constant(2);
4602        assert_eq!(
4603            expression1 % expression2,
4604            ContinuousExpression::BinaryOperation(
4605                BinaryOperator::Rem,
4606                Box::new(ContinuousExpression::Constant(1.0)),
4607                Box::new(ContinuousExpression::FromInteger(Box::new(
4608                    IntegerExpression::Constant(2)
4609                )))
4610            )
4611        );
4612
4613        let expression1 = ContinuousExpression::Constant(1.0);
4614        assert_eq!(
4615            expression1 % iv2,
4616            ContinuousExpression::BinaryOperation(
4617                BinaryOperator::Rem,
4618                Box::new(ContinuousExpression::Constant(1.0)),
4619                Box::new(ContinuousExpression::FromInteger(Box::new(
4620                    IntegerExpression::Variable(iv2.id())
4621                )))
4622            )
4623        );
4624
4625        let expression1 = ContinuousExpression::Constant(1.0);
4626        assert_eq!(
4627            expression1 % irv2,
4628            ContinuousExpression::BinaryOperation(
4629                BinaryOperator::Rem,
4630                Box::new(ContinuousExpression::Constant(1.0)),
4631                Box::new(ContinuousExpression::FromInteger(Box::new(
4632                    IntegerExpression::ResourceVariable(irv2.id())
4633                )))
4634            )
4635        );
4636
4637        let expression2 = ContinuousExpression::Constant(2.0);
4638        assert_eq!(
4639            1.0 % expression2,
4640            ContinuousExpression::BinaryOperation(
4641                BinaryOperator::Rem,
4642                Box::new(ContinuousExpression::Constant(1.0)),
4643                Box::new(ContinuousExpression::Constant(2.0))
4644            )
4645        );
4646
4647        assert_eq!(
4648            1.0 % cv2,
4649            ContinuousExpression::BinaryOperation(
4650                BinaryOperator::Rem,
4651                Box::new(ContinuousExpression::Constant(1.0)),
4652                Box::new(ContinuousExpression::Variable(cv2.id()))
4653            )
4654        );
4655
4656        assert_eq!(
4657            1.0 % crv2,
4658            ContinuousExpression::BinaryOperation(
4659                BinaryOperator::Rem,
4660                Box::new(ContinuousExpression::Constant(1.0)),
4661                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
4662            )
4663        );
4664
4665        let expression2 = IntegerExpression::Constant(2);
4666        assert_eq!(
4667            1.0 % expression2,
4668            ContinuousExpression::BinaryOperation(
4669                BinaryOperator::Rem,
4670                Box::new(ContinuousExpression::Constant(1.0)),
4671                Box::new(ContinuousExpression::FromInteger(Box::new(
4672                    IntegerExpression::Constant(2)
4673                )))
4674            )
4675        );
4676
4677        assert_eq!(
4678            1.0 % iv2,
4679            ContinuousExpression::BinaryOperation(
4680                BinaryOperator::Rem,
4681                Box::new(ContinuousExpression::Constant(1.0)),
4682                Box::new(ContinuousExpression::FromInteger(Box::new(
4683                    IntegerExpression::Variable(iv2.id())
4684                )))
4685            )
4686        );
4687
4688        assert_eq!(
4689            1.0 % irv2,
4690            ContinuousExpression::BinaryOperation(
4691                BinaryOperator::Rem,
4692                Box::new(ContinuousExpression::Constant(1.0)),
4693                Box::new(ContinuousExpression::FromInteger(Box::new(
4694                    IntegerExpression::ResourceVariable(irv2.id())
4695                )))
4696            )
4697        );
4698
4699        let expression2 = ContinuousExpression::Constant(2.0);
4700        assert_eq!(
4701            cv1 % expression2,
4702            ContinuousExpression::BinaryOperation(
4703                BinaryOperator::Rem,
4704                Box::new(ContinuousExpression::Variable(cv1.id())),
4705                Box::new(ContinuousExpression::Constant(2.0))
4706            )
4707        );
4708
4709        assert_eq!(
4710            cv1 % 2.0,
4711            ContinuousExpression::BinaryOperation(
4712                BinaryOperator::Rem,
4713                Box::new(ContinuousExpression::Variable(cv1.id())),
4714                Box::new(ContinuousExpression::Constant(2.0))
4715            )
4716        );
4717
4718        assert_eq!(
4719            cv1 % cv2,
4720            ContinuousExpression::BinaryOperation(
4721                BinaryOperator::Rem,
4722                Box::new(ContinuousExpression::Variable(cv1.id())),
4723                Box::new(ContinuousExpression::Variable(cv2.id()))
4724            )
4725        );
4726
4727        assert_eq!(
4728            cv1 % crv2,
4729            ContinuousExpression::BinaryOperation(
4730                BinaryOperator::Rem,
4731                Box::new(ContinuousExpression::Variable(cv1.id())),
4732                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
4733            )
4734        );
4735
4736        let expression2 = IntegerExpression::Constant(2);
4737        assert_eq!(
4738            cv1 % expression2,
4739            ContinuousExpression::BinaryOperation(
4740                BinaryOperator::Rem,
4741                Box::new(ContinuousExpression::Variable(cv1.id())),
4742                Box::new(ContinuousExpression::FromInteger(Box::new(
4743                    IntegerExpression::Constant(2)
4744                )))
4745            )
4746        );
4747
4748        assert_eq!(
4749            cv1 % iv2,
4750            ContinuousExpression::BinaryOperation(
4751                BinaryOperator::Rem,
4752                Box::new(ContinuousExpression::Variable(cv1.id())),
4753                Box::new(ContinuousExpression::FromInteger(Box::new(
4754                    IntegerExpression::Variable(iv2.id())
4755                )))
4756            )
4757        );
4758
4759        assert_eq!(
4760            cv1 % irv2,
4761            ContinuousExpression::BinaryOperation(
4762                BinaryOperator::Rem,
4763                Box::new(ContinuousExpression::Variable(cv1.id())),
4764                Box::new(ContinuousExpression::FromInteger(Box::new(
4765                    IntegerExpression::ResourceVariable(irv2.id())
4766                )))
4767            )
4768        );
4769
4770        let expression2 = ContinuousExpression::Constant(2.0);
4771        assert_eq!(
4772            crv1 % expression2,
4773            ContinuousExpression::BinaryOperation(
4774                BinaryOperator::Rem,
4775                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
4776                Box::new(ContinuousExpression::Constant(2.0))
4777            )
4778        );
4779
4780        assert_eq!(
4781            crv1 % 2.0,
4782            ContinuousExpression::BinaryOperation(
4783                BinaryOperator::Rem,
4784                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
4785                Box::new(ContinuousExpression::Constant(2.0))
4786            )
4787        );
4788
4789        assert_eq!(
4790            crv1 % cv2,
4791            ContinuousExpression::BinaryOperation(
4792                BinaryOperator::Rem,
4793                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
4794                Box::new(ContinuousExpression::Variable(cv2.id()))
4795            )
4796        );
4797
4798        assert_eq!(
4799            crv1 % crv2,
4800            ContinuousExpression::BinaryOperation(
4801                BinaryOperator::Rem,
4802                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
4803                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
4804            )
4805        );
4806
4807        let expression2 = IntegerExpression::Constant(2);
4808        assert_eq!(
4809            crv1 % expression2,
4810            ContinuousExpression::BinaryOperation(
4811                BinaryOperator::Rem,
4812                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
4813                Box::new(ContinuousExpression::FromInteger(Box::new(
4814                    IntegerExpression::Constant(2)
4815                )))
4816            )
4817        );
4818
4819        assert_eq!(
4820            crv1 % iv2,
4821            ContinuousExpression::BinaryOperation(
4822                BinaryOperator::Rem,
4823                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
4824                Box::new(ContinuousExpression::FromInteger(Box::new(
4825                    IntegerExpression::Variable(iv2.id())
4826                )))
4827            )
4828        );
4829
4830        assert_eq!(
4831            crv1 % irv2,
4832            ContinuousExpression::BinaryOperation(
4833                BinaryOperator::Rem,
4834                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
4835                Box::new(ContinuousExpression::FromInteger(Box::new(
4836                    IntegerExpression::ResourceVariable(irv2.id())
4837                )))
4838            )
4839        );
4840
4841        let expression1 = IntegerExpression::Constant(1);
4842        let expression2 = ContinuousExpression::Constant(2.0);
4843        assert_eq!(
4844            expression1 % expression2,
4845            ContinuousExpression::BinaryOperation(
4846                BinaryOperator::Rem,
4847                Box::new(ContinuousExpression::FromInteger(Box::new(
4848                    IntegerExpression::Constant(1)
4849                ))),
4850                Box::new(ContinuousExpression::Constant(2.0))
4851            )
4852        );
4853
4854        let expression1 = IntegerExpression::Constant(1);
4855        assert_eq!(
4856            expression1 % 2.0,
4857            ContinuousExpression::BinaryOperation(
4858                BinaryOperator::Rem,
4859                Box::new(ContinuousExpression::FromInteger(Box::new(
4860                    IntegerExpression::Constant(1)
4861                ))),
4862                Box::new(ContinuousExpression::Constant(2.0))
4863            )
4864        );
4865
4866        let expression1 = IntegerExpression::Constant(1);
4867        assert_eq!(
4868            expression1 % cv2,
4869            ContinuousExpression::BinaryOperation(
4870                BinaryOperator::Rem,
4871                Box::new(ContinuousExpression::FromInteger(Box::new(
4872                    IntegerExpression::Constant(1)
4873                ))),
4874                Box::new(ContinuousExpression::Variable(cv2.id()))
4875            )
4876        );
4877
4878        let expression1 = IntegerExpression::Constant(1);
4879        assert_eq!(
4880            expression1 % crv2,
4881            ContinuousExpression::BinaryOperation(
4882                BinaryOperator::Rem,
4883                Box::new(ContinuousExpression::FromInteger(Box::new(
4884                    IntegerExpression::Constant(1)
4885                ))),
4886                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
4887            )
4888        );
4889
4890        let expression2 = ContinuousExpression::Constant(2.0);
4891        assert_eq!(
4892            iv1 % expression2,
4893            ContinuousExpression::BinaryOperation(
4894                BinaryOperator::Rem,
4895                Box::new(ContinuousExpression::FromInteger(Box::new(
4896                    IntegerExpression::Variable(iv1.id())
4897                ))),
4898                Box::new(ContinuousExpression::Constant(2.0))
4899            )
4900        );
4901
4902        assert_eq!(
4903            iv1 % 2.0,
4904            ContinuousExpression::BinaryOperation(
4905                BinaryOperator::Rem,
4906                Box::new(ContinuousExpression::FromInteger(Box::new(
4907                    IntegerExpression::Variable(iv1.id())
4908                ))),
4909                Box::new(ContinuousExpression::Constant(2.0))
4910            )
4911        );
4912
4913        assert_eq!(
4914            iv1 % cv2,
4915            ContinuousExpression::BinaryOperation(
4916                BinaryOperator::Rem,
4917                Box::new(ContinuousExpression::FromInteger(Box::new(
4918                    IntegerExpression::Variable(iv1.id())
4919                ))),
4920                Box::new(ContinuousExpression::Variable(cv2.id()))
4921            )
4922        );
4923
4924        assert_eq!(
4925            iv1 % crv2,
4926            ContinuousExpression::BinaryOperation(
4927                BinaryOperator::Rem,
4928                Box::new(ContinuousExpression::FromInteger(Box::new(
4929                    IntegerExpression::Variable(iv1.id())
4930                ))),
4931                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
4932            )
4933        );
4934
4935        let expression2 = ContinuousExpression::Constant(2.0);
4936        assert_eq!(
4937            irv1 % expression2,
4938            ContinuousExpression::BinaryOperation(
4939                BinaryOperator::Rem,
4940                Box::new(ContinuousExpression::FromInteger(Box::new(
4941                    IntegerExpression::ResourceVariable(irv1.id())
4942                ))),
4943                Box::new(ContinuousExpression::Constant(2.0))
4944            )
4945        );
4946
4947        assert_eq!(
4948            irv1 % 2.0,
4949            ContinuousExpression::BinaryOperation(
4950                BinaryOperator::Rem,
4951                Box::new(ContinuousExpression::FromInteger(Box::new(
4952                    IntegerExpression::ResourceVariable(irv1.id())
4953                ))),
4954                Box::new(ContinuousExpression::Constant(2.0))
4955            )
4956        );
4957
4958        assert_eq!(
4959            irv1 % cv2,
4960            ContinuousExpression::BinaryOperation(
4961                BinaryOperator::Rem,
4962                Box::new(ContinuousExpression::FromInteger(Box::new(
4963                    IntegerExpression::ResourceVariable(irv1.id())
4964                ))),
4965                Box::new(ContinuousExpression::Variable(cv2.id()))
4966            )
4967        );
4968
4969        assert_eq!(
4970            irv1 % crv2,
4971            ContinuousExpression::BinaryOperation(
4972                BinaryOperator::Rem,
4973                Box::new(ContinuousExpression::FromInteger(Box::new(
4974                    IntegerExpression::ResourceVariable(irv1.id())
4975                ))),
4976                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
4977            )
4978        );
4979
4980        let expression2 = ContinuousExpression::Constant(2.0);
4981        assert_eq!(
4982            1 % expression2,
4983            ContinuousExpression::BinaryOperation(
4984                BinaryOperator::Rem,
4985                Box::new(ContinuousExpression::Constant(1.0)),
4986                Box::new(ContinuousExpression::Constant(2.0))
4987            )
4988        );
4989
4990        assert_eq!(
4991            1 % cv2,
4992            ContinuousExpression::BinaryOperation(
4993                BinaryOperator::Rem,
4994                Box::new(ContinuousExpression::Constant(1.0)),
4995                Box::new(ContinuousExpression::Variable(cv2.id()))
4996            )
4997        );
4998
4999        assert_eq!(
5000            1 % crv2,
5001            ContinuousExpression::BinaryOperation(
5002                BinaryOperator::Rem,
5003                Box::new(ContinuousExpression::Constant(1.0)),
5004                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
5005            )
5006        );
5007    }
5008
5009    #[test]
5010    fn max() {
5011        let mut metadata = StateMetadata::default();
5012        let iv1 = metadata.add_integer_variable(String::from("iv1"));
5013        assert!(iv1.is_ok());
5014        let iv1 = iv1.unwrap();
5015        let iv2 = metadata.add_integer_variable(String::from("iv2"));
5016        assert!(iv2.is_ok());
5017        let iv2 = iv2.unwrap();
5018        let irv1 = metadata.add_integer_resource_variable(String::from("irv1"), true);
5019        assert!(irv1.is_ok());
5020        let irv1 = irv1.unwrap();
5021        let irv2 = metadata.add_integer_resource_variable(String::from("irv2"), false);
5022        assert!(irv2.is_ok());
5023        let irv2 = irv2.unwrap();
5024        let cv1 = metadata.add_continuous_variable(String::from("cv1"));
5025        assert!(cv1.is_ok());
5026        let cv1 = cv1.unwrap();
5027        let cv2 = metadata.add_continuous_variable(String::from("cv2"));
5028        assert!(cv2.is_ok());
5029        let cv2 = cv2.unwrap();
5030        let crv1 = metadata.add_continuous_resource_variable(String::from("crv1"), true);
5031        assert!(crv1.is_ok());
5032        let crv1 = crv1.unwrap();
5033        let crv2 = metadata.add_continuous_resource_variable(String::from("crv2"), false);
5034        assert!(crv2.is_ok());
5035        let crv2 = crv2.unwrap();
5036
5037        let expression1 = ContinuousExpression::Constant(1.0);
5038        let expression2 = ContinuousExpression::Constant(2.0);
5039        assert_eq!(
5040            MaxMin::max(expression1, expression2),
5041            ContinuousExpression::BinaryOperation(
5042                BinaryOperator::Max,
5043                Box::new(ContinuousExpression::Constant(1.0)),
5044                Box::new(ContinuousExpression::Constant(2.0))
5045            )
5046        );
5047
5048        let expression1 = ContinuousExpression::Constant(1.0);
5049        assert_eq!(
5050            MaxMin::max(expression1, 2.0),
5051            ContinuousExpression::BinaryOperation(
5052                BinaryOperator::Max,
5053                Box::new(ContinuousExpression::Constant(1.0)),
5054                Box::new(ContinuousExpression::Constant(2.0))
5055            )
5056        );
5057
5058        let expression1 = ContinuousExpression::Constant(1.0);
5059        assert_eq!(
5060            MaxMin::max(expression1, cv2),
5061            ContinuousExpression::BinaryOperation(
5062                BinaryOperator::Max,
5063                Box::new(ContinuousExpression::Constant(1.0)),
5064                Box::new(ContinuousExpression::Variable(cv2.id()))
5065            )
5066        );
5067
5068        let expression1 = ContinuousExpression::Constant(1.0);
5069        assert_eq!(
5070            MaxMin::max(expression1, crv2),
5071            ContinuousExpression::BinaryOperation(
5072                BinaryOperator::Max,
5073                Box::new(ContinuousExpression::Constant(1.0)),
5074                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
5075            )
5076        );
5077
5078        let expression1 = ContinuousExpression::Constant(1.0);
5079        let expression2 = IntegerExpression::Constant(2);
5080        assert_eq!(
5081            MaxMin::max(expression1, expression2),
5082            ContinuousExpression::BinaryOperation(
5083                BinaryOperator::Max,
5084                Box::new(ContinuousExpression::Constant(1.0)),
5085                Box::new(ContinuousExpression::FromInteger(Box::new(
5086                    IntegerExpression::Constant(2)
5087                )))
5088            )
5089        );
5090
5091        let expression1 = ContinuousExpression::Constant(1.0);
5092        assert_eq!(
5093            MaxMin::max(expression1, iv2),
5094            ContinuousExpression::BinaryOperation(
5095                BinaryOperator::Max,
5096                Box::new(ContinuousExpression::Constant(1.0)),
5097                Box::new(ContinuousExpression::FromInteger(Box::new(
5098                    IntegerExpression::Variable(iv2.id())
5099                )))
5100            )
5101        );
5102
5103        let expression1 = ContinuousExpression::Constant(1.0);
5104        assert_eq!(
5105            MaxMin::max(expression1, irv2),
5106            ContinuousExpression::BinaryOperation(
5107                BinaryOperator::Max,
5108                Box::new(ContinuousExpression::Constant(1.0)),
5109                Box::new(ContinuousExpression::FromInteger(Box::new(
5110                    IntegerExpression::ResourceVariable(irv2.id())
5111                )))
5112            )
5113        );
5114
5115        let expression2 = ContinuousExpression::Constant(2.0);
5116        assert_eq!(
5117            MaxMin::max(1.0, expression2),
5118            ContinuousExpression::BinaryOperation(
5119                BinaryOperator::Max,
5120                Box::new(ContinuousExpression::Constant(1.0)),
5121                Box::new(ContinuousExpression::Constant(2.0))
5122            )
5123        );
5124
5125        assert_eq!(
5126            MaxMin::max(1.0, cv2),
5127            ContinuousExpression::BinaryOperation(
5128                BinaryOperator::Max,
5129                Box::new(ContinuousExpression::Constant(1.0)),
5130                Box::new(ContinuousExpression::Variable(cv2.id()))
5131            )
5132        );
5133
5134        assert_eq!(
5135            MaxMin::max(1.0, crv2),
5136            ContinuousExpression::BinaryOperation(
5137                BinaryOperator::Max,
5138                Box::new(ContinuousExpression::Constant(1.0)),
5139                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
5140            )
5141        );
5142
5143        let expression2 = IntegerExpression::Constant(2);
5144        assert_eq!(
5145            MaxMin::max(1.0, expression2),
5146            ContinuousExpression::BinaryOperation(
5147                BinaryOperator::Max,
5148                Box::new(ContinuousExpression::Constant(1.0)),
5149                Box::new(ContinuousExpression::FromInteger(Box::new(
5150                    IntegerExpression::Constant(2)
5151                )))
5152            )
5153        );
5154
5155        assert_eq!(
5156            MaxMin::max(1.0, iv2),
5157            ContinuousExpression::BinaryOperation(
5158                BinaryOperator::Max,
5159                Box::new(ContinuousExpression::Constant(1.0)),
5160                Box::new(ContinuousExpression::FromInteger(Box::new(
5161                    IntegerExpression::Variable(iv2.id())
5162                )))
5163            )
5164        );
5165
5166        assert_eq!(
5167            MaxMin::max(1.0, irv2),
5168            ContinuousExpression::BinaryOperation(
5169                BinaryOperator::Max,
5170                Box::new(ContinuousExpression::Constant(1.0)),
5171                Box::new(ContinuousExpression::FromInteger(Box::new(
5172                    IntegerExpression::ResourceVariable(irv2.id())
5173                )))
5174            )
5175        );
5176
5177        let expression2 = ContinuousExpression::Constant(2.0);
5178        assert_eq!(
5179            MaxMin::max(cv1, expression2),
5180            ContinuousExpression::BinaryOperation(
5181                BinaryOperator::Max,
5182                Box::new(ContinuousExpression::Variable(cv1.id())),
5183                Box::new(ContinuousExpression::Constant(2.0))
5184            )
5185        );
5186
5187        assert_eq!(
5188            MaxMin::max(cv1, 2.0),
5189            ContinuousExpression::BinaryOperation(
5190                BinaryOperator::Max,
5191                Box::new(ContinuousExpression::Variable(cv1.id())),
5192                Box::new(ContinuousExpression::Constant(2.0))
5193            )
5194        );
5195
5196        assert_eq!(
5197            MaxMin::max(cv1, cv2),
5198            ContinuousExpression::BinaryOperation(
5199                BinaryOperator::Max,
5200                Box::new(ContinuousExpression::Variable(cv1.id())),
5201                Box::new(ContinuousExpression::Variable(cv2.id()))
5202            )
5203        );
5204
5205        assert_eq!(
5206            MaxMin::max(cv1, crv2),
5207            ContinuousExpression::BinaryOperation(
5208                BinaryOperator::Max,
5209                Box::new(ContinuousExpression::Variable(cv1.id())),
5210                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
5211            )
5212        );
5213
5214        let expression2 = IntegerExpression::Constant(2);
5215        assert_eq!(
5216            MaxMin::max(cv1, expression2),
5217            ContinuousExpression::BinaryOperation(
5218                BinaryOperator::Max,
5219                Box::new(ContinuousExpression::Variable(cv1.id())),
5220                Box::new(ContinuousExpression::FromInteger(Box::new(
5221                    IntegerExpression::Constant(2)
5222                )))
5223            )
5224        );
5225
5226        assert_eq!(
5227            MaxMin::max(cv1, iv2),
5228            ContinuousExpression::BinaryOperation(
5229                BinaryOperator::Max,
5230                Box::new(ContinuousExpression::Variable(cv1.id())),
5231                Box::new(ContinuousExpression::FromInteger(Box::new(
5232                    IntegerExpression::Variable(iv2.id())
5233                )))
5234            )
5235        );
5236
5237        assert_eq!(
5238            MaxMin::max(cv1, irv2),
5239            ContinuousExpression::BinaryOperation(
5240                BinaryOperator::Max,
5241                Box::new(ContinuousExpression::Variable(cv1.id())),
5242                Box::new(ContinuousExpression::FromInteger(Box::new(
5243                    IntegerExpression::ResourceVariable(irv2.id())
5244                )))
5245            )
5246        );
5247
5248        let expression2 = ContinuousExpression::Constant(2.0);
5249        assert_eq!(
5250            MaxMin::max(crv1, expression2),
5251            ContinuousExpression::BinaryOperation(
5252                BinaryOperator::Max,
5253                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
5254                Box::new(ContinuousExpression::Constant(2.0))
5255            )
5256        );
5257
5258        assert_eq!(
5259            MaxMin::max(crv1, 2.0),
5260            ContinuousExpression::BinaryOperation(
5261                BinaryOperator::Max,
5262                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
5263                Box::new(ContinuousExpression::Constant(2.0))
5264            )
5265        );
5266
5267        assert_eq!(
5268            MaxMin::max(crv1, cv2),
5269            ContinuousExpression::BinaryOperation(
5270                BinaryOperator::Max,
5271                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
5272                Box::new(ContinuousExpression::Variable(cv2.id()))
5273            )
5274        );
5275
5276        assert_eq!(
5277            MaxMin::max(crv1, crv2),
5278            ContinuousExpression::BinaryOperation(
5279                BinaryOperator::Max,
5280                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
5281                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
5282            )
5283        );
5284
5285        let expression2 = IntegerExpression::Constant(2);
5286        assert_eq!(
5287            MaxMin::max(crv1, expression2),
5288            ContinuousExpression::BinaryOperation(
5289                BinaryOperator::Max,
5290                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
5291                Box::new(ContinuousExpression::FromInteger(Box::new(
5292                    IntegerExpression::Constant(2)
5293                )))
5294            )
5295        );
5296
5297        assert_eq!(
5298            MaxMin::max(crv1, iv2),
5299            ContinuousExpression::BinaryOperation(
5300                BinaryOperator::Max,
5301                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
5302                Box::new(ContinuousExpression::FromInteger(Box::new(
5303                    IntegerExpression::Variable(iv2.id())
5304                )))
5305            )
5306        );
5307
5308        assert_eq!(
5309            MaxMin::max(crv1, irv2),
5310            ContinuousExpression::BinaryOperation(
5311                BinaryOperator::Max,
5312                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
5313                Box::new(ContinuousExpression::FromInteger(Box::new(
5314                    IntegerExpression::ResourceVariable(irv2.id())
5315                )))
5316            )
5317        );
5318
5319        let expression1 = IntegerExpression::Constant(1);
5320        let expression2 = ContinuousExpression::Constant(2.0);
5321        assert_eq!(
5322            MaxMin::max(expression1, expression2),
5323            ContinuousExpression::BinaryOperation(
5324                BinaryOperator::Max,
5325                Box::new(ContinuousExpression::FromInteger(Box::new(
5326                    IntegerExpression::Constant(1)
5327                ))),
5328                Box::new(ContinuousExpression::Constant(2.0))
5329            )
5330        );
5331
5332        let expression1 = IntegerExpression::Constant(1);
5333        assert_eq!(
5334            MaxMin::max(expression1, 2.0),
5335            ContinuousExpression::BinaryOperation(
5336                BinaryOperator::Max,
5337                Box::new(ContinuousExpression::FromInteger(Box::new(
5338                    IntegerExpression::Constant(1)
5339                ))),
5340                Box::new(ContinuousExpression::Constant(2.0))
5341            )
5342        );
5343
5344        let expression1 = IntegerExpression::Constant(1);
5345        assert_eq!(
5346            MaxMin::max(expression1, cv2),
5347            ContinuousExpression::BinaryOperation(
5348                BinaryOperator::Max,
5349                Box::new(ContinuousExpression::FromInteger(Box::new(
5350                    IntegerExpression::Constant(1)
5351                ))),
5352                Box::new(ContinuousExpression::Variable(cv2.id()))
5353            )
5354        );
5355
5356        let expression1 = IntegerExpression::Constant(1);
5357        assert_eq!(
5358            MaxMin::max(expression1, crv2),
5359            ContinuousExpression::BinaryOperation(
5360                BinaryOperator::Max,
5361                Box::new(ContinuousExpression::FromInteger(Box::new(
5362                    IntegerExpression::Constant(1)
5363                ))),
5364                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
5365            )
5366        );
5367
5368        let expression2 = ContinuousExpression::Constant(2.0);
5369        assert_eq!(
5370            MaxMin::max(iv1, expression2),
5371            ContinuousExpression::BinaryOperation(
5372                BinaryOperator::Max,
5373                Box::new(ContinuousExpression::FromInteger(Box::new(
5374                    IntegerExpression::Variable(iv1.id())
5375                ))),
5376                Box::new(ContinuousExpression::Constant(2.0))
5377            )
5378        );
5379
5380        assert_eq!(
5381            MaxMin::max(iv1, 2.0),
5382            ContinuousExpression::BinaryOperation(
5383                BinaryOperator::Max,
5384                Box::new(ContinuousExpression::FromInteger(Box::new(
5385                    IntegerExpression::Variable(iv1.id())
5386                ))),
5387                Box::new(ContinuousExpression::Constant(2.0))
5388            )
5389        );
5390
5391        assert_eq!(
5392            MaxMin::max(iv1, cv2),
5393            ContinuousExpression::BinaryOperation(
5394                BinaryOperator::Max,
5395                Box::new(ContinuousExpression::FromInteger(Box::new(
5396                    IntegerExpression::Variable(iv1.id())
5397                ))),
5398                Box::new(ContinuousExpression::Variable(cv2.id()))
5399            )
5400        );
5401
5402        assert_eq!(
5403            MaxMin::max(iv1, crv2),
5404            ContinuousExpression::BinaryOperation(
5405                BinaryOperator::Max,
5406                Box::new(ContinuousExpression::FromInteger(Box::new(
5407                    IntegerExpression::Variable(iv1.id())
5408                ))),
5409                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
5410            )
5411        );
5412
5413        let expression2 = ContinuousExpression::Constant(2.0);
5414        assert_eq!(
5415            MaxMin::max(irv1, expression2),
5416            ContinuousExpression::BinaryOperation(
5417                BinaryOperator::Max,
5418                Box::new(ContinuousExpression::FromInteger(Box::new(
5419                    IntegerExpression::ResourceVariable(irv1.id())
5420                ))),
5421                Box::new(ContinuousExpression::Constant(2.0))
5422            )
5423        );
5424
5425        assert_eq!(
5426            MaxMin::max(irv1, 2.0),
5427            ContinuousExpression::BinaryOperation(
5428                BinaryOperator::Max,
5429                Box::new(ContinuousExpression::FromInteger(Box::new(
5430                    IntegerExpression::ResourceVariable(irv1.id())
5431                ))),
5432                Box::new(ContinuousExpression::Constant(2.0))
5433            )
5434        );
5435
5436        assert_eq!(
5437            MaxMin::max(irv1, cv2),
5438            ContinuousExpression::BinaryOperation(
5439                BinaryOperator::Max,
5440                Box::new(ContinuousExpression::FromInteger(Box::new(
5441                    IntegerExpression::ResourceVariable(irv1.id())
5442                ))),
5443                Box::new(ContinuousExpression::Variable(cv2.id()))
5444            )
5445        );
5446
5447        assert_eq!(
5448            MaxMin::max(irv1, crv2),
5449            ContinuousExpression::BinaryOperation(
5450                BinaryOperator::Max,
5451                Box::new(ContinuousExpression::FromInteger(Box::new(
5452                    IntegerExpression::ResourceVariable(irv1.id())
5453                ))),
5454                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
5455            )
5456        );
5457
5458        let expression2 = ContinuousExpression::Constant(2.0);
5459        assert_eq!(
5460            MaxMin::max(1, expression2),
5461            ContinuousExpression::BinaryOperation(
5462                BinaryOperator::Max,
5463                Box::new(ContinuousExpression::Constant(1.0)),
5464                Box::new(ContinuousExpression::Constant(2.0))
5465            )
5466        );
5467
5468        assert_eq!(
5469            MaxMin::max(1, cv2),
5470            ContinuousExpression::BinaryOperation(
5471                BinaryOperator::Max,
5472                Box::new(ContinuousExpression::Constant(1.0)),
5473                Box::new(ContinuousExpression::Variable(cv2.id()))
5474            )
5475        );
5476
5477        assert_eq!(
5478            MaxMin::max(1, crv2),
5479            ContinuousExpression::BinaryOperation(
5480                BinaryOperator::Max,
5481                Box::new(ContinuousExpression::Constant(1.0)),
5482                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
5483            )
5484        );
5485    }
5486
5487    #[test]
5488    fn min() {
5489        let mut metadata = StateMetadata::default();
5490        let iv1 = metadata.add_integer_variable(String::from("iv1"));
5491        assert!(iv1.is_ok());
5492        let iv1 = iv1.unwrap();
5493        let iv2 = metadata.add_integer_variable(String::from("iv2"));
5494        assert!(iv2.is_ok());
5495        let iv2 = iv2.unwrap();
5496        let irv1 = metadata.add_integer_resource_variable(String::from("irv1"), true);
5497        assert!(irv1.is_ok());
5498        let irv1 = irv1.unwrap();
5499        let irv2 = metadata.add_integer_resource_variable(String::from("irv2"), false);
5500        assert!(irv2.is_ok());
5501        let irv2 = irv2.unwrap();
5502        let cv1 = metadata.add_continuous_variable(String::from("cv1"));
5503        assert!(cv1.is_ok());
5504        let cv1 = cv1.unwrap();
5505        let cv2 = metadata.add_continuous_variable(String::from("cv2"));
5506        assert!(cv2.is_ok());
5507        let cv2 = cv2.unwrap();
5508        let crv1 = metadata.add_continuous_resource_variable(String::from("crv1"), true);
5509        assert!(crv1.is_ok());
5510        let crv1 = crv1.unwrap();
5511        let crv2 = metadata.add_continuous_resource_variable(String::from("crv2"), false);
5512        assert!(crv2.is_ok());
5513        let crv2 = crv2.unwrap();
5514
5515        let expression1 = ContinuousExpression::Constant(1.0);
5516        let expression2 = ContinuousExpression::Constant(2.0);
5517        assert_eq!(
5518            MaxMin::min(expression1, expression2),
5519            ContinuousExpression::BinaryOperation(
5520                BinaryOperator::Min,
5521                Box::new(ContinuousExpression::Constant(1.0)),
5522                Box::new(ContinuousExpression::Constant(2.0))
5523            )
5524        );
5525
5526        let expression1 = ContinuousExpression::Constant(1.0);
5527        assert_eq!(
5528            MaxMin::min(expression1, 2.0),
5529            ContinuousExpression::BinaryOperation(
5530                BinaryOperator::Min,
5531                Box::new(ContinuousExpression::Constant(1.0)),
5532                Box::new(ContinuousExpression::Constant(2.0))
5533            )
5534        );
5535
5536        let expression1 = ContinuousExpression::Constant(1.0);
5537        assert_eq!(
5538            MaxMin::min(expression1, cv2),
5539            ContinuousExpression::BinaryOperation(
5540                BinaryOperator::Min,
5541                Box::new(ContinuousExpression::Constant(1.0)),
5542                Box::new(ContinuousExpression::Variable(cv2.id()))
5543            )
5544        );
5545
5546        let expression1 = ContinuousExpression::Constant(1.0);
5547        assert_eq!(
5548            MaxMin::min(expression1, crv2),
5549            ContinuousExpression::BinaryOperation(
5550                BinaryOperator::Min,
5551                Box::new(ContinuousExpression::Constant(1.0)),
5552                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
5553            )
5554        );
5555
5556        let expression1 = ContinuousExpression::Constant(1.0);
5557        let expression2 = IntegerExpression::Constant(2);
5558        assert_eq!(
5559            MaxMin::min(expression1, expression2),
5560            ContinuousExpression::BinaryOperation(
5561                BinaryOperator::Min,
5562                Box::new(ContinuousExpression::Constant(1.0)),
5563                Box::new(ContinuousExpression::FromInteger(Box::new(
5564                    IntegerExpression::Constant(2)
5565                )))
5566            )
5567        );
5568
5569        let expression1 = ContinuousExpression::Constant(1.0);
5570        assert_eq!(
5571            MaxMin::min(expression1, iv2),
5572            ContinuousExpression::BinaryOperation(
5573                BinaryOperator::Min,
5574                Box::new(ContinuousExpression::Constant(1.0)),
5575                Box::new(ContinuousExpression::FromInteger(Box::new(
5576                    IntegerExpression::Variable(iv2.id())
5577                )))
5578            )
5579        );
5580
5581        let expression1 = ContinuousExpression::Constant(1.0);
5582        assert_eq!(
5583            MaxMin::min(expression1, irv2),
5584            ContinuousExpression::BinaryOperation(
5585                BinaryOperator::Min,
5586                Box::new(ContinuousExpression::Constant(1.0)),
5587                Box::new(ContinuousExpression::FromInteger(Box::new(
5588                    IntegerExpression::ResourceVariable(irv2.id())
5589                )))
5590            )
5591        );
5592
5593        let expression2 = ContinuousExpression::Constant(2.0);
5594        assert_eq!(
5595            MaxMin::min(1.0, expression2),
5596            ContinuousExpression::BinaryOperation(
5597                BinaryOperator::Min,
5598                Box::new(ContinuousExpression::Constant(1.0)),
5599                Box::new(ContinuousExpression::Constant(2.0))
5600            )
5601        );
5602
5603        assert_eq!(
5604            MaxMin::min(1.0, cv2),
5605            ContinuousExpression::BinaryOperation(
5606                BinaryOperator::Min,
5607                Box::new(ContinuousExpression::Constant(1.0)),
5608                Box::new(ContinuousExpression::Variable(cv2.id()))
5609            )
5610        );
5611
5612        assert_eq!(
5613            MaxMin::min(1.0, crv2),
5614            ContinuousExpression::BinaryOperation(
5615                BinaryOperator::Min,
5616                Box::new(ContinuousExpression::Constant(1.0)),
5617                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
5618            )
5619        );
5620
5621        let expression2 = IntegerExpression::Constant(2);
5622        assert_eq!(
5623            MaxMin::min(1.0, expression2),
5624            ContinuousExpression::BinaryOperation(
5625                BinaryOperator::Min,
5626                Box::new(ContinuousExpression::Constant(1.0)),
5627                Box::new(ContinuousExpression::FromInteger(Box::new(
5628                    IntegerExpression::Constant(2)
5629                )))
5630            )
5631        );
5632
5633        assert_eq!(
5634            MaxMin::min(1.0, iv2),
5635            ContinuousExpression::BinaryOperation(
5636                BinaryOperator::Min,
5637                Box::new(ContinuousExpression::Constant(1.0)),
5638                Box::new(ContinuousExpression::FromInteger(Box::new(
5639                    IntegerExpression::Variable(iv2.id())
5640                )))
5641            )
5642        );
5643
5644        assert_eq!(
5645            MaxMin::min(1.0, irv2),
5646            ContinuousExpression::BinaryOperation(
5647                BinaryOperator::Min,
5648                Box::new(ContinuousExpression::Constant(1.0)),
5649                Box::new(ContinuousExpression::FromInteger(Box::new(
5650                    IntegerExpression::ResourceVariable(irv2.id())
5651                )))
5652            )
5653        );
5654
5655        let expression2 = ContinuousExpression::Constant(2.0);
5656        assert_eq!(
5657            MaxMin::min(cv1, expression2),
5658            ContinuousExpression::BinaryOperation(
5659                BinaryOperator::Min,
5660                Box::new(ContinuousExpression::Variable(cv1.id())),
5661                Box::new(ContinuousExpression::Constant(2.0))
5662            )
5663        );
5664
5665        assert_eq!(
5666            MaxMin::min(cv1, 2.0),
5667            ContinuousExpression::BinaryOperation(
5668                BinaryOperator::Min,
5669                Box::new(ContinuousExpression::Variable(cv1.id())),
5670                Box::new(ContinuousExpression::Constant(2.0))
5671            )
5672        );
5673
5674        assert_eq!(
5675            MaxMin::min(cv1, cv2),
5676            ContinuousExpression::BinaryOperation(
5677                BinaryOperator::Min,
5678                Box::new(ContinuousExpression::Variable(cv1.id())),
5679                Box::new(ContinuousExpression::Variable(cv2.id()))
5680            )
5681        );
5682
5683        assert_eq!(
5684            MaxMin::min(cv1, crv2),
5685            ContinuousExpression::BinaryOperation(
5686                BinaryOperator::Min,
5687                Box::new(ContinuousExpression::Variable(cv1.id())),
5688                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
5689            )
5690        );
5691
5692        let expression2 = IntegerExpression::Constant(2);
5693        assert_eq!(
5694            MaxMin::min(cv1, expression2),
5695            ContinuousExpression::BinaryOperation(
5696                BinaryOperator::Min,
5697                Box::new(ContinuousExpression::Variable(cv1.id())),
5698                Box::new(ContinuousExpression::FromInteger(Box::new(
5699                    IntegerExpression::Constant(2)
5700                )))
5701            )
5702        );
5703
5704        assert_eq!(
5705            MaxMin::min(cv1, iv2),
5706            ContinuousExpression::BinaryOperation(
5707                BinaryOperator::Min,
5708                Box::new(ContinuousExpression::Variable(cv1.id())),
5709                Box::new(ContinuousExpression::FromInteger(Box::new(
5710                    IntegerExpression::Variable(iv2.id())
5711                )))
5712            )
5713        );
5714
5715        assert_eq!(
5716            MaxMin::min(cv1, irv2),
5717            ContinuousExpression::BinaryOperation(
5718                BinaryOperator::Min,
5719                Box::new(ContinuousExpression::Variable(cv1.id())),
5720                Box::new(ContinuousExpression::FromInteger(Box::new(
5721                    IntegerExpression::ResourceVariable(irv2.id())
5722                )))
5723            )
5724        );
5725
5726        let expression2 = ContinuousExpression::Constant(2.0);
5727        assert_eq!(
5728            MaxMin::min(crv1, expression2),
5729            ContinuousExpression::BinaryOperation(
5730                BinaryOperator::Min,
5731                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
5732                Box::new(ContinuousExpression::Constant(2.0))
5733            )
5734        );
5735
5736        assert_eq!(
5737            MaxMin::min(crv1, 2.0),
5738            ContinuousExpression::BinaryOperation(
5739                BinaryOperator::Min,
5740                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
5741                Box::new(ContinuousExpression::Constant(2.0))
5742            )
5743        );
5744
5745        assert_eq!(
5746            MaxMin::min(crv1, cv2),
5747            ContinuousExpression::BinaryOperation(
5748                BinaryOperator::Min,
5749                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
5750                Box::new(ContinuousExpression::Variable(cv2.id()))
5751            )
5752        );
5753
5754        assert_eq!(
5755            MaxMin::min(crv1, crv2),
5756            ContinuousExpression::BinaryOperation(
5757                BinaryOperator::Min,
5758                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
5759                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
5760            )
5761        );
5762
5763        let expression2 = IntegerExpression::Constant(2);
5764        assert_eq!(
5765            MaxMin::min(crv1, expression2),
5766            ContinuousExpression::BinaryOperation(
5767                BinaryOperator::Min,
5768                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
5769                Box::new(ContinuousExpression::FromInteger(Box::new(
5770                    IntegerExpression::Constant(2)
5771                )))
5772            )
5773        );
5774
5775        assert_eq!(
5776            MaxMin::min(crv1, iv2),
5777            ContinuousExpression::BinaryOperation(
5778                BinaryOperator::Min,
5779                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
5780                Box::new(ContinuousExpression::FromInteger(Box::new(
5781                    IntegerExpression::Variable(iv2.id())
5782                )))
5783            )
5784        );
5785
5786        assert_eq!(
5787            MaxMin::min(crv1, irv2),
5788            ContinuousExpression::BinaryOperation(
5789                BinaryOperator::Min,
5790                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
5791                Box::new(ContinuousExpression::FromInteger(Box::new(
5792                    IntegerExpression::ResourceVariable(irv2.id())
5793                )))
5794            )
5795        );
5796
5797        let expression1 = IntegerExpression::Constant(1);
5798        let expression2 = ContinuousExpression::Constant(2.0);
5799        assert_eq!(
5800            MaxMin::min(expression1, expression2),
5801            ContinuousExpression::BinaryOperation(
5802                BinaryOperator::Min,
5803                Box::new(ContinuousExpression::FromInteger(Box::new(
5804                    IntegerExpression::Constant(1)
5805                ))),
5806                Box::new(ContinuousExpression::Constant(2.0))
5807            )
5808        );
5809
5810        let expression1 = IntegerExpression::Constant(1);
5811        assert_eq!(
5812            MaxMin::min(expression1, 2.0),
5813            ContinuousExpression::BinaryOperation(
5814                BinaryOperator::Min,
5815                Box::new(ContinuousExpression::FromInteger(Box::new(
5816                    IntegerExpression::Constant(1)
5817                ))),
5818                Box::new(ContinuousExpression::Constant(2.0))
5819            )
5820        );
5821
5822        let expression1 = IntegerExpression::Constant(1);
5823        assert_eq!(
5824            MaxMin::min(expression1, cv2),
5825            ContinuousExpression::BinaryOperation(
5826                BinaryOperator::Min,
5827                Box::new(ContinuousExpression::FromInteger(Box::new(
5828                    IntegerExpression::Constant(1)
5829                ))),
5830                Box::new(ContinuousExpression::Variable(cv2.id()))
5831            )
5832        );
5833
5834        let expression1 = IntegerExpression::Constant(1);
5835        assert_eq!(
5836            MaxMin::min(expression1, crv2),
5837            ContinuousExpression::BinaryOperation(
5838                BinaryOperator::Min,
5839                Box::new(ContinuousExpression::FromInteger(Box::new(
5840                    IntegerExpression::Constant(1)
5841                ))),
5842                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
5843            )
5844        );
5845
5846        let expression2 = ContinuousExpression::Constant(2.0);
5847        assert_eq!(
5848            MaxMin::min(iv1, expression2),
5849            ContinuousExpression::BinaryOperation(
5850                BinaryOperator::Min,
5851                Box::new(ContinuousExpression::FromInteger(Box::new(
5852                    IntegerExpression::Variable(iv1.id())
5853                ))),
5854                Box::new(ContinuousExpression::Constant(2.0))
5855            )
5856        );
5857
5858        assert_eq!(
5859            MaxMin::min(iv1, 2.0),
5860            ContinuousExpression::BinaryOperation(
5861                BinaryOperator::Min,
5862                Box::new(ContinuousExpression::FromInteger(Box::new(
5863                    IntegerExpression::Variable(iv1.id())
5864                ))),
5865                Box::new(ContinuousExpression::Constant(2.0))
5866            )
5867        );
5868
5869        assert_eq!(
5870            MaxMin::min(iv1, cv2),
5871            ContinuousExpression::BinaryOperation(
5872                BinaryOperator::Min,
5873                Box::new(ContinuousExpression::FromInteger(Box::new(
5874                    IntegerExpression::Variable(iv1.id())
5875                ))),
5876                Box::new(ContinuousExpression::Variable(cv2.id()))
5877            )
5878        );
5879
5880        assert_eq!(
5881            MaxMin::min(iv1, crv2),
5882            ContinuousExpression::BinaryOperation(
5883                BinaryOperator::Min,
5884                Box::new(ContinuousExpression::FromInteger(Box::new(
5885                    IntegerExpression::Variable(iv1.id())
5886                ))),
5887                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
5888            )
5889        );
5890
5891        let expression2 = ContinuousExpression::Constant(2.0);
5892        assert_eq!(
5893            MaxMin::min(irv1, expression2),
5894            ContinuousExpression::BinaryOperation(
5895                BinaryOperator::Min,
5896                Box::new(ContinuousExpression::FromInteger(Box::new(
5897                    IntegerExpression::ResourceVariable(irv1.id())
5898                ))),
5899                Box::new(ContinuousExpression::Constant(2.0))
5900            )
5901        );
5902
5903        assert_eq!(
5904            MaxMin::min(irv1, 2.0),
5905            ContinuousExpression::BinaryOperation(
5906                BinaryOperator::Min,
5907                Box::new(ContinuousExpression::FromInteger(Box::new(
5908                    IntegerExpression::ResourceVariable(irv1.id())
5909                ))),
5910                Box::new(ContinuousExpression::Constant(2.0))
5911            )
5912        );
5913
5914        assert_eq!(
5915            MaxMin::min(irv1, cv2),
5916            ContinuousExpression::BinaryOperation(
5917                BinaryOperator::Min,
5918                Box::new(ContinuousExpression::FromInteger(Box::new(
5919                    IntegerExpression::ResourceVariable(irv1.id())
5920                ))),
5921                Box::new(ContinuousExpression::Variable(cv2.id()))
5922            )
5923        );
5924
5925        assert_eq!(
5926            MaxMin::min(irv1, crv2),
5927            ContinuousExpression::BinaryOperation(
5928                BinaryOperator::Min,
5929                Box::new(ContinuousExpression::FromInteger(Box::new(
5930                    IntegerExpression::ResourceVariable(irv1.id())
5931                ))),
5932                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
5933            )
5934        );
5935
5936        let expression2 = ContinuousExpression::Constant(2.0);
5937        assert_eq!(
5938            MaxMin::min(1, expression2),
5939            ContinuousExpression::BinaryOperation(
5940                BinaryOperator::Min,
5941                Box::new(ContinuousExpression::Constant(1.0)),
5942                Box::new(ContinuousExpression::Constant(2.0))
5943            )
5944        );
5945
5946        assert_eq!(
5947            MaxMin::min(1, cv2),
5948            ContinuousExpression::BinaryOperation(
5949                BinaryOperator::Min,
5950                Box::new(ContinuousExpression::Constant(1.0)),
5951                Box::new(ContinuousExpression::Variable(cv2.id()))
5952            )
5953        );
5954
5955        assert_eq!(
5956            MaxMin::min(1, crv2),
5957            ContinuousExpression::BinaryOperation(
5958                BinaryOperator::Min,
5959                Box::new(ContinuousExpression::Constant(1.0)),
5960                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
5961            )
5962        );
5963    }
5964
5965    #[test]
5966    fn pow() {
5967        let mut metadata = StateMetadata::default();
5968        let iv1 = metadata.add_integer_variable(String::from("iv1"));
5969        assert!(iv1.is_ok());
5970        let iv1 = iv1.unwrap();
5971        let iv2 = metadata.add_integer_variable(String::from("iv2"));
5972        assert!(iv2.is_ok());
5973        let iv2 = iv2.unwrap();
5974        let irv1 = metadata.add_integer_resource_variable(String::from("irv1"), true);
5975        assert!(irv1.is_ok());
5976        let irv1 = irv1.unwrap();
5977        let irv2 = metadata.add_integer_resource_variable(String::from("irv2"), false);
5978        assert!(irv2.is_ok());
5979        let irv2 = irv2.unwrap();
5980        let cv1 = metadata.add_continuous_variable(String::from("cv1"));
5981        assert!(cv1.is_ok());
5982        let cv1 = cv1.unwrap();
5983        let cv2 = metadata.add_continuous_variable(String::from("cv2"));
5984        assert!(cv2.is_ok());
5985        let cv2 = cv2.unwrap();
5986        let crv1 = metadata.add_continuous_resource_variable(String::from("crv1"), true);
5987        assert!(crv1.is_ok());
5988        let crv1 = crv1.unwrap();
5989        let crv2 = metadata.add_continuous_resource_variable(String::from("crv2"), false);
5990        assert!(crv2.is_ok());
5991        let crv2 = crv2.unwrap();
5992
5993        let expression1 = ContinuousExpression::Constant(1.0);
5994        let expression2 = ContinuousExpression::Constant(2.0);
5995        assert_eq!(
5996            ContinuousBinaryOperation::pow(expression1, expression2),
5997            ContinuousExpression::ContinuousBinaryOperation(
5998                ContinuousBinaryOperator::Pow,
5999                Box::new(ContinuousExpression::Constant(1.0)),
6000                Box::new(ContinuousExpression::Constant(2.0))
6001            )
6002        );
6003
6004        let expression1 = ContinuousExpression::Constant(1.0);
6005        assert_eq!(
6006            ContinuousBinaryOperation::pow(expression1, 2.0),
6007            ContinuousExpression::ContinuousBinaryOperation(
6008                ContinuousBinaryOperator::Pow,
6009                Box::new(ContinuousExpression::Constant(1.0)),
6010                Box::new(ContinuousExpression::Constant(2.0))
6011            )
6012        );
6013
6014        let expression1 = ContinuousExpression::Constant(1.0);
6015        assert_eq!(
6016            ContinuousBinaryOperation::pow(expression1, cv2),
6017            ContinuousExpression::ContinuousBinaryOperation(
6018                ContinuousBinaryOperator::Pow,
6019                Box::new(ContinuousExpression::Constant(1.0)),
6020                Box::new(ContinuousExpression::Variable(cv2.id()))
6021            )
6022        );
6023
6024        let expression1 = ContinuousExpression::Constant(1.0);
6025        assert_eq!(
6026            ContinuousBinaryOperation::pow(expression1, crv2),
6027            ContinuousExpression::ContinuousBinaryOperation(
6028                ContinuousBinaryOperator::Pow,
6029                Box::new(ContinuousExpression::Constant(1.0)),
6030                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
6031            )
6032        );
6033
6034        let expression1 = ContinuousExpression::Constant(1.0);
6035        let expression2 = IntegerExpression::Constant(2);
6036        assert_eq!(
6037            ContinuousBinaryOperation::pow(expression1, expression2),
6038            ContinuousExpression::ContinuousBinaryOperation(
6039                ContinuousBinaryOperator::Pow,
6040                Box::new(ContinuousExpression::Constant(1.0)),
6041                Box::new(ContinuousExpression::FromInteger(Box::new(
6042                    IntegerExpression::Constant(2)
6043                )))
6044            )
6045        );
6046
6047        let expression1 = ContinuousExpression::Constant(1.0);
6048        assert_eq!(
6049            ContinuousBinaryOperation::pow(expression1, iv2),
6050            ContinuousExpression::ContinuousBinaryOperation(
6051                ContinuousBinaryOperator::Pow,
6052                Box::new(ContinuousExpression::Constant(1.0)),
6053                Box::new(ContinuousExpression::FromInteger(Box::new(
6054                    IntegerExpression::Variable(iv2.id())
6055                )))
6056            )
6057        );
6058
6059        let expression1 = ContinuousExpression::Constant(1.0);
6060        assert_eq!(
6061            ContinuousBinaryOperation::pow(expression1, irv2),
6062            ContinuousExpression::ContinuousBinaryOperation(
6063                ContinuousBinaryOperator::Pow,
6064                Box::new(ContinuousExpression::Constant(1.0)),
6065                Box::new(ContinuousExpression::FromInteger(Box::new(
6066                    IntegerExpression::ResourceVariable(irv2.id())
6067                )))
6068            )
6069        );
6070
6071        let expression2 = ContinuousExpression::Constant(2.0);
6072        assert_eq!(
6073            ContinuousBinaryOperation::pow(1.0, expression2),
6074            ContinuousExpression::ContinuousBinaryOperation(
6075                ContinuousBinaryOperator::Pow,
6076                Box::new(ContinuousExpression::Constant(1.0)),
6077                Box::new(ContinuousExpression::Constant(2.0))
6078            )
6079        );
6080
6081        assert_eq!(
6082            ContinuousBinaryOperation::pow(1.0, cv2),
6083            ContinuousExpression::ContinuousBinaryOperation(
6084                ContinuousBinaryOperator::Pow,
6085                Box::new(ContinuousExpression::Constant(1.0)),
6086                Box::new(ContinuousExpression::Variable(cv2.id()))
6087            )
6088        );
6089
6090        assert_eq!(
6091            ContinuousBinaryOperation::pow(1.0, crv2),
6092            ContinuousExpression::ContinuousBinaryOperation(
6093                ContinuousBinaryOperator::Pow,
6094                Box::new(ContinuousExpression::Constant(1.0)),
6095                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
6096            )
6097        );
6098
6099        let expression2 = IntegerExpression::Constant(2);
6100        assert_eq!(
6101            ContinuousBinaryOperation::pow(1.0, expression2),
6102            ContinuousExpression::ContinuousBinaryOperation(
6103                ContinuousBinaryOperator::Pow,
6104                Box::new(ContinuousExpression::Constant(1.0)),
6105                Box::new(ContinuousExpression::FromInteger(Box::new(
6106                    IntegerExpression::Constant(2)
6107                )))
6108            )
6109        );
6110
6111        assert_eq!(
6112            ContinuousBinaryOperation::pow(1.0, iv2),
6113            ContinuousExpression::ContinuousBinaryOperation(
6114                ContinuousBinaryOperator::Pow,
6115                Box::new(ContinuousExpression::Constant(1.0)),
6116                Box::new(ContinuousExpression::FromInteger(Box::new(
6117                    IntegerExpression::Variable(iv2.id())
6118                )))
6119            )
6120        );
6121
6122        assert_eq!(
6123            ContinuousBinaryOperation::pow(1.0, irv2),
6124            ContinuousExpression::ContinuousBinaryOperation(
6125                ContinuousBinaryOperator::Pow,
6126                Box::new(ContinuousExpression::Constant(1.0)),
6127                Box::new(ContinuousExpression::FromInteger(Box::new(
6128                    IntegerExpression::ResourceVariable(irv2.id())
6129                )))
6130            )
6131        );
6132
6133        let expression2 = ContinuousExpression::Constant(2.0);
6134        assert_eq!(
6135            ContinuousBinaryOperation::pow(cv1, expression2),
6136            ContinuousExpression::ContinuousBinaryOperation(
6137                ContinuousBinaryOperator::Pow,
6138                Box::new(ContinuousExpression::Variable(cv1.id())),
6139                Box::new(ContinuousExpression::Constant(2.0))
6140            )
6141        );
6142
6143        assert_eq!(
6144            ContinuousBinaryOperation::pow(cv1, 2.0),
6145            ContinuousExpression::ContinuousBinaryOperation(
6146                ContinuousBinaryOperator::Pow,
6147                Box::new(ContinuousExpression::Variable(cv1.id())),
6148                Box::new(ContinuousExpression::Constant(2.0))
6149            )
6150        );
6151
6152        assert_eq!(
6153            ContinuousBinaryOperation::pow(cv1, cv2),
6154            ContinuousExpression::ContinuousBinaryOperation(
6155                ContinuousBinaryOperator::Pow,
6156                Box::new(ContinuousExpression::Variable(cv1.id())),
6157                Box::new(ContinuousExpression::Variable(cv2.id()))
6158            )
6159        );
6160
6161        assert_eq!(
6162            ContinuousBinaryOperation::pow(cv1, crv2),
6163            ContinuousExpression::ContinuousBinaryOperation(
6164                ContinuousBinaryOperator::Pow,
6165                Box::new(ContinuousExpression::Variable(cv1.id())),
6166                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
6167            )
6168        );
6169
6170        let expression2 = IntegerExpression::Constant(2);
6171        assert_eq!(
6172            ContinuousBinaryOperation::pow(cv1, expression2),
6173            ContinuousExpression::ContinuousBinaryOperation(
6174                ContinuousBinaryOperator::Pow,
6175                Box::new(ContinuousExpression::Variable(cv1.id())),
6176                Box::new(ContinuousExpression::FromInteger(Box::new(
6177                    IntegerExpression::Constant(2)
6178                )))
6179            )
6180        );
6181
6182        assert_eq!(
6183            ContinuousBinaryOperation::pow(cv1, iv2),
6184            ContinuousExpression::ContinuousBinaryOperation(
6185                ContinuousBinaryOperator::Pow,
6186                Box::new(ContinuousExpression::Variable(cv1.id())),
6187                Box::new(ContinuousExpression::FromInteger(Box::new(
6188                    IntegerExpression::Variable(iv2.id())
6189                )))
6190            )
6191        );
6192
6193        assert_eq!(
6194            ContinuousBinaryOperation::pow(cv1, irv2),
6195            ContinuousExpression::ContinuousBinaryOperation(
6196                ContinuousBinaryOperator::Pow,
6197                Box::new(ContinuousExpression::Variable(cv1.id())),
6198                Box::new(ContinuousExpression::FromInteger(Box::new(
6199                    IntegerExpression::ResourceVariable(irv2.id())
6200                )))
6201            )
6202        );
6203
6204        let expression2 = ContinuousExpression::Constant(2.0);
6205        assert_eq!(
6206            ContinuousBinaryOperation::pow(crv1, expression2),
6207            ContinuousExpression::ContinuousBinaryOperation(
6208                ContinuousBinaryOperator::Pow,
6209                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
6210                Box::new(ContinuousExpression::Constant(2.0))
6211            )
6212        );
6213
6214        assert_eq!(
6215            ContinuousBinaryOperation::pow(crv1, 2.0),
6216            ContinuousExpression::ContinuousBinaryOperation(
6217                ContinuousBinaryOperator::Pow,
6218                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
6219                Box::new(ContinuousExpression::Constant(2.0))
6220            )
6221        );
6222
6223        assert_eq!(
6224            ContinuousBinaryOperation::pow(crv1, cv2),
6225            ContinuousExpression::ContinuousBinaryOperation(
6226                ContinuousBinaryOperator::Pow,
6227                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
6228                Box::new(ContinuousExpression::Variable(cv2.id()))
6229            )
6230        );
6231
6232        assert_eq!(
6233            ContinuousBinaryOperation::pow(crv1, crv2),
6234            ContinuousExpression::ContinuousBinaryOperation(
6235                ContinuousBinaryOperator::Pow,
6236                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
6237                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
6238            )
6239        );
6240
6241        let expression2 = IntegerExpression::Constant(2);
6242        assert_eq!(
6243            ContinuousBinaryOperation::pow(crv1, expression2),
6244            ContinuousExpression::ContinuousBinaryOperation(
6245                ContinuousBinaryOperator::Pow,
6246                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
6247                Box::new(ContinuousExpression::FromInteger(Box::new(
6248                    IntegerExpression::Constant(2)
6249                )))
6250            )
6251        );
6252
6253        assert_eq!(
6254            ContinuousBinaryOperation::pow(crv1, iv2),
6255            ContinuousExpression::ContinuousBinaryOperation(
6256                ContinuousBinaryOperator::Pow,
6257                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
6258                Box::new(ContinuousExpression::FromInteger(Box::new(
6259                    IntegerExpression::Variable(iv2.id())
6260                )))
6261            )
6262        );
6263
6264        assert_eq!(
6265            ContinuousBinaryOperation::pow(crv1, irv2),
6266            ContinuousExpression::ContinuousBinaryOperation(
6267                ContinuousBinaryOperator::Pow,
6268                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
6269                Box::new(ContinuousExpression::FromInteger(Box::new(
6270                    IntegerExpression::ResourceVariable(irv2.id())
6271                )))
6272            )
6273        );
6274
6275        let expression1 = IntegerExpression::Constant(1);
6276        let expression2 = ContinuousExpression::Constant(2.0);
6277        assert_eq!(
6278            ContinuousBinaryOperation::pow(expression1, expression2),
6279            ContinuousExpression::ContinuousBinaryOperation(
6280                ContinuousBinaryOperator::Pow,
6281                Box::new(ContinuousExpression::FromInteger(Box::new(
6282                    IntegerExpression::Constant(1)
6283                ))),
6284                Box::new(ContinuousExpression::Constant(2.0))
6285            )
6286        );
6287
6288        let expression1 = IntegerExpression::Constant(1);
6289        assert_eq!(
6290            ContinuousBinaryOperation::pow(expression1, 2.0),
6291            ContinuousExpression::ContinuousBinaryOperation(
6292                ContinuousBinaryOperator::Pow,
6293                Box::new(ContinuousExpression::FromInteger(Box::new(
6294                    IntegerExpression::Constant(1)
6295                ))),
6296                Box::new(ContinuousExpression::Constant(2.0))
6297            )
6298        );
6299
6300        let expression1 = IntegerExpression::Constant(1);
6301        assert_eq!(
6302            ContinuousBinaryOperation::pow(expression1, cv2),
6303            ContinuousExpression::ContinuousBinaryOperation(
6304                ContinuousBinaryOperator::Pow,
6305                Box::new(ContinuousExpression::FromInteger(Box::new(
6306                    IntegerExpression::Constant(1)
6307                ))),
6308                Box::new(ContinuousExpression::Variable(cv2.id()))
6309            )
6310        );
6311
6312        let expression1 = IntegerExpression::Constant(1);
6313        assert_eq!(
6314            ContinuousBinaryOperation::pow(expression1, crv2),
6315            ContinuousExpression::ContinuousBinaryOperation(
6316                ContinuousBinaryOperator::Pow,
6317                Box::new(ContinuousExpression::FromInteger(Box::new(
6318                    IntegerExpression::Constant(1)
6319                ))),
6320                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
6321            )
6322        );
6323
6324        let expression2 = ContinuousExpression::Constant(2.0);
6325        assert_eq!(
6326            ContinuousBinaryOperation::pow(iv1, expression2),
6327            ContinuousExpression::ContinuousBinaryOperation(
6328                ContinuousBinaryOperator::Pow,
6329                Box::new(ContinuousExpression::FromInteger(Box::new(
6330                    IntegerExpression::Variable(iv1.id())
6331                ))),
6332                Box::new(ContinuousExpression::Constant(2.0))
6333            )
6334        );
6335
6336        assert_eq!(
6337            ContinuousBinaryOperation::pow(iv1, 2.0),
6338            ContinuousExpression::ContinuousBinaryOperation(
6339                ContinuousBinaryOperator::Pow,
6340                Box::new(ContinuousExpression::FromInteger(Box::new(
6341                    IntegerExpression::Variable(iv1.id())
6342                ))),
6343                Box::new(ContinuousExpression::Constant(2.0))
6344            )
6345        );
6346
6347        assert_eq!(
6348            ContinuousBinaryOperation::pow(iv1, cv2),
6349            ContinuousExpression::ContinuousBinaryOperation(
6350                ContinuousBinaryOperator::Pow,
6351                Box::new(ContinuousExpression::FromInteger(Box::new(
6352                    IntegerExpression::Variable(iv1.id())
6353                ))),
6354                Box::new(ContinuousExpression::Variable(cv2.id()))
6355            )
6356        );
6357
6358        assert_eq!(
6359            ContinuousBinaryOperation::pow(iv1, crv2),
6360            ContinuousExpression::ContinuousBinaryOperation(
6361                ContinuousBinaryOperator::Pow,
6362                Box::new(ContinuousExpression::FromInteger(Box::new(
6363                    IntegerExpression::Variable(iv1.id())
6364                ))),
6365                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
6366            )
6367        );
6368
6369        let expression2 = ContinuousExpression::Constant(2.0);
6370        assert_eq!(
6371            ContinuousBinaryOperation::pow(irv1, expression2),
6372            ContinuousExpression::ContinuousBinaryOperation(
6373                ContinuousBinaryOperator::Pow,
6374                Box::new(ContinuousExpression::FromInteger(Box::new(
6375                    IntegerExpression::ResourceVariable(irv1.id())
6376                ))),
6377                Box::new(ContinuousExpression::Constant(2.0))
6378            )
6379        );
6380
6381        assert_eq!(
6382            ContinuousBinaryOperation::pow(irv1, 2.0),
6383            ContinuousExpression::ContinuousBinaryOperation(
6384                ContinuousBinaryOperator::Pow,
6385                Box::new(ContinuousExpression::FromInteger(Box::new(
6386                    IntegerExpression::ResourceVariable(irv1.id())
6387                ))),
6388                Box::new(ContinuousExpression::Constant(2.0))
6389            )
6390        );
6391
6392        assert_eq!(
6393            ContinuousBinaryOperation::pow(irv1, cv2),
6394            ContinuousExpression::ContinuousBinaryOperation(
6395                ContinuousBinaryOperator::Pow,
6396                Box::new(ContinuousExpression::FromInteger(Box::new(
6397                    IntegerExpression::ResourceVariable(irv1.id())
6398                ))),
6399                Box::new(ContinuousExpression::Variable(cv2.id()))
6400            )
6401        );
6402
6403        assert_eq!(
6404            ContinuousBinaryOperation::pow(irv1, crv2),
6405            ContinuousExpression::ContinuousBinaryOperation(
6406                ContinuousBinaryOperator::Pow,
6407                Box::new(ContinuousExpression::FromInteger(Box::new(
6408                    IntegerExpression::ResourceVariable(irv1.id())
6409                ))),
6410                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
6411            )
6412        );
6413
6414        let expression2 = ContinuousExpression::Constant(2.0);
6415        assert_eq!(
6416            ContinuousBinaryOperation::pow(1, expression2),
6417            ContinuousExpression::ContinuousBinaryOperation(
6418                ContinuousBinaryOperator::Pow,
6419                Box::new(ContinuousExpression::Constant(1.0)),
6420                Box::new(ContinuousExpression::Constant(2.0))
6421            )
6422        );
6423
6424        assert_eq!(
6425            ContinuousBinaryOperation::pow(1, cv2),
6426            ContinuousExpression::ContinuousBinaryOperation(
6427                ContinuousBinaryOperator::Pow,
6428                Box::new(ContinuousExpression::Constant(1.0)),
6429                Box::new(ContinuousExpression::Variable(cv2.id()))
6430            )
6431        );
6432
6433        assert_eq!(
6434            ContinuousBinaryOperation::pow(1, crv2),
6435            ContinuousExpression::ContinuousBinaryOperation(
6436                ContinuousBinaryOperator::Pow,
6437                Box::new(ContinuousExpression::Constant(1.0)),
6438                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
6439            )
6440        );
6441    }
6442
6443    #[test]
6444    fn log() {
6445        let mut metadata = StateMetadata::default();
6446        let iv1 = metadata.add_integer_variable(String::from("iv1"));
6447        assert!(iv1.is_ok());
6448        let iv1 = iv1.unwrap();
6449        let iv2 = metadata.add_integer_variable(String::from("iv2"));
6450        assert!(iv2.is_ok());
6451        let iv2 = iv2.unwrap();
6452        let irv1 = metadata.add_integer_resource_variable(String::from("irv1"), true);
6453        assert!(irv1.is_ok());
6454        let irv1 = irv1.unwrap();
6455        let irv2 = metadata.add_integer_resource_variable(String::from("irv2"), false);
6456        assert!(irv2.is_ok());
6457        let irv2 = irv2.unwrap();
6458        let cv1 = metadata.add_continuous_variable(String::from("cv1"));
6459        assert!(cv1.is_ok());
6460        let cv1 = cv1.unwrap();
6461        let cv2 = metadata.add_continuous_variable(String::from("cv2"));
6462        assert!(cv2.is_ok());
6463        let cv2 = cv2.unwrap();
6464        let crv1 = metadata.add_continuous_resource_variable(String::from("crv1"), true);
6465        assert!(crv1.is_ok());
6466        let crv1 = crv1.unwrap();
6467        let crv2 = metadata.add_continuous_resource_variable(String::from("crv2"), false);
6468        assert!(crv2.is_ok());
6469        let crv2 = crv2.unwrap();
6470
6471        let expression1 = ContinuousExpression::Constant(1.0);
6472        let expression2 = ContinuousExpression::Constant(2.0);
6473        assert_eq!(
6474            ContinuousBinaryOperation::log(expression1, expression2),
6475            ContinuousExpression::ContinuousBinaryOperation(
6476                ContinuousBinaryOperator::Log,
6477                Box::new(ContinuousExpression::Constant(1.0)),
6478                Box::new(ContinuousExpression::Constant(2.0))
6479            )
6480        );
6481
6482        let expression1 = ContinuousExpression::Constant(1.0);
6483        assert_eq!(
6484            ContinuousBinaryOperation::log(expression1, 2.0),
6485            ContinuousExpression::ContinuousBinaryOperation(
6486                ContinuousBinaryOperator::Log,
6487                Box::new(ContinuousExpression::Constant(1.0)),
6488                Box::new(ContinuousExpression::Constant(2.0))
6489            )
6490        );
6491
6492        let expression1 = ContinuousExpression::Constant(1.0);
6493        assert_eq!(
6494            ContinuousBinaryOperation::log(expression1, cv2),
6495            ContinuousExpression::ContinuousBinaryOperation(
6496                ContinuousBinaryOperator::Log,
6497                Box::new(ContinuousExpression::Constant(1.0)),
6498                Box::new(ContinuousExpression::Variable(cv2.id()))
6499            )
6500        );
6501
6502        let expression1 = ContinuousExpression::Constant(1.0);
6503        assert_eq!(
6504            ContinuousBinaryOperation::log(expression1, crv2),
6505            ContinuousExpression::ContinuousBinaryOperation(
6506                ContinuousBinaryOperator::Log,
6507                Box::new(ContinuousExpression::Constant(1.0)),
6508                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
6509            )
6510        );
6511
6512        let expression1 = ContinuousExpression::Constant(1.0);
6513        let expression2 = IntegerExpression::Constant(2);
6514        assert_eq!(
6515            ContinuousBinaryOperation::log(expression1, expression2),
6516            ContinuousExpression::ContinuousBinaryOperation(
6517                ContinuousBinaryOperator::Log,
6518                Box::new(ContinuousExpression::Constant(1.0)),
6519                Box::new(ContinuousExpression::FromInteger(Box::new(
6520                    IntegerExpression::Constant(2)
6521                )))
6522            )
6523        );
6524
6525        let expression1 = ContinuousExpression::Constant(1.0);
6526        assert_eq!(
6527            ContinuousBinaryOperation::log(expression1, iv2),
6528            ContinuousExpression::ContinuousBinaryOperation(
6529                ContinuousBinaryOperator::Log,
6530                Box::new(ContinuousExpression::Constant(1.0)),
6531                Box::new(ContinuousExpression::FromInteger(Box::new(
6532                    IntegerExpression::Variable(iv2.id())
6533                )))
6534            )
6535        );
6536
6537        let expression1 = ContinuousExpression::Constant(1.0);
6538        assert_eq!(
6539            ContinuousBinaryOperation::log(expression1, irv2),
6540            ContinuousExpression::ContinuousBinaryOperation(
6541                ContinuousBinaryOperator::Log,
6542                Box::new(ContinuousExpression::Constant(1.0)),
6543                Box::new(ContinuousExpression::FromInteger(Box::new(
6544                    IntegerExpression::ResourceVariable(irv2.id())
6545                )))
6546            )
6547        );
6548
6549        let expression2 = ContinuousExpression::Constant(2.0);
6550        assert_eq!(
6551            ContinuousBinaryOperation::log(1.0, expression2),
6552            ContinuousExpression::ContinuousBinaryOperation(
6553                ContinuousBinaryOperator::Log,
6554                Box::new(ContinuousExpression::Constant(1.0)),
6555                Box::new(ContinuousExpression::Constant(2.0))
6556            )
6557        );
6558
6559        assert_eq!(
6560            ContinuousBinaryOperation::log(1.0, cv2),
6561            ContinuousExpression::ContinuousBinaryOperation(
6562                ContinuousBinaryOperator::Log,
6563                Box::new(ContinuousExpression::Constant(1.0)),
6564                Box::new(ContinuousExpression::Variable(cv2.id()))
6565            )
6566        );
6567
6568        assert_eq!(
6569            ContinuousBinaryOperation::log(1.0, crv2),
6570            ContinuousExpression::ContinuousBinaryOperation(
6571                ContinuousBinaryOperator::Log,
6572                Box::new(ContinuousExpression::Constant(1.0)),
6573                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
6574            )
6575        );
6576
6577        let expression2 = IntegerExpression::Constant(2);
6578        assert_eq!(
6579            ContinuousBinaryOperation::log(1.0, expression2),
6580            ContinuousExpression::ContinuousBinaryOperation(
6581                ContinuousBinaryOperator::Log,
6582                Box::new(ContinuousExpression::Constant(1.0)),
6583                Box::new(ContinuousExpression::FromInteger(Box::new(
6584                    IntegerExpression::Constant(2)
6585                )))
6586            )
6587        );
6588
6589        assert_eq!(
6590            ContinuousBinaryOperation::log(1.0, iv2),
6591            ContinuousExpression::ContinuousBinaryOperation(
6592                ContinuousBinaryOperator::Log,
6593                Box::new(ContinuousExpression::Constant(1.0)),
6594                Box::new(ContinuousExpression::FromInteger(Box::new(
6595                    IntegerExpression::Variable(iv2.id())
6596                )))
6597            )
6598        );
6599
6600        assert_eq!(
6601            ContinuousBinaryOperation::log(1.0, irv2),
6602            ContinuousExpression::ContinuousBinaryOperation(
6603                ContinuousBinaryOperator::Log,
6604                Box::new(ContinuousExpression::Constant(1.0)),
6605                Box::new(ContinuousExpression::FromInteger(Box::new(
6606                    IntegerExpression::ResourceVariable(irv2.id())
6607                )))
6608            )
6609        );
6610
6611        let expression2 = ContinuousExpression::Constant(2.0);
6612        assert_eq!(
6613            ContinuousBinaryOperation::log(cv1, expression2),
6614            ContinuousExpression::ContinuousBinaryOperation(
6615                ContinuousBinaryOperator::Log,
6616                Box::new(ContinuousExpression::Variable(cv1.id())),
6617                Box::new(ContinuousExpression::Constant(2.0))
6618            )
6619        );
6620
6621        assert_eq!(
6622            ContinuousBinaryOperation::log(cv1, 2.0),
6623            ContinuousExpression::ContinuousBinaryOperation(
6624                ContinuousBinaryOperator::Log,
6625                Box::new(ContinuousExpression::Variable(cv1.id())),
6626                Box::new(ContinuousExpression::Constant(2.0))
6627            )
6628        );
6629
6630        assert_eq!(
6631            ContinuousBinaryOperation::log(cv1, cv2),
6632            ContinuousExpression::ContinuousBinaryOperation(
6633                ContinuousBinaryOperator::Log,
6634                Box::new(ContinuousExpression::Variable(cv1.id())),
6635                Box::new(ContinuousExpression::Variable(cv2.id()))
6636            )
6637        );
6638
6639        assert_eq!(
6640            ContinuousBinaryOperation::log(cv1, crv2),
6641            ContinuousExpression::ContinuousBinaryOperation(
6642                ContinuousBinaryOperator::Log,
6643                Box::new(ContinuousExpression::Variable(cv1.id())),
6644                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
6645            )
6646        );
6647
6648        let expression2 = IntegerExpression::Constant(2);
6649        assert_eq!(
6650            ContinuousBinaryOperation::log(cv1, expression2),
6651            ContinuousExpression::ContinuousBinaryOperation(
6652                ContinuousBinaryOperator::Log,
6653                Box::new(ContinuousExpression::Variable(cv1.id())),
6654                Box::new(ContinuousExpression::FromInteger(Box::new(
6655                    IntegerExpression::Constant(2)
6656                )))
6657            )
6658        );
6659
6660        assert_eq!(
6661            ContinuousBinaryOperation::log(cv1, iv2),
6662            ContinuousExpression::ContinuousBinaryOperation(
6663                ContinuousBinaryOperator::Log,
6664                Box::new(ContinuousExpression::Variable(cv1.id())),
6665                Box::new(ContinuousExpression::FromInteger(Box::new(
6666                    IntegerExpression::Variable(iv2.id())
6667                )))
6668            )
6669        );
6670
6671        assert_eq!(
6672            ContinuousBinaryOperation::log(cv1, irv2),
6673            ContinuousExpression::ContinuousBinaryOperation(
6674                ContinuousBinaryOperator::Log,
6675                Box::new(ContinuousExpression::Variable(cv1.id())),
6676                Box::new(ContinuousExpression::FromInteger(Box::new(
6677                    IntegerExpression::ResourceVariable(irv2.id())
6678                )))
6679            )
6680        );
6681
6682        let expression2 = ContinuousExpression::Constant(2.0);
6683        assert_eq!(
6684            ContinuousBinaryOperation::log(crv1, expression2),
6685            ContinuousExpression::ContinuousBinaryOperation(
6686                ContinuousBinaryOperator::Log,
6687                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
6688                Box::new(ContinuousExpression::Constant(2.0))
6689            )
6690        );
6691
6692        assert_eq!(
6693            ContinuousBinaryOperation::log(crv1, 2.0),
6694            ContinuousExpression::ContinuousBinaryOperation(
6695                ContinuousBinaryOperator::Log,
6696                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
6697                Box::new(ContinuousExpression::Constant(2.0))
6698            )
6699        );
6700
6701        assert_eq!(
6702            ContinuousBinaryOperation::log(crv1, cv2),
6703            ContinuousExpression::ContinuousBinaryOperation(
6704                ContinuousBinaryOperator::Log,
6705                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
6706                Box::new(ContinuousExpression::Variable(cv2.id()))
6707            )
6708        );
6709
6710        assert_eq!(
6711            ContinuousBinaryOperation::log(crv1, crv2),
6712            ContinuousExpression::ContinuousBinaryOperation(
6713                ContinuousBinaryOperator::Log,
6714                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
6715                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
6716            )
6717        );
6718
6719        let expression2 = IntegerExpression::Constant(2);
6720        assert_eq!(
6721            ContinuousBinaryOperation::log(crv1, expression2),
6722            ContinuousExpression::ContinuousBinaryOperation(
6723                ContinuousBinaryOperator::Log,
6724                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
6725                Box::new(ContinuousExpression::FromInteger(Box::new(
6726                    IntegerExpression::Constant(2)
6727                )))
6728            )
6729        );
6730
6731        assert_eq!(
6732            ContinuousBinaryOperation::log(crv1, iv2),
6733            ContinuousExpression::ContinuousBinaryOperation(
6734                ContinuousBinaryOperator::Log,
6735                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
6736                Box::new(ContinuousExpression::FromInteger(Box::new(
6737                    IntegerExpression::Variable(iv2.id())
6738                )))
6739            )
6740        );
6741
6742        assert_eq!(
6743            ContinuousBinaryOperation::log(crv1, irv2),
6744            ContinuousExpression::ContinuousBinaryOperation(
6745                ContinuousBinaryOperator::Log,
6746                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
6747                Box::new(ContinuousExpression::FromInteger(Box::new(
6748                    IntegerExpression::ResourceVariable(irv2.id())
6749                )))
6750            )
6751        );
6752
6753        let expression1 = IntegerExpression::Constant(1);
6754        let expression2 = ContinuousExpression::Constant(2.0);
6755        assert_eq!(
6756            ContinuousBinaryOperation::log(expression1, expression2),
6757            ContinuousExpression::ContinuousBinaryOperation(
6758                ContinuousBinaryOperator::Log,
6759                Box::new(ContinuousExpression::FromInteger(Box::new(
6760                    IntegerExpression::Constant(1)
6761                ))),
6762                Box::new(ContinuousExpression::Constant(2.0))
6763            )
6764        );
6765
6766        let expression1 = IntegerExpression::Constant(1);
6767        assert_eq!(
6768            ContinuousBinaryOperation::log(expression1, 2.0),
6769            ContinuousExpression::ContinuousBinaryOperation(
6770                ContinuousBinaryOperator::Log,
6771                Box::new(ContinuousExpression::FromInteger(Box::new(
6772                    IntegerExpression::Constant(1)
6773                ))),
6774                Box::new(ContinuousExpression::Constant(2.0))
6775            )
6776        );
6777
6778        let expression1 = IntegerExpression::Constant(1);
6779        assert_eq!(
6780            ContinuousBinaryOperation::log(expression1, cv2),
6781            ContinuousExpression::ContinuousBinaryOperation(
6782                ContinuousBinaryOperator::Log,
6783                Box::new(ContinuousExpression::FromInteger(Box::new(
6784                    IntegerExpression::Constant(1)
6785                ))),
6786                Box::new(ContinuousExpression::Variable(cv2.id()))
6787            )
6788        );
6789
6790        let expression1 = IntegerExpression::Constant(1);
6791        assert_eq!(
6792            ContinuousBinaryOperation::log(expression1, crv2),
6793            ContinuousExpression::ContinuousBinaryOperation(
6794                ContinuousBinaryOperator::Log,
6795                Box::new(ContinuousExpression::FromInteger(Box::new(
6796                    IntegerExpression::Constant(1)
6797                ))),
6798                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
6799            )
6800        );
6801
6802        let expression2 = ContinuousExpression::Constant(2.0);
6803        assert_eq!(
6804            ContinuousBinaryOperation::log(iv1, expression2),
6805            ContinuousExpression::ContinuousBinaryOperation(
6806                ContinuousBinaryOperator::Log,
6807                Box::new(ContinuousExpression::FromInteger(Box::new(
6808                    IntegerExpression::Variable(iv1.id())
6809                ))),
6810                Box::new(ContinuousExpression::Constant(2.0))
6811            )
6812        );
6813
6814        assert_eq!(
6815            ContinuousBinaryOperation::log(iv1, 2.0),
6816            ContinuousExpression::ContinuousBinaryOperation(
6817                ContinuousBinaryOperator::Log,
6818                Box::new(ContinuousExpression::FromInteger(Box::new(
6819                    IntegerExpression::Variable(iv1.id())
6820                ))),
6821                Box::new(ContinuousExpression::Constant(2.0))
6822            )
6823        );
6824
6825        assert_eq!(
6826            ContinuousBinaryOperation::log(iv1, cv2),
6827            ContinuousExpression::ContinuousBinaryOperation(
6828                ContinuousBinaryOperator::Log,
6829                Box::new(ContinuousExpression::FromInteger(Box::new(
6830                    IntegerExpression::Variable(iv1.id())
6831                ))),
6832                Box::new(ContinuousExpression::Variable(cv2.id()))
6833            )
6834        );
6835
6836        assert_eq!(
6837            ContinuousBinaryOperation::log(iv1, crv2),
6838            ContinuousExpression::ContinuousBinaryOperation(
6839                ContinuousBinaryOperator::Log,
6840                Box::new(ContinuousExpression::FromInteger(Box::new(
6841                    IntegerExpression::Variable(iv1.id())
6842                ))),
6843                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
6844            )
6845        );
6846
6847        let expression2 = ContinuousExpression::Constant(2.0);
6848        assert_eq!(
6849            ContinuousBinaryOperation::log(irv1, expression2),
6850            ContinuousExpression::ContinuousBinaryOperation(
6851                ContinuousBinaryOperator::Log,
6852                Box::new(ContinuousExpression::FromInteger(Box::new(
6853                    IntegerExpression::ResourceVariable(irv1.id())
6854                ))),
6855                Box::new(ContinuousExpression::Constant(2.0))
6856            )
6857        );
6858
6859        assert_eq!(
6860            ContinuousBinaryOperation::log(irv1, 2.0),
6861            ContinuousExpression::ContinuousBinaryOperation(
6862                ContinuousBinaryOperator::Log,
6863                Box::new(ContinuousExpression::FromInteger(Box::new(
6864                    IntegerExpression::ResourceVariable(irv1.id())
6865                ))),
6866                Box::new(ContinuousExpression::Constant(2.0))
6867            )
6868        );
6869
6870        assert_eq!(
6871            ContinuousBinaryOperation::log(irv1, cv2),
6872            ContinuousExpression::ContinuousBinaryOperation(
6873                ContinuousBinaryOperator::Log,
6874                Box::new(ContinuousExpression::FromInteger(Box::new(
6875                    IntegerExpression::ResourceVariable(irv1.id())
6876                ))),
6877                Box::new(ContinuousExpression::Variable(cv2.id()))
6878            )
6879        );
6880
6881        assert_eq!(
6882            ContinuousBinaryOperation::log(irv1, crv2),
6883            ContinuousExpression::ContinuousBinaryOperation(
6884                ContinuousBinaryOperator::Log,
6885                Box::new(ContinuousExpression::FromInteger(Box::new(
6886                    IntegerExpression::ResourceVariable(irv1.id())
6887                ))),
6888                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
6889            )
6890        );
6891
6892        let expression2 = ContinuousExpression::Constant(2.0);
6893        assert_eq!(
6894            ContinuousBinaryOperation::log(1, expression2),
6895            ContinuousExpression::ContinuousBinaryOperation(
6896                ContinuousBinaryOperator::Log,
6897                Box::new(ContinuousExpression::Constant(1.0)),
6898                Box::new(ContinuousExpression::Constant(2.0))
6899            )
6900        );
6901
6902        assert_eq!(
6903            ContinuousBinaryOperation::log(1, cv2),
6904            ContinuousExpression::ContinuousBinaryOperation(
6905                ContinuousBinaryOperator::Log,
6906                Box::new(ContinuousExpression::Constant(1.0)),
6907                Box::new(ContinuousExpression::Variable(cv2.id()))
6908            )
6909        );
6910
6911        assert_eq!(
6912            ContinuousBinaryOperation::log(1, crv2),
6913            ContinuousExpression::ContinuousBinaryOperation(
6914                ContinuousBinaryOperator::Log,
6915                Box::new(ContinuousExpression::Constant(1.0)),
6916                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
6917            )
6918        );
6919    }
6920
6921    #[test]
6922    fn set_len() {
6923        let expression = SetExpression::Reference(ReferenceExpression::Constant(Set::default()));
6924        assert_eq!(
6925            expression.clone().len_continuous(),
6926            ContinuousExpression::Cardinality(expression)
6927        );
6928
6929        let mut metadata = StateMetadata::default();
6930        let ob = metadata.add_object_type(String::from("something"), 10);
6931        assert!(ob.is_ok());
6932        let ob = ob.unwrap();
6933        let v = metadata.add_set_variable(String::from("sv"), ob);
6934        assert!(v.is_ok());
6935        let v = v.unwrap();
6936        assert_eq!(
6937            v.len_continuous(),
6938            ContinuousExpression::Cardinality(SetExpression::Reference(
6939                ReferenceExpression::Variable(v.id())
6940            ))
6941        );
6942    }
6943
6944    #[test]
6945    fn table_element() {
6946        let mut registry = TableRegistry::default();
6947
6948        let t = registry.add_table_1d(String::from("t1"), vec![0.0, 1.0]);
6949        assert!(t.is_ok());
6950        let t = t.unwrap();
6951        assert_eq!(
6952            Table1DHandle::<Continuous>::element(&t, 0),
6953            ContinuousExpression::Table(Box::new(NumericTableExpression::Table1D(
6954                t.id(),
6955                ElementExpression::Constant(0)
6956            )))
6957        );
6958        assert_eq!(
6959            t.sum(SetExpression::default()),
6960            ContinuousExpression::Table(Box::new(NumericTableExpression::Table1DReduce(
6961                ReduceOperator::Sum,
6962                t.id(),
6963                SetExpression::default(),
6964            )))
6965        );
6966        assert_eq!(
6967            t.product(SetExpression::default()),
6968            ContinuousExpression::Table(Box::new(NumericTableExpression::Table1DReduce(
6969                ReduceOperator::Product,
6970                t.id(),
6971                SetExpression::default(),
6972            )))
6973        );
6974        assert_eq!(
6975            t.max(SetExpression::default()),
6976            ContinuousExpression::Table(Box::new(NumericTableExpression::Table1DReduce(
6977                ReduceOperator::Max,
6978                t.id(),
6979                SetExpression::default(),
6980            )))
6981        );
6982        assert_eq!(
6983            t.min(SetExpression::default()),
6984            ContinuousExpression::Table(Box::new(NumericTableExpression::Table1DReduce(
6985                ReduceOperator::Min,
6986                t.id(),
6987                SetExpression::default(),
6988            )))
6989        );
6990
6991        let t = registry.add_table_2d(String::from("t2"), vec![vec![0.0, 1.0]]);
6992        assert!(t.is_ok());
6993        let t = t.unwrap();
6994        assert_eq!(
6995            Table2DHandle::<Continuous>::element(&t, 0, 0),
6996            ContinuousExpression::Table(Box::new(NumericTableExpression::Table2D(
6997                t.id(),
6998                ElementExpression::Constant(0),
6999                ElementExpression::Constant(0),
7000            )))
7001        );
7002        assert_eq!(
7003            t.sum_x(SetExpression::default(), 0),
7004            ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduceX(
7005                ReduceOperator::Sum,
7006                t.id(),
7007                SetExpression::default(),
7008                ElementExpression::Constant(0),
7009            )))
7010        );
7011        assert_eq!(
7012            t.sum_y(0, SetExpression::default()),
7013            ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduceY(
7014                ReduceOperator::Sum,
7015                t.id(),
7016                ElementExpression::Constant(0),
7017                SetExpression::default(),
7018            )))
7019        );
7020        assert_eq!(
7021            t.sum(SetExpression::default(), SetExpression::default()),
7022            ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduce(
7023                ReduceOperator::Sum,
7024                t.id(),
7025                SetExpression::default(),
7026                SetExpression::default(),
7027            )))
7028        );
7029        assert_eq!(
7030            t.product_x(SetExpression::default(), 0),
7031            ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduceX(
7032                ReduceOperator::Product,
7033                t.id(),
7034                SetExpression::default(),
7035                ElementExpression::Constant(0),
7036            )))
7037        );
7038        assert_eq!(
7039            t.product_y(0, SetExpression::default()),
7040            ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduceY(
7041                ReduceOperator::Product,
7042                t.id(),
7043                ElementExpression::Constant(0),
7044                SetExpression::default(),
7045            )))
7046        );
7047        assert_eq!(
7048            t.product(SetExpression::default(), SetExpression::default()),
7049            ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduce(
7050                ReduceOperator::Product,
7051                t.id(),
7052                SetExpression::default(),
7053                SetExpression::default(),
7054            )))
7055        );
7056        assert_eq!(
7057            t.max_x(SetExpression::default(), 0),
7058            ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduceX(
7059                ReduceOperator::Max,
7060                t.id(),
7061                SetExpression::default(),
7062                ElementExpression::Constant(0),
7063            )))
7064        );
7065        assert_eq!(
7066            t.max_y(0, SetExpression::default()),
7067            ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduceY(
7068                ReduceOperator::Max,
7069                t.id(),
7070                ElementExpression::Constant(0),
7071                SetExpression::default(),
7072            )))
7073        );
7074        assert_eq!(
7075            t.max(SetExpression::default(), SetExpression::default()),
7076            ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduce(
7077                ReduceOperator::Max,
7078                t.id(),
7079                SetExpression::default(),
7080                SetExpression::default(),
7081            )))
7082        );
7083        assert_eq!(
7084            t.min_x(SetExpression::default(), 0),
7085            ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduceX(
7086                ReduceOperator::Min,
7087                t.id(),
7088                SetExpression::default(),
7089                ElementExpression::Constant(0),
7090            )))
7091        );
7092        assert_eq!(
7093            t.min_y(0, SetExpression::default()),
7094            ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduceY(
7095                ReduceOperator::Min,
7096                t.id(),
7097                ElementExpression::Constant(0),
7098                SetExpression::default(),
7099            )))
7100        );
7101        assert_eq!(
7102            t.min(SetExpression::default(), SetExpression::default()),
7103            ContinuousExpression::Table(Box::new(NumericTableExpression::Table2DReduce(
7104                ReduceOperator::Min,
7105                t.id(),
7106                SetExpression::default(),
7107                SetExpression::default(),
7108            )))
7109        );
7110
7111        let t = registry.add_table_3d(String::from("t3"), vec![vec![vec![0.0, 1.0]]]);
7112        assert!(t.is_ok());
7113        let t = t.unwrap();
7114        assert_eq!(
7115            Table3DHandle::<Continuous>::element(&t, 0, 0, 0),
7116            ContinuousExpression::Table(Box::new(NumericTableExpression::Table3D(
7117                t.id(),
7118                ElementExpression::Constant(0),
7119                ElementExpression::Constant(0),
7120                ElementExpression::Constant(0),
7121            )))
7122        );
7123        assert_eq!(
7124            Table3DHandle::<Continuous>::sum(&t, 0, 0, SetExpression::default()),
7125            ContinuousExpression::Table(Box::new(NumericTableExpression::Table3DReduce(
7126                ReduceOperator::Sum,
7127                t.id(),
7128                ArgumentExpression::Element(ElementExpression::Constant(0)),
7129                ArgumentExpression::Element(ElementExpression::Constant(0)),
7130                ArgumentExpression::Set(SetExpression::default()),
7131            )))
7132        );
7133        assert_eq!(
7134            Table3DHandle::<Continuous>::product(&t, 0, 0, SetExpression::default()),
7135            ContinuousExpression::Table(Box::new(NumericTableExpression::Table3DReduce(
7136                ReduceOperator::Product,
7137                t.id(),
7138                ArgumentExpression::Element(ElementExpression::Constant(0)),
7139                ArgumentExpression::Element(ElementExpression::Constant(0)),
7140                ArgumentExpression::Set(SetExpression::default()),
7141            )))
7142        );
7143        assert_eq!(
7144            Table3DHandle::<Continuous>::max(&t, 0, 0, SetExpression::default()),
7145            ContinuousExpression::Table(Box::new(NumericTableExpression::Table3DReduce(
7146                ReduceOperator::Max,
7147                t.id(),
7148                ArgumentExpression::Element(ElementExpression::Constant(0)),
7149                ArgumentExpression::Element(ElementExpression::Constant(0)),
7150                ArgumentExpression::Set(SetExpression::default()),
7151            )))
7152        );
7153        assert_eq!(
7154            Table3DHandle::<Continuous>::min(&t, 0, 0, SetExpression::default()),
7155            ContinuousExpression::Table(Box::new(NumericTableExpression::Table3DReduce(
7156                ReduceOperator::Min,
7157                t.id(),
7158                ArgumentExpression::Element(ElementExpression::Constant(0)),
7159                ArgumentExpression::Element(ElementExpression::Constant(0)),
7160                ArgumentExpression::Set(SetExpression::default()),
7161            )))
7162        );
7163
7164        let mut map = FxHashMap::default();
7165        map.insert(vec![0, 0, 0, 0], 1.0);
7166        let t = registry.add_table(String::from("t"), map, 0.0);
7167        assert!(t.is_ok());
7168        let t = t.unwrap();
7169        assert_eq!(
7170            TableHandle::<Continuous>::element(&t, vec![0, 0, 0, 0]),
7171            ContinuousExpression::Table(Box::new(NumericTableExpression::Table(
7172                t.id(),
7173                vec![
7174                    ElementExpression::Constant(0),
7175                    ElementExpression::Constant(0),
7176                    ElementExpression::Constant(0),
7177                    ElementExpression::Constant(0),
7178                ],
7179            )))
7180        );
7181        assert_eq!(
7182            TableHandle::<Continuous>::sum(
7183                &t,
7184                vec![
7185                    ArgumentExpression::from(0),
7186                    ArgumentExpression::from(0),
7187                    ArgumentExpression::from(0),
7188                    ArgumentExpression::from(Set::default())
7189                ]
7190            ),
7191            ContinuousExpression::Table(Box::new(NumericTableExpression::TableReduce(
7192                ReduceOperator::Sum,
7193                t.id(),
7194                vec![
7195                    ArgumentExpression::Element(ElementExpression::Constant(0)),
7196                    ArgumentExpression::Element(ElementExpression::Constant(0)),
7197                    ArgumentExpression::Element(ElementExpression::Constant(0)),
7198                    ArgumentExpression::Set(SetExpression::default()),
7199                ]
7200            )))
7201        );
7202        assert_eq!(
7203            TableHandle::<Continuous>::product(
7204                &t,
7205                vec![
7206                    ArgumentExpression::from(0),
7207                    ArgumentExpression::from(0),
7208                    ArgumentExpression::from(0),
7209                    ArgumentExpression::from(Set::default())
7210                ]
7211            ),
7212            ContinuousExpression::Table(Box::new(NumericTableExpression::TableReduce(
7213                ReduceOperator::Product,
7214                t.id(),
7215                vec![
7216                    ArgumentExpression::Element(ElementExpression::Constant(0)),
7217                    ArgumentExpression::Element(ElementExpression::Constant(0)),
7218                    ArgumentExpression::Element(ElementExpression::Constant(0)),
7219                    ArgumentExpression::Set(SetExpression::default()),
7220                ]
7221            )))
7222        );
7223        assert_eq!(
7224            TableHandle::<Continuous>::max(
7225                &t,
7226                vec![
7227                    ArgumentExpression::from(0),
7228                    ArgumentExpression::from(0),
7229                    ArgumentExpression::from(0),
7230                    ArgumentExpression::from(Set::default())
7231                ]
7232            ),
7233            ContinuousExpression::Table(Box::new(NumericTableExpression::TableReduce(
7234                ReduceOperator::Max,
7235                t.id(),
7236                vec![
7237                    ArgumentExpression::Element(ElementExpression::Constant(0)),
7238                    ArgumentExpression::Element(ElementExpression::Constant(0)),
7239                    ArgumentExpression::Element(ElementExpression::Constant(0)),
7240                    ArgumentExpression::Set(SetExpression::default()),
7241                ]
7242            )))
7243        );
7244        assert_eq!(
7245            TableHandle::<Continuous>::min(
7246                &t,
7247                vec![
7248                    ArgumentExpression::from(0),
7249                    ArgumentExpression::from(0),
7250                    ArgumentExpression::from(0),
7251                    ArgumentExpression::from(Set::default())
7252                ]
7253            ),
7254            ContinuousExpression::Table(Box::new(NumericTableExpression::TableReduce(
7255                ReduceOperator::Min,
7256                t.id(),
7257                vec![
7258                    ArgumentExpression::Element(ElementExpression::Constant(0)),
7259                    ArgumentExpression::Element(ElementExpression::Constant(0)),
7260                    ArgumentExpression::Element(ElementExpression::Constant(0)),
7261                    ArgumentExpression::Set(SetExpression::default()),
7262                ]
7263            )))
7264        );
7265    }
7266
7267    #[test]
7268    fn if_then_else() {
7269        let mut metadata = StateMetadata::default();
7270        let iv1 = metadata.add_integer_variable(String::from("iv1"));
7271        assert!(iv1.is_ok());
7272        let iv1 = iv1.unwrap();
7273        let iv2 = metadata.add_integer_variable(String::from("iv2"));
7274        assert!(iv2.is_ok());
7275        let iv2 = iv2.unwrap();
7276        let irv1 = metadata.add_integer_resource_variable(String::from("irv1"), true);
7277        assert!(irv1.is_ok());
7278        let irv1 = irv1.unwrap();
7279        let irv2 = metadata.add_integer_resource_variable(String::from("irv2"), false);
7280        assert!(irv2.is_ok());
7281        let irv2 = irv2.unwrap();
7282        let cv1 = metadata.add_continuous_variable(String::from("cv1"));
7283        assert!(cv1.is_ok());
7284        let cv1 = cv1.unwrap();
7285        let cv2 = metadata.add_continuous_variable(String::from("cv2"));
7286        assert!(cv2.is_ok());
7287        let cv2 = cv2.unwrap();
7288        let crv1 = metadata.add_continuous_resource_variable(String::from("crv1"), true);
7289        assert!(crv1.is_ok());
7290        let crv1 = crv1.unwrap();
7291        let crv2 = metadata.add_continuous_resource_variable(String::from("crv2"), false);
7292        assert!(crv2.is_ok());
7293        let crv2 = crv2.unwrap();
7294
7295        let condition = Condition::Constant(true);
7296        let expression1 = ContinuousExpression::Constant(1.0);
7297        let expression2 = ContinuousExpression::Constant(2.0);
7298        assert_eq!(
7299            IfThenElse::<ContinuousExpression>::if_then_else(condition, expression1, expression2),
7300            ContinuousExpression::If(
7301                Box::new(Condition::Constant(true)),
7302                Box::new(ContinuousExpression::Constant(1.0)),
7303                Box::new(ContinuousExpression::Constant(2.0))
7304            )
7305        );
7306
7307        let condition = Condition::Constant(true);
7308        let expression1 = ContinuousExpression::Constant(1.0);
7309        assert_eq!(
7310            IfThenElse::<ContinuousExpression>::if_then_else(condition, expression1, 2.0),
7311            ContinuousExpression::If(
7312                Box::new(Condition::Constant(true)),
7313                Box::new(ContinuousExpression::Constant(1.0)),
7314                Box::new(ContinuousExpression::Constant(2.0))
7315            )
7316        );
7317
7318        let condition = Condition::Constant(true);
7319        let expression1 = ContinuousExpression::Constant(1.0);
7320        assert_eq!(
7321            IfThenElse::<ContinuousExpression>::if_then_else(condition, expression1, cv2),
7322            ContinuousExpression::If(
7323                Box::new(Condition::Constant(true)),
7324                Box::new(ContinuousExpression::Constant(1.0)),
7325                Box::new(ContinuousExpression::Variable(cv2.id()))
7326            )
7327        );
7328
7329        let condition = Condition::Constant(true);
7330        let expression1 = ContinuousExpression::Constant(1.0);
7331        assert_eq!(
7332            IfThenElse::<ContinuousExpression>::if_then_else(condition, expression1, crv2),
7333            ContinuousExpression::If(
7334                Box::new(Condition::Constant(true)),
7335                Box::new(ContinuousExpression::Constant(1.0)),
7336                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
7337            )
7338        );
7339
7340        let condition = Condition::Constant(true);
7341        let expression1 = ContinuousExpression::Constant(1.0);
7342        let expression2 = IntegerExpression::Constant(2);
7343        assert_eq!(
7344            IfThenElse::<ContinuousExpression>::if_then_else(condition, expression1, expression2),
7345            ContinuousExpression::If(
7346                Box::new(Condition::Constant(true)),
7347                Box::new(ContinuousExpression::Constant(1.0)),
7348                Box::new(ContinuousExpression::FromInteger(Box::new(
7349                    IntegerExpression::Constant(2)
7350                )))
7351            )
7352        );
7353
7354        let condition = Condition::Constant(true);
7355        let expression1 = ContinuousExpression::Constant(1.0);
7356        assert_eq!(
7357            IfThenElse::<ContinuousExpression>::if_then_else(condition, expression1, iv2),
7358            ContinuousExpression::If(
7359                Box::new(Condition::Constant(true)),
7360                Box::new(ContinuousExpression::Constant(1.0)),
7361                Box::new(ContinuousExpression::FromInteger(Box::new(
7362                    IntegerExpression::Variable(iv2.id())
7363                )))
7364            )
7365        );
7366
7367        let condition = Condition::Constant(true);
7368        let expression1 = ContinuousExpression::Constant(1.0);
7369        assert_eq!(
7370            IfThenElse::<ContinuousExpression>::if_then_else(condition, expression1, irv2),
7371            ContinuousExpression::If(
7372                Box::new(Condition::Constant(true)),
7373                Box::new(ContinuousExpression::Constant(1.0)),
7374                Box::new(ContinuousExpression::FromInteger(Box::new(
7375                    IntegerExpression::ResourceVariable(irv2.id())
7376                )))
7377            )
7378        );
7379
7380        let condition = Condition::Constant(true);
7381        let expression2 = ContinuousExpression::Constant(2.0);
7382        assert_eq!(
7383            IfThenElse::<ContinuousExpression>::if_then_else(condition, 1.0, expression2),
7384            ContinuousExpression::If(
7385                Box::new(Condition::Constant(true)),
7386                Box::new(ContinuousExpression::Constant(1.0)),
7387                Box::new(ContinuousExpression::Constant(2.0))
7388            )
7389        );
7390
7391        let condition = Condition::Constant(true);
7392        assert_eq!(
7393            IfThenElse::<ContinuousExpression>::if_then_else(condition, 1.0, cv2),
7394            ContinuousExpression::If(
7395                Box::new(Condition::Constant(true)),
7396                Box::new(ContinuousExpression::Constant(1.0)),
7397                Box::new(ContinuousExpression::Variable(cv2.id()))
7398            )
7399        );
7400
7401        let condition = Condition::Constant(true);
7402        assert_eq!(
7403            IfThenElse::<ContinuousExpression>::if_then_else(condition, 1.0, crv2),
7404            ContinuousExpression::If(
7405                Box::new(Condition::Constant(true)),
7406                Box::new(ContinuousExpression::Constant(1.0)),
7407                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
7408            )
7409        );
7410
7411        let condition = Condition::Constant(true);
7412        let expression2 = IntegerExpression::Constant(2);
7413        assert_eq!(
7414            IfThenElse::<ContinuousExpression>::if_then_else(condition, 1.0, expression2),
7415            ContinuousExpression::If(
7416                Box::new(Condition::Constant(true)),
7417                Box::new(ContinuousExpression::Constant(1.0)),
7418                Box::new(ContinuousExpression::FromInteger(Box::new(
7419                    IntegerExpression::Constant(2)
7420                )))
7421            )
7422        );
7423
7424        let condition = Condition::Constant(true);
7425        assert_eq!(
7426            IfThenElse::<ContinuousExpression>::if_then_else(condition, 1.0, iv2),
7427            ContinuousExpression::If(
7428                Box::new(Condition::Constant(true)),
7429                Box::new(ContinuousExpression::Constant(1.0)),
7430                Box::new(ContinuousExpression::FromInteger(Box::new(
7431                    IntegerExpression::Variable(iv2.id())
7432                )))
7433            )
7434        );
7435
7436        let condition = Condition::Constant(true);
7437        assert_eq!(
7438            IfThenElse::<ContinuousExpression>::if_then_else(condition, 1.0, irv2),
7439            ContinuousExpression::If(
7440                Box::new(Condition::Constant(true)),
7441                Box::new(ContinuousExpression::Constant(1.0)),
7442                Box::new(ContinuousExpression::FromInteger(Box::new(
7443                    IntegerExpression::ResourceVariable(irv2.id())
7444                )))
7445            )
7446        );
7447
7448        let condition = Condition::Constant(true);
7449        let expression2 = ContinuousExpression::Constant(2.0);
7450        assert_eq!(
7451            IfThenElse::<ContinuousExpression>::if_then_else(condition, cv1, expression2),
7452            ContinuousExpression::If(
7453                Box::new(Condition::Constant(true)),
7454                Box::new(ContinuousExpression::Variable(cv1.id())),
7455                Box::new(ContinuousExpression::Constant(2.0))
7456            )
7457        );
7458
7459        let condition = Condition::Constant(true);
7460        assert_eq!(
7461            IfThenElse::<ContinuousExpression>::if_then_else(condition, cv1, 2.0),
7462            ContinuousExpression::If(
7463                Box::new(Condition::Constant(true)),
7464                Box::new(ContinuousExpression::Variable(cv1.id())),
7465                Box::new(ContinuousExpression::Constant(2.0))
7466            )
7467        );
7468
7469        let condition = Condition::Constant(true);
7470        assert_eq!(
7471            IfThenElse::<ContinuousExpression>::if_then_else(condition, cv1, cv2),
7472            ContinuousExpression::If(
7473                Box::new(Condition::Constant(true)),
7474                Box::new(ContinuousExpression::Variable(cv1.id())),
7475                Box::new(ContinuousExpression::Variable(cv2.id()))
7476            )
7477        );
7478
7479        let condition = Condition::Constant(true);
7480        assert_eq!(
7481            IfThenElse::<ContinuousExpression>::if_then_else(condition, cv1, crv2),
7482            ContinuousExpression::If(
7483                Box::new(Condition::Constant(true)),
7484                Box::new(ContinuousExpression::Variable(cv1.id())),
7485                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
7486            )
7487        );
7488
7489        let condition = Condition::Constant(true);
7490        let expression2 = IntegerExpression::Constant(2);
7491        assert_eq!(
7492            IfThenElse::<ContinuousExpression>::if_then_else(condition, cv1, expression2),
7493            ContinuousExpression::If(
7494                Box::new(Condition::Constant(true)),
7495                Box::new(ContinuousExpression::Variable(cv1.id())),
7496                Box::new(ContinuousExpression::FromInteger(Box::new(
7497                    IntegerExpression::Constant(2)
7498                )))
7499            )
7500        );
7501
7502        let condition = Condition::Constant(true);
7503        assert_eq!(
7504            IfThenElse::<ContinuousExpression>::if_then_else(condition, cv1, iv2),
7505            ContinuousExpression::If(
7506                Box::new(Condition::Constant(true)),
7507                Box::new(ContinuousExpression::Variable(cv1.id())),
7508                Box::new(ContinuousExpression::FromInteger(Box::new(
7509                    IntegerExpression::Variable(iv2.id())
7510                )))
7511            )
7512        );
7513
7514        let condition = Condition::Constant(true);
7515        assert_eq!(
7516            IfThenElse::<ContinuousExpression>::if_then_else(condition, cv1, irv2),
7517            ContinuousExpression::If(
7518                Box::new(Condition::Constant(true)),
7519                Box::new(ContinuousExpression::Variable(cv1.id())),
7520                Box::new(ContinuousExpression::FromInteger(Box::new(
7521                    IntegerExpression::ResourceVariable(irv2.id())
7522                )))
7523            )
7524        );
7525
7526        let condition = Condition::Constant(true);
7527        let expression2 = ContinuousExpression::Constant(2.0);
7528        assert_eq!(
7529            IfThenElse::<ContinuousExpression>::if_then_else(condition, crv1, expression2),
7530            ContinuousExpression::If(
7531                Box::new(Condition::Constant(true)),
7532                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
7533                Box::new(ContinuousExpression::Constant(2.0))
7534            )
7535        );
7536
7537        let condition = Condition::Constant(true);
7538        assert_eq!(
7539            IfThenElse::<ContinuousExpression>::if_then_else(condition, crv1, 2.0),
7540            ContinuousExpression::If(
7541                Box::new(Condition::Constant(true)),
7542                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
7543                Box::new(ContinuousExpression::Constant(2.0))
7544            )
7545        );
7546
7547        let condition = Condition::Constant(true);
7548        assert_eq!(
7549            IfThenElse::<ContinuousExpression>::if_then_else(condition, crv1, cv2),
7550            ContinuousExpression::If(
7551                Box::new(Condition::Constant(true)),
7552                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
7553                Box::new(ContinuousExpression::Variable(cv2.id()))
7554            )
7555        );
7556
7557        let condition = Condition::Constant(true);
7558        assert_eq!(
7559            IfThenElse::<ContinuousExpression>::if_then_else(condition, crv1, crv2),
7560            ContinuousExpression::If(
7561                Box::new(Condition::Constant(true)),
7562                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
7563                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
7564            )
7565        );
7566
7567        let condition = Condition::Constant(true);
7568        let expression2 = IntegerExpression::Constant(2);
7569        assert_eq!(
7570            IfThenElse::<ContinuousExpression>::if_then_else(condition, crv1, expression2),
7571            ContinuousExpression::If(
7572                Box::new(Condition::Constant(true)),
7573                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
7574                Box::new(ContinuousExpression::FromInteger(Box::new(
7575                    IntegerExpression::Constant(2)
7576                )))
7577            )
7578        );
7579
7580        let condition = Condition::Constant(true);
7581        assert_eq!(
7582            IfThenElse::<ContinuousExpression>::if_then_else(condition, crv1, iv2),
7583            ContinuousExpression::If(
7584                Box::new(Condition::Constant(true)),
7585                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
7586                Box::new(ContinuousExpression::FromInteger(Box::new(
7587                    IntegerExpression::Variable(iv2.id())
7588                )))
7589            )
7590        );
7591
7592        let condition = Condition::Constant(true);
7593        assert_eq!(
7594            IfThenElse::<ContinuousExpression>::if_then_else(condition, crv1, irv2),
7595            ContinuousExpression::If(
7596                Box::new(Condition::Constant(true)),
7597                Box::new(ContinuousExpression::ResourceVariable(crv1.id())),
7598                Box::new(ContinuousExpression::FromInteger(Box::new(
7599                    IntegerExpression::ResourceVariable(irv2.id())
7600                )))
7601            )
7602        );
7603
7604        let condition = Condition::Constant(true);
7605        let expression1 = IntegerExpression::Constant(1);
7606        let expression2 = ContinuousExpression::Constant(2.0);
7607        assert_eq!(
7608            IfThenElse::<ContinuousExpression>::if_then_else(condition, expression1, expression2),
7609            ContinuousExpression::If(
7610                Box::new(Condition::Constant(true)),
7611                Box::new(ContinuousExpression::FromInteger(Box::new(
7612                    IntegerExpression::Constant(1)
7613                ))),
7614                Box::new(ContinuousExpression::Constant(2.0))
7615            )
7616        );
7617
7618        let condition = Condition::Constant(true);
7619        let expression1 = IntegerExpression::Constant(1);
7620        assert_eq!(
7621            IfThenElse::<ContinuousExpression>::if_then_else(condition, expression1, 2.0),
7622            ContinuousExpression::If(
7623                Box::new(Condition::Constant(true)),
7624                Box::new(ContinuousExpression::FromInteger(Box::new(
7625                    IntegerExpression::Constant(1)
7626                ))),
7627                Box::new(ContinuousExpression::Constant(2.0))
7628            )
7629        );
7630
7631        let condition = Condition::Constant(true);
7632        let expression1 = IntegerExpression::Constant(1);
7633        assert_eq!(
7634            IfThenElse::<ContinuousExpression>::if_then_else(condition, expression1, cv2),
7635            ContinuousExpression::If(
7636                Box::new(Condition::Constant(true)),
7637                Box::new(ContinuousExpression::FromInteger(Box::new(
7638                    IntegerExpression::Constant(1)
7639                ))),
7640                Box::new(ContinuousExpression::Variable(cv2.id()))
7641            )
7642        );
7643
7644        let condition = Condition::Constant(true);
7645        let expression1 = IntegerExpression::Constant(1);
7646        assert_eq!(
7647            IfThenElse::<ContinuousExpression>::if_then_else(condition, expression1, crv2),
7648            ContinuousExpression::If(
7649                Box::new(Condition::Constant(true)),
7650                Box::new(ContinuousExpression::FromInteger(Box::new(
7651                    IntegerExpression::Constant(1)
7652                ))),
7653                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
7654            )
7655        );
7656
7657        let condition = Condition::Constant(true);
7658        let expression2 = ContinuousExpression::Constant(2.0);
7659        assert_eq!(
7660            IfThenElse::<ContinuousExpression>::if_then_else(condition, iv1, expression2),
7661            ContinuousExpression::If(
7662                Box::new(Condition::Constant(true)),
7663                Box::new(ContinuousExpression::FromInteger(Box::new(
7664                    IntegerExpression::Variable(iv1.id())
7665                ))),
7666                Box::new(ContinuousExpression::Constant(2.0))
7667            )
7668        );
7669
7670        let condition = Condition::Constant(true);
7671        assert_eq!(
7672            IfThenElse::<ContinuousExpression>::if_then_else(condition, iv1, 2.0),
7673            ContinuousExpression::If(
7674                Box::new(Condition::Constant(true)),
7675                Box::new(ContinuousExpression::FromInteger(Box::new(
7676                    IntegerExpression::Variable(iv1.id())
7677                ))),
7678                Box::new(ContinuousExpression::Constant(2.0))
7679            )
7680        );
7681
7682        let condition = Condition::Constant(true);
7683        assert_eq!(
7684            IfThenElse::<ContinuousExpression>::if_then_else(condition, iv1, cv2),
7685            ContinuousExpression::If(
7686                Box::new(Condition::Constant(true)),
7687                Box::new(ContinuousExpression::FromInteger(Box::new(
7688                    IntegerExpression::Variable(iv1.id())
7689                ))),
7690                Box::new(ContinuousExpression::Variable(cv2.id()))
7691            )
7692        );
7693
7694        let condition = Condition::Constant(true);
7695        assert_eq!(
7696            IfThenElse::<ContinuousExpression>::if_then_else(condition, iv1, crv2),
7697            ContinuousExpression::If(
7698                Box::new(Condition::Constant(true)),
7699                Box::new(ContinuousExpression::FromInteger(Box::new(
7700                    IntegerExpression::Variable(iv1.id())
7701                ))),
7702                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
7703            )
7704        );
7705
7706        let condition = Condition::Constant(true);
7707        let expression2 = ContinuousExpression::Constant(2.0);
7708        assert_eq!(
7709            IfThenElse::<ContinuousExpression>::if_then_else(condition, irv1, expression2),
7710            ContinuousExpression::If(
7711                Box::new(Condition::Constant(true)),
7712                Box::new(ContinuousExpression::FromInteger(Box::new(
7713                    IntegerExpression::ResourceVariable(irv1.id())
7714                ))),
7715                Box::new(ContinuousExpression::Constant(2.0))
7716            )
7717        );
7718
7719        let condition = Condition::Constant(true);
7720        assert_eq!(
7721            IfThenElse::<ContinuousExpression>::if_then_else(condition, irv1, 2.0),
7722            ContinuousExpression::If(
7723                Box::new(Condition::Constant(true)),
7724                Box::new(ContinuousExpression::FromInteger(Box::new(
7725                    IntegerExpression::ResourceVariable(irv1.id())
7726                ))),
7727                Box::new(ContinuousExpression::Constant(2.0))
7728            )
7729        );
7730
7731        let condition = Condition::Constant(true);
7732        assert_eq!(
7733            IfThenElse::<ContinuousExpression>::if_then_else(condition, irv1, cv2),
7734            ContinuousExpression::If(
7735                Box::new(Condition::Constant(true)),
7736                Box::new(ContinuousExpression::FromInteger(Box::new(
7737                    IntegerExpression::ResourceVariable(irv1.id())
7738                ))),
7739                Box::new(ContinuousExpression::Variable(cv2.id()))
7740            )
7741        );
7742
7743        let condition = Condition::Constant(true);
7744        assert_eq!(
7745            IfThenElse::<ContinuousExpression>::if_then_else(condition, irv1, crv2),
7746            ContinuousExpression::If(
7747                Box::new(Condition::Constant(true)),
7748                Box::new(ContinuousExpression::FromInteger(Box::new(
7749                    IntegerExpression::ResourceVariable(irv1.id())
7750                ))),
7751                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
7752            )
7753        );
7754
7755        let condition = Condition::Constant(true);
7756        let expression2 = ContinuousExpression::Constant(2.0);
7757        assert_eq!(
7758            IfThenElse::<ContinuousExpression>::if_then_else(condition, 1, expression2),
7759            ContinuousExpression::If(
7760                Box::new(Condition::Constant(true)),
7761                Box::new(ContinuousExpression::Constant(1.0)),
7762                Box::new(ContinuousExpression::Constant(2.0))
7763            )
7764        );
7765
7766        let condition = Condition::Constant(true);
7767        assert_eq!(
7768            IfThenElse::<ContinuousExpression>::if_then_else(condition, 1, cv2),
7769            ContinuousExpression::If(
7770                Box::new(Condition::Constant(true)),
7771                Box::new(ContinuousExpression::Constant(1.0)),
7772                Box::new(ContinuousExpression::Variable(cv2.id()))
7773            )
7774        );
7775
7776        let condition = Condition::Constant(true);
7777        assert_eq!(
7778            IfThenElse::<ContinuousExpression>::if_then_else(condition, 1, crv2),
7779            ContinuousExpression::If(
7780                Box::new(Condition::Constant(true)),
7781                Box::new(ContinuousExpression::Constant(1.0)),
7782                Box::new(ContinuousExpression::ResourceVariable(crv2.id()))
7783            )
7784        );
7785    }
7786
7787    #[test]
7788    fn constant_eval() {
7789        let state = State::default();
7790        let state_functions = StateFunctions::default();
7791        let mut function_cache = StateFunctionCache::new(&state_functions);
7792        let registry = TableRegistry::default();
7793        let expression = ContinuousExpression::Constant(1.0);
7794        assert_eq!(
7795            expression.eval(&state, &mut function_cache, &state_functions, &registry),
7796            1.0
7797        );
7798    }
7799
7800    #[test]
7801    fn variable_eval() {
7802        let state = State {
7803            signature_variables: SignatureVariables {
7804                continuous_variables: vec![0.0],
7805                ..Default::default()
7806            },
7807            ..Default::default()
7808        };
7809        let state_functions = StateFunctions::default();
7810        let mut function_cache = StateFunctionCache::new(&state_functions);
7811        let registry = TableRegistry::default();
7812        let expression = ContinuousExpression::Variable(0);
7813        assert_eq!(
7814            expression.eval(&state, &mut function_cache, &state_functions, &registry),
7815            0.0
7816        );
7817    }
7818
7819    #[test]
7820    fn resource_variable_eval() {
7821        let state = State {
7822            resource_variables: ResourceVariables {
7823                continuous_variables: vec![0.0],
7824                ..Default::default()
7825            },
7826            ..Default::default()
7827        };
7828        let state_functions = StateFunctions::default();
7829        let mut function_cache = StateFunctionCache::new(&state_functions);
7830        let registry = TableRegistry::default();
7831        let expression = ContinuousExpression::ResourceVariable(0);
7832        assert_eq!(
7833            expression.eval(&state, &mut function_cache, &state_functions, &registry),
7834            0.0
7835        );
7836    }
7837
7838    #[test]
7839    fn state_function_eval() {
7840        let mut state_metadata = StateMetadata::default();
7841        let v = state_metadata.add_continuous_variable("v");
7842        assert!(v.is_ok());
7843        let v = v.unwrap();
7844
7845        let mut state_functions = StateFunctions::default();
7846        let f = state_functions.add_continuous_function("f", v + 1);
7847        assert!(f.is_ok());
7848        let f = f.unwrap();
7849        let g = state_functions.add_continuous_function("g", v + 2);
7850        assert!(g.is_ok());
7851        let g = g.unwrap();
7852
7853        let state = State {
7854            signature_variables: SignatureVariables {
7855                continuous_variables: vec![0.0],
7856                ..Default::default()
7857            },
7858            ..Default::default()
7859        };
7860
7861        let mut function_cache = StateFunctionCache::new(&state_functions);
7862        let registry = TableRegistry::default();
7863
7864        assert_relative_eq!(
7865            f.eval(&state, &mut function_cache, &state_functions, &registry),
7866            1.0
7867        );
7868
7869        assert_relative_eq!(
7870            g.eval(&state, &mut function_cache, &state_functions, &registry),
7871            2.0
7872        );
7873
7874        assert_relative_eq!(
7875            f.eval(&state, &mut function_cache, &state_functions, &registry),
7876            1.0
7877        );
7878        assert_relative_eq!(
7879            g.eval(&state, &mut function_cache, &state_functions, &registry),
7880            2.0
7881        );
7882    }
7883
7884    #[test]
7885    fn eval_cost() {
7886        let state = State::default();
7887        let state_functions = StateFunctions::default();
7888        let mut function_cache = StateFunctionCache::new(&state_functions);
7889        let registry = TableRegistry::default();
7890        let expression = ContinuousExpression::Cost;
7891        assert_eq!(
7892            expression.eval_cost(
7893                10.0,
7894                &state,
7895                &mut function_cache,
7896                &state_functions,
7897                &registry
7898            ),
7899            10.0
7900        );
7901    }
7902
7903    #[test]
7904    #[should_panic]
7905    fn eval_cost_panic() {
7906        let state = State::default();
7907        let state_functions = StateFunctions::default();
7908        let mut function_cache = StateFunctionCache::new(&state_functions);
7909        let registry = TableRegistry::default();
7910        let expression = ContinuousExpression::Cost;
7911        expression.eval(&state, &mut function_cache, &state_functions, &registry);
7912    }
7913
7914    #[test]
7915    fn unary_operation_eval() {
7916        let state = State::default();
7917        let state_functions = StateFunctions::default();
7918        let mut function_cache = StateFunctionCache::new(&state_functions);
7919        let registry = TableRegistry::default();
7920        let expression = ContinuousExpression::UnaryOperation(
7921            UnaryOperator::Abs,
7922            Box::new(ContinuousExpression::Constant(-1.0)),
7923        );
7924        assert_eq!(
7925            expression.eval(&state, &mut function_cache, &state_functions, &registry),
7926            1.0
7927        );
7928    }
7929
7930    #[test]
7931    fn continuous_unary_operation_eval() {
7932        let state = State::default();
7933        let state_functions = StateFunctions::default();
7934        let mut function_cache = StateFunctionCache::new(&state_functions);
7935        let registry = TableRegistry::default();
7936        let expression = ContinuousExpression::ContinuousUnaryOperation(
7937            ContinuousUnaryOperator::Sqrt,
7938            Box::new(ContinuousExpression::Constant(4.0)),
7939        );
7940        assert_eq!(
7941            expression.eval(&state, &mut function_cache, &state_functions, &registry),
7942            2.0
7943        );
7944    }
7945
7946    #[test]
7947    fn round_eval() {
7948        let state = State::default();
7949        let state_functions = StateFunctions::default();
7950        let mut function_cache = StateFunctionCache::new(&state_functions);
7951        let registry = TableRegistry::default();
7952        let expression = ContinuousExpression::Round(
7953            CastOperator::Floor,
7954            Box::new(ContinuousExpression::Constant(2.5)),
7955        );
7956        assert_eq!(
7957            expression.eval(&state, &mut function_cache, &state_functions, &registry),
7958            2.0
7959        );
7960    }
7961
7962    #[test]
7963    fn binary_operation_eval() {
7964        let state = State::default();
7965        let state_functions = StateFunctions::default();
7966        let mut function_cache = StateFunctionCache::new(&state_functions);
7967        let registry = TableRegistry::default();
7968        let expression = ContinuousExpression::BinaryOperation(
7969            BinaryOperator::Add,
7970            Box::new(ContinuousExpression::Constant(1.0)),
7971            Box::new(ContinuousExpression::Constant(2.0)),
7972        );
7973        assert_eq!(
7974            expression.eval(&state, &mut function_cache, &state_functions, &registry),
7975            3.0
7976        );
7977    }
7978
7979    #[test]
7980    fn continuous_binary_operation_eval() {
7981        let state = State::default();
7982        let state_functions = StateFunctions::default();
7983        let mut function_cache = StateFunctionCache::new(&state_functions);
7984        let registry = TableRegistry::default();
7985        let expression = ContinuousExpression::ContinuousBinaryOperation(
7986            ContinuousBinaryOperator::Pow,
7987            Box::new(ContinuousExpression::Constant(2.0)),
7988            Box::new(ContinuousExpression::Constant(2.0)),
7989        );
7990        assert_eq!(
7991            expression.eval(&state, &mut function_cache, &state_functions, &registry),
7992            4.0
7993        );
7994    }
7995
7996    #[test]
7997    fn cardinality_eval() {
7998        let state = State::default();
7999        let state_functions = StateFunctions::default();
8000        let mut function_cache = StateFunctionCache::new(&state_functions);
8001        let registry = TableRegistry::default();
8002        let mut set = Set::with_capacity(5);
8003        set.insert(1);
8004        set.insert(4);
8005        let expression = ContinuousExpression::Cardinality(SetExpression::Reference(
8006            ReferenceExpression::Constant(set),
8007        ));
8008        assert_eq!(
8009            expression.eval(&state, &mut function_cache, &state_functions, &registry),
8010            2.0
8011        );
8012    }
8013
8014    #[test]
8015    fn length_eval() {
8016        let state = State::default();
8017        let state_functions = StateFunctions::default();
8018        let mut function_cache = StateFunctionCache::new(&state_functions);
8019        let registry = TableRegistry::default();
8020        let expression = ContinuousExpression::Length(VectorExpression::Reference(
8021            ReferenceExpression::Constant(vec![1, 4]),
8022        ));
8023        assert_eq!(
8024            expression.eval(&state, &mut function_cache, &state_functions, &registry),
8025            2.0
8026        );
8027    }
8028
8029    #[test]
8030    fn table_eval() {
8031        let state = State::default();
8032        let state_functions = StateFunctions::default();
8033        let mut function_cache = StateFunctionCache::new(&state_functions);
8034        let registry = TableRegistry::default();
8035        let expression =
8036            ContinuousExpression::Table(Box::new(NumericTableExpression::Constant(0.0)));
8037        assert_eq!(
8038            expression.eval(&state, &mut function_cache, &state_functions, &registry),
8039            0.0
8040        );
8041    }
8042
8043    #[test]
8044    fn if_eval() {
8045        let state = State::default();
8046        let state_functions = StateFunctions::default();
8047        let mut function_cache = StateFunctionCache::new(&state_functions);
8048        let registry = TableRegistry::default();
8049
8050        let expression = ContinuousExpression::If(
8051            Box::new(Condition::Constant(true)),
8052            Box::new(ContinuousExpression::Constant(1.0)),
8053            Box::new(ContinuousExpression::Constant(2.0)),
8054        );
8055        assert_eq!(
8056            expression.eval(&state, &mut function_cache, &state_functions, &registry),
8057            1.0
8058        );
8059
8060        let expression = ContinuousExpression::If(
8061            Box::new(Condition::Constant(false)),
8062            Box::new(ContinuousExpression::Constant(1.0)),
8063            Box::new(ContinuousExpression::Constant(2.0)),
8064        );
8065        assert_eq!(
8066            expression.eval(&state, &mut function_cache, &state_functions, &registry),
8067            2.0
8068        );
8069    }
8070
8071    #[test]
8072    fn from_integer_eval() {
8073        let state = State::default();
8074        let state_functions = StateFunctions::default();
8075        let mut function_cache = StateFunctionCache::new(&state_functions);
8076        let registry = TableRegistry::default();
8077
8078        let expression =
8079            ContinuousExpression::FromInteger(Box::new(IntegerExpression::Constant(1)));
8080        assert_eq!(
8081            expression.eval(&state, &mut function_cache, &state_functions, &registry),
8082            1.0
8083        );
8084    }
8085
8086    #[test]
8087    fn last_eval() {
8088        let state = State::default();
8089        let state_functions = StateFunctions::default();
8090        let mut function_cache = StateFunctionCache::new(&state_functions);
8091        let registry = TableRegistry::default();
8092
8093        let expression =
8094            ContinuousExpression::Last(Box::new(ContinuousVectorExpression::Constant(vec![
8095                1.0, 2.0, 3.0,
8096            ])));
8097        assert_eq!(
8098            expression.eval(&state, &mut function_cache, &state_functions, &registry),
8099            3.0
8100        );
8101    }
8102
8103    #[test]
8104    fn at_eval() {
8105        let state = State::default();
8106        let state_functions = StateFunctions::default();
8107        let mut function_cache = StateFunctionCache::new(&state_functions);
8108        let registry = TableRegistry::default();
8109
8110        let expression = ContinuousExpression::At(
8111            Box::new(ContinuousVectorExpression::Constant(vec![1.0, 2.0, 3.0])),
8112            ElementExpression::Constant(0),
8113        );
8114        assert_eq!(
8115            expression.eval(&state, &mut function_cache, &state_functions, &registry),
8116            1.0
8117        );
8118    }
8119
8120    #[test]
8121    fn reduce_eval() {
8122        let state = State::default();
8123        let state_functions = StateFunctions::default();
8124        let mut function_cache = StateFunctionCache::new(&state_functions);
8125        let registry = TableRegistry::default();
8126
8127        let expression = ContinuousExpression::Reduce(
8128            ReduceOperator::Sum,
8129            Box::new(ContinuousVectorExpression::Constant(vec![1.0, 2.0, 3.0])),
8130        );
8131        assert_eq!(
8132            expression.eval(&state, &mut function_cache, &state_functions, &registry),
8133            6.0
8134        );
8135    }
8136
8137    #[test]
8138    fn constant_simplify() {
8139        let registry = TableRegistry::default();
8140        let expression = ContinuousExpression::Constant(1.0);
8141        assert_eq!(expression.simplify(&registry), expression);
8142    }
8143
8144    #[test]
8145    fn variable_simplify() {
8146        let registry = TableRegistry::default();
8147        let expression = ContinuousExpression::Variable(0);
8148        assert_eq!(expression.simplify(&registry), expression);
8149    }
8150
8151    #[test]
8152    fn resource_variable_simplify() {
8153        let registry = TableRegistry::default();
8154        let expression = ContinuousExpression::ResourceVariable(0);
8155        assert_eq!(expression.simplify(&registry), expression);
8156    }
8157
8158    #[test]
8159    fn cost_simplify() {
8160        let registry = TableRegistry::default();
8161        let expression = ContinuousExpression::Cost;
8162        assert_eq!(expression.simplify(&registry), expression);
8163    }
8164
8165    #[test]
8166    fn unary_operation_simplify() {
8167        let registry = TableRegistry::default();
8168        let expression = ContinuousExpression::UnaryOperation(
8169            UnaryOperator::Abs,
8170            Box::new(ContinuousExpression::Constant(-1.0)),
8171        );
8172        assert_eq!(
8173            expression.simplify(&registry),
8174            ContinuousExpression::Constant(1.0)
8175        );
8176        let expression = ContinuousExpression::UnaryOperation(
8177            UnaryOperator::Abs,
8178            Box::new(ContinuousExpression::Variable(0)),
8179        );
8180        assert_eq!(expression.simplify(&registry), expression);
8181    }
8182
8183    #[test]
8184    fn continuous_unary_operation_simplify() {
8185        let registry = TableRegistry::default();
8186        let expression = ContinuousExpression::ContinuousUnaryOperation(
8187            ContinuousUnaryOperator::Sqrt,
8188            Box::new(ContinuousExpression::Constant(4.0)),
8189        );
8190        assert_eq!(
8191            expression.simplify(&registry),
8192            ContinuousExpression::Constant(2.0)
8193        );
8194        let expression = ContinuousExpression::ContinuousUnaryOperation(
8195            ContinuousUnaryOperator::Sqrt,
8196            Box::new(ContinuousExpression::Variable(0)),
8197        );
8198        assert_eq!(expression.simplify(&registry), expression);
8199    }
8200
8201    #[test]
8202    fn round_simplify() {
8203        let registry = TableRegistry::default();
8204        let expression = ContinuousExpression::Round(
8205            CastOperator::Floor,
8206            Box::new(ContinuousExpression::Constant(1.5)),
8207        );
8208        assert_eq!(
8209            expression.simplify(&registry),
8210            ContinuousExpression::Constant(1.0)
8211        );
8212        let expression = ContinuousExpression::Round(
8213            CastOperator::Floor,
8214            Box::new(ContinuousExpression::Variable(0)),
8215        );
8216        assert_eq!(expression.simplify(&registry), expression);
8217    }
8218
8219    #[test]
8220    fn binary_operation_simplify() {
8221        let registry = TableRegistry::default();
8222        let expression = ContinuousExpression::BinaryOperation(
8223            BinaryOperator::Add,
8224            Box::new(ContinuousExpression::Constant(1.0)),
8225            Box::new(ContinuousExpression::Constant(2.0)),
8226        );
8227        assert_eq!(
8228            expression.simplify(&registry),
8229            ContinuousExpression::Constant(3.0)
8230        );
8231        let expression = ContinuousExpression::BinaryOperation(
8232            BinaryOperator::Add,
8233            Box::new(ContinuousExpression::Variable(0)),
8234            Box::new(ContinuousExpression::Constant(2.0)),
8235        );
8236        assert_eq!(expression.simplify(&registry), expression);
8237    }
8238
8239    #[test]
8240    fn continuous_binary_operation_simplify() {
8241        let registry = TableRegistry::default();
8242        let expression = ContinuousExpression::ContinuousBinaryOperation(
8243            ContinuousBinaryOperator::Pow,
8244            Box::new(ContinuousExpression::Constant(2.0)),
8245            Box::new(ContinuousExpression::Constant(2.0)),
8246        );
8247        assert_eq!(
8248            expression.simplify(&registry),
8249            ContinuousExpression::Constant(4.0)
8250        );
8251        let expression = ContinuousExpression::ContinuousBinaryOperation(
8252            ContinuousBinaryOperator::Pow,
8253            Box::new(ContinuousExpression::Variable(0)),
8254            Box::new(ContinuousExpression::Constant(2.0)),
8255        );
8256        assert_eq!(expression.simplify(&registry), expression);
8257    }
8258
8259    #[test]
8260    fn cardinality_simplify() {
8261        let registry = TableRegistry::default();
8262        let mut set = Set::with_capacity(5);
8263        set.insert(1);
8264        set.insert(4);
8265        let expression = ContinuousExpression::Cardinality(SetExpression::Reference(
8266            ReferenceExpression::Constant(set),
8267        ));
8268        assert_eq!(
8269            expression.simplify(&registry),
8270            ContinuousExpression::Constant(2.0)
8271        );
8272        let expression = ContinuousExpression::Cardinality(SetExpression::Reference(
8273            ReferenceExpression::Variable(0),
8274        ));
8275        assert_eq!(expression.simplify(&registry), expression);
8276    }
8277
8278    #[test]
8279    fn length_simplify() {
8280        let registry = TableRegistry::default();
8281        let expression = ContinuousExpression::Length(VectorExpression::Reference(
8282            ReferenceExpression::Constant(vec![1, 4]),
8283        ));
8284        assert_eq!(
8285            expression.simplify(&registry),
8286            ContinuousExpression::Constant(2.0)
8287        );
8288        let expression = ContinuousExpression::Length(VectorExpression::Reference(
8289            ReferenceExpression::Variable(0),
8290        ));
8291        assert_eq!(expression.simplify(&registry), expression);
8292    }
8293
8294    #[test]
8295    fn table_simplify() {
8296        let registry = TableRegistry::default();
8297        let expression =
8298            ContinuousExpression::Table(Box::new(NumericTableExpression::Constant(0.0)));
8299        assert_eq!(
8300            expression.simplify(&registry),
8301            ContinuousExpression::Constant(0.0)
8302        );
8303        let expression = ContinuousExpression::Table(Box::new(NumericTableExpression::Table1D(
8304            0,
8305            ElementExpression::Variable(0),
8306        )));
8307        assert_eq!(expression.simplify(&registry), expression,);
8308    }
8309
8310    #[test]
8311    fn if_simplify() {
8312        let registry = TableRegistry::default();
8313
8314        let expression = ContinuousExpression::If(
8315            Box::new(Condition::Constant(true)),
8316            Box::new(ContinuousExpression::Constant(1.0)),
8317            Box::new(ContinuousExpression::Constant(2.0)),
8318        );
8319        assert_eq!(
8320            expression.simplify(&registry),
8321            ContinuousExpression::Constant(1.0)
8322        );
8323
8324        let expression = ContinuousExpression::If(
8325            Box::new(Condition::Constant(false)),
8326            Box::new(ContinuousExpression::Constant(1.0)),
8327            Box::new(ContinuousExpression::Constant(2.0)),
8328        );
8329        assert_eq!(
8330            expression.simplify(&registry),
8331            ContinuousExpression::Constant(2.0)
8332        );
8333
8334        let expression = ContinuousExpression::If(
8335            Box::new(Condition::Table(Box::new(TableExpression::Table1D(
8336                0,
8337                ElementExpression::Variable(0),
8338            )))),
8339            Box::new(ContinuousExpression::Constant(1.0)),
8340            Box::new(ContinuousExpression::Constant(2.0)),
8341        );
8342        assert_eq!(expression.simplify(&registry), expression);
8343    }
8344
8345    #[test]
8346    fn from_integer_simplify() {
8347        let registry = TableRegistry::default();
8348
8349        let expression =
8350            ContinuousExpression::FromInteger(Box::new(IntegerExpression::Constant(1)));
8351        assert_eq!(
8352            expression.simplify(&registry),
8353            ContinuousExpression::Constant(1.0)
8354        );
8355
8356        let expression =
8357            ContinuousExpression::FromInteger(Box::new(IntegerExpression::Variable(0)));
8358        assert_eq!(expression.simplify(&registry), expression);
8359    }
8360
8361    #[test]
8362    fn last_simplify() {
8363        let registry = TableRegistry::default();
8364
8365        let expression =
8366            ContinuousExpression::Last(Box::new(ContinuousVectorExpression::Constant(vec![
8367                1.0, 2.0, 3.0,
8368            ])));
8369        assert_eq!(
8370            expression.simplify(&registry),
8371            ContinuousExpression::Constant(3.0)
8372        );
8373
8374        let expression = ContinuousExpression::Last(Box::new(ContinuousVectorExpression::Table(
8375            Box::new(TableVectorExpression::Table1D(
8376                0,
8377                VectorExpression::Reference(ReferenceExpression::Variable(0)),
8378            )),
8379        )));
8380        assert_eq!(expression.simplify(&registry), expression);
8381    }
8382
8383    #[test]
8384    fn at_simplify() {
8385        let registry = TableRegistry::default();
8386
8387        let expression = ContinuousExpression::At(
8388            Box::new(ContinuousVectorExpression::Constant(vec![1.0, 2.0, 3.0])),
8389            ElementExpression::Constant(0),
8390        );
8391        assert_eq!(
8392            expression.simplify(&registry),
8393            ContinuousExpression::Constant(1.0)
8394        );
8395
8396        let expression = ContinuousExpression::At(
8397            Box::new(ContinuousVectorExpression::Table(Box::new(
8398                TableVectorExpression::Table1D(
8399                    0,
8400                    VectorExpression::Reference(ReferenceExpression::Variable(0)),
8401                ),
8402            ))),
8403            ElementExpression::Constant(0),
8404        );
8405        assert_eq!(expression.simplify(&registry), expression);
8406    }
8407
8408    #[test]
8409    fn reduce_simplify() {
8410        let registry = TableRegistry::default();
8411
8412        let expression = ContinuousExpression::Reduce(
8413            ReduceOperator::Sum,
8414            Box::new(ContinuousVectorExpression::Constant(vec![1.0, 2.0, 3.0])),
8415        );
8416        assert_eq!(
8417            expression.simplify(&registry),
8418            ContinuousExpression::Constant(6.0)
8419        );
8420
8421        let expression = ContinuousExpression::Reduce(
8422            ReduceOperator::Sum,
8423            Box::new(ContinuousVectorExpression::Table(Box::new(
8424                TableVectorExpression::Table1D(
8425                    0,
8426                    VectorExpression::Reference(ReferenceExpression::Variable(0)),
8427                ),
8428            ))),
8429        );
8430        assert_eq!(expression.simplify(&registry), expression);
8431    }
8432}