Constraint Reference
Every constraint type available in the Jia language.
Comparison constraints
The most general constraint form. Compare two expressions with a relational operator:
comparison_stmt = expr cmp_op expr
cmp_op = '<=' | '>=' | '<' | '>' | '==' | '!='
Used for precedence relationships, makespan bounds, deadlines, and any custom temporal or arithmetic relationship.
end_of(task_a) <= start_of(task_b) // task_a must finish before task_b starts
start_of(task_b) >= end_of(task_a) + 2 // at least 2-unit gap
end_of(task_c) <= makespan // task_c ends within the makespan
x + y >= 10 // LP linear constraint
LP models use comparison constraints for all linear inequalities and equalities:
@model lp
model lp_constraints
variables {
Real: x, y, z
}
domains {
x in 0..inf
y in 0..inf
z in 0..inf
}
constraints {
x + y + z >= 15
2 * x + y <= 30
x + 2 * z == 20
}
minimize x + y + z
no_overlap
Ensures that no two intervals in the group execute at the same time. This is the core machine-scheduling constraint — each machine processes at most one task at a time.
no_overlap_stmt = 'no_overlap' '(' IDENT (',' IDENT)* ')'
Pass a Set[Interval] name to apply the constraint to all members of the set:
no_overlap(machine1)
no_overlap(machine2)
Or list individual interval names directly:
no_overlap(task_a, task_b, task_c)
Complete example — two-machine job shop:
model no_overlap_example
variables {
Interval: j1_op1, j1_op2
Interval: j2_op1, j2_op2
Integer: makespan
Set[Interval]: machine1, machine2
}
domains {
duration(j1_op1) = 3
duration(j1_op2) = 2
duration(j2_op1) = 4
duration(j2_op2) = 1
machine1 = {j1_op1, j2_op2}
machine2 = {j1_op2, j2_op1}
makespan in 0..50
}
constraints {
end_of(j1_op1) <= start_of(j1_op2)
end_of(j2_op1) <= start_of(j2_op2)
no_overlap(machine1)
no_overlap(machine2)
end_of(j1_op2) <= makespan
end_of(j2_op2) <= makespan
}
minimize makespan
cumulative
Ensures the total demand on a resource never exceeds its capacity at any instant.
Each interval in the resource set consumes its declared demand while active.
cumulative_stmt = 'cumulative' '(' IDENT ',' expr ')'
- First argument: the
Set[Interval]representing the resource. - Second argument: the resource capacity (an expression, so it can reference a variable).
cumulative(workers, 4) // at most 4 workers active at once
cumulative(memory, max_mem) // capacity from an Integer variable
Demands must be declared in the domains block:
demand(task_a, workers) = 2
demand(task_b, workers) = 3
Complete example — two-resource project:
model cumulative_example
variables {
Interval: compile, link, test
Integer: makespan
Set[Interval]: cpu, memory
}
domains {
duration(compile) = 4
duration(link) = 2
duration(test) = 3
cpu = {compile, link, test}
memory = {compile, test}
demand(compile, cpu) = 3
demand(link, cpu) = 1
demand(test, cpu) = 2
demand(compile, memory) = 2
demand(test, memory) = 3
makespan in 0..20
}
constraints {
end_of(compile) <= start_of(link)
cumulative(cpu, 4)
cumulative(memory, 4)
end_of(link) <= makespan
end_of(test) <= makespan
}
minimize makespan
span
The parent interval spans all present children: its start equals the earliest child start, and its end equals the latest child end.
span_stmt = 'span' '(' IDENT ',' IDENT ')'
- First argument: the parent
Interval. - Second argument: a
Set[Interval]of child intervals.
span(project, phases)
Complete example — project composed of phases:
model span_example
variables {
Interval: project, phase1, phase2, phase3
Set[Interval]: phases
}
domains {
duration(phase1) = 3
duration(phase2) = 5
duration(phase3) = 2
phases = {phase1, phase2, phase3}
}
constraints {
end_of(phase1) <= start_of(phase2)
span(project, phases)
}
minimize end_of(project)
The project interval automatically covers the full extent of all three phases.
alternative
Exactly one interval from the set is present (scheduled), and the parent interval mirrors that interval's time window. All other members of the set are absent.
alternative_stmt = 'alternative' '(' IDENT ',' IDENT ')'
- First argument: the parent
Interval. - Second argument: a
Set[Interval]of candidate intervals.
The candidate intervals must be declared optional in the domains block.
optional(candidate_a, candidate_b)
alternative(operation, candidates)
Complete example — operation that can run on either of two machines:
model alternative_example
variables {
Interval: op1, op1_machine_a, op1_machine_b
Interval: op2
Integer: makespan
Set[Interval]: op1_candidates
Set[Interval]: machine_a, machine_b
}
domains {
duration(op1_machine_a) = 3
duration(op1_machine_b) = 5
duration(op2) = 2
optional(op1_machine_a, op1_machine_b)
op1_candidates = {op1_machine_a, op1_machine_b}
machine_a = {op1_machine_a}
machine_b = {op1_machine_b, op2}
makespan in 0..20
}
constraints {
alternative(op1, op1_candidates)
no_overlap(machine_a)
no_overlap(machine_b)
end_of(op1) <= makespan
end_of(op2) <= makespan
}
minimize makespan
The solver chooses which machine processes op1 and schedules it accordingly.