Ask Your Question
2

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

asked 2019-07-21 02:24:18 +0100

millermj gravatar image

updated 2023-05-19 22:11:12 +0100

FrédéricC gravatar image

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 flag offensive close merge delete

2 Answers

Sort by » oldest newest most voted
1

answered 2019-07-21 13:05:17 +0100

rburing gravatar image

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).

edit flag offensive delete link more

Comments

Thanks! This does what I need.

millermj gravatar imagemillermj ( 2019-08-11 21:12:28 +0100 )edit
0

answered 2019-07-21 15:17:33 +0100

vdelecroix gravatar image

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".

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2019-07-21 02:24:18 +0100

Seen: 357 times

Last updated: Jul 21 '19