Skip to main content

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}