[Python] Ortools can not evaluate LinearExpr edge case

Discussão em 'Python' iniciado por Stack, Novembro 27, 2024.

  1. Stack

    Stack Membro Participativo

    I encounter a specific edge case in a CP model. All my variables are int based but the objective which is float based.

    In a lot of usage of my model, there is no issue doing this. But in one specific instanciantion, I encounter an error while evaluating the objective.

    An error is raised in the evaluation function :

    # The librairie function
    def evaluate_linear_expr(
    expression: LinearExprT, solution: cp_model_pb2.CpSolverResponse
    ) -> int:
    """Evaluate a linear expression against a solution."""
    if isinstance(expression, IntegralTypes):
    return int(expression)
    if not isinstance(expression, LinearExpr):
    raise TypeError("Cannot interpret %s as a linear expression." % expression)

    value = 0
    to_process = [(expression, 1)]
    while to_process:
    expr, coeff = to_process.pop()
    if isinstance(expr, IntegralTypes):
    value += int(expr) * coeff
    elif isinstance(expr, _ProductCst):
    to_process.append((expr.expression(), coeff * expr.coefficient()))
    elif isinstance(expr, _Sum):
    to_process.append((expr.left(), coeff))
    to_process.append((expr.right(), coeff))
    elif isinstance(expr, _SumArray):
    for e in expr.expressions():
    to_process.append((e, coeff))
    value += expr.constant() * coeff
    elif isinstance(expr, _WeightedSum):
    for e, c in zip(expr.expressions(), expr.coefficients()):
    to_process.append((e, coeff * c))
    value += expr.constant() * coeff
    elif isinstance(expr, IntVar):
    value += coeff * solution.solution[expr.index]
    elif isinstance(expr, _NotBooleanVariable):
    value += coeff * (1 - solution.solution[expr.negated().index])
    else:
    # It raises here !
    raise TypeError(f"Cannot interpret {expr} as a linear expression.")

    return value


    The error: TypeError: Cannot interpret 4000000.0 as a linear expression.

    Here is what I can see in debug:

    > expression
    (7.209805335255949e-08 * (((((((3000 * (VAR300 + (quotient + has_remainder))) + (93000 * VAR879)) + (60000 * VAR300)) + ((1500 * VAR564) + (25000 * VAR780))) + ((2000 * VAR578) + (140000 * VAR781))) + ((9570.300000000001 * VAR832) + (40000 * VAR882))) + 4000000.0))

    > type(expression)
    <class 'ortools.sat.python.cp_model._ProductCst'>

    > type(expr)
    <class 'float'>



    I feel like it should be handled by the librairie... or I am doing something wrong ?

    Versions Used: Python 3.9.0 ; ortools 9.11.4210

    Update I figured out that the only difference between the working instances and this one is the inclusion of a constant float offset, which the evaluation function is unable to process. I found it inconsistant since, in any case, my objective is a floating value and is correctly handled without this constant.

    Continue reading...

Compartilhe esta Página