Rpy2: set a R formulat from python - python

I am little confused by R syntax formula
I created the following python function with Rpy2:
objects.r('''
project_var <- function(grid,points) {
coordinates(points) = ~X + Y
gridded(grid) = ~X+Y
grid = idw(Z~1, points,grid)
grid <- as.data.frame(grid)
return(grid)
}
''')
Then I import it
project_var = robjects.globalenv['project_var']
Then I call it:
test = project_var(model,points_top)
And it works as expected!
I would like to'Z' to be set by an argument of my function, something like this:
project_var <- function(grid,points,feature_name) {
...
grid = idw(feature_name~1, points,grid)
My Problem :
idw(feature_name~1, points,grid)
I do not really understand this line and what is really feature name (because it is not a string nor known variable at this point, but the name of a column as a formula).
for info idw comes from gstat library... and I do not know R...
here is the doc:
idw.locations(formula, locations, data, newdata, nmax = Inf, nmin = 0,
omax = 0, maxdist = Inf, block, na.action = na.pass, idp = 2.0,
debug.level = 1)
https://cran.r-project.org/web/packages/gstat/gstat.pdf
So what should I put for feature_name in the python side ? or how to build it in R so it would transform the string feature_name into something that would work ?
Any help would be appreciate.
Thank you for reading so far.

I do not really understand this line and what is really feature name (because it is not a string nor known variable at this point, but the name of a column).
R differs from Python as expressions in a function call (here idw(Z~1, points,grid)) will only be evaluated within the function, and the unevaluated expression itself is available to the code in the body of the function.
In addition to that, Z~1 is itself a special thing: it is an R formula. You could write fml <- Z ~ 1 in R and the object fml will be a "formula". The constructor for the formula is somewhat hidden as <something> ~ <something> is considered a language construct in R, but in fact you have something like build_formula(<left_side_expression>, <right_side_expression>). You can try in R fml <- get("~")(Z, 1) and see that this is exactly that happening.

okay, just need to use as.formula to convert a string to a formula :-)
idw(as.formula(feature_name), points,grid)

Related

Assigned a complex value in cupy RawKernel

I am a beginner learning how to exploit GPU for parallel computation using python and cupy. I would like to implement my code to simulate some problems in physics and require to use complex number, but don't know how to manage it. Although there are examples in Cupy's official document, it only mentions about include complex.cuh library and how to declare a complex variable. I can't find any example about how to assign a complex number correctly, as well ass how to call the function in the complex.cuh library to do calculation.
I am stuck in line 11 of this code. I want to make a complex number value equal x[tIdx]+j*y[t_Idx], j is the imaginary number. I tried several ways and no one works, so I left this one here.
import cupy as cp
import time
add_kernel = cp.RawKernel(r'''
#include <cupy/complex.cuh>
extern "C" __global__
void test(double* x, double* y, complex<float>* z){
int tId_x = blockDim.x*blockIdx.x + threadIdx.x;
int tId_y = blockDim.y*blockIdx.y + threadIdx.y;
complex<float>* value = complex(x[tId_x],y[tId_y]);
z[tId_x*blockDim.y*gridDim.y+tId_y] = value;
}''',"test")
x = cp.random.rand(1,8,4096,dtype = cp.float32)
y = cp.random.rand(1,8,4096,dtype = cp.float32)
z = cp.zeros((4096,4096), dtype = cp.complex64)
t1 = time.time()
add_kernel((128,128),(32,32),(x,y,z))
print(time.time()-t1)
What is the proper way to assign a complex number in the RawKernel?
Thank you for answering this question!
#plaeonix, thank you very much for your hint. I find out the answer.
This line:
complex<float>* value = complex(x[tId_x],y[tId_y])
should be replaced to:
complex<float> value = complex<float>(x[tId_x],y[tId_y])
Then the assignment of a complex number works.

Unknown result in z3 python for Int type

I was trying to solve certain set of constraints using z3 in python. My code:
import math
from z3 import *
### declaration
n_co2 = []
c_co2 = []
alpha = []
beta = []
m_dot_air = []
n_pir = []
pir_sensor = []
for i in range(2):
c_co2.append(Real('c_co2_'+str(i)))
n_pir.append(Real('n_pir_'+str(i)))
n_co2.append(Real('n_co2_'+str(0)))
alpha.append(Real('alpha_'+str(0)))
beta.append(Real('beta_'+str(0)))
m_dot_air.append(Real('m_dot_air_'+str(0)))
pir_sensor.append(Real('pir_sensor_'+str(0)))
s = Solver()
s.add(n_co2[0]>0)
s.add(c_co2[0]>0)
s.add(c_co2[1]>=0.95*c_co2[0])
s.add(c_co2[1]<=1.05*c_co2[0])
s.add(n_co2[0]>=0.95*n_pir[1])
s.add(n_co2[0]<=1.05*n_pir[1])
s.add(c_co2[1]>0)
s.add(alpha[0]<=-1)
s.add(beta[0]>0)
s.add(m_dot_air[0]>0)
s.add(alpha[0]==-1*(1+ m_dot_air[0] + (m_dot_air[0]**2)/2.0 + (m_dot_air[0]**3)/6.0 ))
s.add(beta[0]== (1-alpha[0])/m_dot_air[0])
s.add(n_co2[0]== (c_co2[1]-alpha[0]*c_co2[0])/(beta[0]*19.6)-(m_dot_air[0]*339)/19.6)
s.add(n_pir[1]>=0)
s.add(pir_sensor[0]>=-1)
s.add(pir_sensor[0]<=1)
s.add(Not(pir_sensor[0]==0))
s.add(n_pir[1]==(n_pir[0]+pir_sensor[0]))
#### testing
s.add(pir_sensor[0]==1)
s.add(n_pir[1]==1)
s.add(n_co2[0]==1)
print(s.check())
print(s.reason_unknown())
print(s.model())
The output of the code:
sat
[c_co2_0 = 355,
c_co2_1 = 1841/5,
m_dot_air_0 = 1,
n_co2_0 = 1,
n_pir_1 = 1,
pir_sensor_0 = 1,
n_pir_0 = 0,
beta_0 = 11/3,
alpha_0 = -8/3,
/0 = [(19723/15, 1078/15) -> 1793/98,
(11/3, 1) -> 11/3,
else -> 0]]
What is the significance "/0 = ..." part of the output model.
But when I change the type of n_pir from Real to Int, z3 cannot solve it. Although we saw that we have an Int solution for n_pir. Reason of unknown:
smt tactic failed to show goal to be sat/unsat (incomplete (theory arithmetic))
How this problem can be solved? Could anyone please provide reasoning about this problem?
For the "/0" part: It's an internally generated constraint from converting real to int solutions. You can totally ignore that. In fact, you shouldn't really even look at the value of that, it's an artifact of the z3py bindings and should probably be hidden from the user.
For your question regarding why you cannot make 'Real' to 'Int'. That's because you have a non-linear set of equations (where you multiply or divide two variables), and non-linear integer arithmetic is undecidable in general. (Whereas non-linear real arithmetic is decidable.) So, when you use 'Int', solver simply uses some heuristics, and in this case fails and says unknown. This is totally expected. Read this answer for more details: How does Z3 handle non-linear integer arithmetic?
Z3 does come with an NRA solver, you can give that a try. Declare your solver as:
s = SolverFor("NRA")
But again you're at the mercy of the heuristics and you may or may not get a solution. Also, watch out for z3py bindings coercing constants to when you mix and match arithmetic like that. A good way is to write:
print s.sexpr()
before you call s.check() and take a look at the output and convince yourself that the translation has been done correctly. For details on that, see this question: Python and Z3: integers and floating, how to manage them in the correct way?

Can `sympy.codegen.ast` be used with `sympy.utilities.autowrap`?

I'm working on producing compiled functions using sympy.code.autowrap, specifically the make_routine, autowrap, and ufuncify functions of that module. I would like to be able to use sympy.codegen.ast to generate code to be wrapped. For instance:
import sympy as sy
from sympy.codegen.ast import (Assignment, CodeBlock, Return, Element,
Pointer, Declaration, float64,
FunctionPrototype, FunctionDefinition)
zlist = sy.symarray('z', (5,), real=True)
d1expz = sy.apply_finite_diff(1, x_list=range(-2,3), y_list=zlist)
d2expz = sy.apply_finite_diff(2, x_list=range(-2,3), y_list=zlist)
d1p = Pointer('d1p', float64)
d2p = Pointer('d2p', float64)
d1p0 = Element('d1p', '0')
d2p0 = Element('d2p', '0')
d12fpa = FunctionPrototype(float64, 'd12funca', [d1p, d2p] + list(zlist))
body12a = [
CodeBlock(
Assignment(d1p0, d1expz),
Assignment(d2p0, d2expz),
).cse(),
]
d12funca = FunctionDefinition.from_FunctionPrototype(
d12fpa, body12a
)
print(sy.ccode(d12funca))
This results in the following C code, which looks good:
double d12funca(double * d1p, double * d2p, double z_0, double z_1, double z_2, double z_3, double z_4){
x0 = (1.0/12.0)*z_0;
x1 = -1.0/12.0*z_4;
d1p[0] = x0 + x1 - 2.0/3.0*z_1 + (2.0/3.0)*z_3;
d2p[0] = -x0 + x1 + (4.0/3.0)*z_1 - 5.0/2.0*z_2 + (4.0/3.0)*z_3;
}
sympy.utilities.codegen.codegen also understands this, e.g. the following produces just the kind of results you'd expect.
[(c_name, c_code), (h_name, c_header)] = codegen(
('d12func',
[
sy.Eq(sy.Symbol('d1'), d1expz),
sy.Eq(sy.Symbol('d2'), d2expz)
]),
language='c'
)
I can also produce a nicely wrapped function that does essentially the same thing as follows:
from sympy.utilities.autowrap import autowrap
autowrap_dir = <some path>
derivs = sy.Matrix(
[[
d1expz,
d2expz
]]
)
dvraw = autowrap(
expr=derivs,
args=list(zlist),
backend='Cython',
tempdir=autowrap_dir,
verbose=True
)
But is there any way to use the ast module to specify functions to be wrapped with autowrap? It appears that autowrap, make_routine, and ufuncify cannot accept arbitrary code. The expressions they take can be either lists of straightforward sympy expressions, or lists of sympy.Eq expressions (in which case the wrapped function assigns the RHS of each equality to its LHS and returns each LHS as an output argument).
The problem is that I would like to be able to wrap more involved functions including such things as for loops and branching. The ast module provides the tools to write such functions. But as far as I can tell, autowrap and ast don't play with each other at all.
Any thoughts on how to accomplish this would be appreciated. Thanks.

How to implement a function with Python(Sympy), realizing the same as '_' and replacement rule in Wolfram Mathematica?

In Wolfram Mathematica, I can define named patterns where _ (called Blank) matches any expression and then use the match in a replacement rule.
An example:
testexpr = p1[MM]*p2[NN] + p1[XX]*p2[MM] + p1[XX]^2;
FunTest[expr_] := Expand[expr] /. {(p1[l1_]*p2[l2_]) -> FF1[l1]*FF2[l2],
p1[l1_]^n_ -> 0, p2[l1_]^n_ -> 0}
FunTest[testexpr]
The result is FF1[XX] FF2[MM] + FF1[MM] FF2[NN]
However, I don't know how to use sympy in Python to do the same thing.
import sympy as sp
p1 = sp.IndexedBase("p1")
p2 = sp.IndexedBase("p2")
FF1 = sp.IndexedBase("FF1")
FF2 = sp.IndexedBase("FF2")
MM,NN,XX=sp.symbols('MM NN XX')
SSlist=[MM,NN,XX]
testexpr=p1[MM]*p2[NN] + p1[XX]*p2[MM] + p1[XX]**2
def FunTest(expr):
expr=expr.subs([(p1[SS]*p2[SS2],FF1[SS]*FF2[SS2]) for SS in SSlist
for SS2 in SSlist]+[(p1[SS]**2,0) for SS in SSlist]+[(p2[SS]**2,0)
for SS in SSlist],simultaneous=True)
return expr
rest=FunTest(testexpr)
print(rest)
So the result is also FF1[MM]*FF2[NN] + FF1[XX]*FF2[MM].
But I want to know if there is an easy way to make it more general, as in Wolfram Mathematica. If SSlist is a large list and there are many different variables, it will be a difficult to implement with my solution.
I wonder whether there is an easy way without writing a loop over the whole list, for SS in SSlist, as in Mathematica. Can someone familiar with sympy give me any hints?
Thanks a lot!
I have found out one solution to my own question. It works out as I want. Instead of using subs(), I use wild operator and replace().
import sympy as sp
p1 = sp.IndexedBase("p1")
p2 = sp.IndexedBase("p2")
FF1 = sp.IndexedBase("FF1")
FF2 = sp.IndexedBase("FF2")
MM,NN,XX=sp.symbols('MM NN XX')
SSlist=[MM,NN,XX]
SS = sp.Wild('SS')
SS1 = sp.Wild('SS1')
testexpr=p1[MM]*p2[NN] + p1[XX]*p2[MM] + p1[XX]**2
replacements = {p1[SS]*p2[SS1] : FF1[SS]*FF2[SS1], p1[SS]**2: 0, p2[SS]**2 : 0}
def replaceall(expr, repls):
for i, j in repls.items():
expr = expr.replace(i, j, map=False, simultaneous=True, exact=False)
return expr
rest=replaceall(testexpr,replacements)
print(rest)
The result gives exactly the same as I did before:
FF1[MM]*FF2[NN] + FF1[XX]*FF2[MM]
One thing I want to know is this efficient when there are many symbols because of the for loop. It seems that the two methods are similar, just the one I found recently looks more concise.
I would like to know whether there is a more general way to do such things as Wolfram Mathematica does.
Any comments are welcomed. Thanks!

How to read a system of differential equations from a text file to solve the system with scipy.odeint?

I have a large (>2000 equations) system of ODE's that I want to solve with python scipy's odeint.
I have three problems that I want to solve (maybe I will have to ask 3 different questions?).
For simplicity, I will explain them here with a toy model, but please keep in mind that my system is large.
Suppose I have the following system of ODE's:
dS/dt = -beta*S
dI/dt = beta*S - gamma*I
dR/dt = gamma*I
with beta = cpI
where c, p and gamma are parameters that I want to pass to odeint.
odeint is expecting a file like this:
def myODEs(y, t, params):
c,p, gamma = params
beta = c*p
S = y[0]
I = y[1]
R = y[2]
dydt = [-beta*S*I,
beta*S*I - gamma*I,
- gamma*I]
return dydt
that then can be passed to odeint like this:
myoutput = odeint(myODEs, [1000, 1, 0], np.linspace(0, 100, 50), args = ([c,p,gamma], ))
I generated a text file in Mathematica, say myOdes.txt, where each line of the file corresponds to the RHS of my system of ODE's, so it looks like this
#myODEs.txt
-beta*S*I
beta*S*I - gamma*I
- gamma*I
My text file looks similar to what odeint is expecting, but I am not quite there yet.
I have three main problems:
How can I pass my text file so that odeint understands that this is the RHS of my system?
How can I define my variables in a smart way, that is, in a systematic way? Since there are >2000 of them, I cannot manually define them. Ideally I would define them in a separate file and read that as well.
How can I pass the parameters (there are a lot of them) as a text file too?
I read this question that is close to my problems 1 and 2 and tried to copy it (I directly put values for the parameters so that I didn't have to worry about my point 3 above):
systemOfEquations = []
with open("myODEs.txt", "r") as fp :
for line in fp :
systemOfEquations.append(line)
def dX_dt(X, t):
vals = dict(S=X[0], I=X[1], R=X[2], t=t)
return [eq for eq in systemOfEquations]
out = odeint(dX_dt, [1000,1,0], np.linspace(0, 1, 5))
but I got the error:
odepack.error: Result from function call is not a proper array of floats.
ValueError: could not convert string to float: -((12*0.01/1000)*I*S),
Edit: I modified my code to:
systemOfEquations = []
with open("SIREquationsMathematica2.txt", "r") as fp :
for line in fp :
pattern = regex.compile(r'.+?\s+=\s+(.+?)$')
expressionString = regex.search(pattern, line)
systemOfEquations.append( sympy.sympify( expressionString) )
def dX_dt(X, t):
vals = dict(S=X[0], I=X[1], R=X[2], t=t)
return [eq for eq in systemOfEquations]
out = odeint(dX_dt, [1000,1,0], np.linspace(0, 100, 50), )
and this works (I don't quite get what the first two lines of the for loop are doing). However, I would like to do the process of defining the variables more automatic, and I still don't know how to use this solution and pass parameters in a text file. Along the same lines, how can I define parameters (that will depend on the variables) inside the dX_dt function?
Thanks in advance!
This isn't a full answer, but rather some observations/questions, but they are too long for comments.
dX_dt is called many times by odeint with a 1d array y and tuple t. You provide t via the args parameter. y is generated by odeint and varies with each step. dX_dt should be streamlined so it runs fast.
Usually an expresion like [eq for eq in systemOfEquations] can be simplified to systemOfEquations. [eq for eq...] doesn't do anything meaningful. But there may be something about systemOfEquations that requires it.
I'd suggest you print out systemOfEquations (for this small 3 line case), both for your benefit and ours. You are using sympy to translated the strings from the file into equations. We need to see what it produces.
Note that myODEs is a function, not a file. It may be imported from a module, which of course is a file.
The point to vals = dict(S=X[0], I=X[1], R=X[2], t=t) is to produce a dictionary that the sympy expressions can work with. A more direct (and I think faster) dX_dt function would look like:
def myODEs(y, t, params):
c,p, gamma = params
beta = c*p
dydt = [-beta*y[0]*y[1],
beta*y[0]*y[1] - gamma*y[1],
- gamma*y[1]]
return dydt
I suspect that the dX_dt that runs sympy generated expressions will be a lot slower than a 'hardcoded' one like this.
I'm going add sympy tag, because, as written, that is the key to translating your text file into a function that odeint can use.
I'd be inclined to put the equation variability in the t parameters, rather a list of sympy expressions.
That is replace:
dydt = [-beta*y[0]*y[1],
beta*y[0]*y[1] - gamma*y[1],
- gamma*y[1]]
with something like
arg12=np.array([-beta, beta, 0])
arg1 = np.array([0, -gamma, -gamma])
arg0 = np.array([0,0,0])
dydt = arg12*y[0]*y[1] + arg1*y[1] + arg0*y[0]
Once this is right, then the argxx definitions can be move outside dX_dt, and passed via args. Now dX_dt is just a simple, and fast, calculation.
This whole sympy approach may work fine, but I'm afraid that in practice it will be slow. But someone with more sympy experience may have other insights.

Categories

Resources