Add constraints to the cutpool associated with solver state Handle. Unlike normal constraints, cutpool constraints are not added directly to the problem, and are *NOT* removed on backtracking. Logically, cutpool constraints are valid for all solves of the problem, regardless of when a constraint is added to the pool -- they are `globally valid'. The purpose of the cutpool is to give the user more flexibility on how constraints are used by the external solver.
Constraints is the list of constraints to be added to the cutpool. As they are not removed on backtracking, they can only involve variables that are present at problem setup. Otherwise, an out of range error is raised. Variables can be created for a problem before setup by posting normal constraints involving the variables, in particular, using reals/1. The constraints are normalised before being passed to the external solver. They are not simplified, and no consistency checks are performed. If any of the constraints are ground, a type error is raised. Instantiated variables are treated as constants (i.e. the value they are instantiated to when the predicate is called), even when the execution backtracks to a point before the instantiations.
Options is a possibly empty list of Option:Value pairs specifying the options. Valid options are:
Operationally, the cutpool constraints are taken into account when the external solver is invoked, and the user can specify how they are taken into account by setting the status of these constraints: by default, cutpool constraints are active, and are taken into account during solver invocation: none of these constraints will be violated in the solution produced: they are either part of the problem matrix solved by the external solver, or they have been explicitly checked for non-violation. This is done as follows: active cutpool constraints that are labelled as `add_initially' (the default) are added to the problem matrix, and the external solver is invoked. When a solution is produced, the unadded active cutpool constraints are checked to see if they are violated. Any violated constraints are added to the problem matrix and the problem is resolved by the external solver. This is repeated until there are no violated constraints. This approach allows the user to leave out constraints that might be expensive (i.e. slow down the solving) unless they usefully constrain the problem.
Checking for violations require the solution values of the problem variables. Thus, if the solution option is turned off and no solution value is available, and there are unadded active cutpool constraints, an out of range error would be raised when the solver tries to solve the problem.
The violation checking is only done if the external solver produces a solution with solution values. If the problem is unbounded (or unknown, i.e. the solver cannot determine if the problem is infeasible or unbounded), then all the active cutpool constraints are added to the problem without checking for violations, and the problem is resolved once more. This is done because adding constraints to the problem can make the problem become bounded.
The user can change a cutpool constraint's status to non-active, in which case it is neither checked for violations nor added to the problem. For logical correctness, the user should only make a constraint non-active if it is certain that the constraint will not be violated, e.g. if it is superceded by a stronger constraint.
Cutpool constraints are organised into named groups, allowing multiple constraints to be referred to as a unit, e.g. with the cutpool_info option of lp_get/3.
Note that as the constraints are added to the cutpool, and not to the problem directly, this is not considered as adding new constraints, and will not cause the solver to trigger with the new_constraint trigger condition set.