Lecture 6: Symbols, Variables, and References¶
While Sage works with dynamic typing in a similar fashion as Python,
sometimes we must declare variables explicitly with var
as in var('x')
.
Every variable in Sage has a type. We distinguish between names of variables and the objects variables refer to. Putting quotes around a variable name prevents an evaluation and we see how this may be used to make connections between variables. We cover the (partial) evaluation of expressions as needed in the verification of the solutions of a general cubic equation.
Expressions and Names¶
Sage export mathematical constants, such as pi
.
We can work with pi
as a variable and assign
any value to pi
. For example:
print(pi, type(pi))
pi = 3.14
print(pi, type(pi))
The first statement shows that pi
is an expression.
After the assignment, pi
refers to the value 3.14
which is of type sage.rings.real_mpfr.RealLiteral
.
Did we then loose the value of pi?
With restore
(we could also call the restore
the unassign operation)
we can get back the original value of pi
.
restore('pi')
print(pi, type(pi))
print(numerical_approx(pi, digits=30))
Mind the quotes in the argument of restore
,
without the quotes we would take the value pi
refers to.
After executing the restore
we see that pi
is again
an expression. And sure enough, we can see as many digits
of pi
as we like.
The quotes are of course a general construction from Python where everything put between quotes is a string. A value can be stored as a string and then later evaluated with eval.
x = 3.14
name = 'x'
print(x, name, eval(name))
Verification of Solutions¶
By default, with we solve an equation with``solve`` we receive a list of expressions.
var('z')
equ = z**2 - 3 == 0
sols = solve(equ, z); print(sols)
print(type(sols[0]))
We have the option to return a list of dictionaries.
sols = solve(equ, z, solution_dict=True); print(sols)
Now we see [{z: -sqrt(3)}, {z: sqrt(3)}]
and sols
is a list
of dictionaries. As key for each dictionary
we have the variable name
and its corresponding value is the value of the solution of the equation.
For example, to select the value of the first solution, using as key
the variable name z
, we can proceed as follows
print(sols[0], type(sols[0]))
print(sols[0][z])
The last command prints the value -sqrt(3)
.
The dictionary is useful to
substitute the value of the variable
in the equation we solved, for
verification purposes.
equ.substitute(sols[0])
and we see 0 == 0
.
Suppose we were to assign to z
.
Then we can no longer access the dictionary as directly as before,
because z
now refers to a value, but via keys()
we retrieve the
unevaluated variable with the corresponding value.
But the substitution still works.
z = 3; print('z = ', z)
print(sols[0].keys(), sols[0].values())
equ.substitute(sols[0])
Even though we have lost the use of z
as a general variable,
its former value as a solution is still contained in the dictionary
of solutions sols
.
How do we see the current value to which z refers to?
print(eval(str(sols[0].keys())))
This will show the list [3]
.
Recall that lists in Python allow to work with shared references.
Evaluation of Expressions¶
We can express the roots of a polynomial of degree two with
symbolic coefficients.
Similar formulas exist for a polynomial of degree three.
To start over, we clear all the variables in our worksheet
with the reset()
.
reset()
var('x, a, b, c')
p = x^3 + a*x^2 + b*x + c
s = solve(p == 0, x, solution_dict=True)
print(s)
The formulas look complicated. Let us check a specific example. We want to verify the solution for specific values of the coefficients. An easy choice for the coefficients are the numbers 1.0, 2.0, 3.0 (of type float). Recall that Python allows for simultaneous or tuple assignment.
(a, b, c) = (1.0, 2.0, 3.0)
print(a, b, c)
print(p)
print(s[0])
The outcome is not what we wanted and expected.
Even as we see the specific values for a
, b
, and c
printed,
the polynomial still shows up in its original symbolic
form \(x^3 + a x^2 + b x + c\), and so does its solution.
If we were to retype the expression for the polynomial again,
then the coefficients would be evaluated, but this is tedious
and we do not want to retype the complicated expressions for
the solutions.
How to force the evaluation of the coefficients in p and the solution without retyping the polynomial p? We can evaluate an expression.
print(p(x=x,a=a,b=b,c=c))
s0 = s[0][x](a=a,b=b,c=c); print(s0)
Now we see the polynomial
x^3 + x^2 + 2.00000000000000*x + 3.00000000000000
and a numerical value for the solution.
We can then evaluate the expression p
at s0
.
print(p(x=s0,a=a,b=b,c=c))
To verify whether the value of the expression at the solution will evaluate to zero, we convert to the complex floating point type.
print(complex(p(x=s0,a=a,b=b,c=c)))
and we see that the value is close enough to the machine precision.
Assignments¶
For variables
a
andb
consider the expression\[{\displaystyle \frac{1}{a + b \sqrt{2}}}\]We want to compute expressions for the coefficients of the inverse of \(a + b \sqrt{2}\), written in the same format, that is: as \(c + d \sqrt{2}\) for some variables
c
andd
.Set up the equations on the coefficients
c
andd
such that\[{\displaystyle \left( a + b \sqrt{2} \right) \left( c + d \sqrt{2} \right) = 1.}\]Apply
solve
to the equations to find expressions forc
andd
in function of thea
andb
of the original expression.Verify your solution by making the product \({\displaystyle \left(a + b \sqrt{2}\right)\left(c + d \sqrt{2}\right)}\) and check if the product equals 1 for the computed expressions for
c
andd
.
Execute the statements
reset(); a, b = var('a, b'); b = a; a = 2
and explain the relationships between the variablesa
andb
. Give the Sage commands and their output to illustrate your explanation.Execute the statements
reset(); a, b = var('a, b'); a = 3
in a cell. What is the next statement soprint(a, b)
shows3, a
asb
refers toa
, asa
refers to3
.