jia_parse/jia_lang/ast.rs
1//! AST types for the CP scheduling modelling language.
2//!
3//! The language follows an **X, D, C** pattern:
4//! - **Variables (X)**: Declare names and types (Interval, Integer, Set\[Interval\], Set\[Integer\])
5//! - **Domains (D)**: Bound variable attributes and assign set membership
6//! - **Constraints (C)**: Relationships between variables
7//! - **Objective** (optional): Minimize/maximize an expression
8
9/// The declared model type (from `@model` tag).
10#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize)]
11pub enum ModelType {
12 /// Constraint programming (`@model cp`).
13 Cp,
14 /// Linear programming (`@model lp`).
15 Lp,
16}
17
18/// A complete Jia model.
19#[derive(Debug, Clone, PartialEq, serde::Serialize)]
20pub struct JiaModel {
21 /// Model type (from `@model` tag), or None if not specified.
22 pub model_type: Option<ModelType>,
23 /// Model name (from the `model <name>` declaration).
24 pub name: String,
25 /// Variable declarations.
26 pub variables: Vec<VarDecl>,
27 /// Domain specifications.
28 pub domains: Vec<DomainStmt>,
29 /// Constraints.
30 pub constraints: Vec<Constraint>,
31 /// Optional optimization objective.
32 pub objective: Option<Objective>,
33}
34
35/// A variable declaration: `Type: name1, name2, ...`
36#[derive(Debug, Clone, PartialEq, serde::Serialize)]
37pub struct VarDecl {
38 /// The declared variable names.
39 pub names: Vec<String>,
40 /// The type of all variables in this declaration.
41 pub var_type: VarType,
42}
43
44/// Variable types in the Jia language.
45#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
46pub enum VarType {
47 /// An interval variable with start, end, and duration.
48 Interval,
49 /// An integer decision variable.
50 Integer,
51 /// A continuous real-valued decision variable (LP).
52 Real,
53 /// A set of interval variables.
54 SetInterval,
55 /// A set of integer variables.
56 SetInteger,
57}
58
59/// A domain statement: bounds or assigns values to variables.
60#[derive(Debug, Clone, PartialEq, serde::Serialize)]
61pub enum DomainStmt {
62 /// `duration(x, y) = 3` or `duration(x) in 2..5` or `duration(x) in {2, 5, 7}`
63 IntervalDuration {
64 /// Interval names this applies to.
65 intervals: Vec<String>,
66 /// The domain specification.
67 domain: Domain,
68 },
69 /// `start(x, y) in 0..10`
70 IntervalStart {
71 /// Interval names this applies to.
72 intervals: Vec<String>,
73 /// The domain specification.
74 domain: Domain,
75 },
76 /// `end(x, y) in 0..20`
77 IntervalEnd {
78 /// Interval names this applies to.
79 intervals: Vec<String>,
80 /// The domain specification.
81 domain: Domain,
82 },
83 /// `optional(x, y, z)`
84 IntervalOptional {
85 /// Interval names marked as optional.
86 intervals: Vec<String>,
87 },
88 /// `x in 0..100` or `x in {1, 3, 5}`
89 IntegerDomain {
90 /// The integer variable name.
91 name: String,
92 /// The domain specification.
93 domain: Domain,
94 },
95 /// `x = {a, b, c}`
96 SetDomain {
97 /// The set variable name.
98 name: String,
99 /// The member variable names.
100 members: Vec<String>,
101 },
102 /// `x in 0.0..inf` or `x = 3.14` — real variable domain
103 RealDomain {
104 /// The real variable name.
105 name: String,
106 /// The domain specification.
107 domain: Domain,
108 },
109 /// `demand(interval, set) = value`
110 Demand {
111 /// The interval variable name.
112 interval: String,
113 /// The set (resource) variable name.
114 set: String,
115 /// The demand value.
116 value: i64,
117 },
118}
119
120/// A domain specification: fixed value, range, or enumerated set.
121#[derive(Debug, Clone, PartialEq, serde::Serialize)]
122pub enum Domain {
123 /// A single fixed integer value: `= 3`
124 Fixed(i64),
125 /// An integer range: `in 0..100`
126 Range {
127 /// Minimum (inclusive).
128 min: i64,
129 /// Maximum (inclusive).
130 max: i64,
131 },
132 /// An enumerated set of integer values: `in {1, 3, 5}`
133 Enumerated(Vec<i64>),
134 /// A single fixed real value: `= 3.14`
135 RealFixed(f64),
136 /// A real range: `in 0.0..inf` (f64::INFINITY for unbounded)
137 RealRange {
138 /// Minimum (inclusive). f64::NEG_INFINITY for unbounded below.
139 min: f64,
140 /// Maximum (inclusive). f64::INFINITY for unbounded above.
141 max: f64,
142 },
143}
144
145/// A constraint in the CP model.
146#[derive(Debug, Clone, PartialEq, serde::Serialize)]
147pub enum Constraint {
148 /// `no_overlap(set_or_interval, ...)`
149 NoOverlap {
150 /// The intervals or set names (no two may overlap).
151 intervals: Vec<String>,
152 },
153 /// `cumulative(set, capacity)`
154 Cumulative {
155 /// The set (resource) variable name.
156 set: String,
157 /// The capacity expression.
158 capacity: Expr,
159 },
160 /// `span(parent, set)` — parent covers earliest start to latest end of present children.
161 Span {
162 /// The parent interval.
163 parent: String,
164 /// The set of child intervals.
165 set: String,
166 },
167 /// `alternative(parent, set)` — exactly one interval from set is present.
168 Alternative {
169 /// The parent interval representing the chosen one.
170 parent: String,
171 /// The set of candidate intervals.
172 set: String,
173 },
174 /// `<expr> <op> <expr>`
175 Comparison {
176 /// Left-hand side expression.
177 left: Expr,
178 /// Comparison operator.
179 op: CmpOp,
180 /// Right-hand side expression.
181 right: Expr,
182 },
183}
184
185/// Comparison operators.
186#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize)]
187pub enum CmpOp {
188 /// `<`
189 Lt,
190 /// `<=`
191 Le,
192 /// `>`
193 Gt,
194 /// `>=`
195 Ge,
196 /// `==`
197 Eq,
198 /// `!=`
199 Ne,
200}
201
202/// An expression in the CP language.
203#[derive(Debug, Clone, PartialEq, serde::Serialize)]
204pub enum Expr {
205 /// An integer literal.
206 Number(i64),
207 /// A floating-point literal.
208 Float(f64),
209 /// A variable reference.
210 Var(String),
211 /// `start_of(name)`
212 StartOf(String),
213 /// `end_of(name)`
214 EndOf(String),
215 /// `duration_of(name)`
216 DurationOf(String),
217 /// `present_of(name)` — 0 if absent, 1 if present.
218 PresentOf(String),
219 /// A binary arithmetic operation.
220 BinaryOp {
221 /// The operator.
222 op: ArithOp,
223 /// Left operand.
224 left: Box<Expr>,
225 /// Right operand.
226 right: Box<Expr>,
227 },
228 /// Unary negation.
229 Negate(Box<Expr>),
230}
231
232/// Arithmetic operators.
233#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize)]
234pub enum ArithOp {
235 /// `+`
236 Add,
237 /// `-`
238 Sub,
239 /// `*`
240 Mul,
241 /// `/`
242 Div,
243}
244
245/// An optimization objective.
246#[derive(Debug, Clone, PartialEq, serde::Serialize)]
247pub struct Objective {
248 /// Minimize or maximize.
249 pub direction: OptDirection,
250 /// The expression to optimize.
251 pub expr: Expr,
252}
253
254/// Optimization direction.
255#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize)]
256pub enum OptDirection {
257 /// Minimize the objective.
258 Minimize,
259 /// Maximize the objective.
260 Maximize,
261}
262
263impl std::fmt::Display for CmpOp {
264 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
265 match self {
266 CmpOp::Lt => write!(f, "<"),
267 CmpOp::Le => write!(f, "<="),
268 CmpOp::Gt => write!(f, ">"),
269 CmpOp::Ge => write!(f, ">="),
270 CmpOp::Eq => write!(f, "=="),
271 CmpOp::Ne => write!(f, "!="),
272 }
273 }
274}
275
276impl std::fmt::Display for ArithOp {
277 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
278 match self {
279 ArithOp::Add => write!(f, "+"),
280 ArithOp::Sub => write!(f, "-"),
281 ArithOp::Mul => write!(f, "*"),
282 ArithOp::Div => write!(f, "/"),
283 }
284 }
285}