Substitute variables in an expression in Sagemath

1.4k Views Asked by At

Somewhat similar to this question, I was trying to evaluate a Boolean expression given the right hand side variables in Sage. For simplicity, say, my Boolean expression is, $y=x_0+x_1$. For each of $(x_0,x_1) \in \{(0,0),(0,1),(1,0),(1,1)\}$, I want to evaluate $y$.

This is the basic code block to get started. Note that, when I tried separate substitution, it works. But it does not work when I tried to automatically substitute variables.

B = BooleanPolynomialRing(3, ['x0', 'x1', 'y'])
B.inject_variables()

y = x0 + x1

# This is what I want to evaluate (working fine, but cannot automate, see below)
print (eval('y').subs(x0=0, x1=0))
print (eval('y').subs(x0=0, x1=1))
print (eval('y').subs(x0=1, x1=0))
print (eval('y').subs(x0=1, x1=1))

# This is the part where I tried to automate
from itertools import product
for x in product([0, 1], repeat=2):
    print (y) #### How to automatically substitute variables?

I tried multiple ways including various substitution, eval, sage_eval and exec. Got various errors including

  • SyntaxError: keyword can't be an expression
  • SyntaxError: invalid syntax
  • AttributeError: 'bool' object has no attribute 'items'
  • SyntaxError: invalid syntax
  • KeyError: 'x'
  • AttributeError: 'sage.rings.polynomial.pbori.pbori.BooleanMonomial' object has no attribute 'items'
  • TypeError: subs() takes at most 1 positional argument (2 given)

Therefore, my query is how can I automatically substitute x-variables to evaluate y?

1

There are 1 best solutions below

2
On BEST ANSWER

This works for me:

z = x0 + x1 # didn't want to redefine y
for x in product([0, 1], repeat=2):
    print(z.subs({x0:x[0], x1:x[1]}))

First, no need for eval('z'): just z works fine. Second, pass a dictionary to subs, keys are the "variables" like x0, values are what you want to substitute for them.

This is a little more "automatic":

for x in product([0, 1], repeat=2):
    d = dict(zip((x0, x1), x))
    print(z.subs(d))

and even more:

for x in product([0, 1], repeat=2):
    d = dict(zip(B.gens()[:-1], x))
    print(z.subs(d))

This assumes that the generators for B look like (x0, x1, ..., xn, y) and you are going to substitute the entries of x for all but the last of them: B.gens() gives the generators, and B.gens()[:-1] gives all but the last generator.