How to loop through a vector in TCL? - python

I am new to tcl, and I couldn't figure out how to translate this code from python to TCL
import numpy as np
g0 = 7.88e12
Eox = np.array([155473, 15573, 1553, 1557473, 5473, 473, 1573, 19553])
E1 = 0.55e6
m = 0.7
fot= 1
D = float(input("rad dose"))
Fy = np.array([(abs(Eox)/(abs(Eox)+E1))**m])
Not = np.array([g0*D*Fy*fot])
Not[Not>6.8e18] = 6.8e18
Nit = (1.7e4*D)+1e10
if Nit > 5e12:
Nit = 5e12
print(Not)
print(Nit)

Tcl doesn't process lists of values like numpy does (it's closer to standard Python) without an extension. I remember there being such a thing, but I've not used it and I can't remember the name right now. So I'll use standard Tcl. The closest analogy for a numpy array in standard Tcl is a list of values (though that's got more in common with a Python list or tuple than anything else).
I'll translate these four lines for you:
Eox = np.array([155473, 15573, 1553, 1557473, 5473, 473, 1573, 19553])
Fy = np.array([(abs(Eox)/(abs(Eox)+E1))**m])
Not = np.array([g0*D*Fy*fot])
Not[Not>6.8e18] = 6.8e18
They become:
set Eox {155473 15573 1553 1557473 5473 473 1573 19553}
set Fy [lmap EoxVal $Eox {expr {
(abs($EoxVal) / abs($EoxVal + $E1)) ** $m
}}]
set Not [lmap FyVal $Fy {expr {
$g0 * $D * $FyVal * $fot
}}]
set Not [lmap NotVal $Not {expr {
($NotVal > 6.8e18) ? 6.8e18 : $NotVal
}}]
The use of lmap is doing the same thing that numpy's doing behind the scenes for you on those arrays. The last two commands can be combined though:
set Not [lmap FyVal $Fy {expr {
min($g0 * $D * $FyVal * $fot, 6.8e18)
}}]
(Also, I've split each of the lmap/expr commands over multiple lines for increased clarity. You can write more compact code, but it's harder to read. Clear code is a very good plan in any code you intend to keep around for longer than 5 minutes.)
The other lines of code are pure basic stuff. set, puts, gets and expr will do what you need. And the suspiciously obvious if.

Related

Two consecutive parentheses after name in Matlab

Please excuse me for this amateurish question,
I'm trying to convert some Matlab code to Python, I don't have any experience with Matlab but so far I have been able to deduce what the Matlab code does and the conversion so far has been successful.
But now I am stuck at these lines of code;
SERAstart = []
for n=1:length(bet)
alf = -bet(n) * 1e-2;
SERAstart = [SERAstart(alf - i * bet(n))(alf + i * bet(n))];
end
What I don't understand is this line;
SERAstart(alf - i * bet(n))(alf + i * bet(n))
Two consecutive parentheses after "SERAstart", are they nested array indexing? are they indexing and then function call to return of indexing? are they function call and then function call again to return value of first call?
Please help me understand what is going on here so that I can convert it to Python.
I realize that it might not be possible just from the piece of code I have posted to say definitively what it does, but otherwise if you can help guide me to how to figure it out (without the use of Matlab) then I would also be very grateful.
Thanks a lot for any help!.
EDIT:
This is my own attempt at a conversion, but I don't know if this makes sense;
# SERAstart = [];
SERAstart = [[]]
# for n=1:length(bet)
for n in range(len(bet)):
# alf = -bet(n) * 1e-2;
alf = -bet[n] * 1e-2
# SERAstart = [SERAstart(alf - i * bet(n))(alf + i * bet(n))];
SERAstart = [SERAstart[alf - 1j * bet[n]][alf + 1j * bet[n]]]
# end
EDIT2:
I just noticed this line in the documentation relating to SERAstart:
% SERAstart(N,1) : vector of starting poles [rad/sec]

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.

Rpy2: set a R formulat from 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)

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.

Is vectorizing this triple for loop in Python / Numpy possible?

I am trying to speed up my code which currently takes a little over an hour to run in Python / Numpy. The majority of computation time occurs in the function pasted below.
I'm trying to vectorize Z, but I'm finding it rather difficult for a triple for loop. Could I possible implement the numpy.diff function somewhere? Take a look:
def MyFESolver(KK,D,r,Z):
global tdim
global xdim
global q1
global q2
for k in range(1,tdim):
for i in range(1,xdim-1):
for j in range (1,xdim-1):
Z[k,i,j]=Z[k-1,i,j]+r*q1*Z[k-1,i,j]*(KK-Z[k-1,i,j])+D*q2*(Z[k-1,i-1,j]-4*Z[k-1,i,j]+Z[k-1,i+1,j]+Z[k-1,i,j-1]+Z[k-1,i,j+1])
return Z
tdim = 75 xdim = 25
I agree, it's tricky because the BCs on all four sides, ruin the simple structure of the Stiffness matrix. You can get rid of the space loops as such:
from pylab import *
from scipy.sparse.lil import lil_matrix
tdim = 3; xdim = 4; r = 1.0; q1, q2 = .05, .05; KK= 1.0; D = .5 #random values
Z = ones((tdim, xdim, xdim))
#Iterate in time
for k in range(1,tdim):
Z_prev = Z[k-1,:,:] #may need to flatten
Z_up = Z_prev[1:-1,2:]
Z_down = Z_prev[1:-1,:-2]
Z_left = Z_prev[:-2,1:-1]
Z_right = Z_prev[2:,1:-1]
centre_term = (q1*r*(Z_prev[1:-1,1:-1] + KK) - 4*D*q2)* Z_prev[1:-1,1:-1]
Z[k,1:-1,1:-1]= Z_prev[1:-1,1:-1]+ centre_term + q2*(Z_up+Z_left+Z_right+Z_down)
But I don't think you can get rid of the time loop...
I think the expression:
Z_up = Z_prev[1:-1,2:]
makes a copy in numpy, whereas what you want is a view - if you can figure out how to do this - it should be even faster (how much?)
Finally, I agree with the rest of the answerers - from experience, this kind of loops are better done in C and then wrapped into numpy. But the above should be faster than the original...
This looks like an ideal case for Cython. I'd suggest writing that function in Cython, it'll probably be hundreds of times faster.

Categories

Resources