Skip to main content

conjure_cp_core/ast/
mod.rs

1pub mod ac_operators;
2pub mod assertions;
3mod atom;
4pub mod categories;
5mod collection_domains;
6pub mod comprehension;
7pub mod declaration;
8mod domains;
9pub mod enumerated;
10pub mod eval;
11mod expression_arena;
12mod expression_domains;
13mod expressions;
14mod function_domains;
15mod integer_arithmetic;
16mod literals;
17pub mod matrix;
18mod metadata;
19mod model;
20mod name;
21mod objective;
22pub mod pretty;
23pub mod records;
24mod reference;
25pub mod sat_decision;
26mod sat_encoding;
27pub mod serde;
28mod symbol_table;
29mod types;
30pub mod unnamed;
31mod variables;
32mod versioned_cache;
33
34mod moo;
35mod partial_eval;
36
37pub use atom::Atom;
38pub use declaration::{DeclarationKind, DeclarationPtr};
39pub use domains::domain_has_int_from_values;
40pub use domains::{
41    BinaryAttr, Domain, DomainOpError, DomainPtr, EnumVariantVal, FuncAttr, GroundDomain,
42    HasDomain, IntVal, JectivityAttr, MSetAttr, OXIDE_INT_MAX, OXIDE_INT_MIN, PartialityAttr,
43    PartitionAttr, PermutationAttr, Range, RelAttr, SequenceAttr, SetAttr, UnresolvedDomain,
44};
45pub use eval::generator_values_from_expr;
46pub use eval::{
47    eval_constant, eval_constant_local, finish_root_evaluator_normalisation,
48    normalise_evaluator_local, normalise_root_constraint_deep, normalise_root_constraints_deep,
49    normalise_root_constraints_local, normalise_root_selective_deep_expr,
50};
51pub use expression_arena::{ExpressionArena, ExpressionNodeId};
52pub use expressions::{Expression, discriminant_from_value, print_hash_stats};
53pub use integer_arithmetic::{floor_div, floor_mod};
54pub use literals::AbstractLiteral;
55pub use literals::Literal;
56pub use metadata::Metadata;
57pub use model::*;
58pub use moo::Moo;
59pub use name::Name;
60pub use objective::{Objective, OptimiseDirection};
61pub use partial_eval::{
62    run_partial_evaluator, run_partial_evaluator_local, try_lower_bool_atom_eq_true,
63};
64pub use records::Field;
65pub use reference::Reference;
66pub use sat_decision::SatEncodingDecision;
67pub use sat_encoding::SATIntEncoding;
68pub use symbol_table::{SymbolTable, SymbolTablePtr};
69pub use types::*;
70pub use variables::DecisionVariable;
71
72/// Helper to build a matrix `AbstractLiteral` with given domains
73#[doc(hidden)]
74#[macro_export]
75macro_rules! __matrix_with_domains {
76    // Base case: 1-D list + one domain.
77    ([$($x:expr),* $(,)?]; [$domain:expr $(,)?]) => (
78        $crate::into_matrix![std::vec![$(<_ as ::std::convert::Into<_>>::into($x)),*]; $domain]
79    );
80
81    // Recursive entry: split first domain from remaining domains.
82    ([[$($x:tt)*] $(, [$($xs:tt)*])* $(,)?]; [$domain:expr, $($rest:expr),+ $(,)?]) => (
83        $crate::__matrix_with_domains!(
84            @recurse
85            $domain;
86            [$($rest),+];
87            [$($x)*] $(, [$($xs)*])*
88        )
89    );
90
91    // Recurse with "rest domains" captured as one token tree ($rest:tt).
92    (@recurse $domain:expr; $rest:tt; [$($x:tt)*] $(, [$($xs:tt)*])*) => (
93        $crate::into_matrix![
94            std::vec![
95                <_ as ::std::convert::Into<_>>::into($crate::__matrix_with_domains!([$($x)*]; $rest))
96                $(, <_ as ::std::convert::Into<_>>::into($crate::__matrix_with_domains!([$($xs)*]; $rest)))*
97            ];
98            $domain
99        ]
100    );
101}
102
103/// Helper to build a matrix `Literal` with given domains
104#[doc(hidden)]
105#[macro_export]
106macro_rules! __matrix_lit_with_domains {
107    // Base case: 1-D list + one domain.
108    ([$($x:expr),* $(,)?]; [$domain:expr $(,)?]) => (
109        $crate::ast::Literal::AbstractLiteral(
110            $crate::into_matrix![std::vec![$($crate::ast::Literal::from($x)),*]; $domain]
111        )
112    );
113
114    // Recursive entry: split first domain from remaining domains.
115    ([[$($x:tt)*] $(, [$($xs:tt)*])* $(,)?]; [$domain:expr, $($rest:expr),+ $(,)?]) => (
116        $crate::__matrix_lit_with_domains!(
117            @recurse
118            $domain;
119            [$($rest),+];
120            [$($x)*] $(, [$($xs)*])*
121        )
122    );
123
124    // Recurse with "rest domains" captured as one token tree ($rest:tt).
125    (@recurse $domain:expr; $rest:tt; [$($x:tt)*] $(, [$($xs:tt)*])*) => (
126        $crate::ast::Literal::AbstractLiteral(
127            $crate::into_matrix![
128                std::vec![
129                    $crate::__matrix_lit_with_domains!([$($x)*]; $rest)
130                    $(, $crate::__matrix_lit_with_domains!([$($xs)*]; $rest))*
131                ];
132                $domain
133            ]
134        )
135    );
136}
137
138/// Creates a new matrix [`Literal`] optionally with some index domain.
139///
140///  - `matrix_lit![a,b,c]`
141///  - `matrix_lit![a,b,c;my_domain]`
142///  - `matrix_lit![[a, b, c], [d, e, f]; [domain_1, domain_2]]`
143///
144/// To create one from a (Rust) vector, use [`into_matrix!`].
145#[macro_export]
146macro_rules! matrix_lit {
147    // Empty
148    () => (
149        $crate::ast::Literal::AbstractLiteral($crate::into_matrix![])
150    );
151
152    (;$domain:expr) => (
153        $crate::ast::Literal::AbstractLiteral($crate::into_matrix![;$domain])
154    );
155
156    // Single element
157    ($x:expr) => (
158        $crate::ast::Literal::AbstractLiteral($crate::into_matrix![std::vec![$crate::ast::Literal::from($x)]])
159    );
160
161    ($x:expr;$domain:expr) => (
162        $crate::ast::Literal::AbstractLiteral($crate::into_matrix![std::vec![$crate::ast::Literal::from($x)];$domain])
163    );
164
165    // Multi-dimensional (delegate to matrix! for structural nesting)
166    ([$($x:tt)*] $(, [$($xs:tt)*])* $(,)?) => (
167        $crate::ast::Literal::from(
168            $crate::matrix![
169                $crate::matrix_lit![$($x)*]
170                $(, $crate::matrix_lit![$($xs)*])*
171            ]
172        )
173    );
174
175    ([$($x:tt)*] $(, [$($xs:tt)*])* ; [$domain:expr $(, $domains:expr)+ $(,)?]) => (
176        $crate::__matrix_lit_with_domains!(
177            [[$($x)*] $(, [$($xs)*])*];
178            [$domain $(, $domains)+]
179        )
180    );
181
182    // 1-Dimensional
183    ($($x:expr),*) => (
184        $crate::ast::Literal::AbstractLiteral($crate::into_matrix![std::vec![$($crate::ast::Literal::from($x)),*]])
185    );
186
187    ($($x:expr),*;$domain:expr) => (
188        $crate::ast::Literal::AbstractLiteral($crate::into_matrix![std::vec![$($crate::ast::Literal::from($x)),*];$domain])
189    );
190
191    ($($x:expr,)*) => (
192        $crate::ast::Literal::AbstractLiteral($crate::into_matrix![std::vec![$($crate::ast::Literal::from($x)),*]])
193    );
194
195    ($($x:expr,)*;$domain:expr) => (
196        $crate::ast::Literal::AbstractLiteral($crate::into_matrix![std::vec![$($crate::ast::Literal::from($x)),*];$domain])
197    )
198}
199
200/// Creates a new matrix [`AbstractLiteral`] optionally with some index domain.
201///
202///  - `matrix![a,b,c]`
203///  - `matrix![a,b,c;my_domain]`
204///  - `matrix![[a, b, c], [d, e, f]]`
205///  - `matrix![[a, b, c], [d, e, f]; [domain_1, domain_2]]`
206///
207/// To create one from a (Rust) vector, use [`into_matrix!`].
208///
209/// To create a matrix [`Literal`] (wrapping elements with `Literal::from`), use [`matrix_lit!`].
210#[macro_export]
211macro_rules! matrix {
212    // cases copied from the std vec! macro
213    () => (
214        $crate::into_matrix![]
215    );
216
217    (;$domain:expr) => (
218        $crate::into_matrix![;$domain]
219    );
220
221    ($x:expr) => (
222        $crate::into_matrix![std::vec![<_ as ::std::convert::Into<_>>::into($x)]]
223    );
224
225    ($x:expr;$domain:expr) => (
226        $crate::into_matrix![std::vec![<_ as ::std::convert::Into<_>>::into($x)];$domain]
227    );
228
229    // Multi-dimensional
230    ([$($x:tt)*] $(, [$($xs:tt)*])* $(,)?) => (
231        $crate::into_matrix![
232            std::vec![
233                <_ as ::std::convert::Into<_>>::into($crate::matrix![$($x)*])
234                $(, <_ as ::std::convert::Into<_>>::into($crate::matrix![$($xs)*]))*
235            ]
236        ]
237    );
238
239    ([$($x:tt)*] $(, [$($xs:tt)*])* ; [$domain:expr $(, $domains:expr)+ $(,)?]) => (
240        $crate::__matrix_with_domains!(
241            [[$($x)*] $(, [$($xs)*])*];
242            [$domain $(, $domains)+]
243        )
244    );
245
246    // 1-Dimensional
247    ($($x:expr),*) => (
248        $crate::into_matrix![std::vec![$(<_ as ::std::convert::Into<_>>::into($x)),*]]
249    );
250
251    ($($x:expr),*;$domain:expr) => (
252        $crate::into_matrix![std::vec![$(<_ as ::std::convert::Into<_>>::into($x)),*];$domain]
253    );
254
255    ($($x:expr,)*) => (
256        $crate::into_matrix![std::vec![$(<_ as ::std::convert::Into<_>>::into($x)),*]]
257    );
258
259    ($($x:expr,)*;$domain:expr) => (
260        $crate::into_matrix![std::vec![$(<_ as ::std::convert::Into<_>>::into($x)),*];$domain]
261    )
262}
263
264/// Creates a new matrix [`AbstractLiteral`] from some [`Vec`], optionally with some index domain.
265///
266///  - `matrix![my_vec]`
267///  - `matrix![my_vec;my_domain]`
268///
269/// To create one from a list of elements, use [`matrix!`].
270#[macro_export]
271macro_rules! into_matrix {
272    () => (
273        $crate::into_matrix![std::vec::Vec::new()]
274    );
275
276    (;$domain:expr) => (
277        $crate::into_matrix![std::vec::Vec::new();$domain]
278    );
279    ($x:expr) => (
280        $crate::ast::AbstractLiteral::matrix_implied_indices($x)
281    );
282    ($x:expr;$domain:expr) => (
283        $crate::ast::AbstractLiteral::Matrix($x,$domain)
284    );
285}
286
287/// Creates a new matrix as an [`Expression`], optionally with some index domain.
288///
289/// For usage details, see [`matrix!`].
290///
291/// To create a matrix expression from a [`Vec`], use [`into_matrix_expr!`].
292#[macro_export]
293macro_rules! matrix_expr {
294    () => (
295        $crate::ast::Expression::AbstractLiteral($crate::ast::Metadata::new(),$crate::into_matrix![])
296    );
297
298    (;$domain:expr) => (
299        $crate::ast::Expression::AbstractLiteral($crate::ast::Metadata::new(),$crate::into_matrix![;$domain])
300    );
301
302
303    ($x:expr) => (
304        $crate::ast::Expression::AbstractLiteral($crate::ast::Metadata::new(),$crate::into_matrix![std::vec![$x]])
305    );
306    ($x:expr;$domain:expr) => (
307        $crate::ast::Expression::AbstractLiteral($crate::ast::Metadata::new(),$crate::into_matrix![std::vec![$x];$domain])
308    );
309
310    ($($x:expr),+) => (
311        $crate::ast::Expression::AbstractLiteral($crate::ast::Metadata::new(),$crate::into_matrix![std::vec![$($x),+]])
312    );
313
314    ($($x:expr),+;$domain:expr) => (
315        $crate::ast::Expression::AbstractLiteral($crate::ast::Metadata::new(),$crate::into_matrix![std::vec![$($x),+];$domain])
316    );
317
318    ($($x:expr,)+) => (
319        $crate::ast::Expression::AbstractLiteral($crate::ast::Metadata::new(),$crate::into_matrix![std::vec![$($x),+]])
320    );
321
322    ($($x:expr,)+;$domain:expr) => (
323        $crate::ast::Expression::AbstractLiteral($crate::ast::Metadata::new(),$crate::into_matrix![std::vec![$($x),+];$domain])
324    )
325}
326
327/// Creates a new matrix as an [`Expression`] from a (Rust) vector, optionally with some index
328/// domain.
329///
330/// For usage details, see [`into_matrix!`].
331///
332/// To create a matrix expression from a list of elements, use [`matrix_expr!`].
333#[macro_export]
334macro_rules! into_matrix_expr {
335    () => (
336        $crate::ast::Expression::AbstractLiteral($crate::ast::Metadata::new(),$crate::into_matrix![])
337    );
338
339    (;$domain:expr) => (
340        $crate::ast::Expression::AbstractLiteral($crate::ast::Metadata::new(),$crate::into_matrix![;$domain])
341    );
342    ($x:expr) => (
343        $crate::ast::Expression::AbstractLiteral($crate::ast::Metadata::new(),$crate::into_matrix![$x])
344    );
345    ($x:expr;$domain:expr) => (
346        $crate::ast::Expression::AbstractLiteral($crate::ast::Metadata::new(),$crate::into_matrix![$x;$domain])
347    );
348}