SymPy can print Exponentiation base and exponent? - sympy

Thank you in advance and sorry for the bad english!
I want
1.x : how to Determination of Exponentiation , Determination possible?
2.print : base=b ,exponent=n
 WrongScript.py
from sympy import *
var('x y z a b n')
x=b**n
y=3**n
z=a
# output 1.---------------------------------
print("x=",x) # x= b**n,**
print("y=",y) # y= 3**n,**
print("z=",z) # z= a, not **
# output 2.---------------------------------
print(MyBaseOut(x),MyExponentOut(x)) # b,n
print(MyBaseOut(y),MyExponentOut(y)) # 3,n
def MyBaseOut(p):
# ans=?
return ans
def MyExponentOut(q):
# ans=?
return ans
2018-11-26------------------------------
FullScript.py
from sympy import *
var('b n')
def MyBaseOut(p):
return p.as_base_exp()[0]
def MyExponentOut(q):
return q.as_base_exp()[1]
x=b**n
y=3**n
print(MyBaseOut(x),MyExponentOut(x))
print(MyBaseOut(y),MyExponentOut(y))
# b n
# 3 n

The attribute is_Pow will tell you if it has an exponent other than 1 and the method as_base_exp() will tell you what the base and exponent are -- select element 0 for the base and element 1 for the exponent:
>>> [(i.is_Pow, i.as_base_exp()) for i in (y,1/y,y**2,y**z)]
[(False, (y, 1)), (True, (y, -1)), (True, (y, 2)), (True, (y, z))]

Related

How could I generate random coefficients for polynomials using Sum( f(x), (x,0,b) )?

from sympy import Sum, Eq
from sympy.abc import n,x
import random
def polynomial(x):
i = 0
def random_value(i):
return random.choice([i for i in range(-10,10) if i not in [0]])
eq = Sum(random_value(i)*x**n, (n,0,random_value(i)))
display(Eq(eq,eq.doit(), evaluate=False))
polynomial(x)
polynomial(x)
With this code, the coefficients are always the same.
Also, I am not sure if the algebra evaluations are correct for b < 0 .
One way is to use IndexedBase to generate symbolic-placeholder coefficients, and then substitute them with numerical coefficients.
from sympy import Sum, Eq, Matrix, IndexedBase
from sympy.abc import n, x
import random
def polynomial(x):
# n will go from zero to this positive value
to = random.randint(0, 10)
# generate random coefficients
# It is important for them to be a sympy Matrix or Tuple,
# otherwise the substitution (later step) won't work
coeff = Matrix([random.randint(-10, 10) for i in range(to + 1)])
c = IndexedBase("c")
eq = Sum(c[n]*x**n, (n, 0, to)).doit()
eq = eq.subs(c, coeff)
return eq
display(polynomial(x))
display(polynomial(x))
Another ways is to avoid using Sum, relying instead on list-comprehension syntax and builtin sum:
def polynomial(x):
to = random.randint(0, 10)
coeff = [random.randint(-10, 10) for i in range(to + 1)]
return sum([c * x**n for c, n in zip(coeff, range(to + 1))])
display(polynomial(x))
display(polynomial(x))
You can pass a list of coefficients (with highest order coefficient first and constant last) directly to Poly and then convert that to an expression:
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly([1,2,3,4], x)
Poly(x**3 + 2*x**2 + 3*x + 4, x, domain='ZZ')
>>> _.as_expr()
x**3 + 2*x**2 + 3*x + 4
>>> from random import randint, choice
>>> Poly([choice((-1,1))*randint(1,10) for i in range(randint(0, 10))], x).as_expr()
-3*x**4 + 3*x**3 - x**2 - 6*x + 2

Distance from a point to a line : output nan?

Thank you in advance and sorry for the bad English!
(ref)Distance from a point to a line < wikipedia
https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
from sympy import *
var('a b c x y x1 y1 x2 y2 x0 y0 co si tx ty d DH')
x1=0
y1=solve([a*x+b*y+c],[y])[y].subs({x:0})
x2=solve([a*x+b*y+c],[x])[x].subs({y:0})
y2=0
d=sqrt((x1-x2)**2+(y1-y2)**2)
v=solve([co*0-si*0+tx-x1,si*0+co*0+ty-y1,co*d-si*0+tx-x2,si*d+co*0+ty-y2],[co,si,tx,ty])
A=Matrix([
[v[co],-v[si],v[tx]],
[v[si], v[co],v[ty]],
[0 , 0, 1]
])
B=Matrix([
[x0],
[y0],
[ 1]
])
AinvB=A.inv()*B
DH=simplify(AinvB[1])
print(DH)
print(float(DH.subs({a:1,b:-1,c:10,x0:0,y0:11})))
print(float(DH.subs({a:1,b:-1,c: 0,x0:0,y0: 1})))
# -c*(a*x0 + b*y0 + c)/(a*b*sqrt(c**2*(a**2 + b**2)/(a**2*b**2)))
# -0.7071067811865476
# nan
The expression you generate is not always valid for all substituted values. In the case that gives nan your expression generates 0/0 which is nan.
>>> from sympy import S, fraction, Tuple
>>> eq=S('-c*(a*x0 + b*y0 + c)/(a*b*sqrt(c**2*(a**2 + b**2)/(a**2*b**2)))')
>>> n,d=fraction(eq)
>>> Tuple(n,d).subs(dict(a=1,b=-1,c=0,x0=0,y0=1))
(0, 0)
>>> _[0]/_[1]
nan
You might be interested in using SymPy's geometric objects to help with such calculations and (in this case) compare their expressions to what you generate by other means:
>>> from sympy.abc import b,m,x,y
>>> from sympy import Point, Line
>>> d=Point(x,y).distance(Line(m*x+b-y))
>>> d
sqrt((x-(-b*m+m*y+x)/(m**2+1))**2 + (y-(b+m**2*y+m*x)/(m**2+1))**2)
>>> d.subs(y, m*x+b).simplify()
0

Netwon's method without pre-built functions of Python: Calculation of gradient and Hessian

I am trying to write the basic Newton's method without pre-built solvers.
This is the function:
## definition of variables
x_1, x_2 = sym.symbols("x_1 x_2")
a_T=np.array([[0.3],[0.6],[0.2]])
b_T=np.array([5,26,3])
c_T=np.array([40,1,10])
u= x_1-0.8
v= x_2-(a_T[0]+a_T[1]*u**2*(1-u)**(1/2)-a_T[2]*u)
alpha= -b_T[0]+(b_T[1]*u**2)*(1+u)**(1/2)+(b_T[2])*u
beta= c_T[0]*v**2*(1-c_T[1]*v)/(1+c_T[2]*u**2)
## function
f = alpha**(-beta)
I calculated the gradient and the Hessian and defined the other parameters:
## gradient
gradient_cal = sym.Matrix(1,2,sym.derive_by_array(f, (x_1, x_2)))
## hessian
hessian_cal = sym.Matrix(2, 2, sym.derive_by_array(gradient_cal, (x_1, x_2)))
# initial guess
x_A= Matrix([[1],[0.5]])
xk = x_A
#tolerance
epsilon= 1e-10
#maximum iterations
max_iter=100
And the function itself:
def newton(gradient_cal,hessian_cal,xk,epsilon,max_iter):
for k in range(0,max_iter):
fxk = gradient_cal.evalf(subs={x_1:xk[0], x_2:xk[1]})
if fxk.norm() < epsilon:
print('Found solution after',k,'iterations.')
return xk
Dfxk = hessian_cal.evalf(subs={x_1: xk[0], x_2: xk[1]})
if Dfxk == 0:
print('Zero derivative. No solution found.')
return None
A=hessian_cal.evalf(subs={x_1: xk[0], x_2: xk[1]})
B=gradient_cal.evalf(subs={x_1: xk[0], x_2: xk[1]})
pk= (A.inv().dot(B))
xk = np.subtract(xk, pk)
print('Exceeded maximum iterations. No solution found.')
return None
approx = newton(gradient_cal,hessian_cal,x_A,epsilon,max_iter)
print(approx)
The following error shows up:
TypeError: Shape should contain integers only.
I checked it and saw that the Hessian contains "I" values. Therefore I am not sure if the calculations of the gradient and the Hessian are correct.
Does anyone have a better solution to calculate the gradient and the Hessian for such a complex function?
The jacobian-batteries are already included in SymPy:
>>> from sympy.abc import x, y
>>> f = x/y + x*y**2
>>> Matrix([f]).jacobian((x,y))
Matrix([[y**2 + 1/y, 2*x*y - x/y**2]])
>>> _.jacobian((x,y)) # Hessian
Matrix([
[ 0, 2*y - 1/y**2],
[2*y - 1/y**2, 2*x + 2*x/y**3]])
So you could try
x_1, x_2 = sym.symbols("x_1 x_2")
xx = x_1, x_2
a_T=[0.3,0.6,0.2]
b_T=[5,26,3]
c_T=[40,1,10]
u= x_1-0.8
v= x_2-(a_T[0]+a_T[1]*u**2*(1-u)**(1/2)-a_T[2]*u)
alpha= -b_T[0]+(b_T[1]*u**2)*(1+u)**(1/2)+(b_T[2])*u
beta= c_T[0]*v**2*(1-c_T[1]*v)/(1+c_T[2]*u**2)
## function
f = alpha**(-beta)
jac = Matrix([f]).jacobian(xx)
hes = jac.jacobian(xx)

sympy Sequence : how to use product?

Print a symbol for product (∏) by using SymPy package
What am I doing wrong with the macro?
from sympy import *
i = Idx("i")
a = IndexedBase("a")
n = symbols("n")
f=Product(a[i], (i,2,n) )
print(f)
g=Product(a[i], (i,1,n-1) )
print(g)
print(simplify(f/g))
# Product(a[i], (i, 2, n))
# Product(a[i], (i, 1, n - 1))
# Product(a[i], (i, 2, n))/Product(a[i], (i, 1, n - 1))
# I want
# a(n) a(n-1)
# a(n-1) a(n-2)
# .
# .
# . a(2)
# a(2) a(1)
# ---->
# a(n)/a(1)
Thank you in advance and sorry for the bad english!
There's nothing wrong - simplify does not support this kind of simplification.
Why not write something yourself?

How to implement this constraint in Python with Gurobi?

I have an expression given below and i was wondering if you can help me to formalize as an ILP constraint in order to solve by Gurobi optimizer (Python):
forall ( y in Y), forall (j in M), forall (x in X):
IF r[x][y] = 1 and c[y,j] = 1 THEN p[x,a] = 1 , forall (a in {U[j],...,W[j] - 1} )
Where:
r[x][y], c[y,j] and p[x,a] are 3 binary variables;
U[j] and W[j] are 2 positive integer variables, where U[j] + beta = W[j]
(beta is a positive constant)
I know that this constraint can be written as a logical implication in conjunctive normal form: x ∧ y → z
I have already tried this solution: z≥x+y−1 together with several other possibilities :(
But, i had an error with Gurobi solver
My Python code for this constraint is as follows:
for y in Y:
for j in M:
for x in X:
for a in range(int(U[j]),int(W[j])):
M1.addConstr(r[x][y] + c[y,j] - 1 <= p[x,a], 'TileRequirement_%s_%s_%s_%s'%(y,j,x,a))
I always get the error in this line: for a in range(int(U[j]),int(W[j])):, because both U[j] and W[j] are defined as positive integer variables
So, can someone help me ?
Thanks :)
Best regards
Khadija
You can't build constraints based on yet-to-optimize variables like in:
for a in range(int(U[j]),int(W[j])) # optimized value unknown # build-constr-time
Casting like that looks also dangerous and it solely depends on gurobipy, if that's possible in general (but not helping here).
Your question is hard to read and there is no information about the motivation for these constraints, but the general idea could be:
get rid of the range defined by U[j] and W[j]
formulate your constraint for the full-range
with one modification:
introduce one more activating-variable a:
(x^y)->z becomes: (a^x^y)->z == !a v !x v !y v z
as linear expression: (1-a) + (1-x) + (1-y) + z >= 1
now use the concept of indicator-variables to formulate your activating-variables
Yes, it's messy and because of this (and because information is sparse) i won't post a full solution.
# -*- coding: utf-8 -*-
#programmer: Khadija HS
#date: June 2017
#name: B-C-MCT PLNE Model (Khadija.HS,2017) <---> BCMCT1.py
"""
Solve the B-C-MCTP (fixed Z & min Delta) sub-pb of 3-PSDPP (K-HS et al.,2016), where:
X: list of input tiles (tile x)
Y: list of output tiles (tile y)
Ry: requirement relation between X & Y
<---> is a List of Y list, each sub List define the input tiles required by each y
<---> rxy: incidence matrix (0-1): Input Tiles/Output Tiles (Configuration of each output tile % input tile)
<---> Ry is a list of list where Row <--- x & Column <--- y
alpha: prefetches times (uniform)
beta: computations times (uniform)
Delta: the Total completion time (to be determined)
"""
from gurobipy import *
""" Find Yx: set of output tiles y that required the input tile x """
def OuputTileTe(Ry,X):
Yx=[]
for x in X:
Yx.append(OuputTileTex(Ry,x))
return Yx
""" Find B: List Ts for x """
def OuputTileTex(Ry,x):
B=[]
for y in range(len(Ry)):
if x in Ry[y]:
B.append(y)
return B
""" Find N: Max Value of N ( <---> sum(len(Ry),y in Y)) """
def NbPrefetchTile(S):
N=0
for k in range(0,len(S)):
N += len(S[k])
return N
""" BCMCT1 - Model"""
def BCMCT1(X,Y,Z,Ry,alpha,beta):
# DET VBLES: M,N,Z1,T,K,L
M=list(range(len(Y))) # List of Computation steps
nb=NbPrefetchTile(Ry) # Number of prefetches (Big Value of N)
N=range(nb) # List of Prefetches steps
ListZ=range(Z) # List of Buffers
T=range(alpha*len(X) + beta*len(Y)) # List of Start Date times (Computation+Prefetches)
K=range(alpha) # Interval Time of a prefetch step
L=range(beta) # Interval Time of a compute step
# DET VBLES: A,T1,B,Yx
A=alpha*nb + beta*len(Y) # Big Value of Total Completion Time
T1=range(A) # List of Start Date times (Computation+Prefetches)
minLen=min([len(elt) for elt in Ry]) #1,alpha+1
B=alpha*minLen + beta*len(Y) # Value of LB2
Yx=OuputTileTe(Ry,X) # List of output tile y, for x, x in X
# MODEL
M1=Model("BCMCT1")
# CONSTANT VARIABLES
r=[[0]*len(Y) for i in range(len(X))]
for x in X:
for y in Y:
if x in Ry[Y.index(y)]:
r[x][y]=1
# DECISION VARIABLES
c,p,q,U,W,a={},{},{},{},{},{}
for y in Y:
for j in M:
c[y,j]=M1.addVar(vtype=GRB.BINARY,name="c[%s,%s]"%(y,j)) #obj=beta,
for x in X:
for t in T:
p[x,t]=M1.addVar(vtype=GRB.BINARY,name="p[%s,%s]"%(x,t)) #obj=1,
for x in X:
for t in T:
q[x,t]=M1.addVar(vtype=GRB.BINARY,name="q[%s,%s]"%(x,t)) #obj=1,
for j in M:
U[j]=M1.addVar(vtype='I',name="U_%s"%j)
W[j]=M1.addVar(obj=1,vtype='I',name="W_%s"%j)
for j in M:
a[j]=M1.addVar(vtype=GRB.BINARY,name="a[%s]"%j)
# MODEL UPDATE
M1.update()
# OBJECTIVE
Obj=W[len(M)-1]
M1.setObjective(Obj, GRB.MINIMIZE)
# CONSTRAINTS
""" (1): Computation's Assignement Constraints """
""" (a) """
for j in M:
M1.addConstr(quicksum(c[y,j] for y in Y)==1,'ComputeAssign1_%s'%j)
""" (b) """
for y in Y:
M1.addConstr(quicksum(c[y,j] for j in M)==1,'ComputeAssign2_%s'%y)
""" (2): Buffer's Constraints """
for t in T:
M1.addConstr(quicksum(p[x,t] for x in X) <= Z,'BufferNb_%s'%t)
""" 3): Computation/Prefetch's Constraints """
""" (a) """
for t in T:
M1.addConstr(quicksum(q[x,t] for x in X) <= 1,'PrefetchTileA_%s'%t)
""" (b) """
for x in X:
for t in T[1:]:
for k in K:
M1.addConstr(p[x,t] - p[x,t-1] <= q[x,t-k],'PrefetchTileB_%s_%s_%s'%(x,t,k))
""" (c) """
for y in Y:
for j in M:
for x in X:
for t in T:
M1.addConstr(3 - r[x][y] - c[y,j] - a[j] + p[x,t] >= 1, 'TileRequirement_%s_%s_%s_%s'%(y,j,x,t))
""" (5): Computation Time's Constraint """
""" (a) """
for j in M:
M1.addConstr(W[j] == U[j] + beta,'ComputeTime1_%s'%j)
""" (b) """
for j in M[1:]:
M1.addConstr(W[j-1] <= U[j],'ComputeTime2_%s'%j)
# SOLUTION
M1.__data=c,p,q,U,W,a
return M1
Please find attached my detailed ILP
May be, it will be easier to understand my question about constraint number 17
where,
L = range(beta)
K=range(alpha)
\Lambda (Big M)=alpha*Z*Y+beta*Y
r[x][y]= 1 if x in Ry and 0 otherwise (forall x in X & forall y in Y) : incidence matrix given as input data
I will give you an example that is very simple to understand more my problem as follows:
let:
X=[X1,X2,X3,X4]
Y=[Y1,Y2,Y3]
Ry=[(X1,X2,X3), (X2,X4),(X1,X3,X4)]
Z=3
alpha=2, beta=4
The objective is to find a computation sequence for computing Y1,Y2 & Y3 in order to minimize Delta (total completion time)
An optimal solution is: Y2, Y3, Y1 (or Y2,Y1,Y3) with \Delta=17
ILP Formulation