Problem
Problem(model: b.Model, numeric_type: b.Concept)Define and solve a decision problem on a model.
Use Problem.solve_for to declare decision variables, Problem.minimize/
Problem.maximize to add objectives, and Problem.satisfy to add constraints.
Then call Problem.solve and read results via Problem.variable_values or
Problem.load_point.
Parameters
Section titled “Parameters”
(modelModel) - TheModelto attach solver constructs (variables, objectives, constraints, and results) to.
(numeric_typeConcept) - Numeric type used for bounds, solution values, and numeric literals. Usesemantics.frontend.core.Floatfor HiGHS/Gurobi/Ipopt (even for MIPs), andsemantics.frontend.core.Integerfor MiniZinc.
Examples
Section titled “Examples”Declare a variable and objective:
>>> from relationalai.semantics import Float, Model>>> from relationalai.semantics.reasoners.prescriptive import Problem>>> m = Model("demo")>>> x = m.Relationship(f"{Float:x}")>>> p = Problem(m, Float)>>> p.solve_for(x, name="x", lower=0)>>> p.minimize(x)Attributes
Section titled “Attributes”.Variable
Section titled “.Variable”Problem.Variable: ConceptConcept for the declared solver variables (useful for inspection via
Problem.display).
.Expression
Section titled “.Expression”Problem.Expression: ConceptConcept for objectives and constraints (useful for inspection via
Problem.display).
Methods
Section titled “Methods”.solve_for()
Section titled “.solve_for()”Problem.solve_for( expr: b.Relationship | b.Chain | b.Expression, where: Optional[list[Any]] = None, populate: bool = True, name: Optional[Any | list[Any]] = None, type: Optional[str] = None, lower: Optional[std.NumberValue] = None, upper: Optional[std.NumberValue] = None, start: Optional[std.NumberValue] = None,) -> b.ConceptDeclare decision variables for the problem.
Call this before adding objectives or constraints. The returned concept
can be passed to Problem.display to inspect the generated variables.
Parameters:
(exprRelationship or Chain or Expression) - Expression describing the variable(s) to create (for example, a scalar relationship likexor an indexed property likeItem.cost).
(wherelist[Any], default:None) - Optional conditions restricting which variable instances are created.
(populatebool, default:True) - If True (default), write solved values back to the original relationship/property afterProblem.solve. Set to False when you create multipleProbleminstances that solve for the same relationship on the same model.
(nameAny or list[Any], default:None) - Display name for variables. Use a string for scalars or a list pattern for indexed variables (for example,["x", Item.i]).
(typestr, default:None) - Variable type:"cont"(default forFloat),"int"(default forInteger), or"bin"(binary 0/1).
(lowerVariable or float or int or Decimal, default:None) - Lower/upper bounds and an optional initial value hint.
(upperVariable or float or int or Decimal, default:None) - Lower/upper bounds and an optional initial value hint.
(startVariable or float or int or Decimal, default:None) - Lower/upper bounds and an optional initial value hint.
Returns:
Concept- AVariablesubconcept representing the declared decision variables.
Raises:
ValueError- If variables are already defined for this relationship, or if an argument has an invalid value (for example, an unknowntype).TypeError- If an argument has an invalid type.
Referenced By:
RelationalAI Documentation └── Build With RelationalAI └── Understand how PyRel works > Use advanced reasoning > Prescriptive reasoning > Solve a decision problem ├── Overview │ └── How solving a decision problem works ├── Create a Problem object │ └── Choose a default numeric type ├── Add decision variables │ ├── Declare decision variables │ └── Choose variable types and bounds ├── Solve a decision problem │ └── Avoid common pitfalls └── Work with solutions └── Determine how to access results
.minimize()
Section titled “.minimize()”Problem.minimize( expr: b.Variable | float | int | b.Fragment, name: Optional[Any | list[Any]] = None) -> b.ConceptAdd a minimization objective.
The expression must reference at least one decision variable declared via
Problem.solve_for.
Parameters:
(exprVariable or float or int or Fragment) - Objective expression to minimize.
(nameAny or list[Any], default:None) - Optional objective name (string for scalar, or a list pattern for indexed objectives).
Returns:
Concept- AnExpressionsubconcept representing the objective. Pass it toProblem.displayto inspect.
Raises:
ValueError- If the objective does not reference any declared decision variables.
Referenced By:
RelationalAI Documentation └── Build With RelationalAI └── Understand how PyRel works > Use advanced reasoning > Prescriptive reasoning > Solve a decision problem └── Solve a decision problem └── Solve optimally
.maximize()
Section titled “.maximize()”Problem.maximize( expr: b.Variable | float | int | b.Fragment, name: Optional[Any | list[Any]] = None) -> b.ConceptAdd a maximization objective.
The expression must reference at least one decision variable declared via
Problem.solve_for.
Parameters:
(exprVariable or float or int or Fragment) - Objective expression to maximize.
(nameAny or list[Any], default:None) - Optional objective name (string for scalar, or a list pattern for indexed objectives).
Returns:
Concept- AnExpressionsubconcept representing the objective. Pass it toProblem.displayto inspect.
Raises:
ValueError- If the objective does not reference any declared decision variables.
Referenced By:
RelationalAI Documentation └── Build With RelationalAI └── Understand how PyRel works > Use advanced reasoning > Prescriptive reasoning > Solve a decision problem └── Solve a decision problem └── Solve optimally
.satisfy()
Section titled “.satisfy()”Problem.satisfy(expr: b.Fragment, name: Optional[Any | list[Any]] = None) -> b.ConceptAdd constraints from a model.require(...) fragment.
Use this to turn a require-clause fragment into solver constraints.
The returned concept can be passed to Problem.display to inspect.
Parameters:
(exprFragment) - A fragment created byModel.require(optionally scoped withModel.where).
(nameAny or list[Any], default:None) - Optional constraint name (string for scalar, or a list pattern for indexed constraints).
Returns:
Concept- AnExpressionsubconcept representing the added constraints.
Raises:
TypeError- Ifexpris not a fragment.ValueError- If the fragment has no require clause, or if it includes select/define clauses.
Referenced By:
RelationalAI Documentation
└── Build With RelationalAI
└── Understand how PyRel works > Use advanced reasoning > Prescriptive reasoning > Solve a decision problem
├── Overview
└── Add constraints
├── Add constraints with Problem.satisfy()
└── Avoid common pitfalls.display()
Section titled “.display()”Problem.display(part: Optional[b.Concept] = None) -> strPrint and return a human-readable summary of the problem.
With no arguments, this shows all declared variables, objectives, and
constraints. Pass a subconcept returned by Problem.solve_for,
Problem.minimize, Problem.maximize, or Problem.satisfy to display only
that part.
Parameters:
(partConcept, default:None) - Specific variable/objective/constraint subconcept to display.
Returns:
str- The formatted summary (also printed).
Raises:
ValueError- Ifpartis not a subconcept returned byProblem.solve_for,Problem.minimize,Problem.maximize, orProblem.satisfy.
Examples:
Display the full problem:
>>> from relationalai.semantics import Float, Model>>> from relationalai.semantics.reasoners.prescriptive import Problem>>> m = Model("demo")>>> x = m.Relationship(f"{Float:x}")>>> p = Problem(m, Float)>>> x_vars = p.solve_for(x, name="x", lower=0)>>> p.minimize(x)>>> p.display()Display a single part (a subconcept returned by solve_for/minimize/satisfy):
>>> p.display(x_vars)Notes:
This method queries the model.
Referenced By:
RelationalAI Documentation └── Build With RelationalAI └── Understand how PyRel works > Use advanced reasoning > Prescriptive reasoning > Solve a decision problem ├── Create a Problem object │ └── Inspect a Problem withdisplay()├── Add constraints │ └── InspectProblemconstraints └── Solve a decision problem └── Avoid common pitfalls
.solve()
Section titled “.solve()”Problem.solve( solver: str, *, time_limit_sec: float | None = None, silent: bool | None = None, solution_limit: int | None = None, relative_gap_tolerance: float | None = None, absolute_gap_tolerance: float | None = None, log_to_console: bool = False, print_only: bool = False, print_format: str | None = None, **solver_params: int | float | str | bool) -> NoneSolve the decision problem using a solver backend.
Declare decision variables first with Problem.solve_for. After solving,
inspect results via Problem.variable_values and result properties such as
termination_status and objective_value.
Parameters:
(solverstr) - Solver name (for example"highs","minizinc","ipopt").
(time_limit_secfloat, default:None) - Maximum solve time in seconds. The solver service defaults to 300s if not provided.
(silentbool, default:None) - Whether to suppress solver output.
(solution_limitint, default:None) - Maximum number of solutions to return (when supported).
(relative_gap_tolerancefloat, default:None) - Relative optimality gap tolerance in[0, 1].
(absolute_gap_tolerancefloat, default:None) - Absolute optimality gap tolerance (>= 0).
(log_to_consolebool, default:False) - Whether to stream solver logs to stdout while the job runs.
(print_onlybool, default:False) - If True, request a text representation without solving. Results such asProblem.printed_modelare still accessible afterward.
(print_formatstr, default:None) - Text format for the printed model. Supported formats:"moi"(MOI text),"latex","mof"(MOI JSON),"lp","mps","nl"(AMPL).
(**solver_paramsint or float or str or bool, default:{}) - Raw solver-specific parameters passed through to the solver service.
Raises:
ValueError- If no decision variables have been declared viaProblem.solve_for.TypeError- If any solver-specific parameter value is not anint,float,str, orbool.RuntimeError- If the solver job fails.TimeoutError- If the solver job does not reach a terminal state in time.
Notes:
Passing **solver_params emits a warning because options may not be
portable across solvers.
Referenced By:
RelationalAI Documentation
└── Build With RelationalAI
└── Understand how PyRel works > Use advanced reasoning > Prescriptive reasoning
├── Choose a backend
│ ├── Use Gurobi
│ │ └── Example
│ ├── Use Ipopt
│ │ └── Example
│ └── Use MiniZinc
│ └── Example
└── Solve a decision problem
├── Overview
├── Solve a decision problem
│ ├── What happens when you solve a problem
│ ├── Solve for feasibility
│ ├── Solve optimally
│ ├── Set a time limit
│ ├── Accept a near-optimal solution
│ ├── Tune solver backend behavior
│ ├── Print the translated solver model
│ ├── Check error details when termination status is not OPTIMAL
│ └── Handle solve failures
└── Work with solutions.variable_values()
Section titled “.variable_values()”Problem.variable_values(multiple: bool = False) -> b.FragmentReturn decision variable values from the active solution.
Use this after Problem.solve (and optionally Problem.load_point) to read
variable values as a fragment you can materialize with .to_df() or
print with .inspect().
Parameters:
(multiplebool, default:False) - If True, return values for all solutions from the most recentProblem.solvecall and include a 0-basedsol_indexcolumn.
Returns:
Fragment- A fragment with columnsnameandvalue(andsol_indexif multiple is True).
Raises:
ValueError- IfProblem.solvehas not been called.
Referenced By:
RelationalAI Documentation └── Build With RelationalAI └── Understand how PyRel works > Use advanced reasoning > Prescriptive reasoning > Solve a decision problem ├── Add decision variables │ └── Declare decision variables └── Work with solutions ├── Determine how to access results └── Read solver-level variable values
.load_point()
Section titled “.load_point()”Problem.load_point(point_index: int) -> NoneMake a specific solution point the active solution.
After calling this, Problem.variable_values and populated properties
reflect the selected solution.
Parameters:
(point_indexint) - 0-based solution index (0 selects the first solution).
Raises:
ValueError- Raised in the following cases:- point_index is not a non-negative integer.
Problem.solvehas not been called.- point_index is out of range (>=
Problem.result_count).
Notes:
Each call records a new selection via model.define(...). The next
query may be slower because the model needs to re-evaluate.
.display_solve_info()
Section titled “.display_solve_info()”Problem.display_solve_info() -> strPrint and return a summary of solve metadata.
This includes solver metadata fields such as termination_status
and solve_time_sec.
Returns:
str- A formatted summary string (also printed).
Raises:
ValueError- IfProblem.solvehas not been called.
Notes:
The objective value is not included; use Problem.objective_value.
Referenced By:
RelationalAI Documentation └── Build With RelationalAI └── Understand how PyRel works > Use advanced reasoning > Prescriptive reasoning > Solve a decision problem └── Solve a decision problem └── Inspect solve metadata
Referenced By
Section titled “Referenced By”RelationalAI Documentation └── Build With RelationalAI └── Understand how PyRel works > Use advanced reasoning > Prescriptive reasoning ├── Choose a backend │ ├── Use HiGHS │ │ └── Example │ ├── Use Gurobi │ │ └── Example │ ├── Use Ipopt │ │ └── Example │ └── Use MiniZinc │ └── Example └── Solve a decision problem ├── Overview │ ├── How PyRel represents a decision problem │ └── How solving a decision problem works ├── Create a Problem object │ ├── Choose a default numeric type │ ├── Create a Problem object │ └── Inspect a Problem withdisplay()├── Add decision variables │ ├── Declare decision variables │ ├── Choose variable types and bounds │ └── InspectProblemvariables ├── Add constraints │ ├── Add constraints withProblem.satisfy()│ ├── InspectProblemconstraints │ └── Avoid common pitfalls ├── Solve a decision problem │ ├── What happens when you solve a problem │ ├── Validate before you solve │ ├── Solve for feasibility │ ├── Solve optimally │ ├── Inspect solve metadata │ ├── Set a time limit │ ├── Accept a near-optimal solution │ ├── Tune solver backend behavior │ ├── Print the translated solver model │ ├── Check error details when termination status is notOPTIMAL│ ├── Handle solve failures │ └── Avoid common pitfalls └── Work with solutions ├── Determine how to access results └── Read solver-level variable values