Substituting undefined function in symbolic expression - function

In an expression depending on an unknown function f of r**2, I would like to replace the function f by some actual function and display the result but I cannot find a way to do it. Here's an example:
r = symbols('r', real= True)
phi = r * Function('phi')(r**2)
dphi = phi.diff(r)
print(dphi)
At this stage I get:
2*r**2*Subs(Derivative(phi(_xi_1), _xi_1), _xi_1, r**2) + phi(r**2)
Now let's assume I would like to evaluate dphi when phi(y) = y.
This should give me:
2*r**2 + r**2 = 3*r**3
How do I make the actual substitution of phi in dphi to obtain the desired result ?
#Davide_sd This is an example that works as I expect (but for a function of r alone):
r = symbols('r', real= True)
phi = Function('phi')(r)
om = r * phi
dom = om.diff(r)
dom.subs(phi, sin(r)).doit()
output: r * cos(r) +sin(r)
But I would like to have for example (does not work):
r = symbols('r', real= True)
phi = Function('phi')(r**2)
om = r * phi
dom = om.diff(r)
dom.subs(phi, sin(r)).doit()
output: 2*r**2*Subs(Derivative(phi(_xi_1), _xi_1), _xi_1, r**2) + phi(r**2)
Instead I would like to get:
2*r**2*cos(r**2) + sin(2*r**2)
Thanks in advance for any help,
Regards,
Bernard.

If you want phi(y) = y this is the Id function; replacement can be done as:
>>> from sympy import Id
>>> dphi.subs(Function('phi'), Id).doit() # where dphi is as given at the start
3*r**2
In your example for dom it is not clear what function mapping you want since you use phi for the expression Function('phi')(r**2) and for the function Function('phi'). If you mean the same as in the first example -- something like phi(r) = sin(r) then you would just replace Function('phi') with sin.
Another way to approach this is by using replace to find occurrences of the function of interest and replace them with desired value, regardless of argument.
>>> p = Function('phi')
>>> (1+p(x)).replace(lambda x:x.func==p, lambda x:x.args[0]**3)
x**3 + 1

Based on the above answer and another usage of replace that I discovered here (Why does substitution into a sympy derivative only partly work), here is a summary of two solutions that do exactly what I need:
>>> r = symbols('r', real= True)
>>> phi = Function('phi')
>>> om = r * phi(r**2)
>>> dom = om.diff(r)
# Solution 1
>>> dom.replace(lambda x: x.func == phi, lambda x: x.args[0]**3).doit()
7*r**6
# Solution 2
>>> y = Wild("y")
>>> dom.replace(phi(y), y**3).doit()
7*r**6

Related

How to solve Euler–Bernoulli beam equation in FiPy?

To understand how FiPy works, I want to solve the Euler–Bernoulli beam equation with fixed endpoints:
w''''(x) = q(x,t), w(0) = w(1) = 0, w'(0) = w'(1) = 0.
For simplicity, let q(x,t) = sin(x).
How can I define and solve it in FiPy? How to specify the source term sin(x) with respect to the only independent variable in the equation?
from fipy import CellVariable, Grid1D, DiffusionTerm, ExplicitDiffusionTerm
from fipy.tools import numerix
nx = 50
dx = 1/nx
mesh = Grid1D(nx=nx, dx=dx)
w = CellVariable(name="deformation",mesh=mesh,value=0.0)
valueLeft = 0.0
valueRight = 0.0
w.constrain(valueLeft, mesh.facesLeft)
w.constrain(valueRight, mesh.facesRight)
w.faceGrad.constrain(valueLeft, mesh.facesLeft)
w.faceGrad.constrain(valueRight, mesh.facesRight)
# does not work:
eqX = DiffusionTerm((1.0, 1.0)) == numerix.sin(x)
eqX.solve(var=w)
Here is what seems to be a working version of your problem
from fipy import CellVariable, Grid1D, DiffusionTerm
from fipy.tools import numerix
from fipy.solvers.pysparse.linearPCGSolver import LinearPCGSolver
from fipy import Viewer
import numpy as np
L = 1.
nx = 500
dx = L / nx
mesh = Grid1D(nx=nx, dx=dx)
w = CellVariable(name="deformation",mesh=mesh,value=0.0)
valueLeft = 0.0
valueRight = 0.0
w.constrain(valueLeft, mesh.facesLeft)
w.constrain(valueRight, mesh.facesRight)
w.faceGrad.constrain(valueLeft, mesh.facesLeft)
w.faceGrad.constrain(valueRight, mesh.facesRight)
x = mesh.x
k_0 = 0
k_1 = -1
k_2 = 2 + np.cos(L) - 3 * np.sin(L)
k_3 = -1 + 2 * np.sin(L) - np.cos(L)
w_analytical = numerix.sin(x) + k_3 * x**3 + k_2 * x**2 + k_1 * x + k_0
w_analytical.name = 'analytical'
# does not work:
eqX = DiffusionTerm((1.0, 1.0)) == numerix.sin(x)
eqX.solve(var=w, solver=LinearPCGSolver(iterations=20000))
Viewer([w_analytical, w]).plot()
raw_input('stopped')
After running this, the FiPy solution seems to be quite close to the analytical result.
The two important changes from the OP's implementation.
Using mesh.x which is the correct way to refer to the spatial variable for use in FiPy equations.
Specifying the solver and number of iterations. The problem seems to be slow to converge so needed a lot of iterations. From my experience, fourth order spatial equations often need good preconditioners to converge quickly. You might try using the Trilinos solver package with Fipy to make this work better as it has a wider range of available preconditioners.
Use an explicit float for L to avoid integer maths in Python 2.7 (edit from comment)

how to get probabilities between 0 and 1 using glmnet categorical regression

My response variable is categorical, from 1 to 7. I understand using glmnet I can set the type to response and get the probability of the prediction.
prob.vec = predict.cv.glmnet(cvfit, newx = X.test, s = "lambda.min",
type = "response")
However, I am interested in having the probability of other category as well. I wonder if such functionality exist in glmnet.
Set family = 'multinomial' within cv.glmnet and you should be all set. Here is a simple example.
library(glmnet)
y <- iris$Species
x <- as.matrix(iris[,1:4])
m1 <- cv.glmnet(x, y, family = 'multinomial')
predict(m1, newx = x, s = 'lambda.min', type = 'response')[1:2,,]
# setosa versicolor virginica
#[1,] 0.9992059 0.000794057 2.548623e-20
#[2,] 0.9961627 0.003837330 1.206001e-18

CNTK Providing final LSTM state as input to another LSTM

I'm trying to build the following architecture:
Embeddings -> Forward LSTM -> Backward LSTM -> Concat Final States -> Concat external embedding -> LSTM
My code looks like this:
i = Input(features)
e = Embedding(25)(i)
# Forward and backward LSTM
h_f = Recurrence(LSTM(25), go_backwards=False)(e)
h_b = Recurrence(LSTM(25), go_backwards=True)(e)
# Get the final states and splice
f = sequence.last(h_f)
b = sequence.first(h_b)
e1 = splice(f, b)
# Get the other embedding and concat
i2 = Input(100)
e2 = Embedding(100)(i2)
e2 = sequence.first(word_embedding)
e3 = splice(e1, e2)
# Input concatenated embedding to new LSTM
r = Recurrence(LSTM(50))(e3)
When I do this I get the following error:
Input operand 'Output('Block1994_Output_0', [#], [50])' with #dynamic axes != 2 (1 sequence axis and 1 batch axis) is not supported.
If I do not get the final state of my first bidirectional LSTM then it works fine, but that's not what I want.
I can also reproduce the error with this simple example:
i = Input(features)
e = Embedding(25)(i)
h_f = Fold(LSTM(25), go_backwards=False)(e)
s = Recurrence(LSTM(25))(h_f)
check this link about returning output sequences and states of an LSTM. Then, you can bind the output to the input of another layer.

FiPy Simple Convection

I am trying to understand how FiPy works by working an example, in particular I would like to solve the following simple convection equation with periodic boundary:
$$\partial_t u + \partial_x u = 0$$
If initial data is given by $u(x, 0) = F(x)$, then the analytical solution is $u(x, t) = F(x - t)$. I do get a solution, but it is not correct.
What am I missing? Is there a better resource for understanding FiPy than the documentation? It is very sparse...
Here is my attempt
from fipy import *
import numpy as np
# Generate mesh
nx = 20
dx = 2*np.pi/nx
mesh = PeriodicGrid1D(nx=nx, dx=dx)
# Generate solution object with initial discontinuity
phi = CellVariable(name="solution variable", mesh=mesh)
phiAnalytical = CellVariable(name="analytical value", mesh=mesh)
phi.setValue(1.)
phi.setValue(0., where=x > 1.)
# Define the pde
D = [[-1.]]
eq = TransientTerm() == ConvectionTerm(coeff=D)
# Set discretization so analytical solution is exactly one cell translation
dt = 0.01*dx
steps = 2*int(dx/dt)
# Set the analytical value at the end of simulation
phiAnalytical.setValue(np.roll(phi.value, 1))
for step in range(steps):
eq.solve(var=phi, dt=dt)
print(phi.allclose(phiAnalytical, atol=1e-1))
As addressed on the FiPy mailing list, FiPy is not great at handling convection only PDEs (absent diffusion, pure hyperbolic) as it's missing higher order convection schemes. It is better to use CLAWPACK for this class of problem.
FiPy does have one second order scheme that might help with this problem, the VanLeerConvectionTerm, see an example.
If the VanLeerConvectionTerm is used in the above problem, it does do a better job of preserving the shock.
import numpy as np
import fipy
# Generate mesh
nx = 20
dx = 2*np.pi/nx
mesh = fipy.PeriodicGrid1D(nx=nx, dx=dx)
# Generate solution object with initial discontinuity
phi = fipy.CellVariable(name="solution variable", mesh=mesh)
phiAnalytical = fipy.CellVariable(name="analytical value", mesh=mesh)
phi.setValue(1.)
phi.setValue(0., where=mesh.x > 1.)
# Define the pde
D = [[-1.]]
eq = fipy.TransientTerm() == fipy.VanLeerConvectionTerm(coeff=D)
# Set discretization so analytical solution is exactly one cell translation
dt = 0.01*dx
steps = 2*int(dx/dt)
# Set the analytical value at the end of simulation
phiAnalytical.setValue(np.roll(phi.value, 1))
viewer = fipy.Viewer(phi)
for step in range(steps):
eq.solve(var=phi, dt=dt)
viewer.plot()
raw_input('stopped')
print(phi.allclose(phiAnalytical, atol=1e-1))

PyMC3 how to implement latent dirichlet allocation?

I am trying to implement lda using PyMC3.
However, when defining the last part of the model in which words are sampled based on their topics, I keep getting the error: TypeError: list indices must be integers, not TensorVariable
How to tackle the problem?
The code is as follows:
## Data Preparation
K = 2 # number of topics
N = 4 # number of words
D = 3 # number of documents
import numpy as np
data = np.array([[1, 1, 1, 1], [1, 1, 1, 1], [0, 0, 0, 0]])
Wd = [len(doc) for doc in data] # length of each document
## Model Specification
from pymc3 import Model, Normal, HalfNormal, Dirichlet, Categorical, constant
lda_model = Model()
with lda_model:
# Priors for unknown model parameters
alpha = HalfNormal('alpha', sd=1)
eta = HalfNormal('eta', sd=1)
a1 = eta*np.ones(shape=N)
a2 = alpha*np.ones(shape=K)
beta = [Dirichlet('beta_%i' % i, a1, shape=N) for i in range(K)]
theta = [Dirichlet('theta_%s' % i, a2, shape=K) for i in range(D)]
z = [Categorical('z_%i' % d, p = theta[d], shape=Wd[d]) for d in range(D)]
# That's when you get the error. It is caused by: beta[z[d][w]]
w = [Categorical('w_%i_%i' % (d, w), p = beta[z[d][w]], observed = data[i,j]) for d in range(D) for w in range(Wd[d])]
Any help would be much appreciated!
beta[z[d][w]] is naturally incorrect because z[d][w] is a variable stored by PyMC instead of being an fixed index.
In pymc2 it is solved by lambda function
p=pm.Lambda("phi_z_%s_%s" % (d,i),
lambda z=z[d][w], beta=beta: beta[z])
In pymc3 it is suppose to be solved by
#theano.compile.ops.as_op
def your_function
But there is a problem here that it seems like Theano doesn't allow sending a python list of pymc variable. t.lvector baisically don't work.
More discussion is in this question:
Unable to create lambda function in hierarchical pymc3 model
The following code was adapted from what has been referenced by #Hanan. I've somehow made it work with pymc3.
import numpy as np
import pymc3 as pm
def get_word_dict(collection):
vocab_list = list({word for doc in collection for word in doc})
idx_list = [i for i in range(len(vocab_list))]
return dict(zip(vocab_list,idx_list))
def word_to_idx(dict_vocab_idx, collection):
return [[dict_vocab_idx[word] for word in doc] for doc in collection]
docs = [["sepak","bola","sepak","bola","bola","bola","sepak"],
["uang","ekonomi","uang","uang","uang","ekonomi","ekonomi"],
["sepak","bola","sepak","bola","sepak","sepak"],
["ekonomi","ekonomi","uang","uang"],
["sepak","uang","ekonomi"],
["komputer","komputer","teknologi","teknologi","komputer","teknologi"],
["teknologi","komputer","teknologi"]]
dict_vocab_idx = get_word_dict(docs)
idxed_collection = word_to_idx(dict_vocab_idx, docs)
n_topics = 3
n_vocab = len(dict_vocab_idx)
n_docs = len(idxed_collection)
length_docs = [len(doc) for doc in idxed_collection]
alpha = np.ones([n_docs, n_topics])
beta = np.ones([n_topics, n_vocab])
with pm.Model() as model:
theta = pm.distributions.Dirichlet('theta', a=alpha, shape=(n_docs, n_topics))
phi = pm.distributions.Dirichlet('phi', a=beta, shape=(n_topics, n_vocab))
zs = [pm.Categorical("z_d{}".format(d), p=theta[d], shape=length_docs[d]) for d in range(n_docs)]
ws = [pm.Categorical("w_{}_{}".format(d,i), p=phi[zs[d][i]], observed=idxed_collection[d][i])
for d in range(n_docs) for i in range(length_docs[d])]
trace = pm.sample(2000)
for d in range(n_docs):
value_z=trace.get_values("z_d{}".format(d))
print(value_z[1999])
check out this blog post. I haven't tested it.
import numpy as np
import pymc as pc
def wordDict(collection):
word_id = {}
idCounter = 0
for d in collection:
for w in d:
if (w not in word_id):
word_id[w] = idCounter
idCounter+=1
return word_id
def toNpArray(word_id, collection):
ds = []
for d in collection:
ws = []
for w in d:
ws.append(word_id.get(w,0))
ds.append(ws)
return np.array(ds)
###################################################
#doc1, doc2, ..., doc7
docs = [["sepak","bola","sepak","bola","bola","bola","sepak"],
["uang","ekonomi","uang","uang","uang","ekonomi","ekonomi"],
["sepak","bola","sepak","bola","sepak","sepak"],
["ekonomi","ekonomi","uang","uang"],
["sepak","uang","ekonomi"],
["komputer","komputer","teknologi","teknologi","komputer","teknologi"],
["teknologi","komputer","teknologi"]]
word_dict = wordDict(docs)
collection = toNpArray(word_dict,docs)
#number of topics
K = 3
#number of words (vocab)
V = len(word_dict)
#number of documents
D = len(collection)
#array([1, 1, 1, ..., 1]) K times
alpha = np.ones(K)
#array([1, 1, 1, ..., 1]) V times
beta = np.ones(V)
#array containing the information about doc length in our collection
Nd = [len(doc) for doc in collection]
######################## LDA model ##################################
#topic distribution per-document
theta = pc.Container([pc.CompletedDirichlet("theta_%s" % i,
pc.Dirichlet("ptheta_%s"%i, theta=alpha))
for i in range(D)])
#word distribution per-topic
phi = pc.Container([pc.CompletedDirichlet("phi_%s" % j,
pc.Dirichlet("pphi_%s" % j, theta=beta))
for j in range(K)])
#Please note that this is the tricky part :)
z = pc.Container([pc.Categorical("z_%i" % d,
p = theta[d],
size = Nd[d],
value = np.random.randint(K, size=Nd[d]))
for d in range(D)])
#word generated from phi, given a topic z
w = pc.Container([pc.Categorical("w_%i_%i" % (d,i),
p = pc.Lambda("phi_z_%i_%i" % (d,i),
lambda z=z[d][i], phi=phi : phi[z]),
value=collection[d][i],
observed=True)
for d in range(D) for i in range(Nd[d])])
####################################################################
model = pc.Model([theta, phi, z, w])
mcmc = pc.MCMC(model)
mcmc.sample(iter=5000, burn=1000)
#show the topic assignment for each word, using the last trace
for d in range(D):
print(mcmc.trace('z_%i'%d)[3999])