I need to test an n-variable Boolean Function f = f(x0,...,xn-1). I need to fix x0, then run some tests for the g1 = f(x1,...,xn-1), then fix x1 and so on.
The problem is that I don't really understand how to do it with Sage.
At first, I tried to create a vector of values, that controls "fixing" of the variables
R.<x0,x1,x2,x3> = BooleanPolynomialRing()
v = [None,1,None, 0]
if v[0] != None:
x0=v[0]
if v[1] != None:
x1=v[1]
if v[2] != None:
x2=v[2]
if v[3] != None:
x3=v[3]
f = BooleanFunction(x0+x3+x0*x1+x0*x1*x2)
print(f.algebraic_normal_form())
output:x0*x2
This works fine, but it doesn't fit my task because I want to be able to automate the fixing process.
I want to replace the "if"s with a loop, but in this case, I don't know how to address variables inside the loop using indexes.
I'm new to Sage so I would appreciate any advice!
I'm not sure what BooleanFunction is, but:
sage: R.<x0, x1, x2, x3> = BooleanPolynomialRing()
If at this point you do something like x1 = 1, then x1 is no longer a generator of this ring, so let's try to avoid that.
sage: f = x0 + x3 + x0*x1 + x0*x1*x2 # f is in R
sage: f.substitute({x1: 1})
x0*x2 + x3
I think what you want is a good way to carry out the substitute part of this.
A helpful observation: you can convert strings to variable names:
sage: R('x0')
x0
So:
sage: d = {}
sage: for i in range(len(v)):
....: if v[i] is not None:
....: d[R('x' + str(i))] = v[i]
....:
sage: d
{x1: 1, x3: 0}
sage: f.substitute(d)
x0*x2
The code can now be made more compact in two ways.
Call x the list of generators and use x[i] rather than R('x' + str(i)'):
sage: R.<x0, x1, x2, x3> = BooleanPolynomialRing()
sage: x = R.gens()
sage: x[0]*x[3] + x[1]*x[2]*x[3]
x0*x3 + x1*x2*x3
Use comprehension syntax rather than empty dictionary and for loop:
sage: f = x0 + x3 + x0*x1 + x0*x1*x2
sage: v = [None, 1, None, 0]
sage: f.subs({x[i]: vi for i, vi in enumerate(v) if vi is not None})
x0*x2
Related
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
I need to operate on a sequence of functions
h_k(x) = (I + f_k( ) )^k g(x)
for each k=1,...,N.
A basic example (N=2, f_k=f) is the following:
f(x) = x^2
g(x) = x
h1(x) = g(x) + f(g(x))
h2(x) = g(x) + f(g(x)) + f(g(x) + f(g(x)))
println(h1(1)) # returns 2
println(h2(1)) # returns 6
I need to write this in a loop and it would be best to redefine g(x) at each iteration. Unfortunately, I do not know how to do this in Julia without conflicting with the syntax for a recursive definition of g(x). Indeed,
f(x) = x^2
g(x) = x
for i=1:2
global g(x) = g(x) + f(g(x))
println(g(1))
end
results in a StackOverflowError.
In Julia, what is the proper way to redefine g(x), using its previous definition?
P.S. For those who would suggest that this problem could be solved with recursion: I want to use a for loop because of how the functions f_k(x) (in the above, each f_k = f) are computed in the real problem that this derives from.
I am not sure if it is best, but a natural approach is to use anonymous functions here like this:
let
f(x) = x^2
g = x -> x
for i=1:2
l = g
g = x -> l(x) + f(l(x))
println(g(1))
end
end
or like this
f(x) = x^2
g = x -> x
for i=1:4
l = g
global g = x -> l(x) + f(l(x))
println(g(1))
end
(I prefer the former option using let as it avoids using global variables)
The issue is that l is a loop local variable that gets a fresh binding at each iteration, while g is external to the loop.
You might also check out this section of the Julia manual.
I would like to expand the symbol function $f(x)$ as a Taylor series in SageMath
$$\delta f(x)=\delta x\frac{d}{dx}f+\frac12(\delta x)^2\frac{d^2}
{dx^2}f+O((\delta x)^3)$$
with
$$\delta x = a_1(\delta t)^{\frac12}+a_2(\delta t)+a_3(\delta t)^{\frac32}+O((\delta t)^2)$$
And expand and collect the same power terms of $\delta t$ up to a designated power, say, $\frac32$. $f$ is just a symbol, I just need Mathsage to produce the symbols of derivatives $\frac{d}{dx}$.
How should one set this up in SageMath?
Is this what you want to do?
sage: f = function('f', nargs=1)(x)
sage: f
f(x)
sage: f.taylor(x, 0, 2)
1/2*x^2*D[0, 0](f)(0) + x*D[0](f)(0) + f(0)
With sympy, you would do something like this to get the Taylor series.
import sympy
dt = sympy.Symbol('dt')
a1 = sympy.Symbol('a1')
a2 = sympy.Symbol('a2')
a3 = sympy.Symbol('a3')
dx = a1*dt**(1/2) + a2*dt + a3*dt**(3/2)
from sympy.abc import x
f = sympy.Function('f')(x)
df = dx*sympy.diff(f,x) + 1/2*dx**2*sympy.diff(f,x,2)
df.series(x)
This is assuming x and δx are independent.
I'm a beginner to Prolog and have two requirements:
f(1) = 1
f(x) = 5x + x^2 + f(x - 1)
rules:
f(1,1).
f(X,Y) :-
Y is 5 * X + X * X + f(X-1,Y).
query:
f(4,X).
Output:
ERROR: is/2: Arguments are not sufficiently instantiated
How can I add value of f(X-1)?
This can be easily solved by using auxiliary variables.
For example, consider:
f(1, 1).
f(X, Y) :-
Y #= 5*X + X^2 + T1,
T2 #= X - 1,
f(T2, T1).
This is a straight-forward translation of the rules you give, using auxiliary variables T1 and T2 which stand for the partial expressions f(X-1) and X-1, respectively. As #BallpointBen correctly notes, it is not sufficient to use the terms themselves, because these terms are different from their arithmetic evaluation. In particular, -(2,1) is not the integer 1, but 2 - 1 #= 1 does hold!
Depending on your Prolog system, you may ned to currently still import a library to use the predicate (#=)/2, which expresses equality of integer expressesions.
Your example query now already yields a solution:
?- f(4, X).
X = 75 .
Note that the predicate does not terminate universally in this case:
?- f(4, X), false.
nontermination
We can easily make it so with an additional constraint:
f(1, 1).
f(X, Y) :-
X #> 1,
Y #= 5*X + X^2 + T1,
T2 #= X - 1,
f(T2, T1).
Now we have:
?- f(4, X).
X = 75 ;
false.
Note that we can use this as a true relation, also in the most general case:
?- f(X, Y).
X = Y, Y = 1 ;
X = 2,
Y = 15 ;
X = 3,
Y = 39 ;
X = 4,
Y = 75 ;
etc.
Versions based on lower-level arithmetic typically only cover a very limited subset of instances of such queries. I therefore recommend that you use (#=)/2 instead of (is)/2. Especially for beginners, using (is)/2 is too hard to understand. Take the many related questions filed under instantiation-error as evidence, and see clpfd for declarative solutions.
The issue is that you are trying to evaluate f(X-1,Y) as if it were a number, but of course it is a predicate that may be true or false. After some tinkering, I found this solution:
f(1,1).
f(X,Y) :- X > 0, Z is X-1, f(Z,N), Y is 5*X + X*X + N.
The trick is to let it find its way down to f(1,N) first, without evaluating anything; then let the results bubble back up by satisfying Y is 5*X + X*X + N. In Prolog, order matters for its search. It needs to satisfy f(Z,N) in order to have a value of N for the statement Y is 5*X + X*X + N.
Also, note the condition X > 0 to avoid infinite recursion.
I am using the following map in Sage:
f = lambda x: sgn(x)*sgn(x);
which evaluates to f(x) = 0 for x=0 and f(x)=1 for x!=0;
In symbolic results, sgn(x)^2, sgn(x)^4 and sgn(x)^8, etc. are being treated as unequal, even though they are equal for all values of x. Is there a way that I can substitute something like:
sgn(x)^2 == sgn(x)^4 == sgn(x)^8
for all occurrences of these relations, and for all symbolic values of x?
I could create a new substitution rule for every symbol, e.g.
result.subs(sgn(c)^2 == sgn(c)^4).subs(sgn(d)^2 == sgn(d)^4)...
and so on, but that seems hard to control.
This is perhaps a dumb question for me to ask... is the nature of your result one that you could just factor?
sage: f(x) = sgn(x)^2
sage: f
x |--> sgn(x)^2
sage: Z = (1+f)^3
sage: Z = Z.expand()
sage: Z
x |--> sgn(x)^6 + 3*sgn(x)^4 + 3*sgn(x)^2 + 1
sage: Z.factor()
x |--> (sgn(x)^2 + 1)^3
In which case it makes your question moot, hopefully:
sage: Z.subs(sgn(x)^2==x)
x |--> (x + 1)^3
not that that is your subs, just as an example.
Apparently Sage allows for the use of wildcards in substitution (here's the example that tipped me off). So I did something like:
var('a,b,c,d,e,f');
w = SR.wild(0);
result = f(a,b,c,d,e,f).subs(sgn(w)^4 == sgn(w)^2).subs(sgn(w)^8 == sgn(w)^2);
And it worked! Much easier.