I have some truth table in GF(2) and I compute the corresponding Algebraic Normal Form (ANF) or Zhegalkin polynomial. Below a dummy example with two variables.
from sympy.logic.boolalg import ANFform
from sympy.abc import x, y
truth_table = [0, 1, 1, 1]
expr = ANFform([x, y], truth_table)
which prints
x ^ y ^ (x & y)
I would then like to extract and select the individuals monomials of the resulting expression.
For example, I would have something like this:
expr_monoms[2] # (x & y)
How to achieve this?
You can use .args:
In [50]: from sympy.logic.boolalg import ANFform
...: from sympy.abc import x, y
...:
...: truth_table = [0, 1, 1, 1]
...:
...: expr = ANFform([x, y], truth_table)
In [51]: expr
Out[51]: x ⊻ y ⊻ (x ∧ y)
In [52]: expr.args[2]
Out[52]: x ∧ y
Related
I tried this:
import z3
n,x,y,z = z3.Ints('n x y z')
s = z3.Solver()
s.add(4/n==1/x+1/y+1/z)
s.add(x>0)
s.add(n>0)
s.add(y>0)
s.add(z>0)
s.check()
s.model()
and I get:
[x = 1, n = 2, z = 3, y = 1, div0 = [(1, 1) → 1, (4, 2) → 2, else → 0], mod0 = [(1, 3) → 1, else → 0]]
But 4/2 does not equal 1/1+1/1+1/3.
What am I doing wrong?
You've declared n, x, y, z as integers. So division is done as an integer, giving you 1/1 = 1 and 1/3 = 0; hence satisfying the equality 2=2.
The obvious thing to do is to use Real values for this problem.
Changing the declaration to:
n,x,y,z = z3.Reals('n x y z')
produces:
[z = 1, y = 1, n = 4/3, x = 1]
which does satisfy the equation you posed trivially.
In case you actually do want n, x, y, z to be integers; then you should convert them to reals before you divide, like this:
import z3
n,x,y,z = z3.Ints('n x y z')
s = z3.Solver()
s.add(4/z3.ToReal(n)==1/z3.ToReal(x)+1/z3.ToReal(y)+1/z3.ToReal(z))
s.add(x>0)
s.add(n>0)
s.add(y>0)
s.add(z>0)
print(s.check())
print(s.model())
This prints:
sat
[n = 4, x = 3, z = 3, y = 3]
again satisfying your constraints.
I am currently have an array that has the bounds for an integral (bounds_symbolic). I am trying to substitute the symbolic bounds with an array of values.
At a high level, what I am trying to do is solve the following integral (here it is using the variable names):
integral_variables
And here is an example:
example_integral
Here is my code thus far:
import sympy
import numpy as np
a, b, x, y = sympy.symbols("a b x y")
# Equation of the ellipse solved for y
ellipse = sympy.sqrt((b ** 2) * (1 - ((x ** 2) / (a ** 2))))
# Functions to be tested
test_functions = [(a * b * x), (((a * b) ** 2) * x), (((a * b) ** 3) * x), (((a * b) ** 4) * x), (((a * b) ** 5) * x)]
# Equating ellipse and test_functions so their intersection can be symbolically solved for
equate = [sympy.Eq(ellipse, test_functions[0]), sympy.Eq(ellipse, test_functions[1]), sympy.Eq(ellipse, test_functions[2]), sympy.Eq(ellipse, test_functions[3]), sympy.Eq(ellipse, test_functions[4])]
# Calculating the intersection points of the ellipse and the testing functions
# Array that holds the bounds of the integral solved symbolically
bounds_symbolic = []
for i in range(0, 3):
bounds_symbolic.append(sympy.solve(equate[i], x))
# Array of a-values to plug into the bounds of the integral
a_values = np.linspace(-10, 10, 201)
# Setting b equal to a constant of 1
b = 1
integrand = []
for j in range(0, 3):
integrand.append(ellipse - test_functions[j])
# New array with a-values substituted into the bounds
bounds_a = bounds_symbolic
for j in range(0, 201):
bounds_a.subs(a, a_values[j])
When I run it, I get an error when I attempt to perform bounds_a.subs(a, a_values[j]) operation:
AttributeError: 'list' object has no attribute 'subs'
What I would like to have happen is that the bounds_a array has the same bounds that I solved for above, but with all of the "a" values substituted into it, as opposed to just having a symbolic "a". I would also like to be able to substitute in a "b" value of 1.
How would I go about doing this? Would it be better if I used a NumPy array instead of a list?
Thank you!
In an isympy session with x defined as a variable:
In [51]: x
Out[51]: x
I can make a list of expressions:
In [52]: alist = [2*x, 3*x, 4+x]
and perform subs on each of them:
In [53]: [expr.subs({x:12}) for expr in alist]
Out[53]: [24, 36, 16]
and multiple subs:
In [54]: [[expr.subs({x:val}) for expr in alist] for val in [1,2,3]]
Out[54]: [[2, 3, 5], [4, 6, 6], [6, 9, 7]]
With lambdify I can create a function that takes a numpy array as input (default is numpy mode):
In [61]: f = lambdify(x, alist)
In [62]: print(f.__doc__)
Created with lambdify. Signature:
func(x)
Expression:
[2*x, 3*x, x + 4]
Source code:
def _lambdifygenerated(x):
return ([2*x, 3*x, x + 4])
I can give f a number:
In [63]: [f(i) for i in [1,2,3]]
Out[63]: [[2, 3, 5], [4, 6, 6], [6, 9, 7]]
or array:
In [64]: f(np.array([1,2,3]))
Out[64]: [array([2, 4, 6]), array([3, 6, 9]), array([5, 6, 7])]
I have an expression in sympy that is a linear combination of an evaluated function, f. Schematically
expr = Sum_{m,n} c_{m,n} f(x+a_m,y+a_n)
where c_{m,n} is a coefficient depending on the variables x,y. A very simple example is
import sympy as sp
x, y = sp.symbols("x, y")
f = sp.Function("f")(x,y)
expr = 0
for i in range(0,3):
expr += (x-i)* f.subs({x: x+2*i, y: y+3*i})
In my actual code expr is the result of a long succession of sums and the function g not simplify like here. Is there an efficient way of grouping functions with different argument together, like collect(expr) does for polynomials? What I am after is to obtain a structured list:
In: someFunction(...)
Out: [..., [c_{m,n}, x+a_m, y+a_n ], ...]
in the example above
In: someFunction(expr)
Out: [[x, x, y], [x - 1, x + 2, y + 3], [x - 2, x + 4, y + 6]]
I'm not sure if this does exactly what you want but you can use pattern matching:
In [27]: expr
Out[27]: x⋅f(x, y) + (x - 2)⋅f(x + 4, y + 6) + (x - 1)⋅f(x + 2, y + 3)
In [28]: a, b, c = symbols('a, b, c', cls=Wild)
In [29]: pattern = a*f(b, c)
In [30]: for term in Add.make_args(expr):
...: print(term.match(pattern))
...:
{b_: x, c_: y, a_: x}
{b_: x + 2, c_: y + 3, a_: x - 1}
{b_: x + 4, c_: y + 6, a_: x - 2}
I am trying to construct polynomials over a two-valued finite field {0, 1}, and I want them to automatically simplify using some identities that exist in this setting.
I have tried the following:
from sympy import *
from sympy.polys.domains.finitefield import FiniteField
x, y, z, t = symbols('x y z t')
k = Poly(x+y * z*z + (x + y) + y + 1, domain=FiniteField(2))
This already simplifies to:
Poly(y*z**2 + 1, x, y, z, modulus=2)
However, the z**2 is actually the same as z in the field that I want to use. It does seem to automatically recognize that y + y = 0. How can I implement the other identity, z * z = z (idempotency)?
What you want doesn't seem to implemented for poly but maybe you can simulate the effect:
In [54]: normalise = lambda p: Poly(ratsimpmodprime(p, [n**2-n for n in p.free_symbols]), modulus=2)
In [55]: e = x+y * z*z + (x + y) + y + 1
In [56]: normalise(e)
Out[56]: Poly(y*z + 1, x, y, z, modulus=2)
Given an array of x and y values, the following code will calculate a regression curve for these data points.
# calculate polynomial
z = np.polyfit(x, y, 5)
f = np.poly1d(z)
# calculate new x's and y's
x_new = np.linspace(x[0], x[-1], 50)
y_new = f(x_new)
plt.plot(x,y,'o', x_new, y_new)
plt.xlim([x[0]-1, x[-1] + 1 ])
plt.show()
How can I use the above to derive the actual equation for this curve?
If you want to show the equation, you can use sympy to output latex:
from sympy import S, symbols, printing
from matplotlib import pyplot as plt
import numpy as np
x=np.linspace(0,1,100)
y=np.sin(2 * np.pi * x)
p = np.polyfit(x, y, 5)
f = np.poly1d(p)
# calculate new x's and y's
x_new = np.linspace(x[0], x[-1], 50)
y_new = f(x_new)
x = symbols("x")
poly = sum(S("{:6.2f}".format(v))*x**i for i, v in enumerate(p[::-1]))
eq_latex = printing.latex(poly)
plt.plot(x_new, y_new, label="${}$".format(eq_latex))
plt.legend(fontsize="small")
plt.show()
the result:
Construct a simple example:
In [94]: x=np.linspace(0,1,100)
In [95]: y=2*x**3-3*x**2+x-1
In [96]: z=np.polyfit(x,y,3)
In [97]: z
Out[97]: array([ 2., -3., 1., -1.])
The z coefficients correspond to the [2,-3,1,-1] I used to construct y.
In [98]: f=np.poly1d(z)
In [99]: f
Out[99]: poly1d([ 2., -3., 1., -1.])
The str, or print, string for f is a representation of this polynomial equation. But it's the z coeff that defines the equation.
In [100]: print(f)
3 2
2 x - 3 x + 1 x - 1
In [101]: str(f)
Out[101]: ' 3 2\n2 x - 3 x + 1 x - 1'
What else do you mean by 'actual equation'?
polyval will evaluate f at a specific set of x. Thus to recreate y, use polyval(f,x):
In [107]: np.allclose(np.polyval(f,x),y)
Out[107]: True
If you only want to see the equation on your screen to get an impression about the equation, you only need to add the below line:
print(f)
Here comes more details:
polyfit returns a vector of coefficients of the polynomial fit. poly1d takes this vector and make a polynomial function out of it.
For example (from Numpy documentation for poly1d ):
p = np.poly1d([1, 2, 3])
>>> print(np.poly1d(p))
2
1 x + 2 x + 3