91 lines
2.6 KiB
ReStructuredText
91 lines
2.6 KiB
ReStructuredText
♻️ Evaluation of cyclic-:math:`n` polynomials
|
|
*******************************************************
|
|
|
|
Bertini is software for algebraic geometry. This means we work with systems of polynomials, a critical component of which is system and function evaluation.
|
|
|
|
Bertini2 allows us to set up many kinds of functions, and thus systems, by exploting operator overloading.
|
|
|
|
Make some symbols
|
|
==================
|
|
|
|
Let's start by making some variables, programmatically [1]_.
|
|
|
|
::
|
|
|
|
import pybertini
|
|
import numpy
|
|
|
|
num_vars = 10
|
|
x = [None] * num_vars # preallocate the list
|
|
for ii in range(num_vars):
|
|
x[ii] = pybertini.Variable('x' + str(ii))
|
|
|
|
Huzzah, we have `num_vars` variables! This was hard to do in Bertini 1's classic style input files. Now we can do it directly! 🎯
|
|
|
|
Write a function to produce the cyclic :math:`n` polynomials :cite:`cyclic_n`.
|
|
|
|
::
|
|
|
|
def cyclic(vars):
|
|
n = len(vars)
|
|
f = [None] * len(vars)
|
|
y = []
|
|
for ii in range(2):
|
|
for x in vars:
|
|
y.append(x)
|
|
|
|
for ii in range(n-1):
|
|
f[ii] = numpy.sum( [numpy.prod(y[jj:jj+ii+1]) for jj in range(n)] )
|
|
|
|
# the last one is minus one
|
|
f[-1] = numpy.prod(vars)-1
|
|
return f
|
|
|
|
Now we will make a System, and put the cyclic polynomials into it.
|
|
|
|
::
|
|
|
|
sys = pybertini.System()
|
|
|
|
for f in cyclic(x):
|
|
sys.add_function(f)
|
|
|
|
print(sys) # long screen output, i know
|
|
|
|
We also need to associate the variables with the system. Unassociated variables are left unknown, and retain their value until elsewhere set.
|
|
|
|
::
|
|
|
|
vg = pybertini.VariableGroup()
|
|
for var in x:
|
|
vg.append(var)
|
|
sys.add_variable_group(vg)
|
|
|
|
Let's simplify this. It will modify elements of the constructed function tree, even those held externally -- Bertini uses shared pointers under the hood, so pay attention to where you re-use parts of your functions, because later modification of them without deep cloning will cause ... modification elsewhere, too.
|
|
|
|
::
|
|
|
|
pybertini.system.simplify(sys)
|
|
|
|
Now, let's evaluate it at the origin -- all zero's (0 is the default value for multiprecision complex numbers in Bertini2). The returned value should be all zero's except the last entry, which should be -1.
|
|
|
|
::
|
|
|
|
s = pybertini.multiprec.Vector()
|
|
s.resize(num_vars)
|
|
sys.eval(s)
|
|
|
|
Yay, all zeros, except the last one is -1. Huzzah.
|
|
|
|
Let's change the values of our vector, and re-evaluate.
|
|
|
|
::
|
|
|
|
for ii in range(num_vars):
|
|
s[ii] = pybertini.multiprec.Complex(ii)
|
|
sys.eval(s)
|
|
|
|
|
|
There is much more one can do, too! Please write the authors, particularly Dani Brake, for more.
|
|
|
|
.. [1] This is one of the reasons we wrote Bertini2's symbolic C++ core and exposed it to Python. |