Skip to content

all_different

relationalai.semantics.reasoners.prescriptive
all_different(over: b.Value) -> b.Aggregate

Return an all-different constraint.

Use this inside Model.require and pass the resulting fragment to Problem.satisfy. Arguments must reference decision variables declared via Problem.solve_for. For grouped constraints (for example, “all values are distinct per row”), scope it with Aggregate.per.

.. versionchanged:: 1.29.0 Takes a single over argument. Passing several never expressed distinctness across them: every argument but the last became a projection slot, which the rewriter then rejected. Group with .per() instead.

Parameters

  • over

    (Value) - The bag of values that must be distinct, as a single decision-variable expression over a data grounding (all_different(x * Item.cost), all_different(Cell.val)). Group it with .per() rather than by passing several arguments.

Returns

  • Aggregate - A solver aggregate representing the all-different constraint.

Examples

Constrain values to be distinct per row:

from relationalai.semantics import Integer, Model
from relationalai.semantics.reasoners.prescriptive import Problem, all_different
m = Model("all_different_demo")
Cell = m.Concept("Cell", identify_by={"row": Integer, "col": Integer})
Cell.val = m.Property(f"{Cell} has {Integer:val}")
m.define(
Cell.new(row=0, col=0),
Cell.new(row=0, col=1),
Cell.new(row=1, col=0),
Cell.new(row=1, col=1),
)
problem = Problem(m, Integer)
problem.solve_for(Cell.val, name=["x", Cell.row, Cell.col], lower=1, upper=4)
problem.satisfy(m.require(all_different(Cell.val).per(Cell.row)).where(Cell))

Notes

Members that evaluate to the same value are kept as separate members rather than merged, so distinctness is required over all of them. Two members that tie therefore make the constraint infeasible, which is the intended reading of “all different” over a bag of expressions.