Class Model
- Namespace
- OptalCP
- Assembly
- OptalCP.dll
Central class for building optimization models. Creates variables, constraints, and objectives.
public class Model
- Inheritance
-
Model
- Inherited Members
Remarks
Model captures the problem to be solved. It contains variables, constraints and objective function.
To create an optimization model, you must first create a Model object. Then you can use the methods of the Model to create variables (e.g. Model.IntervalVar), the objective function (Model.Minimize or Model.Maximize) and constraints (e.g. Model.NoOverlap). Note that a boolean expression becomes a constraint only by passing it to Model.Enforce; otherwise, it is not enforced.
To solve a model, pass it to function Model.Solve or to Solver class.
Available modeling elements
Variables
Interval variables can be created by function Model.IntervalVar, integer variables by function Model.IntVar.
Basic integer expressions
- Model.Start: start of an interval variable (optional integer expression).
- Model.End: end of an interval variable (optional integer expression).
- Model.Length: length of an interval variable (optional integer expression).
- Model.Guard: replaces absent value by a constant.
Integer arithmetics
Use standard arithmetic operators on integer expressions: +, -, unary -, *, /.
- Model.Abs: absolute value.
- Model.Min2: minimum of two integer expressions.
- Model.Min: minimum of an array of integer expressions.
- Model.Max2: maximum of two integer expressions.
- Model.Max: maximum of an array of integer expressions.
- Model.Sum: sum of an array of integer expressions.
Comparison operators for integer expressions
Use standard comparison operators on integer expressions: <, <=, ==, !=, >, >=.
- Model.Identity: constraints two integer expressions to be equal, including the presence status.
Boolean operators
- Model.Not: negation.
- Model.And: conjunction.
- Model.Or: disjunction.
- Model.Implies: implication.
Functions returning BoolExpr
- Model.Presence: whether the argument is present or absent.
- Model.InRange: whether an integer expression is within the given range
Basic constraints on interval variables
- Model.Alternative: an alternative between multiple interval variables.
- Model.Span: span (cover) of interval variables.
- Model.EndBeforeEnd, Model.EndBeforeStart, Model.StartBeforeEnd, Model.StartBeforeStart, Model.EndAtStart, Model.StartAtEnd: precedence constraints.
Disjunction (noOverlap)
- Model.SequenceVar: sequence variable over a set of interval variables.
- Model.NoOverlap: constraints a set of interval variables to not overlap (possibly with transition times).
- Model.Position: returns the position of an interval variable in a sequence.
Basic cumulative expressions
- Model.Pulse: changes value during the interval variable.
- Model.StepAtStart: changes value at the start of the interval variable.
- Model.StepAtEnd: changes value at the end of the interval variable.
- Model.StepAt: changes value at a given time.
Combining cumulative expressions
Use standard operators on cumulative expressions: +, -, unary -, and Model.Sum.
Constraints on cumulative expressions
Use comparison operators on cumulative expressions: <=, >=.
Objective
- Model.Minimize: minimize an integer expression.
- Model.Maximize: maximize an integer expression.
Example:
using System;
using System.Linq;
using OptalCP;
// Constants for random problem generation:
int nbTasks = 100;
int nbWorkers = 5;
int maxDuration = 100;
var rng = new Random();
// Start by creating the model:
var model = new Model();
// For each task we will have an interval variable and a cumulative expression:
var tasks = new List<IntervalVar>();
var workerUsage = new List<CumulExpr>();
// Loop over the tasks:
for (int i = 0; i < nbTasks; i++) {
int taskLength = 1 + rng.Next(maxDuration - 1);
var task = model.IntervalVar(name: $"Task{i + 1}", length: taskLength);
tasks.Add(task);
int workersNeeded = 1 + rng.Next(nbWorkers - 1);
workerUsage.Add(task.Pulse(workersNeeded));
}
// Limit the sum of the pulses to the number of workers available:
model.Enforce(model.Sum(workerUsage) <= nbWorkers);
// Minimize the maximum of the ends (makespan):
model.Minimize(model.Max(tasks.Select(t => t.End())));
// Solve the model:
var result = model.Solve(new Parameters {
timeLimit = 3,
nbWorkers = 4,
});
if (result.nbSolutions == 0)
Console.WriteLine("No solution found.");
else {
var solution = result.solution!;
Console.WriteLine($"Solution found with makespan {solution.GetObjective()}");
foreach (var task in tasks) {
var start = solution.GetStart(task);
if (start != null)
Console.WriteLine($"Task {task.Name} starts at {start}");
else
Console.WriteLine($"Task {task.Name} is absent (not scheduled).");
}
}
See also:
Constructors
Model(string?)
Creates an empty optimization model.
public Model(string? name = null)
Parameters
namestringOptional name for the model
Remarks
Creates an empty model with no variables, constraints, or objective.
The optional name parameter can be used to identify the model in logs,
debugging output, and benchmarking reports. When not specified, the model
remains unnamed.
After creating a model, use its methods to define:
- Variables: Model.IntervalVar, Model.IntVar, Model.BoolVar
- Constraints: Model.NoOverlap, Model.EndBeforeStart, Model.Enforce, etc.
- Objective: Model.Minimize or Model.Maximize
// Create an unnamed model
var model = new Model();
// Create a named model (useful for debugging)
var namedModel = new Model(name: "JobShop");
// Add variables and constraints
var task = model.IntervalVar(length: 10, name: "task");
model.Minimize(task.End());
// Solve
var result = model.Solve();
See also:
- Model — for available modeling methods.
- Model.Solve — to solve the model.
Fields
IntVarMax
public const int IntVarMax = 1073741823
Field Value
Remarks
Maximum value of a decision variable or a decision expression (such as x+1 where x is a variable).
Arithmetic expressions must stay within the range [Model.IntVarMin, Model.IntVarMax]. If an expression exceeds this range for all possible variable assignments, the model becomes infeasible.
Example:
x*x exceeds IntVarMax for all values in the variable's domain:
var model = new Model();
var x = model.IntVar(min: 10000000, max: 20000000);
// Constraint x*x >= 1:
model.Enforce(x * x >= 1);
var result = model.Solve();
For any value of x in the range [10000000, 20000000], the expression x*x exceeds Model.IntVarMax and cannot be computed, making the model infeasible.
IntVarMin
public const int IntVarMin = -1073741823
Field Value
Remarks
Minimum value of a decision variable or a decision expression (such as x+1 where x is a variable).
The opposite of Model.IntVarMax.
Use IntVarMin when you need to allow the full range of negative values for an integer variable.
Example:
var model = new Model();
// IntVarMin is the minimum allowed value for integer variables
var x = model.IntVar(min: Model.IntVarMin, max: 0, name: "x");
IntervalMax
public const int IntervalMax = 715827882
Field Value
Remarks
Maximum value of start or end of an interval variable. The opposite of Model.IntervalMin.
Use IntervalMax when you want to leave the end time of an interval variable unconstrained.
Example:
var model = new Model();
// IntervalMax is the maximum allowed value for interval start/end
var task = model.IntervalVar(end: (0, Model.IntervalMax), length: 10, name: "task");
IntervalMin
public const int IntervalMin = -715827882
Field Value
Remarks
Minimum value of start or end of an interval variable. The opposite of Model.IntervalMax.
Use IntervalMin when you want to leave the start time of an interval variable unconstrained.
Example:
var model = new Model();
// IntervalMin is the minimum allowed value for interval start/end
var task = model.IntervalVar(start: (Model.IntervalMin, 0), length: 10, name: "task");
LengthMax
public const int LengthMax = 1431655764
Field Value
Remarks
Maximum length of an interval variable. The maximum length can be achieved by an interval that starts at Model.IntervalMin and ends at Model.IntervalMax.
Use LengthMax when you want to leave the length of an interval variable unconstrained.
Example:
var model = new Model();
// LengthMax is the maximum allowed length for an interval variable
var task = model.IntervalVar(length: (0, Model.LengthMax), name: "task");
Properties
Name
The name of the model.
public string? Name { get; set; }
Property Value
Remarks
The name is optional and primarily useful for distinguishing between different models during debugging and benchmarking. When set, it helps identify the model in logs and benchmark results.
The name can be set either in the constructor or by assigning to this property. Assigning overwrites any name that was previously set.
// Set name in constructor
var model = new Model(name: "MySchedulingProblem");
Console.WriteLine(model.Name); // "MySchedulingProblem"
// Or set name later
model = new Model();
model.Name = "JobShop";
Console.WriteLine(model.Name); // "JobShop"
// Clear the name
model.Name = null;
Methods
Abs(IntExpr)
Creates an integer expression which is absolute value of arg.
public IntExpr Abs(IntExpr arg)
Parameters
Returns
- IntExpr
The resulting integer expression
Remarks
If arg has value absent then the resulting expression has also value absent.
Same as IntExpr.Abs.
Abs(int)
Creates an integer expression which is absolute value of arg.
public IntExpr Abs(int arg)
Parameters
Returns
- IntExpr
The resulting integer expression
Remarks
If arg has value absent then the resulting expression has also value absent.
Same as IntExpr.Abs.
Alternative(IntervalVar, IEnumerable<IntervalVar>)
Alternative constraint models a choice between different ways to execute an interval.
public Constraint Alternative(IntervalVar main, IEnumerable<IntervalVar> options)
Parameters
mainIntervalVarThe main interval variable.
optionsIEnumerable<IntervalVar>Array of optional interval variables to choose from.
Returns
- Constraint
The alternative constraint.
Remarks
Alternative constraint is a way to model various kinds of choices. For example, we can model a task that could be done by worker A, B, or C. To model such alternative, we use interval variable main that represents the task regardless the chosen worker and three interval variables options = [A, B, C] that represent the task when done by worker A, B, or C. Interval variables A, B, and C should be optional. This way, if e.g. option B is chosen, then B will be present and equal to main (they will start at the same time and end at the same time), the remaining options, A and C, will be absent.
We may also decide not to execute the main task at all (if it is optional). Then main will be absent and all options A, B and C will be absent too.
Formal definition
The constraint alternative(main, options) is satisfied in the following two cases:
- Interval
mainis absent and alloptions[i]are absent too. - Interval
mainis present and exactly one ofoptions[i]is present (the remaining options are absent). Letkbe the index of the present option. Thenmain.start() == options[k].start()andmain.end() == options[k].end().
Example:
- If done by worker A, then its length is 10, and the cost is 5.
- If done by worker B, then its length is 20, and the cost is 2.
- If done by worker C, then its length is 3, and the cost is 10.
Each worker can execute only one task at a time. However, the remaining tasks are omitted in the model below. The objective could be, e.g., to minimize the total cost (also omitted in the model).
var model = new Model();
var T = model.IntervalVar(name: "T");
var T_A = model.IntervalVar(name: "T_A", optional: true, length: 10);
var T_B = model.IntervalVar(name: "T_B", optional: true, length: 20);
var T_C = model.IntervalVar(name: "T_C", optional: true, length: 3);
// T_A, T_B and T_C are different ways to execute task T:
model.Alternative(T, new[] { T_A, T_B, T_C });
// The cost depends on the chosen option:
var costOfT = model.Sum(new IntExpr[] {
model.Presence(T_A) * 5,
model.Presence(T_B) * 2,
model.Presence(T_C) * 10
});
// Each worker A can perform only one task at a time:
model.NoOverlap(new[] { T_A /* ... other Worker A tasks */ }); // Worker A
model.NoOverlap(new[] { T_B /* ... other Worker B tasks */ }); // Worker B
model.NoOverlap(new[] { T_C /* ... other Worker C tasks */ }); // Worker C
// Minimize the total cost:
model.Minimize(model.Sum(new IntExpr[] { costOfT /* ... other costs */ }));
And(BoolExpr, BoolExpr)
Logical AND of boolean expressions lhs and rhs.
public BoolExpr And(BoolExpr lhs, BoolExpr rhs)
Parameters
Returns
- BoolExpr
The resulting Boolean expression
Remarks
If one of the arguments has value absent, then the resulting expression also has value absent.
Same as BoolExpr.And.
And(BoolExpr, bool)
Logical AND of boolean expressions lhs and rhs.
public BoolExpr And(BoolExpr lhs, bool rhs)
Parameters
Returns
- BoolExpr
The resulting Boolean expression
Remarks
If one of the arguments has value absent, then the resulting expression also has value absent.
Same as BoolExpr.And.
And(bool, BoolExpr)
Logical AND of boolean expressions lhs and rhs.
public BoolExpr And(bool lhs, BoolExpr rhs)
Parameters
Returns
- BoolExpr
The resulting Boolean expression
Remarks
If one of the arguments has value absent, then the resulting expression also has value absent.
Same as BoolExpr.And.
BoolVar(bool, string?)
Creates a new boolean variable and adds it to the model.
public BoolVar BoolVar(bool optional = false, string? name = null)
Parameters
optionalboolIf true, the variable can be absent in a solution. The default is false.
namestringOptional name for the variable (useful for debugging).
Returns
- BoolVar
The created boolean variable.
Remarks
A boolean variable represents an unknown truth value (true or false) that the solver must find. Boolean variables are useful for modeling decisions, choices, or logical conditions in your problem.
By default, a boolean variable must be assigned a value (true or false) in every
solution. When optional: true, the variable can also be absent, meaning the
solution does not use the variable at all. This is useful when the variable
represents a decision that may not apply in all scenarios.
Boolean variables support logical operators:
!xfor logical NOTx | yfor logical ORx & yfor logical AND
Note: use & and | (bitwise operators), not && and || (short-circuit operators),
as C# does not allow overloading &&/||.
Example:
var model = new Model();
var useMachineA = model.BoolVar(name: "useMachineA");
var useMachineB = model.BoolVar(name: "useMachineB");
// Constraint: must use at least one machine
model.Enforce(useMachineA | useMachineB);
// Constraint: cannot use both machines
model.Enforce(!(useMachineA & useMachineB));
See also:
- Model.IntervalVar — for the primary variable type for scheduling problems.
- Model.IntVar — for numeric decisions.
Element(IEnumerable<int>, IntExpr)
Creates an integer expression for array element lookup by index.
public IntExpr Element(IEnumerable<int> array, IntExpr subscript)
Parameters
arrayIEnumerable<int>Array of integer values to select from.
subscriptIntExprIndex into the array (0-based).
Returns
- IntExpr
The resulting integer expression equal to
array[subscript].
Remarks
The result of element(array, subscript) is an integer expression equal to array[subscript].
Creating the expression automatically adds a side constraint that restricts subscript to the valid index range 0 to n - 1, where n is the number of elements in array. This constraint must be satisfied in every solution, regardless of how the expression is used. For example, in element(array, subscript) == 5 || x == 1, the subscript must be a valid index even in solutions where x == 1 makes the disjunction true.
When the subscript is absent, the result is also absent.
Example:
element to look up the processing time based on which machine is assigned.
var model = new Model();
// Processing times for each machine:
var durations = new[] { 5, 8, 3 };
// Decision variable: which machine to use (0, 1, or 2):
var machine = model.IntVar(min: 0, max: durations.Length - 1, name: "machine");
// Look up the duration for the chosen machine:
var duration = model.Element(durations, machine);
var task = model.IntervalVar(length: duration, name: "task");
model.Minimize(task.End());
See also:
- Model.IntVar — to create the subscript variable.
Element(IEnumerable<int>, int)
Creates an integer expression for array element lookup by index.
public IntExpr Element(IEnumerable<int> array, int subscript)
Parameters
arrayIEnumerable<int>Array of integer values to select from.
subscriptintIndex into the array (0-based).
Returns
- IntExpr
The resulting integer expression equal to
array[subscript].
Remarks
The result of element(array, subscript) is an integer expression equal to array[subscript].
Creating the expression automatically adds a side constraint that restricts subscript to the valid index range 0 to n - 1, where n is the number of elements in array. This constraint must be satisfied in every solution, regardless of how the expression is used. For example, in element(array, subscript) == 5 || x == 1, the subscript must be a valid index even in solutions where x == 1 makes the disjunction true.
When the subscript is absent, the result is also absent.
Example:
element to look up the processing time based on which machine is assigned.
var model = new Model();
// Processing times for each machine:
var durations = new[] { 5, 8, 3 };
// Decision variable: which machine to use (0, 1, or 2):
var machine = model.IntVar(min: 0, max: durations.Length - 1, name: "machine");
// Look up the duration for the chosen machine:
var duration = model.Element(durations, machine);
var task = model.IntervalVar(length: duration, name: "task");
model.Minimize(task.End());
See also:
- Model.IntVar — to create the subscript variable.
End(IntervalVar)
Creates an integer expression for the end time of an interval variable.
public IntExpr End(IntervalVar interval)
Parameters
intervalIntervalVarThe interval variable.
Returns
- IntExpr
The resulting integer expression
Remarks
If the interval is absent, the resulting expression is also absent.
Example:
y to start after the end of x with a delay of at least 10. In addition, we constrain the length of x to be less or equal to the length of y.
var model = new Model();
var x = model.IntervalVar(name: "x");
var y = model.IntervalVar(name: "y");
model.Enforce(model.End(x) + 10 <= model.Start(y));
model.Enforce(model.Length(x) <= model.Length(y));
When x or y is absent then value of both constraints above is absent and therefore they are satisfied.
See also:
- IntervalVar.End — is equivalent function on IntervalVar.
EndAtEnd(IntervalVar, IntervalVar, IntExpr)
Creates a precedence constraint between two interval variables.
public Constraint EndAtEnd(IntervalVar predecessor, IntervalVar successor, IntExpr delay)
Parameters
predecessorIntervalVarThe predecessor interval variable.
successorIntervalVarThe successor interval variable.
delayIntExprThe minimum delay between intervals.
Returns
- Constraint
The precedence constraint.
Remarks
Same as:
model.Enforce(predecessor.End() + delay == successor.End());
In other words, end of predecessor plus delay must be equal to end of successor.
When one of the two interval variables is absent, then the constraint is satisfied.
See also:
- IntervalVar.EndAtEnd — is equivalent function on IntervalVar.
- IntervalVar.Start
- IntervalVar.End
EndAtEnd(IntervalVar, IntervalVar, int)
Creates a precedence constraint between two interval variables.
public Constraint EndAtEnd(IntervalVar predecessor, IntervalVar successor, int delay = 0)
Parameters
predecessorIntervalVarThe predecessor interval variable.
successorIntervalVarThe successor interval variable.
delayintThe minimum delay between intervals.
Returns
- Constraint
The precedence constraint.
Remarks
Same as:
model.Enforce(predecessor.End() + delay == successor.End());
In other words, end of predecessor plus delay must be equal to end of successor.
When one of the two interval variables is absent, then the constraint is satisfied.
See also:
- IntervalVar.EndAtEnd — is equivalent function on IntervalVar.
- IntervalVar.Start
- IntervalVar.End
EndAtStart(IntervalVar, IntervalVar, IntExpr)
Creates a precedence constraint between two interval variables.
public Constraint EndAtStart(IntervalVar predecessor, IntervalVar successor, IntExpr delay)
Parameters
predecessorIntervalVarThe predecessor interval variable.
successorIntervalVarThe successor interval variable.
delayIntExprThe minimum delay between intervals.
Returns
- Constraint
The precedence constraint.
Remarks
Same as:
model.Enforce(predecessor.End() + delay == successor.Start());
In other words, end of predecessor plus delay must be equal to start of successor.
When one of the two interval variables is absent, then the constraint is satisfied.
See also:
- IntervalVar.EndAtStart — is equivalent function on IntervalVar.
- IntervalVar.Start
- IntervalVar.End
EndAtStart(IntervalVar, IntervalVar, int)
Creates a precedence constraint between two interval variables.
public Constraint EndAtStart(IntervalVar predecessor, IntervalVar successor, int delay = 0)
Parameters
predecessorIntervalVarThe predecessor interval variable.
successorIntervalVarThe successor interval variable.
delayintThe minimum delay between intervals.
Returns
- Constraint
The precedence constraint.
Remarks
Same as:
model.Enforce(predecessor.End() + delay == successor.Start());
In other words, end of predecessor plus delay must be equal to start of successor.
When one of the two interval variables is absent, then the constraint is satisfied.
See also:
- IntervalVar.EndAtStart — is equivalent function on IntervalVar.
- IntervalVar.Start
- IntervalVar.End
EndBeforeEnd(IntervalVar, IntervalVar, IntExpr)
Creates a precedence constraint between two interval variables.
public Constraint EndBeforeEnd(IntervalVar predecessor, IntervalVar successor, IntExpr delay)
Parameters
predecessorIntervalVarThe predecessor interval variable.
successorIntervalVarThe successor interval variable.
delayIntExprThe minimum delay between intervals.
Returns
- Constraint
The precedence constraint.
Remarks
Same as:
model.Enforce(predecessor.End() + delay <= successor.End());
In other words, end of predecessor plus delay must be less than or equal to end of successor.
When one of the two interval variables is absent, then the constraint is satisfied.
See also:
- IntervalVar.EndBeforeEnd — is equivalent function on IntervalVar.
- IntervalVar.Start
- IntervalVar.End
EndBeforeEnd(IntervalVar, IntervalVar, int)
Creates a precedence constraint between two interval variables.
public Constraint EndBeforeEnd(IntervalVar predecessor, IntervalVar successor, int delay = 0)
Parameters
predecessorIntervalVarThe predecessor interval variable.
successorIntervalVarThe successor interval variable.
delayintThe minimum delay between intervals.
Returns
- Constraint
The precedence constraint.
Remarks
Same as:
model.Enforce(predecessor.End() + delay <= successor.End());
In other words, end of predecessor plus delay must be less than or equal to end of successor.
When one of the two interval variables is absent, then the constraint is satisfied.
See also:
- IntervalVar.EndBeforeEnd — is equivalent function on IntervalVar.
- IntervalVar.Start
- IntervalVar.End
EndBeforeStart(IntervalVar, IntervalVar, IntExpr)
Creates a precedence constraint between two interval variables.
public Constraint EndBeforeStart(IntervalVar predecessor, IntervalVar successor, IntExpr delay)
Parameters
predecessorIntervalVarThe predecessor interval variable.
successorIntervalVarThe successor interval variable.
delayIntExprThe minimum delay between intervals.
Returns
- Constraint
The precedence constraint.
Remarks
Same as:
model.Enforce(predecessor.End() + delay <= successor.Start());
In other words, end of predecessor plus delay must be less than or equal to start of successor.
When one of the two interval variables is absent, then the constraint is satisfied.
See also:
- IntervalVar.EndBeforeStart — is equivalent function on IntervalVar.
- IntervalVar.Start
- IntervalVar.End
EndBeforeStart(IntervalVar, IntervalVar, int)
Creates a precedence constraint between two interval variables.
public Constraint EndBeforeStart(IntervalVar predecessor, IntervalVar successor, int delay = 0)
Parameters
predecessorIntervalVarThe predecessor interval variable.
successorIntervalVarThe successor interval variable.
delayintThe minimum delay between intervals.
Returns
- Constraint
The precedence constraint.
Remarks
Same as:
model.Enforce(predecessor.End() + delay <= successor.Start());
In other words, end of predecessor plus delay must be less than or equal to start of successor.
When one of the two interval variables is absent, then the constraint is satisfied.
See also:
- IntervalVar.EndBeforeStart — is equivalent function on IntervalVar.
- IntervalVar.Start
- IntervalVar.End
Enforce(BoolExpr)
Enforces a boolean expression as a constraint in the model.
public void Enforce(BoolExpr expr)
Parameters
exprBoolExpr
Remarks
This is the primary method for enforcing boolean expressions as constraints in the model.
A constraint is satisfied if it is not false. In other words, a constraint is satisfied if it is true or absent.
A boolean expression that is not enforced as a constraint can have arbitrary value in a solution (true, false, or absent). Once enforced as a constraint, it can only be true or absent in the solution.
Note: Constraint objects are automatically registered when created.
Passing them to enforce() is accepted but does nothing. For cumulative
constraints (cumul <= capacity, cumul >= min_level), using enforce() is
recommended for code clarity even though it's not required.
Accepted argument types
The enforce method accepts several types of arguments:
- BoolExpr objects: Boolean expressions created from comparisons
(e.g.,
x <= 5,a == b) or logical operations (e.g.,a & b,~c). - bool values: Python boolean constants
TrueorFalse. - Constraint objects: Accepted but does nothing (constraints auto-register).
Use with cumulative constraints for clarity:
model.enforce(cumul <= capacity). - Iterables: Lists, tuples, or generators of the above types.
Example:
var model = new Model();
var x = model.IntervalVar(length: 10, name: "x");
// Enforce boolean expressions as constraints
model.Enforce(x.Start() >= 0);
model.Enforce(x.End() <= 100);
Example:
var model = new Model();
var tasks = new IntervalVar[5];
for (int i = 0; i < 5; i++)
tasks[i] = model.IntervalVar(length: 10, name: $"task_{i}");
// Enforce multiple constraints at once
model.Enforce(tasks.Select(task => task.Start() >= 0));
// Or inline
model.Enforce(tasks.Select(task => task.End() <= 100));
Example:
var model = new Model();
var x = model.IntVar(min: 0, max: 100, name: "x");
var y = model.IntVar(min: 0, max: 100, name: "y");
// Enforce various boolean expressions
model.Enforce(new BoolExpr[] {
x + y <= 50, // From comparison
x >= 10, // From comparison
});
See also:
- BoolExpr.Enforce — for the fluent-style alternative.
- Model.NoOverlap — for creating no-overlap constraints.
- Model.Minimize — for creating minimization objectives.
- Model.Maximize — for creating maximization objectives.
Enforce(Constraint)
Enforces a boolean expression as a constraint in the model.
public void Enforce(Constraint constraint)
Parameters
constraintConstraintThe constraint, boolean expression, or iterable of these to enforce in the model
Remarks
This is the primary method for enforcing boolean expressions as constraints in the model.
A constraint is satisfied if it is not false. In other words, a constraint is satisfied if it is true or absent.
A boolean expression that is not enforced as a constraint can have arbitrary value in a solution (true, false, or absent). Once enforced as a constraint, it can only be true or absent in the solution.
Note: Constraint objects are automatically registered when created.
Passing them to enforce() is accepted but does nothing. For cumulative
constraints (cumul <= capacity, cumul >= min_level), using enforce() is
recommended for code clarity even though it's not required.
Accepted argument types
The enforce method accepts several types of arguments:
- BoolExpr objects: Boolean expressions created from comparisons
(e.g.,
x <= 5,a == b) or logical operations (e.g.,a & b,~c). - bool values: Python boolean constants
TrueorFalse. - Constraint objects: Accepted but does nothing (constraints auto-register).
Use with cumulative constraints for clarity:
model.enforce(cumul <= capacity). - Iterables: Lists, tuples, or generators of the above types.
Example:
var model = new Model();
var x = model.IntervalVar(length: 10, name: "x");
// Enforce boolean expressions as constraints
model.Enforce(x.Start() >= 0);
model.Enforce(x.End() <= 100);
Example:
var model = new Model();
var tasks = new IntervalVar[5];
for (int i = 0; i < 5; i++)
tasks[i] = model.IntervalVar(length: 10, name: $"task_{i}");
// Enforce multiple constraints at once
model.Enforce(tasks.Select(task => task.Start() >= 0));
// Or inline
model.Enforce(tasks.Select(task => task.End() <= 100));
Example:
var model = new Model();
var x = model.IntVar(min: 0, max: 100, name: "x");
var y = model.IntVar(min: 0, max: 100, name: "y");
// Enforce various boolean expressions
model.Enforce(new BoolExpr[] {
x + y <= 50, // From comparison
x >= 10, // From comparison
});
See also:
- BoolExpr.Enforce — for the fluent-style alternative.
- Model.NoOverlap — for creating no-overlap constraints.
- Model.Minimize — for creating minimization objectives.
- Model.Maximize — for creating maximization objectives.
Enforce(bool)
Enforces a boolean expression as a constraint in the model.
public void Enforce(bool value)
Parameters
valuebool
Remarks
This is the primary method for enforcing boolean expressions as constraints in the model.
A constraint is satisfied if it is not false. In other words, a constraint is satisfied if it is true or absent.
A boolean expression that is not enforced as a constraint can have arbitrary value in a solution (true, false, or absent). Once enforced as a constraint, it can only be true or absent in the solution.
Note: Constraint objects are automatically registered when created.
Passing them to enforce() is accepted but does nothing. For cumulative
constraints (cumul <= capacity, cumul >= min_level), using enforce() is
recommended for code clarity even though it's not required.
Accepted argument types
The enforce method accepts several types of arguments:
- BoolExpr objects: Boolean expressions created from comparisons
(e.g.,
x <= 5,a == b) or logical operations (e.g.,a & b,~c). - bool values: Python boolean constants
TrueorFalse. - Constraint objects: Accepted but does nothing (constraints auto-register).
Use with cumulative constraints for clarity:
model.enforce(cumul <= capacity). - Iterables: Lists, tuples, or generators of the above types.
Example:
var model = new Model();
var x = model.IntervalVar(length: 10, name: "x");
// Enforce boolean expressions as constraints
model.Enforce(x.Start() >= 0);
model.Enforce(x.End() <= 100);
Example:
var model = new Model();
var tasks = new IntervalVar[5];
for (int i = 0; i < 5; i++)
tasks[i] = model.IntervalVar(length: 10, name: $"task_{i}");
// Enforce multiple constraints at once
model.Enforce(tasks.Select(task => task.Start() >= 0));
// Or inline
model.Enforce(tasks.Select(task => task.End() <= 100));
Example:
var model = new Model();
var x = model.IntVar(min: 0, max: 100, name: "x");
var y = model.IntVar(min: 0, max: 100, name: "y");
// Enforce various boolean expressions
model.Enforce(new BoolExpr[] {
x + y <= 50, // From comparison
x >= 10, // From comparison
});
See also:
- BoolExpr.Enforce — for the fluent-style alternative.
- Model.NoOverlap — for creating no-overlap constraints.
- Model.Minimize — for creating minimization objectives.
- Model.Maximize — for creating maximization objectives.
Enforce(IEnumerable<BoolExpr>)
Enforces a boolean expression as a constraint in the model.
public void Enforce(IEnumerable<BoolExpr> expressions)
Parameters
expressionsIEnumerable<BoolExpr>
Remarks
This is the primary method for enforcing boolean expressions as constraints in the model.
A constraint is satisfied if it is not false. In other words, a constraint is satisfied if it is true or absent.
A boolean expression that is not enforced as a constraint can have arbitrary value in a solution (true, false, or absent). Once enforced as a constraint, it can only be true or absent in the solution.
Note: Constraint objects are automatically registered when created.
Passing them to enforce() is accepted but does nothing. For cumulative
constraints (cumul <= capacity, cumul >= min_level), using enforce() is
recommended for code clarity even though it's not required.
Accepted argument types
The enforce method accepts several types of arguments:
- BoolExpr objects: Boolean expressions created from comparisons
(e.g.,
x <= 5,a == b) or logical operations (e.g.,a & b,~c). - bool values: Python boolean constants
TrueorFalse. - Constraint objects: Accepted but does nothing (constraints auto-register).
Use with cumulative constraints for clarity:
model.enforce(cumul <= capacity). - Iterables: Lists, tuples, or generators of the above types.
Example:
var model = new Model();
var x = model.IntervalVar(length: 10, name: "x");
// Enforce boolean expressions as constraints
model.Enforce(x.Start() >= 0);
model.Enforce(x.End() <= 100);
Example:
var model = new Model();
var tasks = new IntervalVar[5];
for (int i = 0; i < 5; i++)
tasks[i] = model.IntervalVar(length: 10, name: $"task_{i}");
// Enforce multiple constraints at once
model.Enforce(tasks.Select(task => task.Start() >= 0));
// Or inline
model.Enforce(tasks.Select(task => task.End() <= 100));
Example:
var model = new Model();
var x = model.IntVar(min: 0, max: 100, name: "x");
var y = model.IntVar(min: 0, max: 100, name: "y");
// Enforce various boolean expressions
model.Enforce(new BoolExpr[] {
x + y <= 50, // From comparison
x >= 10, // From comparison
});
See also:
- BoolExpr.Enforce — for the fluent-style alternative.
- Model.NoOverlap — for creating no-overlap constraints.
- Model.Minimize — for creating minimization objectives.
- Model.Maximize — for creating maximization objectives.
Enforce(IEnumerable<Constraint>)
Enforces a boolean expression as a constraint in the model.
public void Enforce(IEnumerable<Constraint> constraints)
Parameters
constraintsIEnumerable<Constraint>
Remarks
This is the primary method for enforcing boolean expressions as constraints in the model.
A constraint is satisfied if it is not false. In other words, a constraint is satisfied if it is true or absent.
A boolean expression that is not enforced as a constraint can have arbitrary value in a solution (true, false, or absent). Once enforced as a constraint, it can only be true or absent in the solution.
Note: Constraint objects are automatically registered when created.
Passing them to enforce() is accepted but does nothing. For cumulative
constraints (cumul <= capacity, cumul >= min_level), using enforce() is
recommended for code clarity even though it's not required.
Accepted argument types
The enforce method accepts several types of arguments:
- BoolExpr objects: Boolean expressions created from comparisons
(e.g.,
x <= 5,a == b) or logical operations (e.g.,a & b,~c). - bool values: Python boolean constants
TrueorFalse. - Constraint objects: Accepted but does nothing (constraints auto-register).
Use with cumulative constraints for clarity:
model.enforce(cumul <= capacity). - Iterables: Lists, tuples, or generators of the above types.
Example:
var model = new Model();
var x = model.IntervalVar(length: 10, name: "x");
// Enforce boolean expressions as constraints
model.Enforce(x.Start() >= 0);
model.Enforce(x.End() <= 100);
Example:
var model = new Model();
var tasks = new IntervalVar[5];
for (int i = 0; i < 5; i++)
tasks[i] = model.IntervalVar(length: 10, name: $"task_{i}");
// Enforce multiple constraints at once
model.Enforce(tasks.Select(task => task.Start() >= 0));
// Or inline
model.Enforce(tasks.Select(task => task.End() <= 100));
Example:
var model = new Model();
var x = model.IntVar(min: 0, max: 100, name: "x");
var y = model.IntVar(min: 0, max: 100, name: "y");
// Enforce various boolean expressions
model.Enforce(new BoolExpr[] {
x + y <= 50, // From comparison
x >= 10, // From comparison
});
See also:
- BoolExpr.Enforce — for the fluent-style alternative.
- Model.NoOverlap — for creating no-overlap constraints.
- Model.Minimize — for creating minimization objectives.
- Model.Maximize — for creating maximization objectives.
Eval(IntStepFunction, IntExpr)
Evaluates a step function at a given point.
public IntExpr Eval(IntStepFunction func, IntExpr arg)
Parameters
funcIntStepFunctionThe step function.
argIntExprThe point at which to evaluate the step function.
Returns
- IntExpr
The resulting integer expression
Remarks
The result is the value of the step function func at the point arg. If the value of arg is absent, then the result is also absent.
By constraining the returned value, it is possible to limit arg to be only within certain segments of the segmented function. In particular, functions Model.ForbidStart and Model.ForbidEnd work that way.
See also:
- IntStepFunction.Eval — for the equivalent function on IntStepFunction.
- Model.ForbidStart — are convenience functions built on top of
eval. - Model.ForbidEnd — are convenience functions built on top of
eval.
Eval(IntStepFunction, int)
Evaluates a step function at a given point.
public IntExpr Eval(IntStepFunction func, int arg)
Parameters
funcIntStepFunctionThe step function.
argintThe point at which to evaluate the step function.
Returns
- IntExpr
The resulting integer expression
Remarks
The result is the value of the step function func at the point arg. If the value of arg is absent, then the result is also absent.
By constraining the returned value, it is possible to limit arg to be only within certain segments of the segmented function. In particular, functions Model.ForbidStart and Model.ForbidEnd work that way.
See also:
- IntStepFunction.Eval — for the equivalent function on IntStepFunction.
- Model.ForbidStart — are convenience functions built on top of
eval. - Model.ForbidEnd — are convenience functions built on top of
eval.
ForbidEnd(IntervalVar, IntStepFunction)
Constrains the end of the interval variable to be outside of the zero-height segments of the step function.
public Constraint ForbidEnd(IntervalVar interval, IntStepFunction func)
Parameters
intervalIntervalVarThe interval variable.
funcIntStepFunctionThe step function.
Returns
- Constraint
The constraint forbidding the end point.
Remarks
This function is equivalent to:
I.e., the function value at the end of the interval variable cannot be zero.
@example A delivery task that must complete during business hours (not during lunch break):
var model = new Model();
// A 1-hour delivery task
var delivery = model.IntervalVar(length: 1, name: "delivery");
// Allowed end times: 1 = allowed, 0 = forbidden
var allowedEnds = model.StepFunction(new[] {
(0, 0), // Before 9h: forbidden
(9, 1), // 9h: business opens, allowed
(12, 0), // 12h: lunch break, forbidden
(13, 1), // 13h: lunch ends, allowed
(17, 0), // 17h: business closes, forbidden
});
// Delivery cannot end when allowedEnds is 0
model.ForbidEnd(delivery, allowedEnds);
model.Minimize(delivery.End());
var result = model.Solve();
See also:
- IntervalVar.ForbidEnd — for the equivalent function on IntervalVar.
- Model.ForbidStart — for similar function that constrains start an interval variable.
- Model.Eval — for evaluation of a step function.
ForbidExtent(IntervalVar, IntStepFunction)
Forbid the interval variable to overlap with segments of the function where the value is zero.
public Constraint ForbidExtent(IntervalVar interval, IntStepFunction func)
Parameters
intervalIntervalVarThe interval variable.
funcIntStepFunctionThe step function.
Returns
- Constraint
The constraint forbidding the extent (entire interval).
Remarks
This function prevents the specified interval variable from overlapping with segments of the step function where the value is zero. That is, if \([s, e)\) is a segment of the step function where the value is zero, then the interval variable either ends before \(s\) (\(\mathtt{interval.end()} \le s\)) or starts after \(e\) (\(e \le \mathtt{interval.start()}\)).
@example A production task that cannot overlap with scheduled maintenance windows:
var model = new Model();
var production = model.IntervalVar(length: 3, name: "production");
var availability = model.StepFunction(new[] {
(0, 1), (8, 0), (10, 1),
});
model.ForbidExtent(production, availability);
model.Minimize(production.End());
var result = model.Solve();
See also:
- IntervalVar.ForbidExtent — for the equivalent function on IntervalVar.
- Model.ForbidStart — for similar functions that constrain the start/end of an interval variable.
- Model.ForbidEnd — for similar functions that constrain the start/end of an interval variable.
- Model.Eval — for evaluation of a step function.
ForbidStart(IntervalVar, IntStepFunction)
Constrains the start of the interval variable to be outside of the zero-height segments of the step function.
public Constraint ForbidStart(IntervalVar interval, IntStepFunction func)
Parameters
intervalIntervalVarThe interval variable.
funcIntStepFunctionThe step function.
Returns
- Constraint
The constraint forbidding the start point.
Remarks
This function is equivalent to:
I.e., the function value at the start of the interval variable cannot be zero.
@example A factory task that can only start during work hours (excluding breaks):
var model = new Model();
// A 2-hour task on a machine
var task = model.IntervalVar(length: 2, name: "task");
// Allowed start times: 1 = allowed, 0 = forbidden
var allowedStarts = model.StepFunction(new[] {
(0, 0), // Before 6h: forbidden
(6, 1), // 6h: shift starts, allowed
(10, 0), // 10h: break, forbidden
(11, 1), // 11h: break ends, allowed
(14, 0), // 14h: shift ends, forbidden
});
// Task cannot start when allowedStarts is 0
model.ForbidStart(task, allowedStarts);
model.Minimize(task.Start());
var result = model.Solve();
See also:
- IntervalVar.ForbidStart — for the equivalent function on IntervalVar.
- Model.ForbidEnd — for similar function that constrains end an interval variable.
- Model.Eval — for evaluation of a step function.
FromJSON(string)
Creates a model from JSON format.
public static (Model Model, Parameters? Parameters, Solution? WarmStart) FromJSON(string jsonStr)
Parameters
jsonStrstringA string containing the model in JSON format
Returns
- (Model Model, Parameters Parameters, Solution WarmStart)
A tuple containing the model, optional parameters, and optional warm start solution.
Remarks
Creates a new Model instance from a JSON string that was previously exported using Model.ToJSON.
The method returns a tuple with three elements:
- The reconstructed Model
- Parameters (if they were included in the JSON), or None
- Warm start Solution (if it was included in the JSON), or None
Variables in the new model can be accessed using methods like Model.GetIntervalVars, Model.GetIntVars, etc.
// Create and export a model
var model = new Model();
var x = model.IntervalVar(length: 10, name: "task_x");
model.Minimize(x.End());
var parameters = new Parameters { timeLimit = 60 };
var jsonStr = model.ToJSON(parameters);
// Save to file
File.WriteAllText("model.json", jsonStr);
// Later, load from file
var loadedJson = File.ReadAllText("model.json");
// Restore model, parameters, and warm start
var (model2, params2, warmStart2) = Model.FromJSON(loadedJson);
// Access variables
var intervalVars = model2.GetIntervalVars();
Console.WriteLine($"Loaded model with {intervalVars.Count} interval variables");
// Solve with restored parameters
var result = model2.Solve(params2);
See also:
- Model.ToJSON — to export to JSON.
GetBoolVars()
Returns a list of all boolean variables in the model.
public IReadOnlyList<BoolVar> GetBoolVars()
Returns
- IReadOnlyList<BoolVar>
A list of all boolean variables in the model
Remarks
Returns a copy of the list containing all boolean variables that have been created in this model using Model.BoolVar.
Example:
var model = new Model();
var useMachineA = model.BoolVar(name: "use_machine_a");
var useMachineB = model.BoolVar(name: "use_machine_b");
var boolVars = model.GetBoolVars();
Console.WriteLine(boolVars.Count); // 2
foreach (var bv in boolVars)
Console.WriteLine(bv.Name); // "use_machine_a", "use_machine_b"
See also:
GetIntVars()
Returns a list of all integer variables in the model.
public IReadOnlyList<IntVar> GetIntVars()
Returns
- IReadOnlyList<IntVar>
A list of all integer variables in the model
Remarks
Returns a copy of the list containing all integer variables that have been created in this model using Model.IntVar.
Example:
var model = new Model();
var x = model.IntVar(min: 0, max: 10, name: "x");
var y = model.IntVar(min: 0, max: 100, name: "y");
var intVars = model.GetIntVars();
Console.WriteLine(intVars.Count); // 2
foreach (var iv in intVars)
Console.WriteLine(iv.Name); // "x", "y"
See also:
GetIntervalVars()
Returns a list of all interval variables in the model.
public IReadOnlyList<IntervalVar> GetIntervalVars()
Returns
- IReadOnlyList<IntervalVar>
A list of all interval variables in the model
Remarks
Returns a copy of the list containing all interval variables that have been created in this model using Model.IntervalVar.
Example:
var model = new Model();
var task1 = model.IntervalVar(length: 10, name: "task1");
var task2 = model.IntervalVar(length: 20, name: "task2");
var intervals = model.GetIntervalVars();
Console.WriteLine(intervals.Count); // 2
foreach (var iv in intervals)
Console.WriteLine(iv.Name); // "task1", "task2"
See also:
Guard(IntExpr, int)
Creates an expression that replaces value absent by a constant.
public IntExpr Guard(IntExpr arg, int absentValue = 0)
Parameters
Returns
- IntExpr
The resulting integer expression
Remarks
The resulting expression is:
- equal to
argifargis present - and equal to
absentValueotherwise (i.e. whenargis absent).
The default value of absentValue is 0.
The resulting expression is never absent.
Same as IntExpr.Guard.
Guard(int, int)
Creates an expression that replaces value absent by a constant.
public IntExpr Guard(int arg, int absentValue = 0)
Parameters
Returns
- IntExpr
The resulting integer expression
Remarks
The resulting expression is:
- equal to
argifargis present - and equal to
absentValueotherwise (i.e. whenargis absent).
The default value of absentValue is 0.
The resulting expression is never absent.
Same as IntExpr.Guard.
Identity(IntExpr, IntExpr)
Constrains lhs and rhs to be identical, including their presence status.
public Constraint Identity(IntExpr lhs, IntExpr rhs)
Parameters
Returns
- Constraint
The identity constraint.
Remarks
Identity is different than equality. For example, if x is absent, then eq(x, 0) is absent, but identity(x, 0) is false.
Same as IntExpr.Identity.
Identity(IntExpr, int)
Constrains lhs and rhs to be identical, including their presence status.
public Constraint Identity(IntExpr lhs, int rhs)
Parameters
Returns
- Constraint
The identity constraint.
Remarks
Identity is different than equality. For example, if x is absent, then eq(x, 0) is absent, but identity(x, 0) is false.
Same as IntExpr.Identity.
Identity(int, IntExpr)
Constrains lhs and rhs to be identical, including their presence status.
public Constraint Identity(int lhs, IntExpr rhs)
Parameters
Returns
- Constraint
The identity constraint.
Remarks
Identity is different than equality. For example, if x is absent, then eq(x, 0) is absent, but identity(x, 0) is false.
Same as IntExpr.Identity.
Implies(BoolExpr, BoolExpr)
Logical implication of two boolean expressions, that is lhs implies rhs.
public BoolExpr Implies(BoolExpr lhs, BoolExpr rhs)
Parameters
Returns
- BoolExpr
The resulting Boolean expression
Remarks
If one of the arguments has value absent, then the resulting expression also has value absent.
Same as BoolExpr.Implies.
Implies(BoolExpr, bool)
Logical implication of two boolean expressions, that is lhs implies rhs.
public BoolExpr Implies(BoolExpr lhs, bool rhs)
Parameters
Returns
- BoolExpr
The resulting Boolean expression
Remarks
If one of the arguments has value absent, then the resulting expression also has value absent.
Same as BoolExpr.Implies.
Implies(bool, BoolExpr)
Logical implication of two boolean expressions, that is lhs implies rhs.
public BoolExpr Implies(bool lhs, BoolExpr rhs)
Parameters
Returns
- BoolExpr
The resulting Boolean expression
Remarks
If one of the arguments has value absent, then the resulting expression also has value absent.
Same as BoolExpr.Implies.
InRange(IntExpr, int, int)
Creates Boolean expression lb ≤ arg ≤ ub.
public BoolExpr InRange(IntExpr arg, int lb, int ub)
Parameters
Returns
- BoolExpr
The resulting Boolean expression
Remarks
If arg has value absent then the resulting expression has also value absent.
Use Model.Enforce to add this expression as a constraint to the model.
Same as IntExpr.InRange.
InRange(int, int, int)
Creates Boolean expression lb ≤ arg ≤ ub.
public BoolExpr InRange(int arg, int lb, int ub)
Parameters
Returns
- BoolExpr
The resulting Boolean expression
Remarks
If arg has value absent then the resulting expression has also value absent.
Use Model.Enforce to add this expression as a constraint to the model.
Same as IntExpr.InRange.
IntVar(int?, int?, bool, string?)
Creates a new integer variable and adds it to the model.
public IntVar IntVar(int? min = null, int? max = null, bool optional = false, string? name = null)
Parameters
minint?Minimum value for the variable. Default is 0.
maxint?Maximum value for the variable. Default is Model.IntVarMax.
optionalboolIf true, the variable can be absent in a solution. The default is false.
namestringOptional name for debugging purposes.
Returns
- IntVar
The created integer variable.
Remarks
An integer variable represents an unknown value the solver must find. The variable can be optional. In this case, its value in a solution could be absent, meaning that the solution does not use the variable at all.
The default domain is 0 to Model.IntVarMax.
If min or max is not specified (or null), the default value is used.
Example:
var model = new Model();
// Create an integer variable with possible values 1..10:
var x = model.IntVar(min: 1, max: 10, name: "x");
// Create an optional integer variable with possible values 5..Model.IntVarMax:
var y = model.IntVar(min: 5, optional: true, name: "y");
// Create a non-negative integer variable:
var z = model.IntVar(max: 100, name: "z");
Integral(IntStepFunction, IntervalVar)
Computes sum of values of the step function func over the interval interval.
public IntExpr Integral(IntStepFunction func, IntervalVar interval)
Parameters
funcIntStepFunctionThe step function.
intervalIntervalVarThe interval variable.
Returns
- IntExpr
The resulting integer expression
Remarks
The sum is computed over all points in range interval.start() .. interval.end()-1. The sum includes the function value at the start time but not the value at the end time. If the interval variable has zero length, then the result is 0. If the interval variable is absent, then the result is absent.
Requirement: The step function func must be non-negative.
See also:
- IntStepFunction.Integral — for the equivalent function on IntStepFunction.
IntervalVar(IntBound?, IntBound?, IntBound?, bool, string?)
Creates a new interval variable and adds it to the model.
public IntervalVar IntervalVar(IntBound? start = null, IntBound? end = null, IntBound? length = null, bool optional = false, string? name = null)
Parameters
startIntBound?Fixed start time or range [min, max]. Pass an int for a fixed value, a tuple (min, max) for a range, or null for the default range [0, Model.IntervalMax].
endIntBound?Fixed end time or range [min, max]. Pass an int for a fixed value, a tuple (min, max) for a range, or null for the default range [0, Model.IntervalMax].
lengthIntBound?Fixed length or range [min, max]. Pass an int for a fixed value, a tuple (min, max) for a range, or null for the default range [0, Model.IntervalMax].
optionalboolIf true, the interval can be absent in a solution. The default is false.
namestringOptional name for debugging purposes.
Returns
- IntervalVar
The created interval variable.
Remarks
An interval variable represents an unknown interval (a task, operation, action) that the solver assigns a value in such a way as to satisfy all constraints. An interval variable has a start, end, and length. In a solution, start <= end and length = end - start.
The interval variable can be optional. In this case, its value in a solution could be absent, meaning that the task/operation is not performed.
Parameters start, end, and length accept an IntBound, which can be:
- An int for a fixed value
- A tuple
(int min, int max)for a range (use null for either bound to keep the default)
The default range for start, end and length is 0 to Model.IntervalMax.
Example:
var model = new Model();
// Create an interval variable with a fixed start but unknown length:
var x = model.IntervalVar(start: 0, length: (10, 20), name: "x");
// Create an interval variable with start and end ranges:
var y = model.IntervalVar(start: (0, 5), end: (10, 15), name: "y");
// Create an optional interval variable with length range 5..10:
var z = model.IntervalVar(length: (5, 10), optional: true, name: "z");
// Set only startMax (startMin remains the default 0):
var w = model.IntervalVar(start: (null, 100), name: "w");
See also:
Length(IntervalVar)
Creates an integer expression for the duration (end - start) of an interval variable.
public IntExpr Length(IntervalVar interval)
Parameters
intervalIntervalVarThe interval variable.
Returns
- IntExpr
The resulting integer expression
Remarks
If the interval is absent, the resulting expression is also absent.
Example:
y to start after the end of x with a delay of at least 10. In addition, we constrain the length of x to be less or equal to the length of y.
var model = new Model();
var x = model.IntervalVar(name: "x");
var y = model.IntervalVar(name: "y");
model.Enforce(model.End(x) + 10 <= model.Start(y));
model.Enforce(model.Length(x) <= model.Length(y));
When x or y is absent then value of both constraints above is absent and therefore they are satisfied.
See also:
- IntervalVar.Length — is equivalent function on IntervalVar.
LexGe(IEnumerable<IntExpr>, IEnumerable<IntExpr>)
Lexicographic greater than or equal constraint: lhs ≥ rhs.
public Constraint LexGe(IEnumerable<IntExpr> lhs, IEnumerable<IntExpr> rhs)
Parameters
lhsIEnumerable<IntExpr>The left-hand side array of integer expressions.
rhsIEnumerable<IntExpr>The right-hand side array of integer expressions.
Returns
- Constraint
The lexicographic constraint.
Remarks
Constrains lhs to be lexicographically greater than or equal rhs.
Both arrays must have the same length, and the length must be at least 1.
Lexicographic ordering compares arrays element by element from the first
position. The comparison lhs ≥ rhs holds if and only if:
- all elements are equal (
lhs[i] == rhs[i]for alli), or - there exists a position
kwherelhs[k] > rhs[k]and all preceding elements are equal (lhs[i] == rhs[i]for alli < k)
Lexicographic constraints are useful for symmetry breaking. For example, when you have multiple equivalent solutions that differ only in the ordering of symmetric variables, adding a lexicographic constraint can eliminate redundant solutions.
Example:
var model = new Model();
// Variables for a 3x3 matrix where rows should be lexicographically ordered
var rows = Enumerable.Range(0, 3).Select(i =>
Enumerable.Range(0, 3).Select(j => model.IntVar(min: 0, max: 9, name: $"x_{i}_{j}")).ToArray()
).ToArray();
// Break row symmetry: row[0] ≥ row[1] ≥ row[2] lexicographically
model.LexGe(rows[0], rows[1]);
model.LexGe(rows[1], rows[2]);
See also:
- Model.LexLe — for other lexicographic comparisons.
- Model.LexLt — for other lexicographic comparisons.
- Model.LexGt — for other lexicographic comparisons.
LexGe(IEnumerable<object>, IEnumerable<object>)
Lexicographic greater than or equal constraint: lhs ≥ rhs.
public Constraint LexGe(IEnumerable<object> lhs, IEnumerable<object> rhs)
Parameters
lhsIEnumerable<object>The left-hand side array of integer expressions.
rhsIEnumerable<object>The right-hand side array of integer expressions.
Returns
- Constraint
The lexicographic constraint.
Remarks
Constrains lhs to be lexicographically greater than or equal rhs.
Both arrays must have the same length, and the length must be at least 1.
Lexicographic ordering compares arrays element by element from the first
position. The comparison lhs ≥ rhs holds if and only if:
- all elements are equal (
lhs[i] == rhs[i]for alli), or - there exists a position
kwherelhs[k] > rhs[k]and all preceding elements are equal (lhs[i] == rhs[i]for alli < k)
Lexicographic constraints are useful for symmetry breaking. For example, when you have multiple equivalent solutions that differ only in the ordering of symmetric variables, adding a lexicographic constraint can eliminate redundant solutions.
Example:
var model = new Model();
// Variables for a 3x3 matrix where rows should be lexicographically ordered
var rows = Enumerable.Range(0, 3).Select(i =>
Enumerable.Range(0, 3).Select(j => model.IntVar(min: 0, max: 9, name: $"x_{i}_{j}")).ToArray()
).ToArray();
// Break row symmetry: row[0] ≥ row[1] ≥ row[2] lexicographically
model.LexGe(rows[0], rows[1]);
model.LexGe(rows[1], rows[2]);
See also:
- Model.LexLe — for other lexicographic comparisons.
- Model.LexLt — for other lexicographic comparisons.
- Model.LexGt — for other lexicographic comparisons.
LexGt(IEnumerable<IntExpr>, IEnumerable<IntExpr>)
Lexicographic strictly greater than constraint: lhs > rhs.
public Constraint LexGt(IEnumerable<IntExpr> lhs, IEnumerable<IntExpr> rhs)
Parameters
lhsIEnumerable<IntExpr>The left-hand side array of integer expressions.
rhsIEnumerable<IntExpr>The right-hand side array of integer expressions.
Returns
- Constraint
The lexicographic constraint.
Remarks
Constrains lhs to be lexicographically strictly greater than rhs.
Both arrays must have the same length, and the length must be at least 1.
Lexicographic ordering compares arrays element by element from the first
position. The comparison lhs > rhs holds if and only if:
there exists a position k where lhs[k] > rhs[k] and all preceding elements are equal (lhs[i] == rhs[i] for all i < k)
Lexicographic constraints are useful for symmetry breaking. For example, when you have multiple equivalent solutions that differ only in the ordering of symmetric variables, adding a lexicographic constraint can eliminate redundant solutions.
Example:
var model = new Model();
// Variables for a 3x3 matrix where rows should be lexicographically ordered
var rows = Enumerable.Range(0, 3).Select(i =>
Enumerable.Range(0, 3).Select(j => model.IntVar(min: 0, max: 9, name: $"x_{i}_{j}")).ToArray()
).ToArray();
// Break row symmetry: row[0] > row[1] > row[2] lexicographically
model.LexGt(rows[0], rows[1]);
model.LexGt(rows[1], rows[2]);
See also:
- Model.LexLe — for other lexicographic comparisons.
- Model.LexLt — for other lexicographic comparisons.
- Model.LexGe — for other lexicographic comparisons.
LexGt(IEnumerable<object>, IEnumerable<object>)
Lexicographic strictly greater than constraint: lhs > rhs.
public Constraint LexGt(IEnumerable<object> lhs, IEnumerable<object> rhs)
Parameters
lhsIEnumerable<object>The left-hand side array of integer expressions.
rhsIEnumerable<object>The right-hand side array of integer expressions.
Returns
- Constraint
The lexicographic constraint.
Remarks
Constrains lhs to be lexicographically strictly greater than rhs.
Both arrays must have the same length, and the length must be at least 1.
Lexicographic ordering compares arrays element by element from the first
position. The comparison lhs > rhs holds if and only if:
there exists a position k where lhs[k] > rhs[k] and all preceding elements are equal (lhs[i] == rhs[i] for all i < k)
Lexicographic constraints are useful for symmetry breaking. For example, when you have multiple equivalent solutions that differ only in the ordering of symmetric variables, adding a lexicographic constraint can eliminate redundant solutions.
Example:
var model = new Model();
// Variables for a 3x3 matrix where rows should be lexicographically ordered
var rows = Enumerable.Range(0, 3).Select(i =>
Enumerable.Range(0, 3).Select(j => model.IntVar(min: 0, max: 9, name: $"x_{i}_{j}")).ToArray()
).ToArray();
// Break row symmetry: row[0] > row[1] > row[2] lexicographically
model.LexGt(rows[0], rows[1]);
model.LexGt(rows[1], rows[2]);
See also:
- Model.LexLe — for other lexicographic comparisons.
- Model.LexLt — for other lexicographic comparisons.
- Model.LexGe — for other lexicographic comparisons.
LexLe(IEnumerable<IntExpr>, IEnumerable<IntExpr>)
Lexicographic less than or equal constraint: lhs ≤ rhs.
public Constraint LexLe(IEnumerable<IntExpr> lhs, IEnumerable<IntExpr> rhs)
Parameters
lhsIEnumerable<IntExpr>The left-hand side array of integer expressions.
rhsIEnumerable<IntExpr>The right-hand side array of integer expressions.
Returns
- Constraint
The lexicographic constraint.
Remarks
Constrains lhs to be lexicographically less than or equal rhs.
Both arrays must have the same length, and the length must be at least 1.
Lexicographic ordering compares arrays element by element from the first
position. The comparison lhs ≤ rhs holds if and only if:
- all elements are equal (
lhs[i] == rhs[i]for alli), or - there exists a position
kwherelhs[k] < rhs[k]and all preceding elements are equal (lhs[i] == rhs[i]for alli < k)
Lexicographic constraints are useful for symmetry breaking. For example, when you have multiple equivalent solutions that differ only in the ordering of symmetric variables, adding a lexicographic constraint can eliminate redundant solutions.
Example:
var model = new Model();
// Variables for a 3x3 matrix where rows should be lexicographically ordered
var rows = Enumerable.Range(0, 3).Select(i =>
Enumerable.Range(0, 3).Select(j => model.IntVar(min: 0, max: 9, name: $"x_{i}_{j}")).ToArray()
).ToArray();
// Break row symmetry: row[0] ≤ row[1] ≤ row[2] lexicographically
model.LexLe(rows[0], rows[1]);
model.LexLe(rows[1], rows[2]);
See also:
- Model.LexLt — for other lexicographic comparisons.
- Model.LexGe — for other lexicographic comparisons.
- Model.LexGt — for other lexicographic comparisons.
LexLe(IEnumerable<object>, IEnumerable<object>)
Lexicographic less than or equal constraint: lhs ≤ rhs.
public Constraint LexLe(IEnumerable<object> lhs, IEnumerable<object> rhs)
Parameters
lhsIEnumerable<object>The left-hand side array of integer expressions.
rhsIEnumerable<object>The right-hand side array of integer expressions.
Returns
- Constraint
The lexicographic constraint.
Remarks
Constrains lhs to be lexicographically less than or equal rhs.
Both arrays must have the same length, and the length must be at least 1.
Lexicographic ordering compares arrays element by element from the first
position. The comparison lhs ≤ rhs holds if and only if:
- all elements are equal (
lhs[i] == rhs[i]for alli), or - there exists a position
kwherelhs[k] < rhs[k]and all preceding elements are equal (lhs[i] == rhs[i]for alli < k)
Lexicographic constraints are useful for symmetry breaking. For example, when you have multiple equivalent solutions that differ only in the ordering of symmetric variables, adding a lexicographic constraint can eliminate redundant solutions.
Example:
var model = new Model();
// Variables for a 3x3 matrix where rows should be lexicographically ordered
var rows = Enumerable.Range(0, 3).Select(i =>
Enumerable.Range(0, 3).Select(j => model.IntVar(min: 0, max: 9, name: $"x_{i}_{j}")).ToArray()
).ToArray();
// Break row symmetry: row[0] ≤ row[1] ≤ row[2] lexicographically
model.LexLe(rows[0], rows[1]);
model.LexLe(rows[1], rows[2]);
See also:
- Model.LexLt — for other lexicographic comparisons.
- Model.LexGe — for other lexicographic comparisons.
- Model.LexGt — for other lexicographic comparisons.
LexLt(IEnumerable<IntExpr>, IEnumerable<IntExpr>)
Lexicographic strictly less than constraint: lhs < rhs.
public Constraint LexLt(IEnumerable<IntExpr> lhs, IEnumerable<IntExpr> rhs)
Parameters
lhsIEnumerable<IntExpr>The left-hand side array of integer expressions.
rhsIEnumerable<IntExpr>The right-hand side array of integer expressions.
Returns
- Constraint
The lexicographic constraint.
Remarks
Constrains lhs to be lexicographically strictly less than rhs.
Both arrays must have the same length, and the length must be at least 1.
Lexicographic ordering compares arrays element by element from the first
position. The comparison lhs < rhs holds if and only if:
there exists a position k where lhs[k] < rhs[k] and all preceding elements are equal (lhs[i] == rhs[i] for all i < k)
Lexicographic constraints are useful for symmetry breaking. For example, when you have multiple equivalent solutions that differ only in the ordering of symmetric variables, adding a lexicographic constraint can eliminate redundant solutions.
Example:
var model = new Model();
// Variables for a 3x3 matrix where rows should be lexicographically ordered
var rows = Enumerable.Range(0, 3).Select(i =>
Enumerable.Range(0, 3).Select(j => model.IntVar(min: 0, max: 9, name: $"x_{i}_{j}")).ToArray()
).ToArray();
// Break row symmetry: row[0] < row[1] < row[2] lexicographically
model.LexLt(rows[0], rows[1]);
model.LexLt(rows[1], rows[2]);
See also:
- Model.LexLe — for other lexicographic comparisons.
- Model.LexGe — for other lexicographic comparisons.
- Model.LexGt — for other lexicographic comparisons.
LexLt(IEnumerable<object>, IEnumerable<object>)
Lexicographic strictly less than constraint: lhs < rhs.
public Constraint LexLt(IEnumerable<object> lhs, IEnumerable<object> rhs)
Parameters
lhsIEnumerable<object>The left-hand side array of integer expressions.
rhsIEnumerable<object>The right-hand side array of integer expressions.
Returns
- Constraint
The lexicographic constraint.
Remarks
Constrains lhs to be lexicographically strictly less than rhs.
Both arrays must have the same length, and the length must be at least 1.
Lexicographic ordering compares arrays element by element from the first
position. The comparison lhs < rhs holds if and only if:
there exists a position k where lhs[k] < rhs[k] and all preceding elements are equal (lhs[i] == rhs[i] for all i < k)
Lexicographic constraints are useful for symmetry breaking. For example, when you have multiple equivalent solutions that differ only in the ordering of symmetric variables, adding a lexicographic constraint can eliminate redundant solutions.
Example:
var model = new Model();
// Variables for a 3x3 matrix where rows should be lexicographically ordered
var rows = Enumerable.Range(0, 3).Select(i =>
Enumerable.Range(0, 3).Select(j => model.IntVar(min: 0, max: 9, name: $"x_{i}_{j}")).ToArray()
).ToArray();
// Break row symmetry: row[0] < row[1] < row[2] lexicographically
model.LexLt(rows[0], rows[1]);
model.LexLt(rows[1], rows[2]);
See also:
- Model.LexLe — for other lexicographic comparisons.
- Model.LexGe — for other lexicographic comparisons.
- Model.LexGt — for other lexicographic comparisons.
Max(IEnumerable<IntExpr>)
Creates an integer expression for the maximum of the arguments.
public IntExpr Max(IEnumerable<IntExpr> args)
Parameters
argsIEnumerable<IntExpr>Array of integer expressions to compute maximum of.
Returns
- IntExpr
The resulting integer expression
Remarks
Absent arguments are ignored as if they were not specified in the input array args. Maximum of an empty set (i.e. max([]) is absent. The maximum is absent also if all arguments are absent.
Note that binary function Model.Max2 handles absent values differently. For example, when x is absent then:
max2(x, 5)is absent.max([x, 5])is 5.max([x])is absent.
Example:
var model = new Model();
var tasks = Enumerable.Range(0, 5)
.Select(i => model.IntervalVar(length: 10, name: $"task_{i}")).ToArray();
// Create an array of end times of the tasks:
var endTimes = tasks.Select(t => t.End());
var makespan = model.Max(endTimes);
model.Minimize(makespan);
Notice that when a task is absent (not executed), then its end time is absent. And therefore, the absent task is not included in the maximum.
See also:
- Model.Max2
- Model.Span — constraints interval variable to start and end at minimum and maximum of the given set of intervals.
Max(IEnumerable<object>)
Creates an integer expression for the maximum of the arguments.
public IntExpr Max(IEnumerable<object> args)
Parameters
argsIEnumerable<object>Array of integer expressions to compute maximum of.
Returns
- IntExpr
The resulting integer expression
Remarks
Absent arguments are ignored as if they were not specified in the input array args. Maximum of an empty set (i.e. max([]) is absent. The maximum is absent also if all arguments are absent.
Note that binary function Model.Max2 handles absent values differently. For example, when x is absent then:
max2(x, 5)is absent.max([x, 5])is 5.max([x])is absent.
Example:
var model = new Model();
var tasks = Enumerable.Range(0, 5)
.Select(i => model.IntervalVar(length: 10, name: $"task_{i}")).ToArray();
// Create an array of end times of the tasks:
var endTimes = tasks.Select(t => t.End());
var makespan = model.Max(endTimes);
model.Minimize(makespan);
Notice that when a task is absent (not executed), then its end time is absent. And therefore, the absent task is not included in the maximum.
See also:
- Model.Max2
- Model.Span — constraints interval variable to start and end at minimum and maximum of the given set of intervals.
Max2(IntExpr, IntExpr)
Creates an integer expression which is the maximum of lhs and rhs.
public IntExpr Max2(IntExpr lhs, IntExpr rhs)
Parameters
Returns
- IntExpr
The resulting integer expression
Remarks
If one of the arguments has value absent, then the resulting expression also has value absent.
Same as IntExpr.Max2. See Model.Max for n-ary maximum.
Max2(IntExpr, int)
Creates an integer expression which is the maximum of lhs and rhs.
public IntExpr Max2(IntExpr lhs, int rhs)
Parameters
Returns
- IntExpr
The resulting integer expression
Remarks
If one of the arguments has value absent, then the resulting expression also has value absent.
Same as IntExpr.Max2. See Model.Max for n-ary maximum.
Max2(int, IntExpr)
Creates an integer expression which is the maximum of lhs and rhs.
public IntExpr Max2(int lhs, IntExpr rhs)
Parameters
Returns
- IntExpr
The resulting integer expression
Remarks
If one of the arguments has value absent, then the resulting expression also has value absent.
Same as IntExpr.Max2. See Model.Max for n-ary maximum.
Maximize(IntExpr)
Creates a maximization objective for the provided expression.
public Objective Maximize(IntExpr expr)
Parameters
exprIntExprThe expression to maximize
Returns
- Objective
An Objective that maximizes the expression.
Remarks
Creates an Objective to maximize the given expression. A model can have at most one objective. New objective replaces the old one.
Equivalent of function IntExpr.Maximize.
Example:
x:
var model = new Model();
var x = model.IntervalVar(length: (10, 20), name: "x");
model.Maximize(x.Length());
var result = model.Solve();
See also:
- Model.Minimize
- IntExpr.Maximize — for fluent-style maximization.
Maximize(int)
Creates a maximization objective for the provided expression.
public Objective Maximize(int value)
Parameters
valueint
Returns
- Objective
An Objective that maximizes the expression.
Remarks
Creates an Objective to maximize the given expression. A model can have at most one objective. New objective replaces the old one.
Equivalent of function IntExpr.Maximize.
Example:
x:
var model = new Model();
var x = model.IntervalVar(length: (10, 20), name: "x");
model.Maximize(x.Length());
var result = model.Solve();
See also:
- Model.Minimize
- IntExpr.Maximize — for fluent-style maximization.
Min(IEnumerable<IntExpr>)
Creates an integer expression for the minimum of the arguments.
public IntExpr Min(IEnumerable<IntExpr> args)
Parameters
argsIEnumerable<IntExpr>Array of integer expressions to compute minimum of.
Returns
- IntExpr
The resulting integer expression
Remarks
Absent arguments are ignored as if they were not specified in the input array args. Minimum of an empty set (i.e. min([])) is absent. The minimum is absent also if all arguments are absent.
Note that binary function Model.Min2 handles absent values differently. For example, when x is absent then:
min2(x, 5)is absent.min([x, 5])is 5.min([x])is absent.
Example:
tasks starts, i.e. the minimum of the starting times.
var model = new Model();
var tasks = Enumerable.Range(0, 5)
.Select(i => model.IntervalVar(length: 10, name: $"task_{i}")).ToArray();
// Create an array of start times of the tasks:
var startTimes = tasks.Select(t => t.Start());
var firstStartTime = model.Min(startTimes);
Notice that when a task is absent (not executed), its end time is absent. And therefore, the absent task is not included in the minimum.
See also:
- Model.Min2
- Model.Span — constraints interval variable to start and end at minimum and maximum of the given set of intervals.
Min(IEnumerable<object>)
Creates an integer expression for the minimum of the arguments.
public IntExpr Min(IEnumerable<object> args)
Parameters
argsIEnumerable<object>Array of integer expressions to compute minimum of.
Returns
- IntExpr
The resulting integer expression
Remarks
Absent arguments are ignored as if they were not specified in the input array args. Minimum of an empty set (i.e. min([])) is absent. The minimum is absent also if all arguments are absent.
Note that binary function Model.Min2 handles absent values differently. For example, when x is absent then:
min2(x, 5)is absent.min([x, 5])is 5.min([x])is absent.
Example:
tasks starts, i.e. the minimum of the starting times.
var model = new Model();
var tasks = Enumerable.Range(0, 5)
.Select(i => model.IntervalVar(length: 10, name: $"task_{i}")).ToArray();
// Create an array of start times of the tasks:
var startTimes = tasks.Select(t => t.Start());
var firstStartTime = model.Min(startTimes);
Notice that when a task is absent (not executed), its end time is absent. And therefore, the absent task is not included in the minimum.
See also:
- Model.Min2
- Model.Span — constraints interval variable to start and end at minimum and maximum of the given set of intervals.
Min2(IntExpr, IntExpr)
Creates an integer expression which is the minimum of lhs and rhs.
public IntExpr Min2(IntExpr lhs, IntExpr rhs)
Parameters
Returns
- IntExpr
The resulting integer expression
Remarks
If one of the arguments has value absent, then the resulting expression also has value absent.
Same as IntExpr.Min2. See Model.Min for n-ary minimum.
Min2(IntExpr, int)
Creates an integer expression which is the minimum of lhs and rhs.
public IntExpr Min2(IntExpr lhs, int rhs)
Parameters
Returns
- IntExpr
The resulting integer expression
Remarks
If one of the arguments has value absent, then the resulting expression also has value absent.
Same as IntExpr.Min2. See Model.Min for n-ary minimum.
Min2(int, IntExpr)
Creates an integer expression which is the minimum of lhs and rhs.
public IntExpr Min2(int lhs, IntExpr rhs)
Parameters
Returns
- IntExpr
The resulting integer expression
Remarks
If one of the arguments has value absent, then the resulting expression also has value absent.
Same as IntExpr.Min2. See Model.Min for n-ary minimum.
Minimize(IntExpr)
Creates a minimization objective for the provided expression.
public Objective Minimize(IntExpr expr)
Parameters
exprIntExprThe expression to minimize
Returns
- Objective
An Objective that minimizes the expression.
Remarks
Creates an Objective to minimize the given expression. A model can have at most one objective. New objective replaces the old one.
Equivalent of function IntExpr.Minimize.
Example:
x and y:
var model = new Model();
var x = model.IntervalVar(length: 10, name: "x");
var y = model.IntervalVar(length: 20, name: "y");
model.Minimize(model.Max2(x.End(), y.End()));
var result = model.Solve();
See also:
- Model.Maximize
- IntExpr.Minimize — for fluent-style minimization.
Minimize(int)
Creates a minimization objective for the provided expression.
public Objective Minimize(int value)
Parameters
valueint
Returns
- Objective
An Objective that minimizes the expression.
Remarks
Creates an Objective to minimize the given expression. A model can have at most one objective. New objective replaces the old one.
Equivalent of function IntExpr.Minimize.
Example:
x and y:
var model = new Model();
var x = model.IntervalVar(length: 10, name: "x");
var y = model.IntervalVar(length: 20, name: "y");
model.Minimize(model.Max2(x.End(), y.End()));
var result = model.Solve();
See also:
- Model.Maximize
- IntExpr.Minimize — for fluent-style minimization.
NoOverlap(SequenceVar, IEnumerable<IEnumerable<int>>?)
Constrain a set of interval variables not to overlap.
public Constraint NoOverlap(SequenceVar sequence, IEnumerable<IEnumerable<int>>? transitions = null)
Parameters
sequenceSequenceVartransitionsIEnumerable<IEnumerable<int>>A 2D square array of minimum transition times between the intervals
Returns
- Constraint
The no-overlap constraint.
Remarks
This function constrains a set of interval variables so they do not overlap.
That is, for each pair of interval variables x and y, one of the
following must hold:
- Interval variable
xoryis absent. In this case, the absent interval is not scheduled (the task is not performed), so it cannot overlap with any other interval. Only optional interval variables can be absent. - Interval variable
xis beforey, that is,x.end()is less than or equal toy.start(). - The interval variable
yis beforex. That is,y.end()is less than or equal tox.start().
The function can also take a square array transitions of minimum
transition times between the intervals. The transition time is the time
that must elapse between the end of the first interval and the start of the
second interval. The transition time cannot be negative. When transition
times are specified, the above conditions 2 and 3 are modified as follows:
x.end() + transitions[i][j]is less than or equal toy.start().y.end() + transitions[j][i]is less than or equal tox.start().
Where i and j are types of x and y. When an array of intervals is passed,
the type of each interval is its index in the array.
Note that minimum transition times are enforced between all pairs of intervals, not only between direct neighbors.
Instead of an array of interval variables, a SequenceVar can be passed. See Model.SequenceVar for how to assign types to intervals in a sequence.
Example:
Let's consider a set of tasks that must be performed by a single machine. The machine can handle only one task at a time. Each task is characterized by its length and a deadline. The goal is to schedule the tasks on the machine so that the number of missed deadlines is minimized.
var tasks = new[] {
new { length = 10, deadline = 70 },
new { length = 20, deadline = 50 },
new { length = 15, deadline = 50 },
new { length = 30, deadline = 100 },
new { length = 20, deadline = 120 },
new { length = 25, deadline = 90 },
new { length = 30, deadline = 80 },
new { length = 10, deadline = 40 },
new { length = 20, deadline = 60 },
new { length = 25, deadline = 150 },
};
var model = new Model();
// An interval variable for each task:
var taskVars = new List<IntervalVar>();
// A boolean expression that is true if the task is late:
var isLate = new List<BoolExpr>();
for (int i = 0; i < tasks.Length; i++) {
var taskVar = model.IntervalVar(name: $"Task{i}", length: tasks[i].length);
taskVars.Add(taskVar);
isLate.Add(taskVar.End() >= tasks[i].deadline);
}
// Tasks cannot overlap:
model.NoOverlap(taskVars);
// Minimize the number of late tasks:
model.Minimize(model.Sum(isLate));
var result = model.Solve();
See also:
- SequenceVar.NoOverlap — is the equivalent method on SequenceVar.
NoOverlap(IEnumerable<IntervalVar>, IEnumerable<IEnumerable<int>>?)
Constrain a set of interval variables not to overlap.
public Constraint NoOverlap(IEnumerable<IntervalVar> intervals, IEnumerable<IEnumerable<int>>? transitions = null)
Parameters
intervalsIEnumerable<IntervalVar>An array of interval variables or a sequence variable to constrain
transitionsIEnumerable<IEnumerable<int>>A 2D square array of minimum transition times between the intervals
Returns
- Constraint
The no-overlap constraint.
Remarks
This function constrains a set of interval variables so they do not overlap.
That is, for each pair of interval variables x and y, one of the
following must hold:
- Interval variable
xoryis absent. In this case, the absent interval is not scheduled (the task is not performed), so it cannot overlap with any other interval. Only optional interval variables can be absent. - Interval variable
xis beforey, that is,x.end()is less than or equal toy.start(). - The interval variable
yis beforex. That is,y.end()is less than or equal tox.start().
The function can also take a square array transitions of minimum
transition times between the intervals. The transition time is the time
that must elapse between the end of the first interval and the start of the
second interval. The transition time cannot be negative. When transition
times are specified, the above conditions 2 and 3 are modified as follows:
x.end() + transitions[i][j]is less than or equal toy.start().y.end() + transitions[j][i]is less than or equal tox.start().
Where i and j are types of x and y. When an array of intervals is passed,
the type of each interval is its index in the array.
Note that minimum transition times are enforced between all pairs of intervals, not only between direct neighbors.
Instead of an array of interval variables, a SequenceVar can be passed. See Model.SequenceVar for how to assign types to intervals in a sequence.
Example:
Let's consider a set of tasks that must be performed by a single machine. The machine can handle only one task at a time. Each task is characterized by its length and a deadline. The goal is to schedule the tasks on the machine so that the number of missed deadlines is minimized.
var tasks = new[] {
new { length = 10, deadline = 70 },
new { length = 20, deadline = 50 },
new { length = 15, deadline = 50 },
new { length = 30, deadline = 100 },
new { length = 20, deadline = 120 },
new { length = 25, deadline = 90 },
new { length = 30, deadline = 80 },
new { length = 10, deadline = 40 },
new { length = 20, deadline = 60 },
new { length = 25, deadline = 150 },
};
var model = new Model();
// An interval variable for each task:
var taskVars = new List<IntervalVar>();
// A boolean expression that is true if the task is late:
var isLate = new List<BoolExpr>();
for (int i = 0; i < tasks.Length; i++) {
var taskVar = model.IntervalVar(name: $"Task{i}", length: tasks[i].length);
taskVars.Add(taskVar);
isLate.Add(taskVar.End() >= tasks[i].deadline);
}
// Tasks cannot overlap:
model.NoOverlap(taskVars);
// Minimize the number of late tasks:
model.Minimize(model.Sum(isLate));
var result = model.Solve();
See also:
- SequenceVar.NoOverlap — is the equivalent method on SequenceVar.
Not(BoolExpr)
Negation of the boolean expression arg.
public BoolExpr Not(BoolExpr arg)
Parameters
Returns
- BoolExpr
The resulting Boolean expression
Remarks
If the argument has value absent then the resulting expression has also value absent.
Same as BoolExpr.Not.
Not(bool)
Negation of the boolean expression arg.
public BoolExpr Not(bool arg)
Parameters
Returns
- BoolExpr
The resulting Boolean expression
Remarks
If the argument has value absent then the resulting expression has also value absent.
Same as BoolExpr.Not.
Or(BoolExpr, BoolExpr)
Logical OR of boolean expressions lhs and rhs.
public BoolExpr Or(BoolExpr lhs, BoolExpr rhs)
Parameters
Returns
- BoolExpr
The resulting Boolean expression
Remarks
If one of the arguments has value absent, then the resulting expression also has value absent.
Same as BoolExpr.Or.
Or(BoolExpr, bool)
Logical OR of boolean expressions lhs and rhs.
public BoolExpr Or(BoolExpr lhs, bool rhs)
Parameters
Returns
- BoolExpr
The resulting Boolean expression
Remarks
If one of the arguments has value absent, then the resulting expression also has value absent.
Same as BoolExpr.Or.
Or(bool, BoolExpr)
Logical OR of boolean expressions lhs and rhs.
public BoolExpr Or(bool lhs, BoolExpr rhs)
Parameters
Returns
- BoolExpr
The resulting Boolean expression
Remarks
If one of the arguments has value absent, then the resulting expression also has value absent.
Same as BoolExpr.Or.
Position(IntervalVar, SequenceVar)
Creates an expression equal to the position of the interval on the sequence.
public IntExpr Position(IntervalVar interval, SequenceVar sequence)
Parameters
intervalIntervalVarThe interval variable.
sequenceSequenceVarThe sequence variable.
Returns
- IntExpr
The resulting integer expression
Remarks
In the solution, the interval which is scheduled first has position 0, the second interval has position 1, etc. The position of an absent interval is absent.
The position expression cannot be used with interval variables of possibly zero length (because the position of two simultaneous zero-length intervals would be undefined). Also, position cannot be used in case of Model.NoOverlap constraint with transition times.
See also:
- IntervalVar.Position — is equivalent function on IntervalVar.
- Model.NoOverlap — for constraints on overlapping intervals.
- Model.SequenceVar — for creating sequence variables.
Presence(IntExpr)
Creates a boolean expression that is true if the given argument is present in the solution.
public BoolExpr Presence(IntExpr expr)
Parameters
exprIntExpr
Returns
- BoolExpr
A boolean expression that is true if the argument is present in the solution.
Remarks
The value of the expression remains unknown until a solution is found. The expression can be used in a constraint to restrict possible solutions.
The function is equivalent to IntervalVar.Presence and IntExpr.Presence.
Example:
x and y must have the same presence status.
I.e. they must either be both *present* or both *absent*.
var model = new Model();
var x = model.IntervalVar(name: "x", optional: true, length: 10, start: (0, 100));
var y = model.IntervalVar(name: "y", optional: true, length: 10, start: (0, 100));
model.Enforce(model.Presence(x) == model.Presence(y));
Simple constraints over presence
The solver treats binary constraints over presence in a special way: it
uses them to better propagate other constraints over the same pairs of variables.
Let's extend the previous example by a constraint that x must end before
y starts:
var x = model.IntervalVar(name: "x", optional: true, length: 10, start: (0, 100));
var y = model.IntervalVar(name: "y", optional: true, length: 10, start: (0, 100));
model.Enforce(model.Presence(x) == model.Presence(y));
// x.end <= y.start:
var precedence = x.End() <= y.Start();
model.Enforce(precedence);
In this example, the solver sees (propagates) that the minimum start time of
y is 10 and maximum end time of x is 90. Without the constraint over
presence, the solver could not propagate that because one
of the intervals can be absent and the other one present (and so the
value of precedence would be absent and the constraint would be
satisfied).
To achieve good propagation, it is recommended to use binary
constraints over presence when possible. For example, multiple binary
constraints can be used instead of a single complicated constraint.
Presence(IntervalVar)
Creates a boolean expression that is true if the given argument is present in the solution.
public BoolExpr Presence(IntervalVar arg)
Parameters
argIntervalVarThe argument to check for presence in the solution
Returns
- BoolExpr
A boolean expression that is true if the argument is present in the solution.
Remarks
The value of the expression remains unknown until a solution is found. The expression can be used in a constraint to restrict possible solutions.
The function is equivalent to IntervalVar.Presence and IntExpr.Presence.
Example:
x and y must have the same presence status.
I.e. they must either be both *present* or both *absent*.
var model = new Model();
var x = model.IntervalVar(name: "x", optional: true, length: 10, start: (0, 100));
var y = model.IntervalVar(name: "y", optional: true, length: 10, start: (0, 100));
model.Enforce(model.Presence(x) == model.Presence(y));
Simple constraints over presence
The solver treats binary constraints over presence in a special way: it
uses them to better propagate other constraints over the same pairs of variables.
Let's extend the previous example by a constraint that x must end before
y starts:
var x = model.IntervalVar(name: "x", optional: true, length: 10, start: (0, 100));
var y = model.IntervalVar(name: "y", optional: true, length: 10, start: (0, 100));
model.Enforce(model.Presence(x) == model.Presence(y));
// x.end <= y.start:
var precedence = x.End() <= y.Start();
model.Enforce(precedence);
In this example, the solver sees (propagates) that the minimum start time of
y is 10 and maximum end time of x is 90. Without the constraint over
presence, the solver could not propagate that because one
of the intervals can be absent and the other one present (and so the
value of precedence would be absent and the constraint would be
satisfied).
To achieve good propagation, it is recommended to use binary
constraints over presence when possible. For example, multiple binary
constraints can be used instead of a single complicated constraint.
Presence(int)
Creates a boolean expression that is true if the given argument is present in the solution.
public BoolExpr Presence(int value)
Parameters
valueint
Returns
- BoolExpr
A boolean expression that is true if the argument is present in the solution.
Remarks
The value of the expression remains unknown until a solution is found. The expression can be used in a constraint to restrict possible solutions.
The function is equivalent to IntervalVar.Presence and IntExpr.Presence.
Example:
x and y must have the same presence status.
I.e. they must either be both *present* or both *absent*.
var model = new Model();
var x = model.IntervalVar(name: "x", optional: true, length: 10, start: (0, 100));
var y = model.IntervalVar(name: "y", optional: true, length: 10, start: (0, 100));
model.Enforce(model.Presence(x) == model.Presence(y));
Simple constraints over presence
The solver treats binary constraints over presence in a special way: it
uses them to better propagate other constraints over the same pairs of variables.
Let's extend the previous example by a constraint that x must end before
y starts:
var x = model.IntervalVar(name: "x", optional: true, length: 10, start: (0, 100));
var y = model.IntervalVar(name: "y", optional: true, length: 10, start: (0, 100));
model.Enforce(model.Presence(x) == model.Presence(y));
// x.end <= y.start:
var precedence = x.End() <= y.Start();
model.Enforce(precedence);
In this example, the solver sees (propagates) that the minimum start time of
y is 10 and maximum end time of x is 90. Without the constraint over
presence, the solver could not propagate that because one
of the intervals can be absent and the other one present (and so the
value of precedence would be absent and the constraint would be
satisfied).
To achieve good propagation, it is recommended to use binary
constraints over presence when possible. For example, multiple binary
constraints can be used instead of a single complicated constraint.
Pulse(IntervalVar, IntExpr)
Creates cumulative function (expression) pulse for the given interval variable and height.
public CumulExpr Pulse(IntervalVar interval, IntExpr height)
Parameters
intervalIntervalVarThe interval variable.
heightIntExprThe height value.
Returns
- CumulExpr
The resulting cumulative expression
Remarks
Pulse can be used to model a resource requirement during an interval variable. The given amount height of the resource is used throughout the interval (from start to end).
Limitation: The height must be non-negative. Pulses with negative height are not supported. If you need negative contributions, use step functions instead (see Model.StepAtStart and Model.StepAtEnd).
Formal definition
Pulse creates a cumulative function which has the value:
0beforeinterval.start(),heightbetweeninterval.start()andinterval.end(),0afterinterval.end()
If interval is absent, the pulse is 0 everywhere.
The height can be a constant value or an expression. In particular, the height can be given by an IntVar. In such a case, the height is unknown at the time of the model creation but is determined during the search.
Note that the interval and the height may have different presence statuses (when the height is given by a variable or an expression). In this case, the pulse is present only if both the interval and the height are present. Therefore, it is helpful to constrain the height to have the same presence status as the interval.
Cumulative functions can be combined using operators (+, -, unary -) and Model.Sum. A cumulative function's minimum and maximum height can be constrained using comparison operators (<=, >=).
Example:
demand). Our goal is to schedule the tasks so that the length of the schedule (makespan) is minimal.
// The input data:
int nbWorkers = 3;
var tasks = new[] {
new { length = 10, demand = 3 },
new { length = 20, demand = 2 },
new { length = 15, demand = 1 },
new { length = 30, demand = 2 },
new { length = 20, demand = 1 },
new { length = 25, demand = 2 },
new { length = 10, demand = 1 },
};
var model = new Model();
// A set of pulses, one for each task:
var pulses = new List<CumulExpr>();
// End times of the tasks:
var ends = new List<IntExpr>();
for (int i = 0; i < tasks.Length; i++) {
// Create a task:
var task = model.IntervalVar(name: $"T{i + 1}", length: tasks[i].length);
// Create a pulse for the task:
pulses.Add(model.Pulse(task, tasks[i].demand));
// Store the end of the task:
ends.Add(task.End());
}
// The number of workers used at any time cannot exceed nbWorkers:
model.Enforce(model.Sum(pulses) <= nbWorkers);
// Minimize the maximum of the ends (makespan):
model.Minimize(model.Max(ends));
var result = model.Solve(new Parameters { searchType = "FDS" });
Example:
x, y, and z that represent some tasks. Variables x and y are present, but variable z is optional. Each task requires a certain number of workers. The length of the task depends on the assigned number of workers. The number of assigned workers is modeled using integer variables wx, wy, and wz.
There are 7 workers. Therefore, at any time, the sum of the workers assigned to the running tasks must be less or equal to 7.
If the task z is absent, then the variable wz has no meaning, and therefore, it should also be absent.
var model = new Model();
var x = model.IntervalVar(name: "x");
var y = model.IntervalVar(name: "y");
var z = model.IntervalVar(name: "z", optional: true);
var wx = model.IntVar(min: 1, max: 5, name: "wx");
var wy = model.IntVar(min: 1, max: 5, name: "wy");
var wz = model.IntVar(min: 1, max: 5, name: "wz", optional: true);
// wz is present if and only if z is present:
model.Enforce(z.Presence() == wz.Presence());
var px = model.Pulse(x, wx);
var py = model.Pulse(y, wy);
var pz = model.Pulse(z, wz);
// There are at most 7 workers at any time:
model.Enforce(model.Sum(new[] { px, py, pz }) <= 7);
// Length of the task depends on the number of workers using the following formula:
// length * wx = 12
model.Enforce(x.Length() * wx == 12);
model.Enforce(y.Length() * wy == 12);
model.Enforce(z.Length() * wz == 12);
See also:
- IntervalVar.Pulse — is equivalent function on IntervalVar.
- Model.StepAtStart — for other basic cumulative functions.
- Model.StepAtEnd — for other basic cumulative functions.
- Model.StepAt — for other basic cumulative functions.
- CumulExpr — for constraining cumulative functions using comparison operators (
<=,>=).
Pulse(IntervalVar, int)
Creates cumulative function (expression) pulse for the given interval variable and height.
public CumulExpr Pulse(IntervalVar interval, int height)
Parameters
intervalIntervalVarThe interval variable.
heightintThe height value.
Returns
- CumulExpr
The resulting cumulative expression
Remarks
Pulse can be used to model a resource requirement during an interval variable. The given amount height of the resource is used throughout the interval (from start to end).
Limitation: The height must be non-negative. Pulses with negative height are not supported. If you need negative contributions, use step functions instead (see Model.StepAtStart and Model.StepAtEnd).
Formal definition
Pulse creates a cumulative function which has the value:
0beforeinterval.start(),heightbetweeninterval.start()andinterval.end(),0afterinterval.end()
If interval is absent, the pulse is 0 everywhere.
The height can be a constant value or an expression. In particular, the height can be given by an IntVar. In such a case, the height is unknown at the time of the model creation but is determined during the search.
Note that the interval and the height may have different presence statuses (when the height is given by a variable or an expression). In this case, the pulse is present only if both the interval and the height are present. Therefore, it is helpful to constrain the height to have the same presence status as the interval.
Cumulative functions can be combined using operators (+, -, unary -) and Model.Sum. A cumulative function's minimum and maximum height can be constrained using comparison operators (<=, >=).
Example:
demand). Our goal is to schedule the tasks so that the length of the schedule (makespan) is minimal.
// The input data:
int nbWorkers = 3;
var tasks = new[] {
new { length = 10, demand = 3 },
new { length = 20, demand = 2 },
new { length = 15, demand = 1 },
new { length = 30, demand = 2 },
new { length = 20, demand = 1 },
new { length = 25, demand = 2 },
new { length = 10, demand = 1 },
};
var model = new Model();
// A set of pulses, one for each task:
var pulses = new List<CumulExpr>();
// End times of the tasks:
var ends = new List<IntExpr>();
for (int i = 0; i < tasks.Length; i++) {
// Create a task:
var task = model.IntervalVar(name: $"T{i + 1}", length: tasks[i].length);
// Create a pulse for the task:
pulses.Add(model.Pulse(task, tasks[i].demand));
// Store the end of the task:
ends.Add(task.End());
}
// The number of workers used at any time cannot exceed nbWorkers:
model.Enforce(model.Sum(pulses) <= nbWorkers);
// Minimize the maximum of the ends (makespan):
model.Minimize(model.Max(ends));
var result = model.Solve(new Parameters { searchType = "FDS" });
Example:
x, y, and z that represent some tasks. Variables x and y are present, but variable z is optional. Each task requires a certain number of workers. The length of the task depends on the assigned number of workers. The number of assigned workers is modeled using integer variables wx, wy, and wz.
There are 7 workers. Therefore, at any time, the sum of the workers assigned to the running tasks must be less or equal to 7.
If the task z is absent, then the variable wz has no meaning, and therefore, it should also be absent.
var model = new Model();
var x = model.IntervalVar(name: "x");
var y = model.IntervalVar(name: "y");
var z = model.IntervalVar(name: "z", optional: true);
var wx = model.IntVar(min: 1, max: 5, name: "wx");
var wy = model.IntVar(min: 1, max: 5, name: "wy");
var wz = model.IntVar(min: 1, max: 5, name: "wz", optional: true);
// wz is present if and only if z is present:
model.Enforce(z.Presence() == wz.Presence());
var px = model.Pulse(x, wx);
var py = model.Pulse(y, wy);
var pz = model.Pulse(z, wz);
// There are at most 7 workers at any time:
model.Enforce(model.Sum(new[] { px, py, pz }) <= 7);
// Length of the task depends on the number of workers using the following formula:
// length * wx = 12
model.Enforce(x.Length() * wx == 12);
model.Enforce(y.Length() * wy == 12);
model.Enforce(z.Length() * wz == 12);
See also:
- IntervalVar.Pulse — is equivalent function on IntervalVar.
- Model.StepAtStart — for other basic cumulative functions.
- Model.StepAtEnd — for other basic cumulative functions.
- Model.StepAt — for other basic cumulative functions.
- CumulExpr — for constraining cumulative functions using comparison operators (
<=,>=).
SequenceVar(IEnumerable<IntervalVar>, IEnumerable<int>?, string?)
Creates a sequence variable from the provided set of interval variables.
public SequenceVar SequenceVar(IEnumerable<IntervalVar> intervals, IEnumerable<int>? types = null, string? name = null)
Parameters
intervalsIEnumerable<IntervalVar>Interval variables that will form the sequence in the solution
typesIEnumerable<int>Types of the intervals, used in particular for transition times
namestringName assigned to the sequence variable
Returns
- SequenceVar
The created sequence variable
Remarks
Sequence variable is used together with SequenceVar.NoOverlap constraint to model a set of intervals that cannot overlap and so they form a sequence in the solution. Sequence variable allows us to constrain the sequence further. For example, by specifying sequence-dependent minimum transition times.
Types can be used to mark intervals with similar properties. In
particular, they behave similarly in terms of transition times.
Interval variable intervals[0] will have type type[0], intervals[1]
will have type type[1] and so on.
If types are not specified then intervals[0] will have type 0,
intervals[1] will have type 1, and so on.
The length of the array types must be the same as the length of the array
intervals. Types should be integer numbers in the range 0 to n-1 where n is the
number of types.
See also:
- SequenceVar.NoOverlap — for an example of sequenceVar usage with transition times.
- SequenceVar
- Model.NoOverlap
Solve(Parameters?, Solution?)
Solves the model and returns the result.
public SolveResult Solve(Parameters? parameters = null, Solution? warmStart = null)
Parameters
parametersParametersThe parameters for solving
warmStartSolutionThe solution to start with
Returns
- SolveResult
The result of the solve.
Remarks
Solves the model using the OptalCP solver and returns the result. This is the main entry point for solving constraint programming models.
The solver searches for solutions that satisfy all constraints in the model. If an objective was specified (using Model.Minimize or Model.Maximize), the solver searches for optimal or near-optimal solutions within the given time limit.
The returned SolveResult contains:
solution- The best solution found, orNoneif no solution was found. Use this to query variable values via methods likeget_start(),get_end(), andget_value().objective- The objective value of the best solution (if an objective was specified).nb_solutions- The total number of solutions found during the search.proof- Whether the solver proved optimality or infeasibility.duration- The total time spent solving.- Statistics like
nb_branches,nb_fails, andnb_restarts.
When an error occurs (e.g., invalid model, solver not found), the function raises an exception.
Parameters
Solver behavior can be controlled via the parameters argument. Common parameters
include:
timeLimit- Maximum solving time in seconds.solutionLimit- Stop after finding this many solutions.nbWorkers- Number of parallel threads to use.searchType- Search strategy ("LNS","FDS", etc.).
See Parameters for the complete list.
Warm start
If the warm_start parameter is specified, the solver will start with the
given solution. The solution must be compatible with the model; otherwise,
an error will be raised. The solver will take advantage of the
solution to speed up the search: it will search only for better solutions
(if it is a minimization or maximization problem). The solver may also try to
improve the provided solution by Large Neighborhood Search.
Advanced usage
This is a simple blocking function for basic usage. For advanced features like event callbacks, progress monitoring, or async support, use the Solver class instead.
This method works seamlessly in both regular Python scripts and Jupyter notebooks. In Jupyter (where an event loop is already running), it automatically handles nested event loops.
var model = new Model();
var x = model.IntervalVar(length: 10, name: "task_x");
var y = model.IntervalVar(length: 20, name: "task_y");
x.EndBeforeStart(y);
model.Minimize(y.End());
// Basic solve
var result = model.Solve();
Console.WriteLine($"Objective: {result.objective}");
// Solve with parameters
var parameters = new Parameters { timeLimit = 60, searchType = "LNS" };
result = model.Solve(parameters);
// Solve with warm start
if (result.solution != null) {
var result2 = model.Solve(parameters, result.solution);
}
See also:
- Solver — for async solving with event callbacks.
- Parameters — for available solver parameters.
- SolveResult — for the result structure.
- Solution — for working with solutions.
Span(IntervalVar, IEnumerable<IntervalVar>)
Constrains an interval variable to span (cover) a set of other interval variables.
public Constraint Span(IntervalVar main, IEnumerable<IntervalVar> covered)
Parameters
mainIntervalVarThe spanning interval variable.
coveredIEnumerable<IntervalVar>The set of interval variables to cover.
Returns
- Constraint
The span constraint.
Remarks
Span constraint can be used to model, for example, a composite task that consists of several subtasks.
The constraint makes sure that interval variable main starts with the first interval in covered and ends with the last interval in covered. Absent interval variables in covered are ignored.
Formal definition
Span constraint is satisfied in one of the following two cases:
Interval variable
mainis absent and all interval variables incoveredare absent too.Interval variable
mainis present, at least one interval incoveredis present and:main.start()is equal to the minimum starting time of all present intervals incovered.main.end()is equal to the maximum ending time of all present intervals incovered.
Example:
T, which consists of 3 subtasks: T1, T2, and T3. Subtasks are independent, could be processed in any order, and may overlap. However, task T is blocking a particular location, and no other task can be processed there. The location is blocked as soon as the first task from T1, T2, T3 starts, and it remains blocked until the last one of them finishes.
var model = new Model();
// Subtasks have known lengths:
var T1 = model.IntervalVar(name: "T1", length: 10);
var T2 = model.IntervalVar(name: "T2", length: 5);
var T3 = model.IntervalVar(name: "T3", length: 15);
// The main task has unknown length though:
var T = model.IntervalVar(name: "T");
// T spans/covers T1, T2 and T3:
model.Span(T, new[] { T1, T2, T3 });
// Tasks requiring the same location cannot overlap.
// Other tasks are not included in the example, therefore '...' below:
model.NoOverlap(new[] { T /* ... other tasks sharing the same location */ });
See also:
- IntervalVar.Span — is equivalent function on IntervalVar.
Start(IntervalVar)
Creates an integer expression for the start time of an interval variable.
public IntExpr Start(IntervalVar interval)
Parameters
intervalIntervalVarThe interval variable.
Returns
- IntExpr
The resulting integer expression
Remarks
If the interval is absent, the resulting expression is also absent.
Example:
y to start after the end of x with a delay of at least 10. In addition, we constrain the length of x to be less or equal to the length of y.
var model = new Model();
var x = model.IntervalVar(name: "x");
var y = model.IntervalVar(name: "y");
model.Enforce(model.End(x) + 10 <= model.Start(y));
model.Enforce(model.Length(x) <= model.Length(y));
When x or y is absent then value of both constraints above is absent and therefore they are satisfied.
See also:
- IntervalVar.Start — is equivalent function on IntervalVar.
StartAtEnd(IntervalVar, IntervalVar, IntExpr)
Creates a precedence constraint between two interval variables.
public Constraint StartAtEnd(IntervalVar predecessor, IntervalVar successor, IntExpr delay)
Parameters
predecessorIntervalVarThe predecessor interval variable.
successorIntervalVarThe successor interval variable.
delayIntExprThe minimum delay between intervals.
Returns
- Constraint
The precedence constraint.
Remarks
Same as:
model.Enforce(predecessor.Start() + delay == successor.End());
In other words, start of predecessor plus delay must be equal to end of successor.
When one of the two interval variables is absent, then the constraint is satisfied.
See also:
- IntervalVar.StartAtEnd — is equivalent function on IntervalVar.
- IntervalVar.Start
- IntervalVar.End
StartAtEnd(IntervalVar, IntervalVar, int)
Creates a precedence constraint between two interval variables.
public Constraint StartAtEnd(IntervalVar predecessor, IntervalVar successor, int delay = 0)
Parameters
predecessorIntervalVarThe predecessor interval variable.
successorIntervalVarThe successor interval variable.
delayintThe minimum delay between intervals.
Returns
- Constraint
The precedence constraint.
Remarks
Same as:
model.Enforce(predecessor.Start() + delay == successor.End());
In other words, start of predecessor plus delay must be equal to end of successor.
When one of the two interval variables is absent, then the constraint is satisfied.
See also:
- IntervalVar.StartAtEnd — is equivalent function on IntervalVar.
- IntervalVar.Start
- IntervalVar.End
StartAtStart(IntervalVar, IntervalVar, IntExpr)
Creates a precedence constraint between two interval variables.
public Constraint StartAtStart(IntervalVar predecessor, IntervalVar successor, IntExpr delay)
Parameters
predecessorIntervalVarThe predecessor interval variable.
successorIntervalVarThe successor interval variable.
delayIntExprThe minimum delay between intervals.
Returns
- Constraint
The precedence constraint.
Remarks
Same as:
model.Enforce(predecessor.Start() + delay == successor.Start());
In other words, start of predecessor plus delay must be equal to start of successor.
When one of the two interval variables is absent, then the constraint is satisfied.
See also:
- IntervalVar.StartAtStart — is equivalent function on IntervalVar.
- IntervalVar.Start
- IntervalVar.End
StartAtStart(IntervalVar, IntervalVar, int)
Creates a precedence constraint between two interval variables.
public Constraint StartAtStart(IntervalVar predecessor, IntervalVar successor, int delay = 0)
Parameters
predecessorIntervalVarThe predecessor interval variable.
successorIntervalVarThe successor interval variable.
delayintThe minimum delay between intervals.
Returns
- Constraint
The precedence constraint.
Remarks
Same as:
model.Enforce(predecessor.Start() + delay == successor.Start());
In other words, start of predecessor plus delay must be equal to start of successor.
When one of the two interval variables is absent, then the constraint is satisfied.
See also:
- IntervalVar.StartAtStart — is equivalent function on IntervalVar.
- IntervalVar.Start
- IntervalVar.End
StartBeforeEnd(IntervalVar, IntervalVar, IntExpr)
Creates a precedence constraint between two interval variables.
public Constraint StartBeforeEnd(IntervalVar predecessor, IntervalVar successor, IntExpr delay)
Parameters
predecessorIntervalVarThe predecessor interval variable.
successorIntervalVarThe successor interval variable.
delayIntExprThe minimum delay between intervals.
Returns
- Constraint
The precedence constraint.
Remarks
Same as:
model.Enforce(predecessor.Start() + delay <= successor.End());
In other words, start of predecessor plus delay must be less than or equal to end of successor.
When one of the two interval variables is absent, then the constraint is satisfied.
See also:
- IntervalVar.StartBeforeEnd — is equivalent function on IntervalVar.
- IntervalVar.Start
- IntervalVar.End
StartBeforeEnd(IntervalVar, IntervalVar, int)
Creates a precedence constraint between two interval variables.
public Constraint StartBeforeEnd(IntervalVar predecessor, IntervalVar successor, int delay = 0)
Parameters
predecessorIntervalVarThe predecessor interval variable.
successorIntervalVarThe successor interval variable.
delayintThe minimum delay between intervals.
Returns
- Constraint
The precedence constraint.
Remarks
Same as:
model.Enforce(predecessor.Start() + delay <= successor.End());
In other words, start of predecessor plus delay must be less than or equal to end of successor.
When one of the two interval variables is absent, then the constraint is satisfied.
See also:
- IntervalVar.StartBeforeEnd — is equivalent function on IntervalVar.
- IntervalVar.Start
- IntervalVar.End
StartBeforeStart(IntervalVar, IntervalVar, IntExpr)
Creates a precedence constraint between two interval variables.
public Constraint StartBeforeStart(IntervalVar predecessor, IntervalVar successor, IntExpr delay)
Parameters
predecessorIntervalVarThe predecessor interval variable.
successorIntervalVarThe successor interval variable.
delayIntExprThe minimum delay between intervals.
Returns
- Constraint
The precedence constraint.
Remarks
Same as:
model.Enforce(predecessor.Start() + delay <= successor.Start());
In other words, start of predecessor plus delay must be less than or equal to start of successor.
When one of the two interval variables is absent, then the constraint is satisfied.
See also:
- IntervalVar.StartBeforeStart — is equivalent function on IntervalVar.
- IntervalVar.Start
- IntervalVar.End
StartBeforeStart(IntervalVar, IntervalVar, int)
Creates a precedence constraint between two interval variables.
public Constraint StartBeforeStart(IntervalVar predecessor, IntervalVar successor, int delay = 0)
Parameters
predecessorIntervalVarThe predecessor interval variable.
successorIntervalVarThe successor interval variable.
delayintThe minimum delay between intervals.
Returns
- Constraint
The precedence constraint.
Remarks
Same as:
model.Enforce(predecessor.Start() + delay <= successor.Start());
In other words, start of predecessor plus delay must be less than or equal to start of successor.
When one of the two interval variables is absent, then the constraint is satisfied.
See also:
- IntervalVar.StartBeforeStart — is equivalent function on IntervalVar.
- IntervalVar.Start
- IntervalVar.End
StepAt(int, IntExpr)
Creates a cumulative function that changes value at a given point.
public CumulExpr StepAt(int x, IntExpr height)
Parameters
xintThe point at which the cumulative function changes value.
heightIntExprThe height value (can be positive, negative, constant, or expression).
Returns
- CumulExpr
The resulting cumulative expression
Remarks
This function is similar to Model.StepAtStart and Model.StepAtEnd, but the time of the change is given by the constant value x instead of by the start/end of an interval variable. The height can be a constant or an expression (e.g., created by Model.IntVar).
Formal definition
stepAt creates a cumulative function which has the value:
- 0 before
x, heightafterx.
See also:
- Model.StepAtStart — for an example with
stepAt. - Model.StepAtEnd — for an example with
stepAt. - CumulExpr — for constraining cumulative functions using comparison operators (
<=,>=).
StepAt(int, int)
Creates a cumulative function that changes value at a given point.
public CumulExpr StepAt(int x, int height)
Parameters
xintThe point at which the cumulative function changes value.
heightintThe height value (can be positive, negative, constant, or expression).
Returns
- CumulExpr
The resulting cumulative expression
Remarks
This function is similar to Model.StepAtStart and Model.StepAtEnd, but the time of the change is given by the constant value x instead of by the start/end of an interval variable. The height can be a constant or an expression (e.g., created by Model.IntVar).
Formal definition
stepAt creates a cumulative function which has the value:
- 0 before
x, heightafterx.
See also:
- Model.StepAtStart — for an example with
stepAt. - Model.StepAtEnd — for an example with
stepAt. - CumulExpr — for constraining cumulative functions using comparison operators (
<=,>=).
StepAtEnd(IntervalVar, IntExpr)
Creates cumulative function (expression) that changes value at end of the interval variable by the given height.
public CumulExpr StepAtEnd(IntervalVar interval, IntExpr height)
Parameters
intervalIntervalVarThe interval variable.
heightIntExprThe height value.
Returns
- CumulExpr
The resulting cumulative expression
Remarks
Cumulative step functions could be used to model a resource that is consumed or produced and, therefore, changes in amount over time. Examples of such a resource are a battery, an account balance, a product's stock, etc.
A stepAtEnd can change the amount of such resource at the end of a given variable. The amount is changed by the given height, which can be positive or negative.
The height can be a constant value or an expression. In particular, the height can be given by an IntVar. In such a case, the height is unknown at the time of the model creation but is determined during the search.
Note that the interval and the height may have different presence statuses (when the height is given by a variable or an expression). In this case, the step is present only if both the interval and the height are present. Therefore, it is helpful to constrain the height to have the same presence status as the interval.
Cumulative steps can be combined using operators (+, -, unary -) and Model.Sum. A cumulative function's minimum and maximum height can be constrained using comparison operators (<=, >=).
Formal definition
stepAtEnd creates a cumulative function which has the value:
0beforeinterval.end(),heightafterinterval.end().
If the interval or the height is absent, the created cumulative function is 0 everywhere.
Example:
budget, and we want to schedule the tasks so that we do not run out of money (i.e., the amount is always non-negative).
Tasks cannot overlap. Our goal is to find the shortest schedule possible.
// The input data:
int budget = 100;
var tasksData = new[] {
(length: 10, money: -150), (length: 20, money: 40),
(length: 15, money: 20), (length: 30, money: -10),
(length: 20, money: 30), (length: 25, money: -20),
(length: 10, money: 10), (length: 20, money: 50),
};
var model = new Model();
var taskVars = new List<IntervalVar>();
var steps = new List<CumulExpr>();
for (int i = 0; i < tasksData.Length; i++) {
var interval = model.IntervalVar(name: $"T{i + 1}", length: tasksData[i].length);
taskVars.Add(interval);
if (tasksData[i].money < 0)
steps.Add(model.StepAtStart(interval, tasksData[i].money));
else
steps.Add(model.StepAtEnd(interval, tasksData[i].money));
}
// The initial budget increases the cumul at time 0:
steps.Add(model.StepAt(0, budget));
// The money must be non-negative at any time:
model.Enforce(model.Sum(steps) >= 0);
// Only one task at a time:
model.NoOverlap(taskVars);
// Minimize the maximum of the ends (makespan):
model.Minimize(model.Max(taskVars.Select(t => t.End())));
var result = model.Solve(new Parameters { searchType = "FDS" });
See also:
- IntervalVar.StepAtEnd — is equivalent function on IntervalVar.
- Model.StepAtStart — for other basic cumulative functions.
- Model.StepAt — for other basic cumulative functions.
- Model.Pulse — for other basic cumulative functions.
- CumulExpr — for constraining cumulative functions using comparison operators (
<=,>=).
StepAtEnd(IntervalVar, int)
Creates cumulative function (expression) that changes value at end of the interval variable by the given height.
public CumulExpr StepAtEnd(IntervalVar interval, int height)
Parameters
intervalIntervalVarThe interval variable.
heightintThe height value.
Returns
- CumulExpr
The resulting cumulative expression
Remarks
Cumulative step functions could be used to model a resource that is consumed or produced and, therefore, changes in amount over time. Examples of such a resource are a battery, an account balance, a product's stock, etc.
A stepAtEnd can change the amount of such resource at the end of a given variable. The amount is changed by the given height, which can be positive or negative.
The height can be a constant value or an expression. In particular, the height can be given by an IntVar. In such a case, the height is unknown at the time of the model creation but is determined during the search.
Note that the interval and the height may have different presence statuses (when the height is given by a variable or an expression). In this case, the step is present only if both the interval and the height are present. Therefore, it is helpful to constrain the height to have the same presence status as the interval.
Cumulative steps can be combined using operators (+, -, unary -) and Model.Sum. A cumulative function's minimum and maximum height can be constrained using comparison operators (<=, >=).
Formal definition
stepAtEnd creates a cumulative function which has the value:
0beforeinterval.end(),heightafterinterval.end().
If the interval or the height is absent, the created cumulative function is 0 everywhere.
Example:
budget, and we want to schedule the tasks so that we do not run out of money (i.e., the amount is always non-negative).
Tasks cannot overlap. Our goal is to find the shortest schedule possible.
// The input data:
int budget = 100;
var tasksData = new[] {
(length: 10, money: -150), (length: 20, money: 40),
(length: 15, money: 20), (length: 30, money: -10),
(length: 20, money: 30), (length: 25, money: -20),
(length: 10, money: 10), (length: 20, money: 50),
};
var model = new Model();
var taskVars = new List<IntervalVar>();
var steps = new List<CumulExpr>();
for (int i = 0; i < tasksData.Length; i++) {
var interval = model.IntervalVar(name: $"T{i + 1}", length: tasksData[i].length);
taskVars.Add(interval);
if (tasksData[i].money < 0)
steps.Add(model.StepAtStart(interval, tasksData[i].money));
else
steps.Add(model.StepAtEnd(interval, tasksData[i].money));
}
// The initial budget increases the cumul at time 0:
steps.Add(model.StepAt(0, budget));
// The money must be non-negative at any time:
model.Enforce(model.Sum(steps) >= 0);
// Only one task at a time:
model.NoOverlap(taskVars);
// Minimize the maximum of the ends (makespan):
model.Minimize(model.Max(taskVars.Select(t => t.End())));
var result = model.Solve(new Parameters { searchType = "FDS" });
See also:
- IntervalVar.StepAtEnd — is equivalent function on IntervalVar.
- Model.StepAtStart — for other basic cumulative functions.
- Model.StepAt — for other basic cumulative functions.
- Model.Pulse — for other basic cumulative functions.
- CumulExpr — for constraining cumulative functions using comparison operators (
<=,>=).
StepAtStart(IntervalVar, IntExpr)
Creates cumulative function (expression) that changes value at start of the interval variable by the given height.
public CumulExpr StepAtStart(IntervalVar interval, IntExpr height)
Parameters
intervalIntervalVarThe interval variable.
heightIntExprThe height value.
Returns
- CumulExpr
The resulting cumulative expression
Remarks
Cumulative step functions could be used to model a resource that is consumed or produced and, therefore, changes in amount over time. Examples of such a resource are a battery, an account balance, a product's stock, etc.
A stepAtStart can change the amount of such resource at the start of a given variable. The amount is changed by the given height, which can be positive or negative.
The height can be a constant value or an expression. In particular, the height can be given by an IntVar. In such a case, the height is unknown at the time of the model creation but is determined during the search.
Note that the interval and the height may have different presence statuses (when the height is given by a variable or an expression). In this case, the step is present only if both the interval and the height are present. Therefore, it is helpful to constrain the height to have the same presence status as the interval.
Cumulative steps can be combined using operators (+, -, unary -) and Model.Sum. A cumulative function's minimum and maximum height can be constrained using comparison operators (<=, >=).
Formal definition
stepAtStart creates a cumulative function which has the value:
0beforeinterval.start(),heightafterinterval.start().
If the interval or the height is absent, the created cumulative function is 0 everywhere.
Example:
budget, and we want to schedule the tasks so that we do not run out of money (i.e., the amount is always non-negative).
Tasks cannot overlap. Our goal is to find the shortest schedule possible.
// The input data:
int budget = 100;
var tasksData = new[] {
(length: 10, money: -150), (length: 20, money: 40),
(length: 15, money: 20), (length: 30, money: -10),
(length: 20, money: 30), (length: 25, money: -20),
(length: 10, money: 10), (length: 20, money: 50),
};
var model = new Model();
var taskVars = new List<IntervalVar>();
var steps = new List<CumulExpr>();
for (int i = 0; i < tasksData.Length; i++) {
var interval = model.IntervalVar(name: $"T{i + 1}", length: tasksData[i].length);
taskVars.Add(interval);
if (tasksData[i].money < 0)
steps.Add(model.StepAtStart(interval, tasksData[i].money));
else
steps.Add(model.StepAtEnd(interval, tasksData[i].money));
}
// The initial budget increases the cumul at time 0:
steps.Add(model.StepAt(0, budget));
// The money must be non-negative at any time:
model.Enforce(model.Sum(steps) >= 0);
// Only one task at a time:
model.NoOverlap(taskVars);
// Minimize the maximum of the ends (makespan):
model.Minimize(model.Max(taskVars.Select(t => t.End())));
var result = model.Solve(new Parameters { searchType = "FDS" });
See also:
- IntervalVar.StepAtStart — is equivalent function on IntervalVar.
- Model.StepAtEnd — for other basic cumulative functions.
- Model.StepAt — for other basic cumulative functions.
- Model.Pulse — for other basic cumulative functions.
- CumulExpr — for constraining cumulative functions using comparison operators (
<=,>=).
StepAtStart(IntervalVar, int)
Creates cumulative function (expression) that changes value at start of the interval variable by the given height.
public CumulExpr StepAtStart(IntervalVar interval, int height)
Parameters
intervalIntervalVarThe interval variable.
heightintThe height value.
Returns
- CumulExpr
The resulting cumulative expression
Remarks
Cumulative step functions could be used to model a resource that is consumed or produced and, therefore, changes in amount over time. Examples of such a resource are a battery, an account balance, a product's stock, etc.
A stepAtStart can change the amount of such resource at the start of a given variable. The amount is changed by the given height, which can be positive or negative.
The height can be a constant value or an expression. In particular, the height can be given by an IntVar. In such a case, the height is unknown at the time of the model creation but is determined during the search.
Note that the interval and the height may have different presence statuses (when the height is given by a variable or an expression). In this case, the step is present only if both the interval and the height are present. Therefore, it is helpful to constrain the height to have the same presence status as the interval.
Cumulative steps can be combined using operators (+, -, unary -) and Model.Sum. A cumulative function's minimum and maximum height can be constrained using comparison operators (<=, >=).
Formal definition
stepAtStart creates a cumulative function which has the value:
0beforeinterval.start(),heightafterinterval.start().
If the interval or the height is absent, the created cumulative function is 0 everywhere.
Example:
budget, and we want to schedule the tasks so that we do not run out of money (i.e., the amount is always non-negative).
Tasks cannot overlap. Our goal is to find the shortest schedule possible.
// The input data:
int budget = 100;
var tasksData = new[] {
(length: 10, money: -150), (length: 20, money: 40),
(length: 15, money: 20), (length: 30, money: -10),
(length: 20, money: 30), (length: 25, money: -20),
(length: 10, money: 10), (length: 20, money: 50),
};
var model = new Model();
var taskVars = new List<IntervalVar>();
var steps = new List<CumulExpr>();
for (int i = 0; i < tasksData.Length; i++) {
var interval = model.IntervalVar(name: $"T{i + 1}", length: tasksData[i].length);
taskVars.Add(interval);
if (tasksData[i].money < 0)
steps.Add(model.StepAtStart(interval, tasksData[i].money));
else
steps.Add(model.StepAtEnd(interval, tasksData[i].money));
}
// The initial budget increases the cumul at time 0:
steps.Add(model.StepAt(0, budget));
// The money must be non-negative at any time:
model.Enforce(model.Sum(steps) >= 0);
// Only one task at a time:
model.NoOverlap(taskVars);
// Minimize the maximum of the ends (makespan):
model.Minimize(model.Max(taskVars.Select(t => t.End())));
var result = model.Solve(new Parameters { searchType = "FDS" });
See also:
- IntervalVar.StepAtStart — is equivalent function on IntervalVar.
- Model.StepAtEnd — for other basic cumulative functions.
- Model.StepAt — for other basic cumulative functions.
- Model.Pulse — for other basic cumulative functions.
- CumulExpr — for constraining cumulative functions using comparison operators (
<=,>=).
StepFunction(IEnumerable<(int, int)>)
Creates a new integer step function.
public IntStepFunction StepFunction(IEnumerable<(int, int)> values)
Parameters
valuesIEnumerable<(int, int)>An array of points defining the step function in the form [[x0, y0], [x1, y1], ..., [xn, yn]], where xi and yi are integers. The array must be sorted by xi
Returns
- IntStepFunction
The created step function
Remarks
Integer step function is a piecewise constant function defined on integer values in range Model.IntVarMin to Model.IntVarMax. The function is defined as follows:
- \(f(x) = 0\) for \(x < x_0\),
- \(f(x) = y_i\) for \(x_i \leq x < x_{i+1}\)
- \(f(x) = y_n\) for \(x \geq x_n\).
Step functions can be used in the following ways:
- Function Model.Eval evaluates the function at the given point (given as IntExpr).
- Function Model.Integral computes a sum (integral) of the function over an IntervalVar.
- Constraints Model.ForbidStart and Model.ForbidEnd forbid the start/end of an IntervalVar to be in a zero-value interval of the function.
- Constraint Model.ForbidExtent forbids the extent of an IntervalVar to be in a zero-value interval of the function.
Sum(IEnumerable<CumulExpr>)
Sum of cumulative expressions.
public CumulExpr Sum(IEnumerable<CumulExpr> args)
Parameters
argsIEnumerable<CumulExpr>Array of cumulative expressions to sum.
Returns
- CumulExpr
The resulting cumulative expression
Remarks
Computes the sum of cumulative functions. The sum can be used, e.g., to combine contributions of individual tasks to total resource consumption.
Limitation: Currently, pulse-based and step-based cumulative expressions cannot be mixed. All expressions in the sum must be either pulse-based or step-based.
Sum(IEnumerable<IntExpr>)
Creates an integer expression for the sum of the arguments.
public IntExpr Sum(IEnumerable<IntExpr> args)
Parameters
argsIEnumerable<IntExpr>Array of integer expressions to sum.
Returns
- IntExpr
The resulting integer expression
Remarks
Absent arguments are ignored (treated as zeros). Therefore, the resulting expression is never absent.
Note that the binary operator + handles absent values differently. For example, when x is absent then:
x + 3is absent.model.Sum(new[] { x, 3 })is 3.
Example:
// Lengths and profits of the tasks:
int[] lengths = { 10, 20, 15, 30, 20, 25, 30, 10, 20, 25 };
int[] profits = { 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
var model = new Model();
var tasks = new List<IntervalVar>();
// Profits of individual tasks. The value will be zero if the task is not executed.
var taskProfits = new List<IntExpr>();
for (int i = 0; i < lengths.Length; i++) {
// All tasks must finish before time 100:
var task = model.IntervalVar(name: $"Task{i}", optional: true, length: lengths[i], end: (null, 100));
tasks.Add(task);
taskProfits.Add(model.Presence(task) * profits[i]);
}
model.Maximize(model.Sum(taskProfits));
// Tasks cannot overlap:
model.NoOverlap(tasks);
var result = model.Solve(new Parameters { searchType = "FDS" });
Sum(IEnumerable<object>)
Creates an integer expression for the sum of the arguments.
public IntExpr Sum(IEnumerable<object> args)
Parameters
argsIEnumerable<object>Array of integer expressions to sum.
Returns
- IntExpr
The resulting integer expression
Remarks
Absent arguments are ignored (treated as zeros). Therefore, the resulting expression is never absent.
Note that the binary operator + handles absent values differently. For example, when x is absent then:
x + 3is absent.model.Sum(new[] { x, 3 })is 3.
Example:
// Lengths and profits of the tasks:
int[] lengths = { 10, 20, 15, 30, 20, 25, 30, 10, 20, 25 };
int[] profits = { 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
var model = new Model();
var tasks = new List<IntervalVar>();
// Profits of individual tasks. The value will be zero if the task is not executed.
var taskProfits = new List<IntExpr>();
for (int i = 0; i < lengths.Length; i++) {
// All tasks must finish before time 100:
var task = model.IntervalVar(name: $"Task{i}", optional: true, length: lengths[i], end: (null, 100));
tasks.Add(task);
taskProfits.Add(model.Presence(task) * profits[i]);
}
model.Maximize(model.Sum(taskProfits));
// Tasks cannot overlap:
model.NoOverlap(tasks);
var result = model.Solve(new Parameters { searchType = "FDS" });
ToJS(Parameters?, Solution?)
Converts the model to equivalent JavaScript code.
public string ToJS(Parameters? parameters = null, Solution? warmStart = null)
Parameters
parametersParametersOptional solver parameters (included in generated code)
warmStartSolutionOptional initial solution to include
Returns
- string
JavaScript code representing the model.
Remarks
The output is human-readable, executable with Node.js, and can be stored in a file. It is meant as a way to export a model to a format that is executable, human-readable, editable, and independent of other libraries.
This feature is experimental and the result is not guaranteed to be valid in all cases.
var model = new Model();
var x = model.IntervalVar(length: 10, name: "task_x");
var y = model.IntervalVar(length: 20, name: "task_y");
x.EndBeforeStart(y);
model.Minimize(y.End());
// Convert to JavaScript code
var jsCode = model.ToJS();
Console.WriteLine(jsCode);
// Save to file
File.WriteAllText("model.js", jsCode);
See also:
- Model.ToText — to export as text format.
- Model.ToJSON — to export as JSON (can be imported back).
ToJSON(Parameters?, Solution?)
Exports the model to JSON format.
public string ToJSON(Parameters? parameters = null, Solution? warmStart = null)
Parameters
parametersParametersOptional solver parameters to include
warmStartSolutionOptional initial solution to include
Returns
- string
A string containing the model in JSON format.
Remarks
The result can be stored in a file for later use. The model can be converted back from JSON format using Model.FromJSON.
var model = new Model();
var x = model.IntervalVar(length: 10, name: "task_x");
var y = model.IntervalVar(length: 20, name: "task_y");
x.EndBeforeStart(y);
model.Minimize(y.End());
// Export to JSON
var jsonStr = model.ToJSON();
// Save to file
File.WriteAllText("model.json", jsonStr);
// Later, load from JSON
var (model2, params2, warmStart2) = Model.FromJSON(jsonStr);
See also:
- Model.FromJSON — to import from JSON.
- Model.ToText — to export as text format.
- Model.ToJS — to export as JavaScript code.
ToText(Parameters?, Solution?)
Converts the model to text format similar to IBM CP Optimizer file format.
public string ToText(Parameters? parameters = null, Solution? warmStart = null)
Parameters
parametersParametersOptional solver parameters (mostly unused)
warmStartSolutionOptional initial solution to include
Returns
- string
Text representation of the model.
Remarks
The output is human-readable and can be stored in a file. Unlike JSON format, there is no way to convert the text format back into a Model.
The result is so similar to the file format used by IBM CP Optimizer that, under some circumstances, the result can be used as an input file for CP Optimizer. However, some differences between OptalCP and CP Optimizer make it impossible to guarantee the result is always valid for CP Optimizer.
Known issues:
- OptalCP supports optional integer expressions, while CP Optimizer does not.
If the model contains optional integer expressions, the result will not be
valid for CP Optimizer or may be badly interpreted. For example, to get
a valid CP Optimizer file, don't use
interval.start(), useinterval.start_or(default)instead. - For the same reason, prefer precedence constraints such as
end_before_start()overmodel.enforce(x.end() <= y.start()). - Negative heights in cumulative expressions (e.g., in
step_at_start()) are not supported by CP Optimizer.
var model = new Model();
var x = model.IntervalVar(length: 10, name: "task_x");
var y = model.IntervalVar(length: 20, name: "task_y");
x.EndBeforeStart(y);
model.Minimize(y.End());
// Convert to text format
var text = model.ToText();
Console.WriteLine(text);
// Save to file
File.WriteAllText("model.txt", text);
See also:
- Model.ToJS — to export as JavaScript code.
- Model.ToJSON — to export as JSON (can be imported back).