# How to recursively substitute from global name space?

In sage 3.x, I used the below function to automatically substitute into an expression all assignments I have made previously. How can I get it to work in Sage 5.x or is there a better way now?

def subsg(variable, *args):
"""
Substitutes all definitions in the global name space for the variables contained in 'variable' and returns the result.
INPUT:
variable -- a symbolic variable
*args -- an optional dictionary containing additional parameter definitions
EXAMPLE:
sage: var ('a b c d')
a b c
sage: f = a*x
sage: a = 2*b
sage: b = c^2
sage: cons1 = dict(c = d^3)
sage: subsg(f,cons1)
2*d^6*x
Or, if cons1 is not to be used:
sage: subsg(f)
2*c^2*x

"""
expr1 = variable
expr2 = variable.subs(globals()).subs(*args)
while expr1 <> expr2:
expr1 = expr2
expr2 = expr1.subs(globals()).subs(*args)
return expr1

edit retag close merge delete

I've been trying to find the same thing -- so far all I could find was this question, and the same question you asked on google groups in 2008.

Sort by » oldest newest most voted Here is a new version of your "subsg" function, with modifications partly inspired by the "update" function from a related question. This seems to work in Sage 5.9 for your examples and in other cases that I have tried so far:

def subsg(expression, *args):
"""
Substitutes all definitions in the global name space for the variables contained in 'expression' and returns the result.
INPUT:
expression -- a symbolic expression
*args -- an optional dictionary containing additional parameter definitions
EXAMPLE:
sage: var ('a b c d')
a b c
sage: f = a*x
sage: a = 2*b
sage: b = c^2
sage: cons1 = dict(c = d^3)
sage: subsg(f,cons1)
2*d^6*x
Or, if cons1 is not to be used:
sage: subsg(f)
2*c^2*x

"""
variables = globals().update(*args)
expr1 = expression
try :
expr2 = expr1.subs(dict(zip(expr1.variables(), map(lambda v:eval(str(v)), expr1.variables()))))
except:
# Return original expression unchanged if there is an error
return expr1
while expr1 <> expr2:
expr1 = expr2
expr2 = expr1.subs(dict(zip(expr1.variables(), map(lambda v:eval(str(v)), expr1.variables()))))
return expr1

more