dypdl/expression/
numeric_table_expression.rs

1use super::argument_expression::ArgumentExpression;
2use super::element_expression::ElementExpression;
3use super::numeric_operator::ReduceOperator;
4use super::reference_expression::ReferenceExpression;
5use super::set_expression::SetExpression;
6use super::vector_expression::VectorExpression;
7use crate::state::StateInterface;
8use crate::state_functions::{StateFunctionCache, StateFunctions};
9use crate::table::{Table1D, Table2D};
10use crate::table_data::TableData;
11use crate::table_registry::TableRegistry;
12use crate::variable_type::{Element, Numeric, Set};
13use num_traits::Num;
14use std::iter::{Product, Sum};
15
16/// Expression referring to a numeric table.
17#[derive(Debug, PartialEq, Clone)]
18pub enum NumericTableExpression<T: Numeric> {
19    /// Constant.
20    Constant(T),
21    /// Constant in a table.
22    Table(usize, Vec<ElementExpression>),
23    /// Reduce constants over sets and vectors in a table.
24    TableReduce(ReduceOperator, usize, Vec<ArgumentExpression>),
25    /// Constant in a 1D table.
26    Table1D(usize, ElementExpression),
27    /// Constant in a 2D table.
28    Table2D(usize, ElementExpression, ElementExpression),
29    /// Constant in a 3D table.
30    Table3D(
31        usize,
32        ElementExpression,
33        ElementExpression,
34        ElementExpression,
35    ),
36    /// Reduce constants over a set in a 1D table.
37    Table1DReduce(ReduceOperator, usize, SetExpression),
38    /// Reduce constants over a vector in a 1D table.
39    Table1DVectorReduce(ReduceOperator, usize, VectorExpression),
40    /// Reduce constants over two sets in a 2D table.
41    Table2DReduce(ReduceOperator, usize, SetExpression, SetExpression),
42    /// Reduce constants over two vectors in a 2D table.
43    Table2DVectorReduce(ReduceOperator, usize, VectorExpression, VectorExpression),
44    /// Reduce constants over a set and a vector in a 2D table.
45    Table2DSetVectorReduce(ReduceOperator, usize, SetExpression, VectorExpression),
46    /// Reduce constants over a vector and a set in a 2D table.
47    Table2DVectorSetReduce(ReduceOperator, usize, VectorExpression, SetExpression),
48    /// Reduce constants over a set in a 2D table.
49    Table2DReduceX(ReduceOperator, usize, SetExpression, ElementExpression),
50    /// Reduce constants over a set in a 2D table.
51    Table2DReduceY(ReduceOperator, usize, ElementExpression, SetExpression),
52    /// Reduce constants over a vector in a 2D table.
53    Table2DVectorReduceX(ReduceOperator, usize, VectorExpression, ElementExpression),
54    /// Reduce constants over a vector in a 2D table.
55    Table2DVectorReduceY(ReduceOperator, usize, ElementExpression, VectorExpression),
56    /// Reduce constants over sets and vectors in a 3D table.
57    Table3DReduce(
58        ReduceOperator,
59        usize,
60        ArgumentExpression,
61        ArgumentExpression,
62        ArgumentExpression,
63    ),
64}
65
66impl<T: Numeric> NumericTableExpression<T> {
67    /// Returns the evaluation result.
68    ///
69    /// # Panics
70    ///
71    /// Panics if the cost of the transitioned state is used or an empty set or vector is passed to a reduce operation or a min/max reduce operation is performed on an empty set or vector.
72    pub fn eval<U: StateInterface>(
73        &self,
74        state: &U,
75        function_cache: &mut StateFunctionCache,
76        state_functions: &StateFunctions,
77        registry: &TableRegistry,
78        tables: &TableData<T>,
79    ) -> T {
80        match self {
81            Self::Constant(value) => *value,
82            Self::Table(i, args) => {
83                let args: Vec<Element> = args
84                    .iter()
85                    .map(|x| x.eval(state, function_cache, state_functions, registry))
86                    .collect();
87                tables.tables[*i].eval(&args)
88            }
89            Self::TableReduce(op, i, args) => {
90                let args = ArgumentExpression::eval_args(
91                    args.iter(),
92                    state,
93                    function_cache,
94                    state_functions,
95                    registry,
96                );
97                op.eval_iter(args.into_iter().map(|args| tables.tables[*i].eval(&args)))
98                    .unwrap()
99            }
100            Self::Table1D(i, x) => {
101                tables.tables_1d[*i].eval(x.eval(state, function_cache, state_functions, registry))
102            }
103            Self::Table2D(i, x, y) => tables.tables_2d[*i].eval(
104                x.eval(state, function_cache, state_functions, registry),
105                y.eval(state, function_cache, state_functions, registry),
106            ),
107            Self::Table3D(i, x, y, z) => tables.tables_3d[*i].eval(
108                x.eval(state, function_cache, state_functions, registry),
109                y.eval(state, function_cache, state_functions, registry),
110                z.eval(state, function_cache, state_functions, registry),
111            ),
112            Self::Table1DReduce(op, i, SetExpression::Reference(x)) => Self::reduce_table_1d(
113                op,
114                &tables.tables_1d[*i],
115                x.eval(state, function_cache, state_functions, registry)
116                    .ones(),
117            ),
118            Self::Table1DReduce(op, i, SetExpression::StateFunction(x)) => Self::reduce_table_1d(
119                op,
120                &tables.tables_1d[*i],
121                function_cache
122                    .get_set_value(*x, state, state_functions, registry)
123                    .ones(),
124            ),
125            Self::Table1DReduce(op, i, x) => Self::reduce_table_1d(
126                op,
127                &tables.tables_1d[*i],
128                x.eval(state, function_cache, state_functions, registry)
129                    .ones(),
130            ),
131            Self::Table1DVectorReduce(op, i, VectorExpression::Reference(x)) => {
132                Self::reduce_table_1d(
133                    op,
134                    &tables.tables_1d[*i],
135                    x.eval(state, function_cache, state_functions, registry)
136                        .iter()
137                        .copied(),
138                )
139            }
140            Self::Table1DVectorReduce(op, i, x) => Self::reduce_table_1d(
141                op,
142                &tables.tables_1d[*i],
143                x.eval(state, function_cache, state_functions, registry)
144                    .into_iter(),
145            ),
146            Self::Table2DReduce(
147                op,
148                i,
149                SetExpression::StateFunction(x),
150                SetExpression::StateFunction(y),
151            ) => {
152                let (x, y) =
153                    function_cache.get_set_value_pair(*x, *y, state, state_functions, registry);
154                Self::reduce_table_2d_set_y(op, &tables.tables_2d[*i], x.ones(), y)
155            }
156            Self::Table2DReduce(
157                op,
158                i,
159                SetExpression::StateFunction(x),
160                SetExpression::Reference(y),
161            ) => {
162                let y = y.eval(state, function_cache, state_functions, registry);
163                let x = function_cache
164                    .get_set_value(*x, state, state_functions, registry)
165                    .ones();
166                Self::reduce_table_2d_set_y(op, &tables.tables_2d[*i], x, y)
167            }
168            Self::Table2DReduce(
169                op,
170                i,
171                SetExpression::Reference(x),
172                SetExpression::StateFunction(y),
173            ) => {
174                let x = x
175                    .eval(state, function_cache, state_functions, registry)
176                    .ones();
177                let y = function_cache.get_set_value(*y, state, state_functions, registry);
178                Self::reduce_table_2d_set_y(op, &tables.tables_2d[*i], x, y)
179            }
180            Self::Table2DReduce(op, i, SetExpression::StateFunction(x), y) => {
181                let y = y.eval(state, function_cache, state_functions, registry);
182                let x = function_cache
183                    .get_set_value(*x, state, state_functions, registry)
184                    .ones();
185                Self::reduce_table_2d_set_y(op, &tables.tables_2d[*i], x, &y)
186            }
187            Self::Table2DReduce(op, i, x, SetExpression::StateFunction(y)) => {
188                let x = x.eval(state, function_cache, state_functions, registry);
189                let y = function_cache.get_set_value(*y, state, state_functions, registry);
190                Self::reduce_table_2d_set_y(op, &tables.tables_2d[*i], x.ones(), y)
191            }
192            Self::Table2DReduce(
193                op,
194                i,
195                SetExpression::Reference(x),
196                SetExpression::Reference(y),
197            ) => {
198                let x = x
199                    .eval(state, function_cache, state_functions, registry)
200                    .ones();
201                let y = y.eval(state, function_cache, state_functions, registry);
202                Self::reduce_table_2d_set_y(op, &tables.tables_2d[*i], x, y)
203            }
204            Self::Table2DReduce(op, i, SetExpression::Reference(x), y) => {
205                let y = y.eval(state, function_cache, state_functions, registry);
206                let x = x
207                    .eval(state, function_cache, state_functions, registry)
208                    .ones();
209                Self::reduce_table_2d_set_y(op, &tables.tables_2d[*i], x, &y)
210            }
211            Self::Table2DReduce(op, i, x, SetExpression::Reference(y)) => {
212                let x = x.eval(state, function_cache, state_functions, registry);
213                let y = y.eval(state, function_cache, state_functions, registry);
214                Self::reduce_table_2d_set_x(op, &tables.tables_2d[*i], &x, y.ones())
215            }
216            Self::Table2DReduce(op, i, x, y) => {
217                let y = y.eval(state, function_cache, state_functions, registry);
218                Self::reduce_table_2d_set_y(
219                    op,
220                    &tables.tables_2d[*i],
221                    x.eval(state, function_cache, state_functions, registry)
222                        .ones(),
223                    &y,
224                )
225            }
226            Self::Table2DVectorReduce(
227                op,
228                i,
229                VectorExpression::Reference(x),
230                VectorExpression::Reference(y),
231            ) => {
232                let x = x
233                    .eval(state, function_cache, state_functions, registry)
234                    .iter()
235                    .copied();
236                let y = y
237                    .eval(state, function_cache, state_functions, registry)
238                    .iter()
239                    .copied();
240                Self::reduce_table_2d(op, &tables.tables_2d[*i], x, y)
241            }
242            Self::Table2DVectorReduce(op, i, VectorExpression::Reference(x), y) => {
243                let x = x
244                    .eval(state, function_cache, state_functions, registry)
245                    .iter()
246                    .copied();
247                let y = y
248                    .eval(state, function_cache, state_functions, registry)
249                    .into_iter();
250                Self::reduce_table_2d(op, &tables.tables_2d[*i], x, y)
251            }
252            Self::Table2DVectorReduce(op, i, x, VectorExpression::Reference(y)) => {
253                let x = x
254                    .eval(state, function_cache, state_functions, registry)
255                    .into_iter();
256                let y = y
257                    .eval(state, function_cache, state_functions, registry)
258                    .iter()
259                    .copied();
260                Self::reduce_table_2d(op, &tables.tables_2d[*i], x, y)
261            }
262            Self::Table2DVectorReduce(op, i, x, y) => {
263                let x = x
264                    .eval(state, function_cache, state_functions, registry)
265                    .into_iter();
266                let y = y
267                    .eval(state, function_cache, state_functions, registry)
268                    .into_iter();
269                Self::reduce_table_2d(op, &tables.tables_2d[*i], x, y)
270            }
271            Self::Table2DSetVectorReduce(
272                op,
273                i,
274                SetExpression::Reference(x),
275                VectorExpression::Reference(y),
276            ) => {
277                let y = y
278                    .eval(state, function_cache, state_functions, registry)
279                    .iter()
280                    .copied();
281                let x = x
282                    .eval(state, function_cache, state_functions, registry)
283                    .ones();
284                Self::reduce_table_2d(op, &tables.tables_2d[*i], x, y)
285            }
286            Self::Table2DSetVectorReduce(op, i, SetExpression::Reference(x), y) => {
287                let y = y
288                    .eval(state, function_cache, state_functions, registry)
289                    .into_iter();
290                Self::reduce_table_2d(
291                    op,
292                    &tables.tables_2d[*i],
293                    x.eval(state, function_cache, state_functions, registry)
294                        .ones(),
295                    y,
296                )
297            }
298            Self::Table2DSetVectorReduce(op, i, x, VectorExpression::Reference(y)) => {
299                let y = y
300                    .eval(state, function_cache, state_functions, registry)
301                    .iter()
302                    .copied();
303                Self::reduce_table_2d(
304                    op,
305                    &tables.tables_2d[*i],
306                    x.eval(state, function_cache, state_functions, registry)
307                        .ones(),
308                    y,
309                )
310            }
311            Self::Table2DSetVectorReduce(op, i, x, y) => {
312                let y = y
313                    .eval(state, function_cache, state_functions, registry)
314                    .into_iter();
315                Self::reduce_table_2d(
316                    op,
317                    &tables.tables_2d[*i],
318                    x.eval(state, function_cache, state_functions, registry)
319                        .ones(),
320                    y,
321                )
322            }
323            Self::Table2DVectorSetReduce(
324                op,
325                i,
326                VectorExpression::Reference(x),
327                SetExpression::Reference(y),
328            ) => {
329                let x = x
330                    .eval(state, function_cache, state_functions, registry)
331                    .iter()
332                    .copied();
333                let y = y.eval(state, function_cache, state_functions, registry);
334                Self::reduce_table_2d_set_y(op, &tables.tables_2d[*i], x, y)
335            }
336            Self::Table2DVectorSetReduce(op, i, x, SetExpression::Reference(y)) => {
337                let x = x
338                    .eval(state, function_cache, state_functions, registry)
339                    .into_iter();
340                let y = y.eval(state, function_cache, state_functions, registry);
341                Self::reduce_table_2d_set_y(op, &tables.tables_2d[*i], x, y)
342            }
343            Self::Table2DVectorSetReduce(op, i, VectorExpression::Reference(x), y) => {
344                let x = x
345                    .eval(state, function_cache, state_functions, registry)
346                    .iter()
347                    .copied();
348                let y = y.eval(state, function_cache, state_functions, registry);
349                Self::reduce_table_2d_set_y(op, &tables.tables_2d[*i], x, &y)
350            }
351            Self::Table2DVectorSetReduce(op, i, x, y) => {
352                let x = x
353                    .eval(state, function_cache, state_functions, registry)
354                    .into_iter();
355                let y = y.eval(state, function_cache, state_functions, registry);
356                Self::reduce_table_2d_set_y(op, &tables.tables_2d[*i], x, &y)
357            }
358            Self::Table2DReduceX(op, i, SetExpression::Reference(x), y) => {
359                let y = y.eval(state, function_cache, state_functions, registry);
360                let x = x
361                    .eval(state, function_cache, state_functions, registry)
362                    .ones();
363                Self::reduce_table_2d_x(op, &tables.tables_2d[*i], x, y)
364            }
365            Self::Table2DReduceX(op, i, x, y) => {
366                let y = y.eval(state, function_cache, state_functions, registry);
367                Self::reduce_table_2d_x(
368                    op,
369                    &tables.tables_2d[*i],
370                    x.eval(state, function_cache, state_functions, registry)
371                        .ones(),
372                    y,
373                )
374            }
375            Self::Table2DReduceY(op, i, x, SetExpression::Reference(y)) => {
376                let x = x.eval(state, function_cache, state_functions, registry);
377                let y = y
378                    .eval(state, function_cache, state_functions, registry)
379                    .ones();
380                Self::reduce_table_2d_y(op, &tables.tables_2d[*i], x, y)
381            }
382            Self::Table2DReduceY(op, i, x, y) => {
383                let x = x.eval(state, function_cache, state_functions, registry);
384                Self::reduce_table_2d_y(
385                    op,
386                    &tables.tables_2d[*i],
387                    x,
388                    y.eval(state, function_cache, state_functions, registry)
389                        .ones(),
390                )
391            }
392            Self::Table2DVectorReduceX(op, i, VectorExpression::Reference(x), y) => {
393                let x = x
394                    .eval(state, function_cache, state_functions, registry)
395                    .iter()
396                    .copied();
397                let y = y.eval(state, function_cache, state_functions, registry);
398                Self::reduce_table_2d_x(op, &tables.tables_2d[*i], x, y)
399            }
400            Self::Table2DVectorReduceX(op, i, x, y) => {
401                let x = x
402                    .eval(state, function_cache, state_functions, registry)
403                    .into_iter();
404                let y = y.eval(state, function_cache, state_functions, registry);
405                Self::reduce_table_2d_x(op, &tables.tables_2d[*i], x, y)
406            }
407            Self::Table2DVectorReduceY(op, i, x, VectorExpression::Reference(y)) => {
408                let x = x.eval(state, function_cache, state_functions, registry);
409                let y = y
410                    .eval(state, function_cache, state_functions, registry)
411                    .iter()
412                    .copied();
413                Self::reduce_table_2d_y(op, &tables.tables_2d[*i], x, y)
414            }
415            Self::Table2DVectorReduceY(op, i, x, y) => {
416                let x = x.eval(state, function_cache, state_functions, registry);
417                let y = y
418                    .eval(state, function_cache, state_functions, registry)
419                    .into_iter();
420                Self::reduce_table_2d_y(op, &tables.tables_2d[*i], x, y)
421            }
422            Self::Table3DReduce(op, i, x, y, z) => {
423                let args = ArgumentExpression::eval_args(
424                    [x, y, z].into_iter(),
425                    state,
426                    function_cache,
427                    state_functions,
428                    registry,
429                );
430                op.eval_iter(
431                    args.into_iter()
432                        .map(|args| tables.tables_3d[*i].eval(args[0], args[1], args[2])),
433                )
434                .unwrap()
435            }
436        }
437    }
438
439    /// Returns a simplified version by precomputation.
440    ///
441    /// # Panics
442    ///
443    /// Panics if a min/max reduce operation is performed on an empty set or vector.
444    pub fn simplify(
445        &self,
446        registry: &TableRegistry,
447        tables: &TableData<T>,
448    ) -> NumericTableExpression<T> {
449        match self {
450            Self::Table(i, args) => {
451                let args: Vec<ElementExpression> =
452                    args.iter().map(|x| x.simplify(registry)).collect();
453                let mut simplified_args = Vec::with_capacity(args.len());
454                for arg in &args {
455                    match arg {
456                        ElementExpression::Constant(arg) => {
457                            simplified_args.push(*arg);
458                        }
459                        _ => return Self::Table(*i, args),
460                    }
461                }
462                Self::Constant(tables.tables[*i].eval(&simplified_args))
463            }
464            Self::TableReduce(op, i, args) => {
465                let args: Vec<ArgumentExpression> =
466                    args.iter().map(|x| x.simplify(registry)).collect();
467                if let Some(args) = ArgumentExpression::simplify_args(args.iter()) {
468                    Self::Constant(
469                        op.eval_iter(args.into_iter().map(|args| tables.tables[*i].eval(&args)))
470                            .unwrap(),
471                    )
472                } else {
473                    Self::TableReduce(op.clone(), *i, args)
474                }
475            }
476            Self::Table1D(i, x) => match x.simplify(registry) {
477                ElementExpression::Constant(x) => Self::Constant(tables.tables_1d[*i].eval(x)),
478                x => Self::Table1D(*i, x),
479            },
480            Self::Table2D(i, x, y) => match (x.simplify(registry), y.simplify(registry)) {
481                (ElementExpression::Constant(x), ElementExpression::Constant(y)) => {
482                    Self::Constant(tables.tables_2d[*i].eval(x, y))
483                }
484                (x, y) => Self::Table2D(*i, x, y),
485            },
486            Self::Table3D(i, x, y, z) => match (
487                x.simplify(registry),
488                y.simplify(registry),
489                z.simplify(registry),
490            ) {
491                (
492                    ElementExpression::Constant(x),
493                    ElementExpression::Constant(y),
494                    ElementExpression::Constant(z),
495                ) => Self::Constant(tables.tables_3d[*i].eval(x, y, z)),
496                (x, y, z) => Self::Table3D(*i, x, y, z),
497            },
498            Self::Table1DReduce(op, i, x) => match x.simplify(registry) {
499                SetExpression::Reference(ReferenceExpression::Constant(x)) => {
500                    Self::Constant(Self::reduce_table_1d(op, &tables.tables_1d[*i], x.ones()))
501                }
502                x => Self::Table1DReduce(op.clone(), *i, x),
503            },
504            Self::Table1DVectorReduce(op, i, x) => match x.simplify(registry) {
505                VectorExpression::Reference(ReferenceExpression::Constant(x)) => Self::Constant(
506                    Self::reduce_table_1d(op, &tables.tables_1d[*i], x.into_iter()),
507                ),
508                x => Self::Table1DVectorReduce(op.clone(), *i, x),
509            },
510            Self::Table2DReduce(op, i, x, y) => {
511                match (x.simplify(registry), y.simplify(registry)) {
512                    (
513                        SetExpression::Reference(ReferenceExpression::Constant(x)),
514                        SetExpression::Reference(ReferenceExpression::Constant(y)),
515                    ) => Self::Constant(Self::reduce_table_2d_set_y(
516                        op,
517                        &tables.tables_2d[*i],
518                        x.ones(),
519                        &y,
520                    )),
521                    (x, y) => Self::Table2DReduce(op.clone(), *i, x, y),
522                }
523            }
524            Self::Table2DVectorReduce(op, i, x, y) => {
525                match (x.simplify(registry), y.simplify(registry)) {
526                    (
527                        VectorExpression::Reference(ReferenceExpression::Constant(x)),
528                        VectorExpression::Reference(ReferenceExpression::Constant(y)),
529                    ) => Self::Constant(Self::reduce_table_2d(
530                        op,
531                        &tables.tables_2d[*i],
532                        x.into_iter(),
533                        y.into_iter(),
534                    )),
535                    (x, y) => Self::Table2DVectorReduce(op.clone(), *i, x, y),
536                }
537            }
538            Self::Table2DSetVectorReduce(op, i, x, y) => {
539                match (x.simplify(registry), y.simplify(registry)) {
540                    (
541                        SetExpression::Reference(ReferenceExpression::Constant(x)),
542                        VectorExpression::Reference(ReferenceExpression::Constant(y)),
543                    ) => Self::Constant(Self::reduce_table_2d(
544                        op,
545                        &tables.tables_2d[*i],
546                        x.ones(),
547                        y.into_iter(),
548                    )),
549                    (x, y) => Self::Table2DSetVectorReduce(op.clone(), *i, x, y),
550                }
551            }
552            Self::Table2DVectorSetReduce(op, i, x, y) => {
553                match (x.simplify(registry), y.simplify(registry)) {
554                    (
555                        VectorExpression::Reference(ReferenceExpression::Constant(x)),
556                        SetExpression::Reference(ReferenceExpression::Constant(y)),
557                    ) => Self::Constant(Self::reduce_table_2d_set_y(
558                        op,
559                        &tables.tables_2d[*i],
560                        x.into_iter(),
561                        &y,
562                    )),
563                    (x, y) => Self::Table2DVectorSetReduce(op.clone(), *i, x, y),
564                }
565            }
566            Self::Table2DReduceX(op, i, x, y) => match (x.simplify(registry), y.simplify(registry))
567            {
568                (
569                    SetExpression::Reference(ReferenceExpression::Constant(x)),
570                    ElementExpression::Constant(y),
571                ) => Self::Constant(Self::reduce_table_2d_x(
572                    op,
573                    &tables.tables_2d[*i],
574                    x.ones(),
575                    y,
576                )),
577                (x, y) => Self::Table2DReduceX(op.clone(), *i, x, y),
578            },
579            Self::Table2DReduceY(op, i, x, y) => match (x.simplify(registry), y.simplify(registry))
580            {
581                (
582                    ElementExpression::Constant(x),
583                    SetExpression::Reference(ReferenceExpression::Constant(y)),
584                ) => Self::Constant(Self::reduce_table_2d_y(
585                    op,
586                    &tables.tables_2d[*i],
587                    x,
588                    y.ones(),
589                )),
590                (x, y) => Self::Table2DReduceY(op.clone(), *i, x, y),
591            },
592            Self::Table2DVectorReduceX(op, i, x, y) => {
593                match (x.simplify(registry), y.simplify(registry)) {
594                    (
595                        VectorExpression::Reference(ReferenceExpression::Constant(x)),
596                        ElementExpression::Constant(y),
597                    ) => Self::Constant(Self::reduce_table_2d_x(
598                        op,
599                        &tables.tables_2d[*i],
600                        x.into_iter(),
601                        y,
602                    )),
603                    (x, y) => Self::Table2DVectorReduceX(op.clone(), *i, x, y),
604                }
605            }
606            Self::Table2DVectorReduceY(op, i, x, y) => {
607                match (x.simplify(registry), y.simplify(registry)) {
608                    (
609                        ElementExpression::Constant(x),
610                        VectorExpression::Reference(ReferenceExpression::Constant(y)),
611                    ) => Self::Constant(Self::reduce_table_2d_y(
612                        op,
613                        &tables.tables_2d[*i],
614                        x,
615                        y.into_iter(),
616                    )),
617                    (x, y) => Self::Table2DVectorReduceY(op.clone(), *i, x, y),
618                }
619            }
620            Self::Table3DReduce(op, i, x, y, z) => {
621                let x = x.simplify(registry);
622                let y = y.simplify(registry);
623                let z = z.simplify(registry);
624                if let Some(args) = ArgumentExpression::simplify_args([&x, &y, &z].into_iter()) {
625                    Self::Constant(
626                        op.eval_iter(
627                            args.into_iter()
628                                .map(|args| tables.tables_3d[*i].eval(args[0], args[1], args[2])),
629                        )
630                        .unwrap(),
631                    )
632                } else {
633                    Self::Table3DReduce(op.clone(), *i, x, y, z)
634                }
635            }
636            _ => self.clone(),
637        }
638    }
639
640    fn reduce_table_1d<I>(op: &ReduceOperator, table: &Table1D<T>, x: I) -> T
641    where
642        T: Num + PartialOrd + Sum + Product,
643        I: Iterator<Item = Element>,
644    {
645        op.eval_iter(x.map(|x| table.eval(x))).unwrap()
646    }
647
648    fn reduce_table_2d<I, J>(op: &ReduceOperator, table: &Table2D<T>, x: I, y: J) -> T
649    where
650        T: Num + PartialOrd + Sum + Product,
651        I: Iterator<Item = Element>,
652        J: Iterator<Item = Element> + Clone,
653    {
654        op.eval_iter(x.map(|x| op.eval_iter(y.clone().map(|y| table.eval(x, y))).unwrap()))
655            .unwrap()
656    }
657
658    fn reduce_table_2d_set_x<I>(op: &ReduceOperator, table: &Table2D<T>, x: &Set, y: I) -> T
659    where
660        T: Num + PartialOrd + Sum + Product,
661        I: Iterator<Item = Element>,
662    {
663        op.eval_iter(y.map(|y| op.eval_iter(x.ones().map(|x| table.eval(x, y))).unwrap()))
664            .unwrap()
665    }
666
667    fn reduce_table_2d_set_y<I>(op: &ReduceOperator, table: &Table2D<T>, x: I, y: &Set) -> T
668    where
669        T: Num + PartialOrd + Sum + Product,
670        I: Iterator<Item = Element>,
671    {
672        op.eval_iter(x.map(|x| op.eval_iter(y.ones().map(|y| table.eval(x, y))).unwrap()))
673            .unwrap()
674    }
675
676    fn reduce_table_2d_x<I>(op: &ReduceOperator, table: &Table2D<T>, x: I, y: Element) -> T
677    where
678        T: Num + PartialOrd + Sum + Product,
679        I: Iterator<Item = Element>,
680    {
681        op.eval_iter(x.map(|x| table.eval(x, y))).unwrap()
682    }
683
684    fn reduce_table_2d_y<I>(op: &ReduceOperator, table: &Table2D<T>, x: Element, y: I) -> T
685    where
686        T: Num + PartialOrd + Sum + Product,
687        I: Iterator<Item = Element>,
688    {
689        op.eval_iter(y.map(|y| table.eval(x, y))).unwrap()
690    }
691}
692
693#[cfg(test)]
694mod tests {
695    use super::super::set_expression::SetElementOperation;
696    use super::*;
697    use crate::state::*;
698    use crate::table;
699    use crate::table_data::TableInterface;
700    use rustc_hash::FxHashMap;
701
702    fn generate_registry() -> TableRegistry {
703        let mut name_to_constant = FxHashMap::default();
704        name_to_constant.insert(String::from("f0"), 0);
705
706        let tables_1d = vec![table::Table1D::new(vec![10, 20, 30])];
707        let mut name_to_table_1d = FxHashMap::default();
708        name_to_table_1d.insert(String::from("f1"), 0);
709
710        let tables_2d = vec![table::Table2D::new(vec![
711            vec![10, 20, 30],
712            vec![40, 50, 60],
713            vec![70, 80, 90],
714        ])];
715        let mut name_to_table_2d = FxHashMap::default();
716        name_to_table_2d.insert(String::from("f2"), 0);
717
718        let tables_3d = vec![table::Table3D::new(vec![
719            vec![vec![10, 20, 30], vec![40, 50, 60], vec![70, 80, 90]],
720            vec![vec![10, 20, 30], vec![40, 50, 60], vec![70, 80, 90]],
721            vec![vec![10, 20, 30], vec![40, 50, 60], vec![70, 80, 90]],
722        ])];
723        let mut name_to_table_3d = FxHashMap::default();
724        name_to_table_3d.insert(String::from("f3"), 0);
725
726        let mut map = FxHashMap::default();
727        let key = vec![0, 1, 0, 0];
728        map.insert(key, 100);
729        let key = vec![0, 1, 0, 1];
730        map.insert(key, 200);
731        let key = vec![0, 1, 2, 0];
732        map.insert(key, 300);
733        let key = vec![0, 1, 2, 1];
734        map.insert(key, 400);
735        let tables = vec![table::Table::new(map, 0)];
736        let mut name_to_table = FxHashMap::default();
737        name_to_table.insert(String::from("f4"), 0);
738
739        TableRegistry {
740            integer_tables: TableData {
741                name_to_constant,
742                tables_1d,
743                name_to_table_1d,
744                tables_2d,
745                name_to_table_2d,
746                tables_3d,
747                name_to_table_3d,
748                tables,
749                name_to_table,
750            },
751            ..Default::default()
752        }
753    }
754
755    fn generate_state() -> State {
756        let mut set1 = Set::with_capacity(3);
757        set1.insert(0);
758        set1.insert(2);
759        let mut set2 = Set::with_capacity(3);
760        set2.insert(0);
761        set2.insert(1);
762        State {
763            signature_variables: SignatureVariables {
764                set_variables: vec![set1, set2, Set::with_capacity(3), Set::with_capacity(3)],
765                vector_variables: vec![vec![0, 2], vec![0, 1], vec![], vec![]],
766                ..Default::default()
767            },
768            ..Default::default()
769        }
770    }
771
772    #[test]
773    fn constant_eval() {
774        let registry = generate_registry();
775        let state_functions = StateFunctions::default();
776        let mut function_cache = StateFunctionCache::new(&state_functions);
777        let state = generate_state();
778        let expression = NumericTableExpression::Constant(10);
779        assert_eq!(
780            expression.eval(
781                &state,
782                &mut function_cache,
783                &state_functions,
784                &registry,
785                &registry.integer_tables
786            ),
787            10
788        );
789    }
790
791    #[test]
792    fn table_1d_eval() {
793        let registry = generate_registry();
794        let state = generate_state();
795        let state_functions = StateFunctions::default();
796        let mut function_cache = StateFunctionCache::new(&state_functions);
797        let expression = NumericTableExpression::Table1D(0, ElementExpression::Constant(0));
798        assert_eq!(
799            expression.eval(
800                &state,
801                &mut function_cache,
802                &state_functions,
803                &registry,
804                &registry.integer_tables
805            ),
806            10
807        );
808        let expression = NumericTableExpression::Table1D(0, ElementExpression::Constant(1));
809        assert_eq!(
810            expression.eval(
811                &state,
812                &mut function_cache,
813                &state_functions,
814                &registry,
815                &registry.integer_tables
816            ),
817            20
818        );
819        let expression = NumericTableExpression::Table1D(0, ElementExpression::Constant(2));
820        assert_eq!(
821            expression.eval(
822                &state,
823                &mut function_cache,
824                &state_functions,
825                &registry,
826                &registry.integer_tables
827            ),
828            30
829        );
830    }
831
832    #[test]
833    fn table_1d_sum_eval() {
834        let registry = generate_registry();
835        let state = generate_state();
836        let state_functions = StateFunctions::default();
837        let mut function_cache = StateFunctionCache::new(&state_functions);
838        let expression = NumericTableExpression::Table1DReduce(
839            ReduceOperator::Sum,
840            0,
841            SetExpression::Reference(ReferenceExpression::Variable(0)),
842        );
843        assert_eq!(
844            expression.eval(
845                &state,
846                &mut function_cache,
847                &state_functions,
848                &registry,
849                &registry.integer_tables
850            ),
851            40
852        );
853        let expression = NumericTableExpression::Table1DReduce(
854            ReduceOperator::Sum,
855            0,
856            SetExpression::Reference(ReferenceExpression::Variable(1)),
857        );
858        assert_eq!(
859            expression.eval(
860                &state,
861                &mut function_cache,
862                &state_functions,
863                &registry,
864                &registry.integer_tables
865            ),
866            30
867        );
868        let expression = NumericTableExpression::Table1DReduce(
869            ReduceOperator::Sum,
870            0,
871            SetExpression::Complement(Box::new(SetExpression::Reference(
872                ReferenceExpression::Variable(0),
873            ))),
874        );
875        assert_eq!(
876            expression.eval(
877                &state,
878                &mut function_cache,
879                &state_functions,
880                &registry,
881                &registry.integer_tables
882            ),
883            20
884        );
885    }
886
887    #[test]
888    fn table_1d_vector_sum_eval() {
889        let registry = generate_registry();
890        let state = generate_state();
891        let state_functions = StateFunctions::default();
892        let mut function_cache = StateFunctionCache::new(&state_functions);
893        let expression = NumericTableExpression::Table1DVectorReduce(
894            ReduceOperator::Sum,
895            0,
896            VectorExpression::Reference(ReferenceExpression::Variable(0)),
897        );
898        assert_eq!(
899            expression.eval(
900                &state,
901                &mut function_cache,
902                &state_functions,
903                &registry,
904                &registry.integer_tables
905            ),
906            40
907        );
908        let expression = NumericTableExpression::Table1DVectorReduce(
909            ReduceOperator::Sum,
910            0,
911            VectorExpression::Reverse(Box::new(VectorExpression::Reference(
912                ReferenceExpression::Variable(0),
913            ))),
914        );
915        assert_eq!(
916            expression.eval(
917                &state,
918                &mut function_cache,
919                &state_functions,
920                &registry,
921                &registry.integer_tables
922            ),
923            40
924        );
925    }
926
927    #[test]
928    fn table_1d_set_state_function_reduce_eval() {
929        let mut state_metadata = StateMetadata::default();
930        let ob = state_metadata.add_object_type("ob", 3);
931        assert!(ob.is_ok());
932        let ob = ob.unwrap();
933        let v = state_metadata.add_set_variable("v", ob);
934        assert!(v.is_ok());
935        let v = v.unwrap();
936
937        let mut state_functions = StateFunctions::default();
938        let f = state_functions.add_set_function("f", v.add(0).add(1));
939        assert!(f.is_ok());
940        let f = f.unwrap();
941
942        let mut registry = TableRegistry::default();
943        let t = registry.add_table_1d("t", vec![1, 2]);
944        assert!(t.is_ok());
945        let t = t.unwrap();
946
947        let state = State {
948            signature_variables: SignatureVariables {
949                set_variables: vec![Set::with_capacity(3)],
950                ..Default::default()
951            },
952            ..Default::default()
953        };
954
955        let expression = NumericTableExpression::Table1DReduce(ReduceOperator::Sum, t.id(), f);
956
957        assert_eq!(
958            expression.eval(
959                &state,
960                &mut StateFunctionCache::new(&state_functions),
961                &state_functions,
962                &registry,
963                &registry.integer_tables,
964            ),
965            3,
966        );
967    }
968
969    #[test]
970    fn table_2d_eval() {
971        let registry = generate_registry();
972        let state = generate_state();
973        let state_functions = StateFunctions::default();
974        let mut function_cache = StateFunctionCache::new(&state_functions);
975        let expression = NumericTableExpression::Table2D(
976            0,
977            ElementExpression::Constant(0),
978            ElementExpression::Constant(1),
979        );
980        assert_eq!(
981            expression.eval(
982                &state,
983                &mut function_cache,
984                &state_functions,
985                &registry,
986                &registry.integer_tables
987            ),
988            20
989        );
990    }
991
992    #[test]
993    fn table_2d_sum_eval() {
994        let registry = generate_registry();
995        let state = generate_state();
996        let state_functions = StateFunctions::default();
997        let mut function_cache = StateFunctionCache::new(&state_functions);
998
999        let expression = NumericTableExpression::Table2DReduce(
1000            ReduceOperator::Sum,
1001            0,
1002            SetExpression::Reference(ReferenceExpression::Variable(0)),
1003            SetExpression::Reference(ReferenceExpression::Variable(1)),
1004        );
1005        assert_eq!(
1006            expression.eval(
1007                &state,
1008                &mut function_cache,
1009                &state_functions,
1010                &registry,
1011                &registry.integer_tables
1012            ),
1013            180
1014        );
1015
1016        let expression = NumericTableExpression::Table2DReduce(
1017            ReduceOperator::Sum,
1018            0,
1019            SetExpression::Reference(ReferenceExpression::Variable(0)),
1020            SetExpression::Complement(Box::new(SetExpression::Complement(Box::new(
1021                SetExpression::Reference(ReferenceExpression::Variable(1)),
1022            )))),
1023        );
1024        assert_eq!(
1025            expression.eval(
1026                &state,
1027                &mut function_cache,
1028                &state_functions,
1029                &registry,
1030                &registry.integer_tables
1031            ),
1032            180
1033        );
1034
1035        let expression = NumericTableExpression::Table2DReduce(
1036            ReduceOperator::Sum,
1037            0,
1038            SetExpression::Complement(Box::new(SetExpression::Complement(Box::new(
1039                SetExpression::Reference(ReferenceExpression::Variable(0)),
1040            )))),
1041            SetExpression::Reference(ReferenceExpression::Variable(1)),
1042        );
1043        assert_eq!(
1044            expression.eval(
1045                &state,
1046                &mut function_cache,
1047                &state_functions,
1048                &registry,
1049                &registry.integer_tables
1050            ),
1051            180
1052        );
1053
1054        let expression = NumericTableExpression::Table2DReduce(
1055            ReduceOperator::Sum,
1056            0,
1057            SetExpression::Complement(Box::new(SetExpression::Complement(Box::new(
1058                SetExpression::Reference(ReferenceExpression::Variable(0)),
1059            )))),
1060            SetExpression::Complement(Box::new(SetExpression::Complement(Box::new(
1061                SetExpression::Reference(ReferenceExpression::Variable(1)),
1062            )))),
1063        );
1064        assert_eq!(
1065            expression.eval(
1066                &state,
1067                &mut function_cache,
1068                &state_functions,
1069                &registry,
1070                &registry.integer_tables
1071            ),
1072            180
1073        );
1074    }
1075
1076    #[test]
1077    fn table_2d_vector_sum_eval() {
1078        let registry = generate_registry();
1079        let state = generate_state();
1080        let state_functions = StateFunctions::default();
1081        let mut function_cache = StateFunctionCache::new(&state_functions);
1082
1083        let expression = NumericTableExpression::Table2DVectorReduce(
1084            ReduceOperator::Sum,
1085            0,
1086            VectorExpression::Reference(ReferenceExpression::Variable(0)),
1087            VectorExpression::Reference(ReferenceExpression::Variable(1)),
1088        );
1089        assert_eq!(
1090            expression.eval(
1091                &state,
1092                &mut function_cache,
1093                &state_functions,
1094                &registry,
1095                &registry.integer_tables
1096            ),
1097            180
1098        );
1099
1100        let expression = NumericTableExpression::Table2DVectorReduce(
1101            ReduceOperator::Sum,
1102            0,
1103            VectorExpression::Reference(ReferenceExpression::Variable(0)),
1104            VectorExpression::Reverse(Box::new(VectorExpression::Reference(
1105                ReferenceExpression::Variable(1),
1106            ))),
1107        );
1108        assert_eq!(
1109            expression.eval(
1110                &state,
1111                &mut function_cache,
1112                &state_functions,
1113                &registry,
1114                &registry.integer_tables
1115            ),
1116            180
1117        );
1118
1119        let expression = NumericTableExpression::Table2DVectorReduce(
1120            ReduceOperator::Sum,
1121            0,
1122            VectorExpression::Reverse(Box::new(VectorExpression::Reference(
1123                ReferenceExpression::Variable(0),
1124            ))),
1125            VectorExpression::Reference(ReferenceExpression::Variable(1)),
1126        );
1127        assert_eq!(
1128            expression.eval(
1129                &state,
1130                &mut function_cache,
1131                &state_functions,
1132                &registry,
1133                &registry.integer_tables
1134            ),
1135            180
1136        );
1137
1138        let expression = NumericTableExpression::Table2DVectorReduce(
1139            ReduceOperator::Sum,
1140            0,
1141            VectorExpression::Reverse(Box::new(VectorExpression::Reference(
1142                ReferenceExpression::Variable(0),
1143            ))),
1144            VectorExpression::Reverse(Box::new(VectorExpression::Reference(
1145                ReferenceExpression::Variable(1),
1146            ))),
1147        );
1148        assert_eq!(
1149            expression.eval(
1150                &state,
1151                &mut function_cache,
1152                &state_functions,
1153                &registry,
1154                &registry.integer_tables
1155            ),
1156            180
1157        );
1158    }
1159
1160    #[test]
1161    fn table_2d_set_vector_sum_eval() {
1162        let registry = generate_registry();
1163        let state = generate_state();
1164        let state_functions = StateFunctions::default();
1165        let mut function_cache = StateFunctionCache::new(&state_functions);
1166
1167        let expression = NumericTableExpression::Table2DSetVectorReduce(
1168            ReduceOperator::Sum,
1169            0,
1170            SetExpression::Reference(ReferenceExpression::Variable(0)),
1171            VectorExpression::Reference(ReferenceExpression::Variable(1)),
1172        );
1173        assert_eq!(
1174            expression.eval(
1175                &state,
1176                &mut function_cache,
1177                &state_functions,
1178                &registry,
1179                &registry.integer_tables
1180            ),
1181            180
1182        );
1183
1184        let expression = NumericTableExpression::Table2DSetVectorReduce(
1185            ReduceOperator::Sum,
1186            0,
1187            SetExpression::Reference(ReferenceExpression::Variable(0)),
1188            VectorExpression::Reverse(Box::new(VectorExpression::Reference(
1189                ReferenceExpression::Variable(1),
1190            ))),
1191        );
1192        assert_eq!(
1193            expression.eval(
1194                &state,
1195                &mut function_cache,
1196                &state_functions,
1197                &registry,
1198                &registry.integer_tables
1199            ),
1200            180
1201        );
1202
1203        let expression = NumericTableExpression::Table2DSetVectorReduce(
1204            ReduceOperator::Sum,
1205            0,
1206            SetExpression::Complement(Box::new(SetExpression::Complement(Box::new(
1207                SetExpression::Reference(ReferenceExpression::Variable(0)),
1208            )))),
1209            VectorExpression::Reference(ReferenceExpression::Variable(1)),
1210        );
1211        assert_eq!(
1212            expression.eval(
1213                &state,
1214                &mut function_cache,
1215                &state_functions,
1216                &registry,
1217                &registry.integer_tables
1218            ),
1219            180
1220        );
1221
1222        let expression = NumericTableExpression::Table2DSetVectorReduce(
1223            ReduceOperator::Sum,
1224            0,
1225            SetExpression::Complement(Box::new(SetExpression::Complement(Box::new(
1226                SetExpression::Reference(ReferenceExpression::Variable(0)),
1227            )))),
1228            VectorExpression::Reverse(Box::new(VectorExpression::Reference(
1229                ReferenceExpression::Variable(1),
1230            ))),
1231        );
1232        assert_eq!(
1233            expression.eval(
1234                &state,
1235                &mut function_cache,
1236                &state_functions,
1237                &registry,
1238                &registry.integer_tables
1239            ),
1240            180
1241        );
1242    }
1243
1244    #[test]
1245    fn table_2d_vector_set_sum_eval() {
1246        let registry = generate_registry();
1247        let state = generate_state();
1248        let state_functions = StateFunctions::default();
1249        let mut function_cache = StateFunctionCache::new(&state_functions);
1250
1251        let expression = NumericTableExpression::Table2DVectorSetReduce(
1252            ReduceOperator::Sum,
1253            0,
1254            VectorExpression::Reference(ReferenceExpression::Variable(0)),
1255            SetExpression::Reference(ReferenceExpression::Variable(1)),
1256        );
1257        assert_eq!(
1258            expression.eval(
1259                &state,
1260                &mut function_cache,
1261                &state_functions,
1262                &registry,
1263                &registry.integer_tables
1264            ),
1265            180
1266        );
1267
1268        let expression = NumericTableExpression::Table2DVectorSetReduce(
1269            ReduceOperator::Sum,
1270            0,
1271            VectorExpression::Reverse(Box::new(VectorExpression::Reference(
1272                ReferenceExpression::Variable(0),
1273            ))),
1274            SetExpression::Reference(ReferenceExpression::Variable(1)),
1275        );
1276        assert_eq!(
1277            expression.eval(
1278                &state,
1279                &mut function_cache,
1280                &state_functions,
1281                &registry,
1282                &registry.integer_tables
1283            ),
1284            180
1285        );
1286
1287        let expression = NumericTableExpression::Table2DVectorSetReduce(
1288            ReduceOperator::Sum,
1289            0,
1290            VectorExpression::Reference(ReferenceExpression::Variable(0)),
1291            SetExpression::Complement(Box::new(SetExpression::Complement(Box::new(
1292                SetExpression::Reference(ReferenceExpression::Variable(1)),
1293            )))),
1294        );
1295        assert_eq!(
1296            expression.eval(
1297                &state,
1298                &mut function_cache,
1299                &state_functions,
1300                &registry,
1301                &registry.integer_tables
1302            ),
1303            180
1304        );
1305
1306        let expression = NumericTableExpression::Table2DVectorSetReduce(
1307            ReduceOperator::Sum,
1308            0,
1309            VectorExpression::Reverse(Box::new(VectorExpression::Reference(
1310                ReferenceExpression::Variable(0),
1311            ))),
1312            SetExpression::Complement(Box::new(SetExpression::Complement(Box::new(
1313                SetExpression::Reference(ReferenceExpression::Variable(1)),
1314            )))),
1315        );
1316        assert_eq!(
1317            expression.eval(
1318                &state,
1319                &mut function_cache,
1320                &state_functions,
1321                &registry,
1322                &registry.integer_tables
1323            ),
1324            180
1325        );
1326    }
1327
1328    #[test]
1329    fn table_2d_sum_x_eval() {
1330        let registry = generate_registry();
1331        let state = generate_state();
1332        let state_functions = StateFunctions::default();
1333        let mut function_cache = StateFunctionCache::new(&state_functions);
1334
1335        let expression = NumericTableExpression::Table2DReduceX(
1336            ReduceOperator::Sum,
1337            0,
1338            SetExpression::Reference(ReferenceExpression::Variable(0)),
1339            ElementExpression::Constant(0),
1340        );
1341        assert_eq!(
1342            expression.eval(
1343                &state,
1344                &mut function_cache,
1345                &state_functions,
1346                &registry,
1347                &registry.integer_tables
1348            ),
1349            80
1350        );
1351
1352        let expression = NumericTableExpression::Table2DReduceX(
1353            ReduceOperator::Sum,
1354            0,
1355            SetExpression::Complement(Box::new(SetExpression::Complement(Box::new(
1356                SetExpression::Reference(ReferenceExpression::Variable(0)),
1357            )))),
1358            ElementExpression::Constant(0),
1359        );
1360        assert_eq!(
1361            expression.eval(
1362                &state,
1363                &mut function_cache,
1364                &state_functions,
1365                &registry,
1366                &registry.integer_tables
1367            ),
1368            80
1369        );
1370    }
1371
1372    #[test]
1373    fn table_2d_vector_sum_x_eval() {
1374        let registry = generate_registry();
1375        let state = generate_state();
1376        let state_functions = StateFunctions::default();
1377        let mut function_cache = StateFunctionCache::new(&state_functions);
1378
1379        let expression = NumericTableExpression::Table2DVectorReduceX(
1380            ReduceOperator::Sum,
1381            0,
1382            VectorExpression::Reference(ReferenceExpression::Variable(0)),
1383            ElementExpression::Constant(0),
1384        );
1385        assert_eq!(
1386            expression.eval(
1387                &state,
1388                &mut function_cache,
1389                &state_functions,
1390                &registry,
1391                &registry.integer_tables
1392            ),
1393            80
1394        );
1395
1396        let expression = NumericTableExpression::Table2DVectorReduceX(
1397            ReduceOperator::Sum,
1398            0,
1399            VectorExpression::Reverse(Box::new(VectorExpression::Reference(
1400                ReferenceExpression::Variable(0),
1401            ))),
1402            ElementExpression::Constant(0),
1403        );
1404        assert_eq!(
1405            expression.eval(
1406                &state,
1407                &mut function_cache,
1408                &state_functions,
1409                &registry,
1410                &registry.integer_tables
1411            ),
1412            80
1413        );
1414    }
1415
1416    #[test]
1417    fn table_2d_sum_y_eval() {
1418        let registry = generate_registry();
1419        let state = generate_state();
1420        let state_functions = StateFunctions::default();
1421        let mut function_cache = StateFunctionCache::new(&state_functions);
1422
1423        let expression = NumericTableExpression::Table2DReduceY(
1424            ReduceOperator::Sum,
1425            0,
1426            ElementExpression::Constant(0),
1427            SetExpression::Reference(ReferenceExpression::Variable(0)),
1428        );
1429        assert_eq!(
1430            expression.eval(
1431                &state,
1432                &mut function_cache,
1433                &state_functions,
1434                &registry,
1435                &registry.integer_tables
1436            ),
1437            40
1438        );
1439
1440        let expression = NumericTableExpression::Table2DReduceY(
1441            ReduceOperator::Sum,
1442            0,
1443            ElementExpression::Constant(0),
1444            SetExpression::Complement(Box::new(SetExpression::Complement(Box::new(
1445                SetExpression::Reference(ReferenceExpression::Variable(0)),
1446            )))),
1447        );
1448        assert_eq!(
1449            expression.eval(
1450                &state,
1451                &mut function_cache,
1452                &state_functions,
1453                &registry,
1454                &registry.integer_tables
1455            ),
1456            40
1457        );
1458    }
1459
1460    #[test]
1461    fn table_2d_vector_sum_y_eval() {
1462        let registry = generate_registry();
1463        let state = generate_state();
1464        let state_functions = StateFunctions::default();
1465        let mut function_cache = StateFunctionCache::new(&state_functions);
1466
1467        let expression = NumericTableExpression::Table2DVectorReduceY(
1468            ReduceOperator::Sum,
1469            0,
1470            ElementExpression::Constant(0),
1471            VectorExpression::Reference(ReferenceExpression::Variable(0)),
1472        );
1473        assert_eq!(
1474            expression.eval(
1475                &state,
1476                &mut function_cache,
1477                &state_functions,
1478                &registry,
1479                &registry.integer_tables
1480            ),
1481            40
1482        );
1483
1484        let expression = NumericTableExpression::Table2DVectorReduceY(
1485            ReduceOperator::Sum,
1486            0,
1487            ElementExpression::Constant(0),
1488            VectorExpression::Reverse(Box::new(VectorExpression::Reference(
1489                ReferenceExpression::Variable(0),
1490            ))),
1491        );
1492        assert_eq!(
1493            expression.eval(
1494                &state,
1495                &mut function_cache,
1496                &state_functions,
1497                &registry,
1498                &registry.integer_tables
1499            ),
1500            40
1501        );
1502    }
1503
1504    #[test]
1505    fn table_2d_set_state_function_element_reduce_x_eval() {
1506        let mut state_metadata = StateMetadata::default();
1507        let ob = state_metadata.add_object_type("ob", 3);
1508        assert!(ob.is_ok());
1509        let ob = ob.unwrap();
1510        let v = state_metadata.add_set_variable("v", ob);
1511        assert!(v.is_ok());
1512        let v = v.unwrap();
1513
1514        let mut state_functions = StateFunctions::default();
1515        let f = state_functions.add_set_function("f", v.add(0).add(1));
1516        assert!(f.is_ok());
1517        let f = f.unwrap();
1518
1519        let mut registry = TableRegistry::default();
1520        let t = registry.add_table_2d("t", vec![vec![1, 2], vec![3, 4]]);
1521        assert!(t.is_ok());
1522        let t = t.unwrap();
1523
1524        let state = State {
1525            signature_variables: SignatureVariables {
1526                set_variables: vec![Set::with_capacity(3)],
1527                ..Default::default()
1528            },
1529            ..Default::default()
1530        };
1531
1532        let expression =
1533            NumericTableExpression::Table2DReduceX(ReduceOperator::Sum, t.id(), f, 1.into());
1534
1535        assert_eq!(
1536            expression.eval(
1537                &state,
1538                &mut StateFunctionCache::new(&state_functions),
1539                &state_functions,
1540                &registry,
1541                &registry.integer_tables,
1542            ),
1543            6,
1544        );
1545    }
1546
1547    #[test]
1548    fn table_2d_element_set_state_function_reduce_y_eval() {
1549        let mut state_metadata = StateMetadata::default();
1550        let ob = state_metadata.add_object_type("ob", 3);
1551        assert!(ob.is_ok());
1552        let ob = ob.unwrap();
1553        let v = state_metadata.add_set_variable("v", ob);
1554        assert!(v.is_ok());
1555        let v = v.unwrap();
1556
1557        let mut state_functions = StateFunctions::default();
1558        let f = state_functions.add_set_function("f", v.add(0).add(1));
1559        assert!(f.is_ok());
1560        let f = f.unwrap();
1561
1562        let mut registry = TableRegistry::default();
1563        let t = registry.add_table_2d("t", vec![vec![1, 2], vec![3, 4]]);
1564        assert!(t.is_ok());
1565        let t = t.unwrap();
1566
1567        let state = State {
1568            signature_variables: SignatureVariables {
1569                set_variables: vec![Set::with_capacity(3)],
1570                ..Default::default()
1571            },
1572            ..Default::default()
1573        };
1574
1575        let expression =
1576            NumericTableExpression::Table2DReduceY(ReduceOperator::Sum, t.id(), 1.into(), f);
1577
1578        assert_eq!(
1579            expression.eval(
1580                &state,
1581                &mut StateFunctionCache::new(&state_functions),
1582                &state_functions,
1583                &registry,
1584                &registry.integer_tables,
1585            ),
1586            7,
1587        );
1588    }
1589
1590    #[test]
1591    fn table_2d_set_state_function_set_state_function_reduce_eval() {
1592        let mut state_metadata = StateMetadata::default();
1593        let ob = state_metadata.add_object_type("ob", 3);
1594        assert!(ob.is_ok());
1595        let ob = ob.unwrap();
1596        let v = state_metadata.add_set_variable("v", ob);
1597        assert!(v.is_ok());
1598        let v = v.unwrap();
1599
1600        let mut state_functions = StateFunctions::default();
1601        let f = state_functions.add_set_function("f", v.add(0).add(1));
1602        assert!(f.is_ok());
1603        let f = f.unwrap();
1604        let g = state_functions.add_set_function("g", v.add(0).add(1));
1605        assert!(g.is_ok());
1606        let g = g.unwrap();
1607
1608        let mut registry = TableRegistry::default();
1609        let t = registry.add_table_2d("t", vec![vec![1, 2], vec![3, 4]]);
1610        assert!(t.is_ok());
1611        let t = t.unwrap();
1612
1613        let state = State {
1614            signature_variables: SignatureVariables {
1615                set_variables: vec![Set::with_capacity(3)],
1616                ..Default::default()
1617            },
1618            ..Default::default()
1619        };
1620
1621        let expression = NumericTableExpression::Table2DReduce(ReduceOperator::Sum, t.id(), f, g);
1622
1623        assert_eq!(
1624            expression.eval(
1625                &state,
1626                &mut StateFunctionCache::new(&state_functions),
1627                &state_functions,
1628                &registry,
1629                &registry.integer_tables,
1630            ),
1631            10,
1632        );
1633    }
1634
1635    #[test]
1636    fn table_2d_set_state_function_set_reference_reduce_eval() {
1637        let mut state_metadata = StateMetadata::default();
1638        let ob = state_metadata.add_object_type("ob", 3);
1639        assert!(ob.is_ok());
1640        let ob = ob.unwrap();
1641        let v = state_metadata.add_set_variable("v", ob);
1642        assert!(v.is_ok());
1643        let v = v.unwrap();
1644
1645        let mut state_functions = StateFunctions::default();
1646        let f = state_functions.add_set_function("f", v.add(0).add(1));
1647        assert!(f.is_ok());
1648        let f = f.unwrap();
1649
1650        let mut registry = TableRegistry::default();
1651        let t = registry.add_table_2d("t", vec![vec![1, 2], vec![3, 4]]);
1652        assert!(t.is_ok());
1653        let t = t.unwrap();
1654
1655        let set = state_metadata.create_set(ob, &[0, 1]);
1656        assert!(set.is_ok());
1657        let set = set.unwrap();
1658
1659        let state = State {
1660            signature_variables: SignatureVariables {
1661                set_variables: vec![Set::with_capacity(3)],
1662                ..Default::default()
1663            },
1664            ..Default::default()
1665        };
1666
1667        let expression =
1668            NumericTableExpression::Table2DReduce(ReduceOperator::Sum, t.id(), f, set.into());
1669
1670        assert_eq!(
1671            expression.eval(
1672                &state,
1673                &mut StateFunctionCache::new(&state_functions),
1674                &state_functions,
1675                &registry,
1676                &registry.integer_tables,
1677            ),
1678            10,
1679        );
1680    }
1681
1682    #[test]
1683    fn table_2d_set_reference_set_state_function_reduce_eval() {
1684        let mut state_metadata = StateMetadata::default();
1685        let ob = state_metadata.add_object_type("ob", 3);
1686        assert!(ob.is_ok());
1687        let ob = ob.unwrap();
1688        let v = state_metadata.add_set_variable("v", ob);
1689        assert!(v.is_ok());
1690        let v = v.unwrap();
1691
1692        let mut state_functions = StateFunctions::default();
1693        let f = state_functions.add_set_function("f", v.add(0).add(1));
1694        assert!(f.is_ok());
1695        let f = f.unwrap();
1696
1697        let mut registry = TableRegistry::default();
1698        let t = registry.add_table_2d("t", vec![vec![1, 2], vec![3, 4]]);
1699        assert!(t.is_ok());
1700        let t = t.unwrap();
1701
1702        let set = state_metadata.create_set(ob, &[0, 1]);
1703        assert!(set.is_ok());
1704        let set = set.unwrap();
1705
1706        let state = State {
1707            signature_variables: SignatureVariables {
1708                set_variables: vec![Set::with_capacity(3)],
1709                ..Default::default()
1710            },
1711            ..Default::default()
1712        };
1713
1714        let expression =
1715            NumericTableExpression::Table2DReduce(ReduceOperator::Sum, t.id(), set.into(), f);
1716
1717        assert_eq!(
1718            expression.eval(
1719                &state,
1720                &mut StateFunctionCache::new(&state_functions),
1721                &state_functions,
1722                &registry,
1723                &registry.integer_tables,
1724            ),
1725            10,
1726        );
1727    }
1728
1729    #[test]
1730    fn table_3d_eval() {
1731        let registry = generate_registry();
1732        let state = generate_state();
1733        let state_functions = StateFunctions::default();
1734        let mut function_cache = StateFunctionCache::new(&state_functions);
1735        let expression = NumericTableExpression::Table3D(
1736            0,
1737            ElementExpression::Constant(0),
1738            ElementExpression::Constant(0),
1739            ElementExpression::Constant(0),
1740        );
1741        assert_eq!(
1742            expression.eval(
1743                &state,
1744                &mut function_cache,
1745                &state_functions,
1746                &registry,
1747                &registry.integer_tables
1748            ),
1749            10
1750        );
1751    }
1752
1753    #[test]
1754    fn table_3d_sum_eval() {
1755        let registry = generate_registry();
1756        let state = generate_state();
1757        let state_functions = StateFunctions::default();
1758        let mut function_cache = StateFunctionCache::new(&state_functions);
1759        let expression = NumericTableExpression::Table3DReduce(
1760            ReduceOperator::Sum,
1761            0,
1762            ArgumentExpression::Element(ElementExpression::Constant(0)),
1763            ArgumentExpression::Set(SetExpression::Reference(ReferenceExpression::Variable(0))),
1764            ArgumentExpression::Vector(VectorExpression::Reference(ReferenceExpression::Variable(
1765                1,
1766            ))),
1767        );
1768        assert_eq!(
1769            expression.eval(
1770                &state,
1771                &mut function_cache,
1772                &state_functions,
1773                &registry,
1774                &registry.integer_tables
1775            ),
1776            180
1777        );
1778    }
1779
1780    #[test]
1781    fn table_eval() {
1782        let registry = generate_registry();
1783        let state = generate_state();
1784        let state_functions = StateFunctions::default();
1785        let mut function_cache = StateFunctionCache::new(&state_functions);
1786        let expression = NumericTableExpression::Table(
1787            0,
1788            vec![
1789                ElementExpression::Constant(0),
1790                ElementExpression::Constant(1),
1791                ElementExpression::Constant(0),
1792                ElementExpression::Constant(0),
1793            ],
1794        );
1795        assert_eq!(
1796            expression.eval(
1797                &state,
1798                &mut function_cache,
1799                &state_functions,
1800                &registry,
1801                &registry.integer_tables
1802            ),
1803            100
1804        );
1805        let expression = NumericTableExpression::Table(
1806            0,
1807            vec![
1808                ElementExpression::Constant(0),
1809                ElementExpression::Constant(1),
1810                ElementExpression::Constant(0),
1811                ElementExpression::Constant(1),
1812            ],
1813        );
1814        assert_eq!(
1815            expression.eval(
1816                &state,
1817                &mut function_cache,
1818                &state_functions,
1819                &registry,
1820                &registry.integer_tables
1821            ),
1822            200
1823        );
1824        let expression = NumericTableExpression::Table(
1825            0,
1826            vec![
1827                ElementExpression::Constant(0),
1828                ElementExpression::Constant(1),
1829                ElementExpression::Constant(2),
1830                ElementExpression::Constant(0),
1831            ],
1832        );
1833        assert_eq!(
1834            expression.eval(
1835                &state,
1836                &mut function_cache,
1837                &state_functions,
1838                &registry,
1839                &registry.integer_tables
1840            ),
1841            300
1842        );
1843        let expression = NumericTableExpression::Table(
1844            0,
1845            vec![
1846                ElementExpression::Constant(0),
1847                ElementExpression::Constant(1),
1848                ElementExpression::Constant(2),
1849                ElementExpression::Constant(1),
1850            ],
1851        );
1852        assert_eq!(
1853            expression.eval(
1854                &state,
1855                &mut function_cache,
1856                &state_functions,
1857                &registry,
1858                &registry.integer_tables
1859            ),
1860            400
1861        );
1862    }
1863
1864    #[test]
1865    fn table_sum_eval() {
1866        let registry = generate_registry();
1867        let state = generate_state();
1868        let state_functions = StateFunctions::default();
1869        let mut function_cache = StateFunctionCache::new(&state_functions);
1870        let expression = NumericTableExpression::TableReduce(
1871            ReduceOperator::Sum,
1872            0,
1873            vec![
1874                ArgumentExpression::Element(ElementExpression::Constant(0)),
1875                ArgumentExpression::Element(ElementExpression::Constant(1)),
1876                ArgumentExpression::Set(SetExpression::Complement(Box::new(
1877                    SetExpression::Complement(Box::new(SetExpression::Reference(
1878                        ReferenceExpression::Variable(0),
1879                    ))),
1880                ))),
1881                ArgumentExpression::Vector(VectorExpression::Reverse(Box::new(
1882                    VectorExpression::Reference(ReferenceExpression::Variable(1)),
1883                ))),
1884            ],
1885        );
1886        assert_eq!(
1887            expression.eval(
1888                &state,
1889                &mut function_cache,
1890                &state_functions,
1891                &registry,
1892                &registry.integer_tables
1893            ),
1894            1000
1895        );
1896    }
1897
1898    #[test]
1899    fn constant_simplify() {
1900        let registry = generate_registry();
1901        let expression = NumericTableExpression::Constant(0);
1902        assert_eq!(
1903            expression.simplify(&registry, &registry.integer_tables),
1904            expression
1905        );
1906    }
1907
1908    #[test]
1909    fn table_1d_simplify() {
1910        let registry = generate_registry();
1911
1912        let expression = NumericTableExpression::Table1D(0, ElementExpression::Constant(0));
1913        assert_eq!(
1914            expression.simplify(&registry, &registry.integer_tables),
1915            NumericTableExpression::Constant(10)
1916        );
1917
1918        let expression = NumericTableExpression::Table1D(0, ElementExpression::Variable(0));
1919        assert_eq!(
1920            expression.simplify(&registry, &registry.integer_tables),
1921            expression
1922        );
1923    }
1924
1925    #[test]
1926    fn table_1d_sum_simplify() {
1927        let registry = generate_registry();
1928
1929        let mut set = Set::with_capacity(3);
1930        set.insert(0);
1931        set.insert(1);
1932        let expression = NumericTableExpression::Table1DReduce(
1933            ReduceOperator::Sum,
1934            0,
1935            SetExpression::Reference(ReferenceExpression::Constant(set)),
1936        );
1937        assert_eq!(
1938            expression.simplify(&registry, &registry.integer_tables),
1939            NumericTableExpression::Constant(30)
1940        );
1941
1942        let expression = NumericTableExpression::Table1DReduce(
1943            ReduceOperator::Sum,
1944            0,
1945            SetExpression::Reference(ReferenceExpression::Variable(0)),
1946        );
1947        assert_eq!(
1948            expression.simplify(&registry, &registry.integer_tables),
1949            expression
1950        );
1951    }
1952
1953    #[test]
1954    fn table_1d_vector_sum_simplify() {
1955        let registry = generate_registry();
1956
1957        let expression = NumericTableExpression::Table1DVectorReduce(
1958            ReduceOperator::Sum,
1959            0,
1960            VectorExpression::Reference(ReferenceExpression::Constant(vec![0, 1])),
1961        );
1962        assert_eq!(
1963            expression.simplify(&registry, &registry.integer_tables),
1964            NumericTableExpression::Constant(30)
1965        );
1966
1967        let expression = NumericTableExpression::Table1DVectorReduce(
1968            ReduceOperator::Sum,
1969            0,
1970            VectorExpression::Reference(ReferenceExpression::Variable(0)),
1971        );
1972        assert_eq!(
1973            expression.simplify(&registry, &registry.integer_tables),
1974            expression
1975        );
1976    }
1977
1978    #[test]
1979    fn table_2d_simplify() {
1980        let registry = generate_registry();
1981
1982        let expression = NumericTableExpression::Table2D(
1983            0,
1984            ElementExpression::Constant(0),
1985            ElementExpression::Constant(0),
1986        );
1987        assert_eq!(
1988            expression.simplify(&registry, &registry.integer_tables),
1989            NumericTableExpression::Constant(10)
1990        );
1991
1992        let expression = NumericTableExpression::Table2D(
1993            0,
1994            ElementExpression::Constant(0),
1995            ElementExpression::Variable(0),
1996        );
1997        assert_eq!(
1998            expression.simplify(&registry, &registry.integer_tables),
1999            expression
2000        );
2001    }
2002
2003    #[test]
2004    fn table_2d_sum_simplify() {
2005        let registry = generate_registry();
2006
2007        let mut set = Set::with_capacity(3);
2008        set.insert(0);
2009        set.insert(1);
2010        let expression = NumericTableExpression::Table2DReduce(
2011            ReduceOperator::Sum,
2012            0,
2013            SetExpression::Reference(ReferenceExpression::Constant(set.clone())),
2014            SetExpression::Reference(ReferenceExpression::Constant(set)),
2015        );
2016        assert_eq!(
2017            expression.simplify(&registry, &registry.integer_tables),
2018            NumericTableExpression::Constant(120)
2019        );
2020
2021        let expression = NumericTableExpression::Table2DReduce(
2022            ReduceOperator::Sum,
2023            0,
2024            SetExpression::Reference(ReferenceExpression::Variable(0)),
2025            SetExpression::Reference(ReferenceExpression::Variable(1)),
2026        );
2027        assert_eq!(
2028            expression.simplify(&registry, &registry.integer_tables),
2029            expression
2030        );
2031    }
2032
2033    #[test]
2034    fn table_2d_vector_sum_simplify() {
2035        let registry = generate_registry();
2036
2037        let expression = NumericTableExpression::Table2DVectorReduce(
2038            ReduceOperator::Sum,
2039            0,
2040            VectorExpression::Reference(ReferenceExpression::Constant(vec![0, 1])),
2041            VectorExpression::Reference(ReferenceExpression::Constant(vec![0, 1])),
2042        );
2043        assert_eq!(
2044            expression.simplify(&registry, &registry.integer_tables),
2045            NumericTableExpression::Constant(120)
2046        );
2047
2048        let expression = NumericTableExpression::Table2DVectorReduce(
2049            ReduceOperator::Sum,
2050            0,
2051            VectorExpression::Reference(ReferenceExpression::Variable(0)),
2052            VectorExpression::Reference(ReferenceExpression::Variable(1)),
2053        );
2054        assert_eq!(
2055            expression.simplify(&registry, &registry.integer_tables),
2056            expression
2057        );
2058    }
2059
2060    #[test]
2061    fn table_2d_set_vector_sum_simplify() {
2062        let registry = generate_registry();
2063
2064        let mut set = Set::with_capacity(3);
2065        set.insert(0);
2066        set.insert(1);
2067        let expression = NumericTableExpression::Table2DSetVectorReduce(
2068            ReduceOperator::Sum,
2069            0,
2070            SetExpression::Reference(ReferenceExpression::Constant(set)),
2071            VectorExpression::Reference(ReferenceExpression::Constant(vec![0, 1])),
2072        );
2073        assert_eq!(
2074            expression.simplify(&registry, &registry.integer_tables),
2075            NumericTableExpression::Constant(120)
2076        );
2077
2078        let expression = NumericTableExpression::Table2DSetVectorReduce(
2079            ReduceOperator::Sum,
2080            0,
2081            SetExpression::Reference(ReferenceExpression::Variable(0)),
2082            VectorExpression::Reference(ReferenceExpression::Variable(1)),
2083        );
2084        assert_eq!(
2085            expression.simplify(&registry, &registry.integer_tables),
2086            expression
2087        );
2088    }
2089
2090    #[test]
2091    fn table_2d_vector_set_sum_simplify() {
2092        let registry = generate_registry();
2093
2094        let mut set = Set::with_capacity(3);
2095        set.insert(0);
2096        set.insert(1);
2097        let expression = NumericTableExpression::Table2DVectorSetReduce(
2098            ReduceOperator::Sum,
2099            0,
2100            VectorExpression::Reference(ReferenceExpression::Constant(vec![0, 1])),
2101            SetExpression::Reference(ReferenceExpression::Constant(set)),
2102        );
2103        assert_eq!(
2104            expression.simplify(&registry, &registry.integer_tables),
2105            NumericTableExpression::Constant(120)
2106        );
2107
2108        let expression = NumericTableExpression::Table2DVectorSetReduce(
2109            ReduceOperator::Sum,
2110            0,
2111            VectorExpression::Reference(ReferenceExpression::Variable(1)),
2112            SetExpression::Reference(ReferenceExpression::Variable(0)),
2113        );
2114        assert_eq!(
2115            expression.simplify(&registry, &registry.integer_tables),
2116            expression
2117        );
2118    }
2119
2120    #[test]
2121    fn table_2d_sum_x_simplify() {
2122        let registry = generate_registry();
2123
2124        let mut set = Set::with_capacity(3);
2125        set.insert(0);
2126        set.insert(1);
2127        let expression = NumericTableExpression::Table2DReduceX(
2128            ReduceOperator::Sum,
2129            0,
2130            SetExpression::Reference(ReferenceExpression::Constant(set)),
2131            ElementExpression::Constant(0),
2132        );
2133        assert_eq!(
2134            expression.simplify(&registry, &registry.integer_tables),
2135            NumericTableExpression::Constant(50)
2136        );
2137
2138        let expression = NumericTableExpression::Table2DReduceX(
2139            ReduceOperator::Sum,
2140            0,
2141            SetExpression::Reference(ReferenceExpression::Variable(0)),
2142            ElementExpression::Constant(0),
2143        );
2144        assert_eq!(
2145            expression.simplify(&registry, &registry.integer_tables),
2146            expression
2147        );
2148    }
2149
2150    #[test]
2151    fn table_2d_sum_y_simplify() {
2152        let registry = generate_registry();
2153
2154        let mut set = Set::with_capacity(3);
2155        set.insert(0);
2156        set.insert(1);
2157        let expression = NumericTableExpression::Table2DReduceY(
2158            ReduceOperator::Sum,
2159            0,
2160            ElementExpression::Constant(0),
2161            SetExpression::Reference(ReferenceExpression::Constant(set)),
2162        );
2163        assert_eq!(
2164            expression.simplify(&registry, &registry.integer_tables),
2165            NumericTableExpression::Constant(30)
2166        );
2167
2168        let expression = NumericTableExpression::Table2DReduceY(
2169            ReduceOperator::Sum,
2170            0,
2171            ElementExpression::Constant(0),
2172            SetExpression::Reference(ReferenceExpression::Variable(0)),
2173        );
2174        assert_eq!(
2175            expression.simplify(&registry, &registry.integer_tables),
2176            expression
2177        );
2178    }
2179
2180    #[test]
2181    fn table_2d_vector_sum_x_simplify() {
2182        let registry = generate_registry();
2183
2184        let expression = NumericTableExpression::Table2DVectorReduceX(
2185            ReduceOperator::Sum,
2186            0,
2187            VectorExpression::Reference(ReferenceExpression::Constant(vec![0, 1])),
2188            ElementExpression::Constant(0),
2189        );
2190        assert_eq!(
2191            expression.simplify(&registry, &registry.integer_tables),
2192            NumericTableExpression::Constant(50)
2193        );
2194
2195        let expression = NumericTableExpression::Table2DVectorReduceX(
2196            ReduceOperator::Sum,
2197            0,
2198            VectorExpression::Reference(ReferenceExpression::Variable(0)),
2199            ElementExpression::Constant(0),
2200        );
2201        assert_eq!(
2202            expression.simplify(&registry, &registry.integer_tables),
2203            expression
2204        );
2205    }
2206
2207    #[test]
2208    fn table_2d_vector_sum_y_simplify() {
2209        let registry = generate_registry();
2210
2211        let expression = NumericTableExpression::Table2DVectorReduceY(
2212            ReduceOperator::Sum,
2213            0,
2214            ElementExpression::Constant(0),
2215            VectorExpression::Reference(ReferenceExpression::Constant(vec![0, 1])),
2216        );
2217        assert_eq!(
2218            expression.simplify(&registry, &registry.integer_tables),
2219            NumericTableExpression::Constant(30)
2220        );
2221
2222        let expression = NumericTableExpression::Table2DVectorReduceY(
2223            ReduceOperator::Sum,
2224            0,
2225            ElementExpression::Constant(0),
2226            VectorExpression::Reference(ReferenceExpression::Variable(0)),
2227        );
2228        assert_eq!(
2229            expression.simplify(&registry, &registry.integer_tables),
2230            expression
2231        );
2232    }
2233
2234    #[test]
2235    fn table_3d_simplify() {
2236        let registry = generate_registry();
2237
2238        let expression = NumericTableExpression::Table3D(
2239            0,
2240            ElementExpression::Constant(0),
2241            ElementExpression::Constant(0),
2242            ElementExpression::Constant(0),
2243        );
2244        assert_eq!(
2245            expression.simplify(&registry, &registry.integer_tables),
2246            NumericTableExpression::Constant(10)
2247        );
2248
2249        let expression = NumericTableExpression::Table3D(
2250            0,
2251            ElementExpression::Constant(0),
2252            ElementExpression::Constant(0),
2253            ElementExpression::Variable(0),
2254        );
2255        assert_eq!(
2256            expression.simplify(&registry, &registry.integer_tables),
2257            expression
2258        );
2259    }
2260
2261    #[test]
2262    fn table_3d_sum_simplify() {
2263        let registry = generate_registry();
2264
2265        let mut set = Set::with_capacity(3);
2266        set.insert(0);
2267        set.insert(2);
2268        let expression = NumericTableExpression::Table3DReduce(
2269            ReduceOperator::Sum,
2270            0,
2271            ArgumentExpression::Element(ElementExpression::Constant(0)),
2272            ArgumentExpression::Set(SetExpression::Reference(ReferenceExpression::Constant(set))),
2273            ArgumentExpression::Vector(VectorExpression::Reference(ReferenceExpression::Constant(
2274                vec![0, 1],
2275            ))),
2276        );
2277        assert_eq!(
2278            expression.simplify(&registry, &registry.integer_tables),
2279            NumericTableExpression::Constant(180)
2280        );
2281
2282        let expression = NumericTableExpression::Table3DReduce(
2283            ReduceOperator::Sum,
2284            0,
2285            ArgumentExpression::Element(ElementExpression::Constant(0)),
2286            ArgumentExpression::Set(SetExpression::Reference(ReferenceExpression::Variable(0))),
2287            ArgumentExpression::Vector(VectorExpression::Reference(ReferenceExpression::Variable(
2288                1,
2289            ))),
2290        );
2291        assert_eq!(
2292            expression.simplify(&registry, &registry.integer_tables),
2293            expression
2294        );
2295    }
2296
2297    #[test]
2298    fn table_simplify() {
2299        let registry = generate_registry();
2300
2301        let expression = NumericTableExpression::Table(
2302            0,
2303            vec![
2304                ElementExpression::Constant(0),
2305                ElementExpression::Constant(1),
2306                ElementExpression::Constant(0),
2307                ElementExpression::Constant(0),
2308            ],
2309        );
2310        assert_eq!(
2311            expression.simplify(&registry, &registry.integer_tables),
2312            NumericTableExpression::Constant(100)
2313        );
2314
2315        let expression = NumericTableExpression::Table(
2316            0,
2317            vec![
2318                ElementExpression::Constant(0),
2319                ElementExpression::Constant(1),
2320                ElementExpression::Constant(0),
2321                ElementExpression::Variable(0),
2322            ],
2323        );
2324        assert_eq!(
2325            expression.simplify(&registry, &registry.integer_tables),
2326            expression
2327        );
2328    }
2329
2330    #[test]
2331    fn table_sum_simplify() {
2332        let registry = generate_registry();
2333
2334        let mut set = Set::with_capacity(3);
2335        set.insert(0);
2336        set.insert(2);
2337        let expression = NumericTableExpression::TableReduce(
2338            ReduceOperator::Sum,
2339            0,
2340            vec![
2341                ArgumentExpression::Element(ElementExpression::Constant(0)),
2342                ArgumentExpression::Element(ElementExpression::Constant(1)),
2343                ArgumentExpression::Set(SetExpression::Complement(Box::new(
2344                    SetExpression::Complement(Box::new(SetExpression::Reference(
2345                        ReferenceExpression::Constant(set),
2346                    ))),
2347                ))),
2348                ArgumentExpression::Vector(VectorExpression::Reverse(Box::new(
2349                    VectorExpression::Reference(ReferenceExpression::Constant(vec![0, 1])),
2350                ))),
2351            ],
2352        );
2353        assert_eq!(
2354            expression.simplify(&registry, &registry.integer_tables),
2355            NumericTableExpression::Constant(1000)
2356        );
2357
2358        let expression = NumericTableExpression::TableReduce(
2359            ReduceOperator::Sum,
2360            0,
2361            vec![
2362                ArgumentExpression::Element(ElementExpression::Constant(0)),
2363                ArgumentExpression::Element(ElementExpression::Constant(1)),
2364                ArgumentExpression::Element(ElementExpression::Constant(0)),
2365                ArgumentExpression::Vector(VectorExpression::Reference(
2366                    ReferenceExpression::Variable(0),
2367                )),
2368            ],
2369        );
2370        assert_eq!(
2371            expression.simplify(&registry, &registry.integer_tables),
2372            expression
2373        );
2374    }
2375}