z3 python change logic gate children - python

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.)

Related

Python Error: "divide by zero encountered in log" in function, how to adjust? (Beginner here)

For my current assignment, I am to establish the stability of intersection/equilibrium points between two nullclines, which I have defined as follows:
def fNullcline(F):
P = (1/k)*((1/beta)*np.log(F/(1-F))-c*F+v)
return P
def pNullcline(P):
F = (1/delta)*(pD-alpha*P+(r*P**2)/(m**2+P**2))
return F
I also have a method "stability" that applies the Hurwitz criteria on the underlying system's Jacobian:
def dPdt(P,F):
return pD-delta*F-alpha*P+(r*P**2)/(m**2+P**2)
def dFdt(P,F):
return s*(1/(1+sym.exp(-beta*(-v+c*F+k*P)))-F)
def stability(P,F):
x = sym.Symbol('x')
ax = sym.diff(dPdt(x, F),x)
ddx = sym.lambdify(x, ax)
a = ddx(P)
# shortening the code here: the same happens for b, c, d
matrix = [[a, b],[c,d]]
eigenvalues, eigenvectors = np.linalg.eig(matrix)
e1 = eigenvalues[0]
e2 = eigenvalues[1]
if(e1 >= 0 or e2 >= 0):
return 0
else:
return 1
The solution I was looking for was later provided. Basically, values became too small! So this code was added to make sure no too small values are being used for checking the stability:
set={0}
for j in range(1,210):
for i in range(1,410):
x=i*0.005
y=j*0.005
x,y=fsolve(System,[x,y])
nexist=1
for i in set:
if(abs(y-i))<0.00001:
nexist=0
if(nexist):
set.add(y)
set.discard(0)
I'm still pretty new to coding so the function in and on itself is still a bit of a mystery to me, but it eventually helped in making the little program run smoothly :) I would again like to express gratitude for all the help I have received on this question. Below, there are still some helpful comments, which is why I will leave this question up in case anyone might run into this problem in the future, and can find a solution thanks to this thread.
After a bit of back and forth, I came to realise that to avoid the log to use unwanted values, I can instead define set as an array:
set = np.arange(0, 2, 0.001)
I get a list of values within this array as output, complete with their according stabilities. This is not a perfect solution as I still get runtime errors (in fact, I now get... three error messages), but I got what I wanted out of it, so I'm counting that as a win?
Edit: I am further elaborating on this in the original post to improve the documentation, however, I would like to point out again here that this solution does not seem to be working, after all. I was too hasty! I apologise for the confusion. It's a very rocky road for me. The correct solution has since been provided, and is documented in the original question.

A strange (because i am new in python) result when i update self variable. Why this happens?

It is now one week that i am stuck with this and i don't know why it is happening. So i want to present to you my problem to see if you have a solution.
I have this code. My purpose here is to update this variables A and B using a loop. So, i first execute all calcs using A and B that i give when i call the class, then the code compute gamma and xi and finally i want to compute new A and B.
I create in my class first the functions that i use to find the values that i need to use for computing gamma and xi. Then i create functions that i use to find gamma and xi. In this function i call the previous functions with self.fun.
Then i create the function that i show here to compute new A and B values and i insert this in a loop because i want to iterate this function until i reach a convergence.
But...
This method works correctly to compute A, but, when it needs to compute B, it uses the new A before computing B. It implies that, when it computes A, old A and B are used to compute gamma and xi and then A. Where it computes B, it uses new A and B to compute gamma and xi but i want that it uses the same that it uses to compute first A.
def update(self):
for n in range(self.iter):
gamma = self.gamma()
xi = self.xi()
# new trans matrix
new_A = []
for i in range(len(self.A)):
temp = []
for j in range(len(self.A[i])):
numerator = 0
denominator = 0
for r in range(len(self.seq)):
for t in range(len(xi[r])):
numerator += xi[r][t][i][j]
denominator += gamma[r][t][i]
aij = numerator / denominator
temp.append(aij)
new_A.append(temp)
self.A = new_A
emission_signals = unique(self.seq[0])
emission_matrix = []
for k in range(len(emission_signals)):
emission_matrix.append([])
for i in range(len(self.A)):
gamma_vec = []
gamma_num = []
for r in range(len(self.seq)):
for t in range(len(self.seq[r])):
gamma_append = gamma[r][t][i]
gamma_vec.append(gamma_append)
if self.seq[r][t] == emission_signals[k]:
gamma_num_append = gamma[r][t][i]
gamma_num.append(gamma_num_append)
bik = sum(gamma_num) / sum(gamma_vec)
emission_matrix[k].append(bik)
new_B = {}
keys = emission_signals
for i in range(len(keys)):
new_B[keys[i]] = emission_matrix[i]
self.A = new_A
self.B = new_B
return {'A': self.A, 'B': self.B}
I don't know if i'm explaining well but this is my problem.
Hope that you can help me!
Thank you !
It's difficult without seeing the rest of your code, but it looks like you are referencing mutable objects A and B (list and dict) multiple times, and editing them from different places.
Just take into account, in python, every time you assign a mutable object to a variable, you are only creating a new reference to same object and not copying it. So every edit you do on that object, will be reflected on all its references.
Ok. the problem was this:
print(self.update().get('A'))
print(self.update().get('B'))
I change it in this way and now it works but i do not understand the logic behind this.
a = self.update()
print('\n---New transition matrix... ---')
print(a.get('A'))
print('\n---New Emission matrix... ---')
print(a.get('B'))
Maybe in the previous way i call update 2 times and then calculations go wrong. i don't know.

Is that way of writing/reading a solution safe?

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.

Fill Z3Py Tree with values

I have this tree datatype, where I want to be able to go up and down. But actually, any structure will work, as long as I can get the parent/left child/right child of a node.
Tree = Datatype('Tree')
Tree.declare('nil')
Tree.declare('node', ('label', IntSort()), ('left', Tree), ('up', Tree), ('right', Tree))
Tree = Tree.create()
But I don't know how to fill the datastructure... I thought I could create the tree one node at a time like the following, but that seems to be the wrong way.
trees = [Const('t' + str(i), Tree) for i in range(3)]
Tree.up(trees[0]) = Tree.nil
Tree.left(trees[0]) = trees[1]
Tree.right(trees[0]) = trees[2]
Tree.up(trees[1]) = trees[0]
Tree.up(trees[2]) = trees[0]
Thanks for your help.
I have the feeling that you are slightly mistaken about how such data structures work. Z3's language, and thus also Z3py's, is the language of first-order logic (modulo theories), in which only assumptions/facts exist. One of the major differences with respect to imperative programming languages is, that you don't have destructive updates*, i.e., you cannot update the value of an entity.
In your code you try to build the data structures in an imperative way by essentially manipulating pointers, e. g., by the (attempted) assignment
Tree.up(trees[0]) = Tree.nil
What you probably had in mind was "making trees[0].up point to nil". However, since destructive updates are not part of a first-order language, you instead have to "think functional", i.e., "assume that up(trees[0]) == nil". Adding such assumptions can be done as follows (online on rise4fun):
s = Solver()
s.add(
Tree.up(trees[0]) == Tree.nil,
Tree.left(trees[0]) == trees[1],
Tree.right(trees[0]) == trees[2],
Tree.up(trees[1]) == trees[0],
Tree.up(trees[2]) == trees[0]
)
print s.check() # sat -> your constraints are satisfiable
A consequence of not having destructive updates is that you cannot modify your data structure in a way typical for imperative programming languages. With such updates it would be possible to modify the tree such that trees[1].up.left != trees[1], for example, by the assignment trees[1].up.left = trees[2] (for trees[1] != trees[2]). However, If you add corresponding assumptions
s.add(
trees[1] != trees[2],
Tree.left(Tree.up(trees[1])) == trees[2]
)
print s.check() # unsat
you'll see that your constraints are no longer satisfiable, because the old and new assumptions contradict.
By the way, your definition of the Tree datatype makes it possible to assume that Tree.up(nil) == someTree. Assuming that t1 != t2 are leaves of a tree and that left(t1) == right(t1) == nil and analogous for t2, then you'll have a contradiction if up(nil) == t1 and up(nil) == t2. I don't know how to prevent this on the level of Z3, though.
* Destructive updates could be added as syntactic sugar because they can be turned into assumptions by a so-called passification transformation. This, for example, is done in the intermediate verification language Boogie.

How can I implement a makefile-style algorithm in python

I am implementing an acoustic feature extraction system in python, and I need to implement a makefile-style algorithm to ensure that all blocks in the feature extraction system are run in the correct order, and without repeating any feature extractions stages.
The input to this feature extraction system will be a graph detailing the links between the feature extraction blocks, and I'd like to work out which functions to run when based upon the graph.
An example of such a system might be the following:
,-> [B] -> [D] ----+
input --> [A] ^ v
`-> [C] ----+---> [E] --> output
and the function calls (assuming each block X is a function of the form output = X(inputs) might be something like:
a = A(input)
b = B(a)
c = C(a)
d = D(b,c) # can't call D until both b and c are ready
output = E(d,c) # can't call E until both c and d are ready
I already have the function graph loaded in the form of a dictionary with each dictionary entry of the form (inputs, function) like so:
blocks = {'A' : (('input'), A),
'B' : (('A'), B),
'C' : (('A'), C),
'D' : (('B','C'), D),
'output' : (('D','C'), E)}
I'm just currently drawing a blank on what the makefile algorithm does exactly, and how to go about implementing it. My google-fu appears to be not-very-helpful here too. If someone at least can give me a pointer to a good discussion of the makefile algorithm that would probably be a good start.
Topological sorting
blocks is basically an adjacency list representation of the (acyclic) dependency graph. Hence, to get the correct order to process the blocks, you can perform a topological sort.
As the other helpful answerers have already pointed out, what I'm after is a topological sort, but I think my particular case is a little simpler because the function graph must always start at input and end at output.
So, here is what I ended up doing (I've edited it slightly to remove some context-dependent stuff, so it may not be completely correct):
def extract(func_graph):
def _getsignal(block,signals):
if block in signals:
return signals[block]
else:
inblocks, fn = func_graph[block]
inputs = [_getsignal(i,signals) for i in inblocks]
signals[block] = fn(inputs)
return signals[block]
def extract_func (input):
signals = dict(input=input)
return _getsignal('output',signals)
return extract_func
So now given I can set up the function with
fn = extract(blocks)
And use it as many times as I like:
list_of_outputs = [fn(i) for i in list_of_inputs]
I should probably also put in some checks for loops, but that is a problem for another day.
For code in many languages, including Python try these Rosetta code links: Topological sort, and Topological sort/Extracted top item.

Categories