Evaluating a form field at a point on vectors in SageMath - sage

I am having trouble matching up terminology in my textbook (Hubbard's Vector Calculus) against SageMath operators. I'd like to understand how to solve the following example problem with Sage:
Let phi = cos(x z) dx /\ dy be a 2-form on R^3. Evaluate it at the point (1, 2, pi) on the vectors [1, 0, 1], [2, 2, 3].
The expected answer is:
cos (1 * pi) * Matrix([1, 2], [0, 2]).det() = -2
So far I have pieced together the following:
E.<x,y,z> = EuclideanSpace(3, 'E')
f = E.diff_form(2, 'f')
f[1, 2] = cos(x * z)
point = E((1,2,pi), name='point')
anchor = f.at(point)
v1 = vector([1, 0, 1])
v2 = vector([2, 2, 3])
show(anchor(v1, v2))
which fails with the error:
TypeError: the argument no. 1 must be a module element
To construct a vector in E, I tried:
p1 = E(v1.list())
p2 = E(v2.list())
show(anchor(p1, p2))
but that fails with the same error. What's the right way to construct two vectors in E?

Almost there.
To evaluate the 2-form at point p,
use vectors based at p.
sage: T = E.tangent_space(point)
sage: T
Tangent space at Point point on the Euclidean space E
sage: pv1 = T(v1)
sage: pv2 = T(v2)
sage: pv1
Vector at Point point on the Euclidean space E
sage: pv2
Vector at Point point on the Euclidean space E
sage: anchor(pv1, pv2)
-2

Related

How do I use method lagrange_polynomial over a PolynomialRing of Integers?

R.<x> = PolynomialRing(RR)
points = [(1,2), (2,2), (3,6)]
R.lagrange_polynomial(points)
2.00000000000000*x^2 - 6.00000000000000*x + 6.00000000000000
The above works fine but since all the coefficients are integers, I would prefer to do this over integers.
However when I try with
R.<x> = PolynomialRing(ZZ)
R.lagrange_polynomial(points)
I get the error
AttributeError: 'PolynomialRing_integral_domain_with_category' object has no attribute 'lagrange_polynomial'
I know I can use QQ instead of RR & get the coefficients printed as integers, but I am wondering why ZZ is not allowed?
The Lagrange polynomial for three points in ZZ^2 does not
always have coefficients in ZZ, so it makes sense to have
it as a method of QQ['x'] and not of ZZ['x'].
sage: R.<x> = PolynomialRing(QQ)
sage: points = [(0, 1), (1, 0), (2, 2)]
sage: R.lagrange_polynomial(points)
3/2*x^2 - 5/2*x + 1
Since for points = [(1, 2), (2, 2), (3, 6)] the Lagrange
polynomial's coefficients end up being integers, one can do:
sage: R.<x> = PolynomialRing(ZZ)
sage: points = [(1, 2), (2, 2), (3, 6)]
sage: q = R.change_ring(QQ).lagrange_polynomial(points)
sage: q
2*x^2 - 6*x + 6
sage: parent(q)
Univariate Polynomial Ring in x over Rational Field
sage: p = R(q)
sage: p
2*x^2 - 6*x + 6
sage: parent(p)
Univariate Polynomial Ring in x over Integer Ring

Walking through multidimensional space in a proper way

Assuming I have a vector of say four dimensions in which every variable lays in a special interval. Thus we got:
Vector k = (x1,x2,x3,x4) with x1 = (-2,2), x2 = (0,2), x3 = (-4,1), x4 = (-1,1)
I am only interested in the points constraint by the intervals.
So to say v1 = (0,1,2,0) is important where v2 = (-5,-5,5,5) is not.
In additon to that the point i+1 should be relatively close to point i among my journey. Therefore I dont want to jump around in space.
Is there a proper way of walking through those interesting points?
For example in 2D space with x1,x2 = (-2,2) like so:
Note: The frequenz of the red line could be higher
There are many ways to create a space-filling curve while preserving closeness. See the Wikipedia article for a few examples (some have associated algorithms for generating them): https://en.wikipedia.org/wiki/Space-filling_curve
Regardless, let's work with your zig-zag pattern for 2D and work on extending it to 3D and 4D. To extend it into 3D, we just add another zig to the zig-zag. Take a look at the (rough) diagram below:
Essentially, we repeat the pattern that we had in 2D but we now have multiple layers that represent the third dimension. The extra zig that we need to add is the switch between bottom-to-top and top-to-bottom every layer. This is pretty simple to abstract:
In 2D, we have x and y axes.
We move across the x domain switching between positive and negative
directions most frequently.
We move across the y domain once.
In 3D, we have x, y, and z axes.
We move across the x domain switching between positive and negative directions most frequently.
We move across the y domain switching between positive and negative directions second most frequently.
We move across the z domain once.
It should be clear how this generalizes to higher dimensions. Now, I'll present some (Python 3) code that implements the zig-zag pattern for 4D. Let's represent the position in 4D space as (x, y, z, w) and the ranges in each dimension as (x0, x1), (y0, y1), (z0, z1), (w0, w1). These are our inputs. Then, we also define xdir, ydir, and zdir to keep track of the direction of the zig-zag.
x, y, z, w = x0, y0, z0, w0
xdir, ydir, zdir = +1, +1, +1
for iw in range(w1 - w0):
for iz in range(z1 - z0):
for iy in range(y1 - y0):
for ix in range(x1 - x0):
print(x, y, z, w)
x = x + xdir
xdir = -xdir
print(x, y, z, w)
y = y + ydir
ydir = -ydir
print(x, y, z, w)
z = z + zdir
zdir = -zdir
print(x, y, z, w)
w = w + 1
This algorithm has the guarantee that no two points printed out after each other have a distance greater than 1.
Using recursion, you can clean this up to make a very nice generalizable method. I hope this helps; let me know if you have any questions.
With the work of #Matthew Miller I implemented this generalization for any given multidimenisonal space:
'''assuming that we take three points out of our intervals [0,2] for a,b,c
which every one of them is corresponding to one dimension i.e. a 3D-space'''
a = [0,1,2]
b = [0,1,2]
c = [0,1,2]
vec_in = []
vec_in.append(a)
vec_in.append(b)
vec_in.append(c)
result = []
hold = []
dir = [False] * len(vec_in)
def create_points(vec , index, temp, desc):
if (desc):
loop_x = len(vec[index])-1
loop_y = -1
loop_z = -1
else:
loop_x = 0
loop_y = len(vec[index])
loop_z = 1
for i in range(loop_x,loop_y,loop_z):
temp.append(vec[index][i])
if (index < (len(vec) - 1)):
create_points(vec, index + 1, temp, dir[index])
else:
u = []
for k in temp:
u.append(k)
result.append(u)
temp.pop()
if (dir[index] == False):
dir[index] = True
else:
dir[index] = False
if len(temp) != 0:
temp.pop()
#render
create_points(vec_in, 0, hold, dir[0])
for x in (result):
print(x)
The result is a journey which covers every possible postion in a continous way:
[0, 0, 0]
[0, 0, 1]
[0, 0, 2]
[0, 1, 2]
[0, 1, 1]
[0, 1, 0]
[0, 2, 0]
[0, 2, 1]
[0, 2, 2]
[1, 2, 2]
[1, 2, 1]
[1, 2, 0]
[1, 1, 0]
[1, 1, 1]
[1, 1, 2]
[1, 0, 2]
[1, 0, 1]
[1, 0, 0]
[2, 0, 0]
[2, 0, 1]
[2, 0, 2]
[2, 1, 2]
[2, 1, 1]
[2, 1, 0]
[2, 2, 0]
[2, 2, 1]
[2, 2, 2]

How to get a linsolve solution in matrix form?

Im using SymPy in Julia. My purpose is to solve a homogeneous system of linear equations (Ax=0) with more unknowns than variables (A is not square).
Then, Im using the following code.
using SymPy
x, y, z, w = symbols("x y z w")
M = sympy.Matrix(((9, 2, 1,- 4, 0), (-4, -3, -1, -5, 0)))
s = linsolve(M, (x, y, z, w))
With this code Im able to get the correct solution. However, I´dont known how to manipulate that solution.
The final goal is to be able to get the solution in matrix form as lines representing (x and y) and column (z and w). (since x(z, w) and y(z,w)).
Thanks
If numerical (rather than symbolic) computations are acceptable, then this will get the job done:
julia> using LinearAlgebra
julia> M = rand(2,4)
2×4 Array{Float64,2}:
0.497965 0.704514 0.152799 0.69448
0.594486 0.695488 0.327688 0.710573
julia> Q,R = qr(M);
C = -R[1:2,1:2]\R[1:2,3:4]
xy(zw) = C*zw;
# Check that `[xy(zw); zw]` is indeed in the nullspace of `M`:
julia> zw = rand(2)
M*[xy(zw);zw]
2-element Array{Float64,1}:
-2.7755575615628914e-17
-1.1102230246251565e-16

Binary Vector in GF(2) to integer

I am using the CAS SAGE. I have a vector v belonging GF(2). How I will be able to find the integer representation of this vector? Any example please?
aux = random_matrix(GF(2), n,2*n)
for i in range(2*n):
x = ZZ(list(aux[:,i]), base=2)
Assuming I understand you, you have a vector living in a space over GF(2):
sage: V = VectorSpace(GF(2), 5)
sage: V
Vector space of dimension 5 over Finite Field of size 2
sage: v = V.random_element()
sage: v
(0, 1, 0, 1, 1)
There are lots of ways to convert this to an Integer, and lots of equally valid representations. One natural one would be:
sage: i = ZZ(list(v), base=2)
sage: i
26
sage: parent(i)
Integer Ring
sage: i.digits(2)
[0, 1, 0, 1, 1]

Code or formula for intersection of two parabolas in any rotation

I am working on a geometry problem that requires finding the intersection of two parabolic arcs in any rotation. I was able to intesect a line and a parabolic arc by rotating the plane to align the arc with an axis, but two parabolas cannot both align with an axis. I am working on deriving the formulas, but I would like to know if there is a resource already available for this.
I'd first define the equation for the parabolic arc in 2D without rotations:
x(t) = ax² + bx + c
y(t) = t;
You can now apply the rotation by building a rotation matrix:
s = sin(angle)
c = cos(angle)
matrix = | c -s |
| s c |
Apply that matrix and you'll get the rotated parametric equation:
x' (t) = x(t) * c - s*t;
y' (t) = x(t) * s + c*t;
This will give you two equations (for x and y) of your parabolic arcs.
Do that for both of your rotated arcs and subtract them. This gives you an equation like this:
xa'(t) = rotated equation of arc1 in x
ya'(t) = rotated equation of arc1 in y.
xb'(t) = rotated equation of arc2 in x
yb'(t) = rotated equation of arc2 in y.
t1 = parametric value of arc1
t2 = parametric value of arc2
0 = xa'(t1) - xb'(t2)
0 = ya'(t1) - yb'(t2)
Each of these equation is just a order 2 polynomial. These are easy to solve.
To find the intersection points you solve the above equation (e.g. find the roots).
You'll get up to two roots for each axis. Any root that is equal on x and y is an intersection point between the curves.
Getting the position is easy now: Just plug the root into your parametric equation and you can directly get x and y.
Unfortunately, the general answer requires solution of a fourth-order polynomial. If we transform coordinates so one of the two parabolas is in the standard form y=x^2, then the second parabola satisfies (ax+by)^2+cx+dy+e==0. To find the intersection, solve both simultaneously. Substituting in y=x^2 we see that the result is a fourth-order polynomial: (ax+bx^2)^2+cx+dx^2+e==0. Nils solution therefore won't work (his mistake: each one is a 2nd order polynomial in each variable separately, but together they're not).
It's easy if you have a CAS at hand.
See the solution in Mathematica.
Choose one parabola and change coordinates so its equation becomes y(x)=a x^2 (Normal form).
The other parabola will have the general form:
A x^2 + B x y + CC y^2 + DD x + EE y + F == 0
where B^2-4 A C ==0 (so it's a parabola)
Let's solve a numeric case:
p = {a -> 1, A -> 1, B -> 2, CC -> 1, DD -> 1, EE -> -1, F -> 1};
p1 = {ToRules#N#Reduce[
(A x^2 + B x y + CC y^2 + DD x + EE y +F /. {y -> a x^2 } /. p) == 0, x]}
{{x -> -2.11769}, {x -> -0.641445},
{x -> 0.379567- 0.76948 I},
{x -> 0.379567+ 0.76948 I}}
Let's plot it:
Show[{
Plot[a x^2 /. p, {x, -10, 10}, PlotRange -> {{-10, 10}, {-5, 5}}],
ContourPlot[(A x^2 + B x y + CC y^2 + DD x + EE y + F /. p) ==
0, {x, -10, 10}, {y, -10, 10}],
Graphics[{
PointSize[Large], Pink, Point[{x, x^2} /. p /. p1[[1]]],
PointSize[Large], Pink, Point[{x, x^2} /. p /. p1[[2]]]
}]}]
The general solution involves calculating the roots of:
4 A F + 4 A DD x + (4 A^2 + 4 a A EE) x^2 + 4 a A B x^3 + a^2 B^2 x^4 == 0
Which is done easily in any CAS.

Resources