I need to compute some automatically generated expressions, which may contain square roots, with the class Zmod
.
For example, I want to evaluate the following expression modulo 9 (thus, using the class Zmod(9
)):
expr = "-1 / sqrt(7) + 5"
In the above case, I want to get the results 7 (for sqrt(7) = 4
) and 3 (for sqrt(7) = 5
).
Is this possible with Sage? How can I get these results? If I need to use another library, which one should I use and how?
I thank you in advance for your answers!
Elements of Zmod
have an .sqrt()
method, but you can also pass them to the sqrt
function. Example:
sage: R = Zmod(9)
sage: a = R(7)
sage: sqrt(a)
4
If you want to automatically parse a string expression like "-1 / sqrt(7) + 5"
and convert all numeric constants to elements of Zmod(9)
, I'd suggest to use Sage's symbolic ring SR
as a parser, and then traverse the expression tree using the .operator()
and .operands()
methods in a recursive function. Like so:
sage: def zmod_eval(exp):
....: if exp.is_numeric():
....: return Zmod(9)(exp)
....: return exp.operator()(*(zmod_eval(op) for op in exp.operands()))
....:
sage: exp = SR("-1 / sqrt(7) + 5")
sage: zmod_eval(exp)
7
This would probably handle most expressions you may have. If you want both results depending on the sign choice for the square root, then modify zmod_eval
to return a list, and handle the sqrt operation specially. Unfortunately, Sage's symbolic ring handles sqrt as a generic power:
sage: exp = SR("-1 / sqrt(7) + 5")
sage: exp.op[0,0]
sqrt(7)
sage: exp.op[0,0].operator()
<built-in function pow>
so if your expression also contains integer powers you will have a difficult time distinguishing between them and the square root.
Ultimately, I'd think it's simpler to modify your expression generator to output Zmod(9)
wherever is needed, rather than trying to play around with Sage.