Can I substitute using a symbolic equation in Sage? - sage

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.

Related

Ways of using(assigning) variables in Sage

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

Reassign function and avoid recursive definition in Julia

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.

How to work with the result of the wild sympy

I have the following code:
f=tan(x)*x**2
q=Wild('q')
s=f.match(tan(q))
s={q_ : x}
How to work with the result of the "wild"? How to not address the array, for example, s[0], s{0}?
Wild can be used when you have an expression which is the result of some complicated calculation, but you know it has to be of the form sin(something) times something else. Then s[q] will be the sympy expression for the "something". And s[p] for the "something else". This could be used to investigate both p and q. Or to further work with a simplified version of f, substituting p and q with new variables, especially if p and q would be complex expressions involving multiple variables.
Many more use cases are possible.
Here is an example:
from sympy import *
from sympy.abc import x, y, z
p = Wild('p')
q = Wild('q')
f = tan(x) * x**2
s = f.match(p*tan(q))
print(f'f is the tangent of "{s[q]}" multiplied by "{s[p]}"')
g = f.xreplace({s[q]: y, s[p]:z})
print(f'f rewritten in simplified form as a function of y and z: "{g}"')
h = s[p] * s[q]
print(f'a new function h, combining parts of f: "{h}"')
Output:
f is the tangent of "x" multiplied by "x**2"
f rewritten in simplified form as a function of y and z: "z*tan(y)"
a new function h, combining parts of f: "x**3"
If you're interested in all arguments from tan that appear in f written as a product, you might try:
from sympy import *
from sympy.abc import x
f = tan(x+2)*tan(x*x+1)*7*(x+1)*tan(1/x)
if f.func == Mul:
all_tan_args = [a.args[0] for a in f.args if a.func == tan]
# note: the [0] is needed because args give a tupple of arguments and
# in the case of tan you'ld want the first (there is only one)
elif f.func == tan:
all_tan_args = [f.args[0]]
else:
all_tan_args = []
prod = 1
for a in all_tan_args:
prod *= a
print(f'All the tangent arguments are: {all_tan_args}')
print(f'Their product is: {prod}')
Output:
All the tangent arguments are: [1/x, x**2 + 1, x + 2]
Their product is: (x + 2)*(x**2 + 1)/x
Note that neither method would work for f = tan(x)**2. For that, you'ld need to write another match and decide whether you'ld want to take the same power of the arguments.

Prolog:: f(x) recursion

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.

solving equations and using values obtained in other calculations - SAGE

the function solve() in SAGE returns symbolic values for the variables i solve the equations for. for e.g:
sage: s=solve(eqn,y)
sage: s
[y == -1/2*(sqrt(-596*x^8 - 168*x^7 - 67*x^6 + 240*x^5 + 144*x^4 - 60*x - 4) + 8*x^4 + 11*x^3 + 12*x^2)/(15*x + 1), y == 1/2*(sqrt(-596*x^8 - 168*x^7 - 67*x^6 + 240*x^5 + 144*x^4 - 60*x - 4) - 8*x^4 - 11*x^3 - 12*x^2)/(15*x + 1)]
My problem is that i need to use the values obtained for y in other calculations, but I cannot assign these values to any other variable. Could someone please help me with this?
(1) You should visit ask.sagemath.org, the Stack Overflow-like forum for Sage users, experts, and developers! </plug>
(2) If you want to use the values of a solve() call in something, then it's probably easiest to use the solution_dict flag:
sage: x,y = var("x, y")
sage: eqn = x**4+5*x*y+3*x-y==17
sage: solve(eqn,y)
[y == -(x^4 + 3*x - 17)/(5*x - 1)]
sage: solve(eqn,y,solution_dict=True)
[{y: -(x^4 + 3*x - 17)/(5*x - 1)}]
This option gives the solutions as a list of dictionaries instead of a list of equations. We can access the results like we would any other dictionary:
sage: sols = solve(eqn,y,solution_dict=True)
sage: sols[0][y]
-(x^4 + 3*x - 17)/(5*x - 1)
and then we can assign that to something else if we like:
sage: z = sols[0][y]
sage: z
-(x^4 + 3*x - 17)/(5*x - 1)
and substitute:
sage: eqn2 = y*(5*x-1)
sage: eqn2.subs(y=z)
-x^4 - 3*x + 17
et cetera. While IMHO the above is more convenient, you could also access the same results without solution_dict via .rhs():
sage: solve(eqn,y)[0].rhs()
-(x^4 + 3*x - 17)/(5*x - 1)
If you have unknown number of variables you can use **kwargs to pass data calculated with solve to next expressions. Here's example:
B_set is an list of variables and its filled in runtime so i dont know
names of variables and their quantity at the time of writing the code
solution = solve(system_of_equations, B_set)[0]
pretty_print(solution)
For example this gives me:
result of solving system of equations
I cant use this answer for further calculations so lets convert it to usable form
solution = {str(elem.lhs()): elem.rhs() for elem in solution}
Which gives us:
result converted to dictionary with string keys
Then we just pass this as **kwargs
approximation = approximation_function(**solution)
pretty_print(approximation)
And that converts this:
approximation without values from solution
Into this:
approximation with values from solution
Note: if you use dictionary output from solve() you still need to convert keys to string.

Resources