# Is there a way to temporarily turn off sage's type checking?

I'm having some difficulties writing sage code to solve linear programming problems using "natural variables", by substituting for them the variables required for MixedIntegerLinearProgram.

The code for "minimize_desired" is what I'd like to do, but it fails during the substitution with the error message "TypeError: no canonical coercion from Linear functions over Real Double Field to Symbolic Ring". What I'd like is for sage to just do the substitution and ignore the lack of coercion.

The code for "minimize_works" works, but I got past the type checking by changing everything to strings and then back into a sage object, which feels like a terrible kludge. However this does illustrate that, despite sage's worries about coercion, everything ends up fine for MixedIntegerLinearProgram.

Is there a way to turn off sage's type checking and just do the substitution?

Thanks,

Mike

Note: I simplified the examples below by eliminating all the code that dealt with constraints.

def minimize_desired(objective):
p = MixedIntegerLinearProgram(maximization=false)
pvar = p.new_variable(real=True, nonnegative=True)

variables=set(objective.arguments())
translation={v:pvar[v] for v in variables}
objective=objective.subs(translation)      # FAILS HERE

p.set_objective(objective)
print p.solve()

def minimize_works(objective):
p = MixedIntegerLinearProgram(maximization=false)
pvar = p.new_variable(real=True, nonnegative=True)

variables=set(str(v) for v in objective.arguments())
translation={v:pvar[v] for v in variables}
objective=sageobj(str(objective), translation)

p.set_objective(objective)
print p.solve()

var('x y')
minimize_works(x+y)
print
minimize_desired(x+y)

edit retag close merge delete

Sort by » oldest newest most voted

Personally I would try to find a way to avoid the symbolic ring (with var, etc.) altogether.

If you want to use the symbolic ring, then you have to do the conversion to a LinearFunction somehow.

Assuming this setup:

sage: var('x,y')
sage: expr = 2*x + y
sage: p = MixedIntegerLinearProgram(maximization=False)
sage: pvar = p.new_variable(real=True, nonnegative=True)


You can do it e.g. like this:

def linear_function_from_symbolic(expr, pvar):
constant_coeff = pvar.mip().base_ring()(expr.subs(dict(zip(expr.variables(), [0]*len(expr.variables())))))
return sum(expr.coefficient(v)*pvar[v] for v in expr.variables()) + constant_coeff


and use it as follows:

sage: linear_function_from_symbolic(expr, pvar)
2*x_0 + x_1


You can convert constraints too:

def linear_constraint_from_symbolic(expr, pvar):
return expr.operator()(linear_function_from_symbolic(expr.lhs(), pvar),
linear_function_from_symbolic(expr.rhs(), pvar))


for example:

sage: linear_constraint_from_symbolic(x <= 1, pvar)
x_0 <= 1


It is reasonable that there is no coercion from the Symbolic Ring to Linear functions over RDF, because it would not be well-defined with respect to the ordering of variables: e.g. coercion of two functions of different variables would depend on the order in which you do it. The function above "suffers" from the same (but probably you don't care).

more

Thanks! This does what I need.

( 2019-08-11 21:12:28 +0200 )edit

This is not really a problem with type checking. The substitution code of symbolic expression assumes that you want to create a symbolic expression. It does "evaluate" the expression as you would like.

sage: x,y = SR.var('x, y')
sage: expr_symb = x + y
sage: expr_synb.subs(x=1, y=3).parent()
Symbolic Ring


Note that the same behavior can be observed for multivariate polynomials

sage: R = ZZ['x,y']
sage: x,y = R.gens()
sage: expr_poly = x + y
sage: expr_poly..subs(x=1, y=3)parent()
Multivariate Polynomial Ring in x, y over Integer Ring


What you want is a form of "function call". It sort of works for polynomials

sage: expr_poly(1, 3).parent()
Integer Ring
sage: expr_poly(x=1, y=3).parent()   # hum... inconsistency?
Multivariate Polynomial Ring in x, y over Integer Ring


But the symbolic ring never spits out an integer

sage: expr_symb(1, 3).parent()
Symbolic Ring
sage: expr_symb(x=1, y=3).parent()
Symbolic Ring


(My) conclusion: this is a desirable feature that is not available. The current behavior is a bit consistent. But we still want to distinguish an "internal substitution" and an "external substitution".

more