Skip to main content

conjure_cp_core/ast/
mod.rs

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