Replace values in sympy NDimArray - sympy

I would like to replace values in a sympy NDimArray.
I have the following code
import sympy as sp
import numpy as np
e = sp.MatrixSymbol('e',3,3)
E = sp.Matrix(e)
# Make E symmetric
E[1,0] = E[0,1]
E[2,0] = E[0,2]
E[2,1] = E[1,2]
result = sp.tensorproduct(E,E)
E_tst = np.random.rand(3,3)
E_tst[1,0] = E_tst[0,1]
E_tst[2,0] = E_tst[0,2]
E_tst[2,1] = E_tst[1,2]
resultNumeric = np.tensordot(E_tst,E_tst,axes=0)
check = resultNumeric - result.as_mutable().subs({E:sym.Matrix(E_tst)})
I get the error AttributeError: 'MutableDenseNDimArray' object has no attribute 'subs'.
How can I replace the symbols in a NDimArray?
Best Regards

Unfortunately, MutableDenseNDimArray doesn't inherit from Basic, whereas ImmutableDenseNDimArray does, therefore some attributes are not available. Don't ask me about this design decision.
However, you can achieve the same result by creating a substitution dictionary:
# substitution dictionary
d = {k: v for k, v in zip(list(E), list(Matrix(E_tst)))}
check = resultNumeric - result.subs(d)

Related

Sympy: Is it possible use function collect() to IndexedBase variables?

I'm trying to use the function collect() to simplify mi expression . My desired result is
My code:
from sympy import *
#index
i = symbols('i' , integer = True )
#constants
a = symbols( 'a' )
#variables
alpha = IndexedBase('alpha', positive=True, domain=QQ)
index = (i, 1, 3)
rho = symbols( 'rho')
U = product( alpha[i]**(1/(rho-1)) , index )
U
:
My solution attempt:
U = U.subs(1/(rho-1),a)
collect(U,rho, evaluate=False)[1]
:
What I'm doing wrong?
You must be using a fairly old version of SymPy because in recent versions the form that you wanted arises automatically. In any case you should be able to use powsimp:
In [9]: U
Out[9]:
a a a
alpha[1] ⋅alpha[2] ⋅alpha[3]
In [10]: powsimp(U, force=True)
Out[10]:
a
(alpha[1]⋅alpha[2]⋅alpha[3])
https://docs.sympy.org/latest/tutorials/intro-tutorial/simplification.html#powsimp

Create indexed functions in sympy

Is it possible to create indexed functions in sympy like fi(t) which might be used in a product or sum, eg Σfi(t)?
import sympy as sp
f = sp.Function('f')
i = sp.symbols('i', integer=True)
t = sp.symbols('t', real=True)
sp.Indexed(f, i)(t)
The above code produces the following error:
TypeError:
The base can only be replaced with a string, Symbol, IndexedBase or an
object with a method for getting items (i.e. an object with a
`__getitem__` method).
Assuming that you just want graphically pleasing output you can use the following
import sympy as sp
class f(sp.Function):
name='f'
def _latex(self, printer=None):
a = [printer.doprint(i) for i in self.args]
name=self.name
return r'{}_{{{}}}\left('.format(name,a[0])+','.join(a[1:])+r'\right)'
i = sp.symbols('i', integer=True)
t = sp.symbols('t', real=True)
f(i,t)
sp.Sum(f(i,t),(i,0,sp.oo))

How to use pandas.Series.str.contains with tqdm progress map?

I'm trying to add a new column to a dataframe (dfA) based on values from another dataframe (dfB):
s = dfA['value'].tolist()
dfB['value'] = dfB['text_bod'].str.contains('|'.join(s))
Can progress_map be used with this setup?
dfB['value] = 'dfB['text_bod].progress_map(func)'
Or is there some other way tqdm can be implemented?
Alternative method using FlashText:
from flashtext import KeywordProcessor
s = dfA['value'].tolist()
processor = KeywordProcessor()
processor.add_keywords_from_list(s)
dfB['value'] = dfB['text_bod'].progress_map(lambda x: processor.extract_keywords(x))
Not aware of a str.contains way, but you can use progress_map with a callback that does the exact same thing, but with re.search:
import re
dfB['value'] = dfB['text_bod'].progress_map(
lambda x: bool(re.search('|'.join(s), x))
)
As a function, you can use
def extract(x, p):
m = p.search(x)
if m:
return m.groups(0)
return np.nan
p = re.compile('|'.join(s))
dfB['value'] = dfB['text_bod'].progress_map(lambda x: extract(x, p))
This should allow you greater flexibility than a lambda.

Change constraints based on variable value in Pyomo

Is there a way of changing the values of a constraint as the solver is running?
Basically, I have a constraint that depends on the value of a variable. The problem is that the constraint is evaluated based on the initial value of the variable, but isn't updated as the variable changes.
Here's a simple example:
from pyomo.environ import *
from pyomo.opt import SolverFactory
import numpy as np
# Setup
model = ConcreteModel()
model.A = Set(initialize = [0,1,2])
model.B = Set(initialize = [0,1,2])
model.x = Var(model.A, model.B, initialize=0)
# A constraint that I'd like to keep updating, based on the value of x
def changing_constraint_rule(model, a):
x_values = list((model.x[a, b].value for b in model.B))
if np.max(x_values) == 0:
return Constraint.Skip
else:
# Not really important what goes here, just as long as it updates the constraint list
if a == 1 : return sum(model.x[a,b] for b in model.B) == 0
else: return sum(model.x[a,b] for b in model.B) == 1
model.changing_constraint = Constraint(model.A, rule = changing_constraint_rule)
# Another constraint that changes the value of x
def bounding_constraint_rule(model, a):
return sum(model.x[a, b] for b in model.B) == 1
model.bounding_constraint = Constraint(
model.A,
rule = bounding_constraint_rule)
# Some objective function
def obj_rule(model):
return(sum(model.x[a,b] for a in model.A for b in model.B))
model.objective = Objective(rule=obj_rule)
# Results
opt = SolverFactory("glpk")
results = opt.solve(model)
results.write()
model.x.display()
If I run model.changing_constraint.pprint() I can see that no constraints have been made, since the initial value of the variable model.x was set to 0.
If it's not possible to change the constraint values while solving, how could I formulate this problem differently to achieve what I'm looking for? I've read this other post but couldn't figure it out from the instructions.
I am giving you the same answer in the other question by #Gabe:
Any if-logic you use inside of rules should not involve the values of
variables (unless it is based on the initial value of a variable, in
which case you would wrap the variable in value() wherever you use it
outside of the main expression that is returned).
for example:
model.x[a, b].value should be model.x[a, b].value()
But still this might not give you the solution what you are looking for.

Sympy not solving convolution integral

I'm trying to solve some convolution integrals but without any luck.
import matplotlib.pyplot as plt
import numpy as np
import sympy as sp
t1 = 0.01
t1_sym = sp.Symbol('t_1')
F0 = 30e3
F0_sym = sp.Symbol('F_0')
m = 4000
m_sym = sp.Symbol('m')
k = 5000e3
k_sym = sp.Symbol('k')
omega0_sym = sp.sqrt(k_sym/m_sym)
t = sp.Symbol('t')
tau = sp.Symbol(r'\tau')
F1_sym= 2*F0_sym*tau/t1_sym
x1_sym = sp.integrate((F1_sym*sp.sin(omega0_sym*(t-tau))/(omega0_sym*m_sym)) ,(tau,0,t))
I would be really grateful for any insights.
In general, it is a good practise to provide sympy any information available about the parameters and variables involved in an integral, instead of simply declaring them as symbols. From the numerical values you are using, it is clear that all variables and parameters are real and positive. You can provide sympy this information when you define them. With this information, sympy provides an expression for the integral (I will leave it to you to check if it is correct or not)
t1_sym = sp.Symbol('t_1', positive = True)
F0_sym = sp.Symbol('F_0', positive = True)
m_sym = sp.Symbol('m', positive = True)
k_sym = sp.Symbol('k', positive = True)
omega0_sym = sp.sqrt(k_sym/m_sym)
t = sp.Symbol('t', positive = True)
tau = sp.Symbol(r'\tau', positive = True)
F1_sym= 2*F0_sym*tau/t1_sym
x1_sym = sp.integrate((F1_sym*sp.sin(omega0_sym*(t-tau))/(omega0_sym*m_sym)) ,(tau,0,t))
print(x1_sym)
2*F_0*t/(k*t_1) - 2*F_0*sqrt(m)*sin(sqrt(k)*t/sqrt(m))/(k**(3/2)*t_1)