Is that way of writing/reading a solution safe? - python

I need to store a solution of expensive FEM calculation to use it in further analysis. Browsing through tutorials I have so far discovered, that I may store my results like this:
from fenics import *
mesh = Mesh('mesh/UnitSquare8x8.xml')
V = FunctionSpace(mesh, 'P', 1)
u = TrialFunction(V)
v = TestFunction(V)
f = Constant(-6.0)
a = dot(grad(u), grad(v))*dx
L = f*v*dx
u_D = Expression('1 + x[0]*x[0] + 2*x[1]*x[1]', degree=2)
def boundary(x, on_boundary):
return on_boundary
bc = DirichletBC(V, u_D, boundary)
A = assemble(a)
b = assemble(L)
bc.apply(A, b)
u = Function(V)
solver = KrylovSolver("cg", "ilu")
solver.solve(A, u.vector(), b)
File('solution.xml') << u.vector()
and later load them like this:
from fenics import *
mesh = Mesh('mesh/UnitSquare8x8.xml')
V = FunctionSpace(mesh, 'P', 1)
u = Function(V)
File('solution.xml') >> u.vector()
Unfortunately I hardly know what exactly I am doing here. Is that a proper way of storing and loading calculated results? Is order of elements in u.vector() (for the same mesh file) fixed within/between different FEniCS versions, or it is just an implementation detail which may change any time? If it is unsafe, then what is the proper way of doing so?
I have found another (possibly even more dangerous) solution. I may use VALUES = u.vector().get_local() and u.vector().set_local(VALUES) methods, as VALUES is a numpy array which I may easily store and load.

No, according to answer to Is the order of Vector elements preserved between runs? the order of Vector elements is not guarranted to be preserved.
It is recommended to use XDMFFile.write_checkpoint() and XDMFFile.read_checkpoint() methods instead.

Related

z3 python change logic gate children

My algorithm needs to modify the children() of the existing logic gate. Suppose i have the following code
a = Bool('a')
b = Bool('b')
c = Bool('c')
or_gate = Or(a, b)
I want to modify or_gate to be Or(a, c).
I have tried the following:
or_gate.children()[1] = c
print(or_gate)
The above code doesn't work, or_gate is still Or(a, b). So how do i change the children of a logic gate in z3?
Edit: i can't create new Or() that contains the children i want due to nested gate. For example consider the following
a = Bool('a')
b = Bool('b')
c = Bool('c')
d = Bool('d')
e = Bool('e')
or_gate_one = Or(a, b)
or_gate_two = Or(or_gate_one, c)
or_gate_three = Or(or_gate_two, d)
If we create new object instead of directly modifying the children of or_gate_one, then or_gate_two and or_gate_three should also be modified, which is horrible for large scale. I need to modify the children of or_gate_one directly.
Use the substitute method:
from z3 import *
a = Bool('a')
b = Bool('b')
c = Bool('c')
or_gate = Or(a, b)
print(or_gate)
or_gate_c = substitute(or_gate, *[(a, c)])
print(or_gate_c)
This prints:
Or(a, b)
Or(c, b)
I wouldn't worry about efficiency, unless you observe it to be a problem down the road: (1) z3 will "share" the internal AST when you use substitute as much as it can, and (2) in most z3 programming, run-time is dominated by solving the constraints, not building them.
If you find that building the constraints is very costly, then you should switch to the lower-level APIs (i.e., C/C++), instead of using Python so you can avoid the extra-level of interpretation in between. But again, only do this if you have run-time evidence that building is the bottleneck, not the solving. (Because in the common case of the latter, switching to C/C++ isn't going to save you much anyhow.)

Solving simultaneous equations (>2) without conversion to matrices in R or Python

I have a set of 4 simultaneous equations:
0.059z = x
0.06w = y
z+w = 8093
x+y = 422
All the solutions I've found so far seem to be for equations that have all the variables present in each equation, then convert to matrices and use the solve function.
Is there an easier way to do this in R or Python using the equations in their original form?
Also, how can I ensure that only positive numbers are returned in the solution?
Hope this makes sense...many thanks for the help
You can use sympy for this:
from sympy import symbols, linsolve, Eq
x,y,z,w = symbols('x y z w')
linsolve([Eq(0.059*z, x), Eq(0.06*w, y), Eq(z+w, 8093), Eq(x+y, 422)], (x, y, z, w))
Output:
Regarding your comments about negative values - there is only one solution to the system of equations, and it has negative values for y and w. If there was more than one solution, sympy would return them, and you could filter the solutions from there to only positive values.
In R, maybe you try it like below:
library(rootSolve)
library(zeallot)
model <- function(v){
c(x,y,z,w) %<-% v
return(c(0.059*z-x, 0.06*w-y, z+w-8093, x+y-422))
}
res <- multiroot(f = model, start = c(0,0,0,0))
then you can get the solution res as
> res
[1] 3751.22 -3329.22 63580.00 -55487.00
there are a few things going on here. first as CDJB notes: if there were any positive solutions then sympy would find them. I searched for those numbers and found this paper which suggests you should be using 7088 instead of 8093. we can do a quick sanity check:
def pct(value):
return f"{value:.1%}"
print(pct(422 / 8093)) # ~5.2%
print(pct(422 / 7088)) # ~6.0%
confirming that you're going to struggle averaging ~5.9% and ~6.0% towards ~5.2%, and explaining the negative solutions in the other answers. further, these are presumably counts so all your variables also need to be whole numbers.
once this correct denominator is used, I'd comment that there are many solutions (11645 by my count) e.g:
cases = [1, 421]
pop = [17, 7071]
rates = [pct(c / p) for c, p in zip(cases, pop)]
gives the appropriate output, as does:
cases = [2, 420]
pop = [34, 7054]
this is because the data was rounded to two decimal places. you probably also don't want to use either of the above, they're just the first two valid solutions I got.
we can define a Python function to enumerate all solutions:
from math import floor, ceil
def solutions(pop, cases, rate1, rate2, err):
target = (pct(rate1), pct(rate2))
for pop1 in range(1, pop):
pop2 = pop - pop1
c1_lo = ceil(pop1 * (rate1 - err))
c1_hi = floor(pop1 * (rate1 + err))
for c1 in range(c1_lo, c1_hi+1):
c2 = cases - c1
if (pct(c1 / pop1), pct(c2 / pop2)) == target:
yield c1, c2, pop1, pop2
all_sols = list(solutions(7088, 422, 0.059, 0.060, 0.0005))
which is where I got my count of 11645 above from.
not sure what to suggest with this, but you could maybe do a bootstrap to see how much your statistic varies with different solutions. another option would be to do a Bayesian analysis which would let you put priors over the population sizes and hence cut this down a lot.

Smart indexing using numpy

So, this is more like a structural problem but I think it's looking fairy ugly at the moment, I have code looking like:
for i in range(length_of_tree):
potential_ways = np.zeros((M, 2))
for m in range(omega):
for s in range(Z):
potential_ways[m][s] = sum([quad[r][m][s] for r in range(reps)])
The code is currently working, but I've noticed that there are several ways using numpy to avoid for-loops, my question is therefore, is there a way for me to make this code a bit more minimalistic?
A sum over values in an array can always be changed into an inner product which is optimised in numpy. As has been suggested here, I don't really understand the context of your question without examples but you should be able to do something like the following:
np.random.seed(1)
# your examples
M = 2
length_of_tree,reps = 100,100
omega,Z = 2,2
# a random matrix of values of shape 100,2,2
quad = np.random.normal(0,1,size=(100,2,2))
# useful initializations
quadT = quad.T
dummy = np.ones(shape=(100,))
for i in range(length_of_tree):
# option 1
potential_ways = np.zeros((M, 2))
for m in range(omega):
for s in range(Z):
potential_ways[m][s] = sum([quad[r][m][s] for r in range(reps)])
# option 2
potential_ways = quadT.dot(dummy).T

Fenics help: Writing a list of data into Expression for nonlinear part in fenics?

I'm trying to solve a nonlinear problem in fenics. Instead of knowing the nonlinear function as an expression, I only know the values in the form of data.
In other words, if i am solving nabla(k(u).nabla(u)) = C, I do not know k(u) or cannot write it in terms of x[0] etc, I only know corresponding values of k for all values of u.
At the moment i have written some interpolating function and called it into 'k' which can project it to a function space, but it does not seem to work when i put it into the variational form and solve.
Below is some code to clarify the problem: I was using method of manufactured solutions where u=x^2 with k=1+u^2 as a test, where k_data = list of data for u=[0,(1+xmax^2)].
I've been told i can look into subclasses in Expression but i have no idea how to do this without knowing it in terms of x[0]. please help!
u = Function(V)
v = TestFunction(V)
u.interpolate(Expression("x[0]"))
k = interpolate_table(u,kappa_data)
plot(project(k,V))
C = Expression("-2.0-10.0*x[0]*x[0]*x[0]*x[0]")
diff_part = k*inner(grad(u),grad(v))*dx
source_part = C*v*dx
Res = diff_part - source_part
J = derivative(Res,u)
problem = NonlinearVariationalProblem(Res, u, bcs, J)
solver = NonlinearVariationalSolver(problem)
solver.solve()
prm = solver.parameters['newton_solver']
prm['relative_tolerance'] = 1E-6
prm['absolute_tolerance'] = 1E-6
prm['maximum_iterations'] = 100

How to extract data in *.txt file and use it in Python?

I have a Python code that converts (u,v)to (s,d):
def d2r(d):
r = d * math.pi / 180.0
return (r)
def r2d(r):
d = r * 180.0 / math.pi
return (d)
def sd2uv(s,d):
r = d2r(d)
u = s * math.sin(r)
v = s * math.cos(r)
return (u,v)
def uv2sd(u,v):
s = math.sqrt((u*u)+(v*v))
r = math.atan2(u,v)
d = r2d(r)
if d < 0:
d = 360 + d
return (s,d)
The u data are stored in u.txt, each line has one number; the v data are stored in v.txt and each line has one number too. My question is how to extract data from these two files and then use them in the Python code to print (s,d)? Thanks!
I think this should do it:
with open('u.txt') as uf, open('v.txt') as vf:
for u,v in zip(uf,vf):
print uv2sd(float(u),float(v))
from itertools import izip, imap
with open('u.txt') as u_data, open('v.txt') as v_data:
for u,v in imap(float, izip(u_data, v_data)):
print uv2sd(u, v)
I can imagine two ways of doing this:
Read all of the data from each file into two separate lists. Iterate through both lists and compute each value until you reach the end of one of the lists.
Read one line from each file at a time. Compute the value you are looking for. Repeat until you have exhausted both files.
The first point has the advantage of saving the data for subsequent use (if needed) without having to open & read the files again. This may not work well at all if you have a very large data set in the file.
The second point has the advantage of saving some memory if you only need to use the data once in the program. This could be slower if you need to use the data over-and-over again.
The first way may look like this:
with open('u.txt') as u_file, open('v.txt') as v_file:
u_values = u_file.readlines()
v_values = v_file.readlines()
for u, v in zip(u_values, v_values):
print uv2sd(float(u), float(v))
# We can use u_values and v_values again if we need to now
The second way is what Akavall and gnibbler came up with.

Categories