Variables

This module provides the core variable types for scheduling models.

Interval Variables

IntervalVar

class pycsp3_scheduling.variables.interval.IntervalVar(name=None, start=<factory>, end=<factory>, size=<factory>, length=None, intensity=None, granularity=1, optional=False, _id=-1)[source]

Bases: object

Represents an interval variable for scheduling.

An interval variable represents a task or activity with a start time, end time, and duration. The interval can be optional (may be absent from the solution).

name

Unique identifier for this interval variable.

Type:

str | None

start

Start time bound as int or (min, max) tuple.

Type:

int | tuple[int, int]

end

End time bound as int or (min, max) tuple.

Type:

int | tuple[int, int]

size

Duration/size bound as int or (min, max) tuple.

Type:

int | tuple[int, int]

length

Length bound (can differ from size with intensity functions).

Type:

int | tuple[int, int] | None

intensity

Stepwise function relating size to length.

Type:

list[tuple[int, int]] | None

granularity

Scale for the intensity function.

Type:

int

optional

If True, the interval may be absent from the solution.

Type:

bool

_id

Internal unique identifier.

Type:

int

Note

When using intensity functions, you should explicitly set length bounds. At lower intensity values, more elapsed time (length) is needed to complete the same amount of work (size). For example, at 50% intensity, a task with size=10 needs length=20. If length is not set, it defaults to size, which may be too restrictive. A warning is issued in this case.

Example

>>> task = IntervalVar(size=10, name="task1")
>>> optional_task = IntervalVar(size=(5, 20), optional=True, name="opt")
>>> bounded_task = IntervalVar(start=(0, 100), end=(10, 200), size=15)
>>> # With intensity: explicitly set length bounds to allow larger values
>>> intensity = [(INTERVAL_MIN, 100), (10, 50)]  # 100% until t=10, then 50%
>>> variable_rate = IntervalVar(
...     size=10,
...     length=(10, 30),  # Allow length up to 30 for lower intensity
...     intensity=intensity,
...     granularity=100,
...     name="variable_rate"
... )
name: str | None = None
start: int | tuple[int, int]
end: int | tuple[int, int]
size: int | tuple[int, int]
length: int | tuple[int, int] | None = None
intensity: list[tuple[int, int]] | None = None
granularity: int = 1
optional: bool = False
__post_init__()[source]

Normalize bounds and assign unique ID.

property start_min: int

Minimum possible start time.

property start_max: int

Maximum possible start time.

property end_min: int

Minimum possible end time.

property end_max: int

Maximum possible end time.

property size_min: int

Minimum possible size/duration.

property size_max: int

Maximum possible size/duration.

property length_min: int

Minimum possible length.

property length_max: int

Maximum possible length.

property is_optional: bool

Whether this interval can be absent.

property is_present: bool

Whether this interval must be present (not optional).

property is_fixed_size: bool

Whether the size is fixed (not a range).

property is_fixed_start: bool

Whether the start is fixed.

property is_fixed_end: bool

Whether the end is fixed.

__hash__()[source]

Hash based on unique ID.

__eq__(other)[source]

Equality based on unique ID.

__le__(other)[source]

Deadline constraint: interval must end by given time.

Parameters:

other (object) – Integer time value.

Returns:

List of constraint nodes for satisfy().

Return type:

list

Example

>>> satisfy(task <= 50)  # task must end by time 50
__lt__(other)[source]

Strict deadline constraint: interval must end before given time. This can be simplified by using deadline with (time - 1).

Parameters:

other (object) – Integer time value.

Returns:

List of constraint nodes for satisfy().

Return type:

list

Example

>>> satisfy(task < 50)  # task must end before time 50
__ge__(other)[source]

Release date constraint: interval cannot start before given time.

Parameters:

other (object) – Integer time value.

Returns:

List of constraint nodes for satisfy().

Return type:

list

Example

>>> satisfy(task >= 10)  # task cannot start before time 10
__gt__(other)[source]

Strict release constraint: interval must start after given time. This can be simplified by using release_date with (time + 1).

Parameters:

other (object) – Integer time value.

Returns:

List of constraint nodes for satisfy().

Return type:

list

Example

>>> satisfy(task > 10)  # task must start after time 10
__repr__()[source]

String representation.

__init__(name=None, start=<factory>, end=<factory>, size=<factory>, length=None, intensity=None, granularity=1, optional=False, _id=-1)

IntervalVarArray

pycsp3_scheduling.variables.interval.IntervalVarArray(size, *, start=None, end=None, size_range=None, length=None, intensity=None, granularity=1, optional=False, name=None)[source]

Create an array of interval variables.

Parameters:
  • size (int | Sequence[int]) – Number of intervals, or tuple for multi-dimensional array.

  • start (int | tuple[int, int] | None) – Start bound for all intervals.

  • end (int | tuple[int, int] | None) – End bound for all intervals.

  • size_range (int | tuple[int, int] | None) – Size/duration bound for all intervals (named size_range to avoid conflict with the size parameter).

  • length (int | tuple[int, int] | None) – Length bound for all intervals.

  • intensity (Sequence[tuple[int, int]] | None) – Stepwise intensity function for all intervals.

  • granularity (int) – Scale for the intensity function.

  • optional (bool) – Whether all intervals are optional.

  • name (str | None) – Base name for intervals (will be suffixed with index).

Returns:

List of IntervalVar objects (nested list for multi-dimensional).

Return type:

list[IntervalVar]

Example

>>> tasks = IntervalVarArray(5, size_range=10, name="task")
>>> ops = IntervalVarArray((3, 4), size_range=(5, 20), optional=True)

IntervalVarDict

pycsp3_scheduling.variables.interval.IntervalVarDict(keys, *, start=None, end=None, size_range=None, length=None, intensity=None, granularity=1, optional=False, name=None)[source]

Create a dictionary of interval variables indexed by keys.

Parameters:
  • keys (Sequence) – Sequence of keys for the dictionary.

  • start (int | tuple[int, int] | None) – Start bound for all intervals.

  • end (int | tuple[int, int] | None) – End bound for all intervals.

  • size_range (int | tuple[int, int] | None) – Size/duration bound for all intervals.

  • length (int | tuple[int, int] | None) – Length bound for all intervals.

  • intensity (Sequence[tuple[int, int]] | None) – Stepwise intensity function for all intervals.

  • granularity (int) – Scale for the intensity function.

  • optional (bool) – Whether all intervals are optional.

  • name (str | None) – Base name for intervals.

Returns:

Dictionary mapping keys to IntervalVar objects.

Return type:

dict

Example

>>> tasks = IntervalVarDict(["A", "B", "C"], size_range=10, name="task")
>>> tasks["A"].size_min  # 10

Constants

pycsp3_scheduling.variables.interval.INTERVAL_MIN = 0

int([x]) -> integer int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.__int__(). For floating point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by ‘+’ or ‘-’ and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal. >>> int(‘0b100’, base=0) 4

pycsp3_scheduling.variables.interval.INTERVAL_MAX = 1073741823

int([x]) -> integer int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.__int__(). For floating point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by ‘+’ or ‘-’ and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal. >>> int(‘0b100’, base=0) 4

Sequence Variables

SequenceVar

class pycsp3_scheduling.variables.sequence.SequenceVar(intervals=<factory>, types=None, name=None, _id=-1)[source]

Bases: object

Represents a sequence variable for scheduling.

A sequence variable represents an ordered set of interval variables. It is typically used to model a disjunctive resource where only one interval can execute at a time.

Each interval in the sequence can optionally have an associated type (integer identifier) used for transition matrix constraints.

intervals

List of interval variables in this sequence.

Type:

list[pycsp3_scheduling.variables.interval.IntervalVar]

types

Optional list of type identifiers (one per interval). Used for transition constraints (setup times).

Type:

list[int] | None

name

Unique identifier for this sequence variable.

Type:

str | None

_id

Internal unique identifier.

Type:

int

Example

>>> task1 = IntervalVar(size=10, name="task1")
>>> task2 = IntervalVar(size=15, name="task2")
>>> task3 = IntervalVar(size=8, name="task3")
>>> seq = SequenceVar(intervals=[task1, task2, task3], name="machine1")
>>> # With types for transition matrix
>>> seq = SequenceVar(
...     intervals=[task1, task2, task3],
...     types=[0, 1, 0],
...     name="machine1"
... )
intervals: list[IntervalVar]
types: list[int] | None = None
name: str | None = None
__post_init__()[source]

Validate and initialize the sequence variable.

property size: int

Number of intervals in this sequence.

property has_types: bool

Whether this sequence has type identifiers.

get_interval(index)[source]

Get interval at given index.

get_type(index)[source]

Get type identifier at given index, or None if no types.

get_intervals_by_type(type_id)[source]

Get all intervals with the given type identifier.

__len__()[source]

Number of intervals in the sequence.

__iter__()[source]

Iterate over intervals.

__getitem__(index)[source]

Get interval by index.

__hash__()[source]

Hash based on unique ID.

__eq__(other)[source]

Equality based on unique ID.

__repr__()[source]

String representation.

__init__(intervals=<factory>, types=None, name=None, _id=-1)

SequenceVarArray

pycsp3_scheduling.variables.sequence.SequenceVarArray(size, intervals_per_sequence=None, *, types_per_sequence=None, name=None)[source]

Create an array of sequence variables.

Parameters:
  • size (int | Sequence[int]) – Number of sequences, or tuple for multi-dimensional array.

  • intervals_per_sequence (list[list[IntervalVar]] | None) – List of interval lists, one per sequence.

  • types_per_sequence (list[list[int]] | None) – Optional list of type lists, one per sequence.

  • name (str | None) – Base name for sequences (will be suffixed with index).

Returns:

List of SequenceVar objects (nested list for multi-dimensional).

Return type:

list[SequenceVar]

Example

>>> # Create sequences for 3 machines
>>> ops_m0 = [IntervalVar(size=10) for _ in range(5)]
>>> ops_m1 = [IntervalVar(size=15) for _ in range(5)]
>>> ops_m2 = [IntervalVar(size=8) for _ in range(5)]
>>> sequences = SequenceVarArray(
...     3,
...     intervals_per_sequence=[ops_m0, ops_m1, ops_m2],
...     name="machine"
... )

Usage Examples

Creating Interval Variables

from pycsp3_scheduling import IntervalVar, IntervalVarArray, IntervalVarDict, INTERVAL_MIN

# Single interval with fixed duration
task = IntervalVar(size=10, name="task1")

# Interval with variable duration
flexible = IntervalVar(size=(5, 20), name="flexible_task")

# Optional interval (can be absent)
optional = IntervalVar(size=10, optional=True, name="optional_task")

# Interval with stepwise intensity
# Important: set explicit length bounds when using intensity!
intensity = [(INTERVAL_MIN, 100), (10, 50)]  # 100% until t=10, then 50%
rate_scaled = IntervalVar(
    size=10,
    length=(10, 25),  # allow larger length for lower intensity
    intensity=intensity,
    granularity=100,
    name="rate_scaled"
)

# Bounded start and end times
bounded = IntervalVar(
    start=(0, 100),
    end=(10, 200),
    size=10,
    name="bounded_task"
)

# Array of intervals
tasks = IntervalVarArray(5, size_range=10, name="task")

# Dictionary of intervals
named_tasks = IntervalVarDict(
    keys=["assembly", "testing", "packaging"],
    size_range=(5, 15),
    name="stage"
)

Creating Sequence Variables

from pycsp3_scheduling import IntervalVar, SequenceVar, SequenceVarArray

# Create tasks
tasks = [IntervalVar(size=10, name=f"task{i}") for i in range(3)]

# Simple sequence (no types)
machine = SequenceVar(intervals=tasks, name="machine1")

# Sequence with types for transition constraints
typed_seq = SequenceVar(
    intervals=tasks,
    types=[0, 1, 0],  # Task types
    name="machine_with_types"
)

# Access sequence properties
print(f"Sequence has {len(machine)} intervals")
print(f"Has types: {machine.has_types}")

Accessing Interval Properties

task = IntervalVar(start=(0, 100), size=(5, 15), name="task")

# Bound properties
print(f"Start range: [{task.start_min}, {task.start_max}]")
print(f"End range: [{task.end_min}, {task.end_max}]")
print(f"Size range: [{task.size_min}, {task.size_max}]")

# Status properties
print(f"Is optional: {task.is_optional}")
print(f"Is fixed size: {task.is_fixed_size}")
print(f"Is fixed start: {task.is_fixed_start}")