Finding path between two nodes - z3

I was wondering if there is a way to build a topology in z3py, if I am given with 6 nodes namely: n1, n2, n3, n4, n5, n6 and they have certain links among them e.g. l12 (which implies there is a link between node n1 and n2), l16, l23, l25, l34,l35, l36. I can define l_{i}{j} as a bool variable so that it may refer whether there exists any link between 2 nodes or node (for sure I will have to define all possible links in this way). The question is how to define the notion of a path in Z3py, so that I can figure out if there exists any path between 2 nodes or not (SAT or UNSAT if SAT which path?). I tried looking for z3py tutorial but it isnt available online anymore, I am new to z3 so kindly bear with me. I could only figure out the following modeling in python which is very naive. Is it possible to model a path as an uninterpreted function in z3py?
graph = {'n1': ['n2', 'n6'],
'n2': ['n3', 'n5'],
'n3': ['n4', 'n5','n6'],
'n4': ['n3'],
'n5': ['n2', 'n3'],
'n6': ['n3','n1']}
def path_finder (graph, start, end, path=[]):
path = path + [start]
if start == end:
return path
if not graph.has_key(start):
return None
for node in graph[start]:
if node not in path:
newpath = path_finder (graph, node, end, path)
if newpath: return newpath
return None
print path_finder (graph, 'n1','n4')

I modified a Fixpoint example to accomplish path search
from z3 import *
# cf. https://ericpony.github.io/z3py-tutorial/fixpoint-examples.htm
fp = Fixedpoint()
fp.set(engine='datalog')
# 3 bits are sufficient to model our 6 nodes
s = BitVecSort(3)
edge = Function('edge', s, s, BoolSort())
path = Function('path', s, s, BoolSort())
a = Const('a', s)
b = Const('b', s)
c = Const('c', s)
# the rules:
# a path can be a single edge or
# a combination of a path and an edge
fp.register_relation(path,edge)
fp.declare_var(a, b, c)
fp.rule(path(a, b), edge(a, b))
fp.rule(path(a, c), [edge(a, b), path(b, c)])
n1 = BitVecVal(1, s)
n2 = BitVecVal(2, s)
n3 = BitVecVal(3, s)
n4 = BitVecVal(4, s)
n5 = BitVecVal(5, s)
n6 = BitVecVal(6, s)
n7 = BitVecVal(7, s)
graph = {n1: [n2, n6, n7],
n2: [n3, n5],
n3: [n4, n5, n6],
n4: [n3],
n5: [n2, n3],
n6: [n3, n1]}
# establish facts by enumerating the graph dictionary
for i, (source, nodes) in enumerate(graph.items()):
for destination in nodes:
fp.fact(edge(source, destination))
print("current set of rules:\n", fp)
print(fp.query(path(n1, n4)), "yes, we can reach n4 from n1\n")
print(fp.query(path(n7, n1)), "no, we cannot reach n1 from n7\n")

Related

Cypher variable lenght pattern aggregated property filtering

I'm working on neo4j and I'm trying to put a condition on a series of relationships, where I need to sum a property of said relationship.
When I do the basic textbook part of filtering for the relationship without the sum, it all works.
MATCH c= (a)-[:VENDE*2..3]->(b)
WHERE ALL (r IN relationships(c)
WHERE r.ammontare = 25000)
RETURN c
When I try to put the condition on the sum of said property, I can't find a way.
I tried REDUCE but it's stuck because the this error I didn't manage to work around: "Type mismatch: accumulator is Integer but expression has type Boolean"
MATCH c= (a)-[:VENDE*2..3]->(b)
WHERE ALL (r IN relationships(c)
WHERE REDUCE( t = 0, n in relationships(c)|t= t+ n.ammontare) = 25000)
RETURN c
I tried with apoc but this doesn't work either. What am I getting wrong?
MATCH c= (a)-[:VENDE*2..3]->(b)
WHERE all(r in relationships(r)
WHERE APOC.COLL.SUM( [r IN relationships(c)| r.ammontare]) = 25000)
return c
The last method runs but it's too heavy and goes into timeout.
MATCH c= (a)-[:VENDE*2]->(b)
WITH c, relationships(c) as rels
UNWIND (rels) as rel
With c, sum(rel.ammontare) as re
where re > 25000
return c
I'm not sure but this will work.
MATCH c= (a)-[:VENDE*2..3]->(b)
WHERE ALL (r IN relationships(c)
WHERE REDUCE( t = 0, n in relationships(c)| t+ n.ammontare) = 25000)
RETURN c

Creating tree from given path of string list in f#

I have a type defination:
type FsTree = Node of (string * FsTree) list
I create an empty node:
let createEmptyFsTree () : FsTree = Node[]
I would love to build a tree from a path of string list, for example:
let fs1 = create ["MainNode";"nodeA";"nodeB"] (createEmptyFsTree())
let fs2 = create ["MainNode";"nodeC";"nodeD"] fs1
let fs3 = create ["MainNode";"nodeC";"nodeE"] fs2
The result will be:
Node [("MainNode", Node [
("nodeA", Node [("nodeB", Node [])]);
("nodeC", Node [
("nodeD", Node[]);
("nodeE", Node[])])])]
This is my code so far. I have been stuck for 2 days. Please help.
let create (p : string list) (fs : FsTree) =
let rec create (p : string list) (fs : FsTree) =
match fs with
| Node n -> match p, n with
| h :: t, (name, rsNode) :: rsTree when name = h -> Node([(h, (create t rsNode))] # rsTree)
| _, lNode :: rsTree -> Node([lNode]#rsTree)
| h :: t, [] -> Node ([h, (create t (createEmptyFsTree()))])
| [],[] -> Node[]
create p fs
I am only able to create the tree from the first path passed:
Node [("MainNode", Node [("nodeA", Node [("nodeB", Node [])])])]
The difficulty of this problem is that there are several structures (the path is a list, each node is a list and a subtree) that need to be traversed recursively at the same time in order for it to work. Doing so in just one function becomes very hard to figure out.
That is why I like to simplify the problem by breaking it down into smaller parts. Here we are going to use 2 mutually recursive functions (notice the syntax). First I am going to rename the functions so that I understand better what they do. I also avoid repeating the same name for functions and variables as it is confusing. My first function will only deal with traversing the path p:
let rec addPath (p : string list) (Node ns) =
match p with
| [] -> Node ns
| hp :: tp -> Node (addHeadPath hp tp ns)
I use pattern matching on the second parameter (Node ns) to get the list of subnodes, that is because the next function will traverse that list.
In my match expression I like to take care first of the empty list case which is the end of the recursion. The second case separates the head and tail and sends them to another function to deal with it:
and addHeadPath hp tp ns =
match ns with
| [] -> [hp, addPath tp (Node[]) ]
| (nn, st) :: tn when nn = hp -> (nn, addPath tp st ) :: tn
| hn :: tn -> hn :: addHeadPath hp tp tn
addHeadPathTo is mutually recursive with addPathTo so I tie them together with and instead of another let rec.
Again the empty case is dealt with first which returns a list with one node and calls addPathTo to add the rest of the path. The second case is when the node already exists in which case we add the rest of the path to the subtree st. The third case keeps looking into the list of nodes by calling itself recursively.
You invoke it this way:
createEmptyFsTree()
|> addPath ["MainNode";"nodeA";"nodeB"]
|> addPath ["MainNode";"nodeC";"nodeD"]
|> addPath ["MainNode";"nodeC";"nodeE"]
|> printfn "%A"

Why is this (very simple) vectorized code orders of magnitude slower than Numpy?

I know very well Julia's philosophy concerning vectorization and the like, and I can accept having my code run even ten times slower than Numpy, but why does this code run much, much slower than Numpy? Maybe there is a mistake in the code; I can't imagine the issue is related to using vectorization rather than loops.
I am using vectorization because my requirements are not strong; furthermore memory allocation doesn't seem to be that incredible (and it proves to be very fast with Numpy). The code is also easy to read.
The following piece of code is written in Python; it computes a generalized continued fraction over a part of the complex plane. The continued fraction is defined by two different functions; I use this code for plotting pictures on this blog: https://kettenreihen.wordpress.com/
The Python code is below; it computes 640x640 values in about 2 seconds:
def K(a, b, C):
s = C.shape
P1 = np.ones(s, dtype=np.complex)
P2 = np.zeros(s, dtype=np.complex)
Q1 = np.zeros(s, dtype=np.complex)
Q2 = np.ones(s, dtype=np.complex)
for n in range(1, 65):
A, B = a(C, n), b(C, n)
P = A*P2 + B*P1
Q = A*Q2 + B*Q1
P1, P2 = P2, P
Q1, Q2 = Q2, Q
return P2/Q2
The following Julia code should do the same, but it takes 2 or 3 minutes for computing the same thing.
function K(a, b, C)
s = size(C)
P1 = ones(Complex, s)
P2 = zeros(Complex, s)
Q1 = zeros(Complex, s)
Q2 = ones(Complex, s)
for n = 1:64
println(n)
A, B = a(C, n), b(C, n)
P = A.*P2 + B.*P1
Q = A.*Q2 + B.*Q1
P1, P2 = P2, P
Q1, Q2 = Q2, Q
end
return P2./Q2
end
You are allocating matrices with an abstract element type: the Complex type is an abstract supertype for all specific Complex{T} types. What you want here is arrays of some concrete element type like Complex128 == Complex{Float64} or Complex64 == Complex{Float32}. Presumably in NumPy dtype=np.complex refers to a specific complex type, probably the equivalent of Complex128.
If you want to write code that is generic and will work for different kinds of C matrices, then assuming C is a complex matrix and what you want is to create matrices of ones and zeros of the same element type and shape, you can just call the ones and zeros functions on C to get matrices with the right element type and shape:
function K(a, b, C)
P1 = ones(C)
P2 = zeros(C)
Q1 = zeros(C)
Q2 = ones(C)
for n = 1:64
println(n)
A, B = a(C, n), b(C, n)
P = A.*P2 + B.*P1
Q = A.*Q2 + B.*Q1
P1, P2 = P2, P
Q1, Q2 = Q2, Q
end
return P2./Q2
end
Hopefully that helps the performance. You might be able to get even more performance by pre-allocating three matrices and doing operations in place, rotating through the matrices. However, the convenient syntax support for that hasn't made it into a stable release yet, so on Julia 0.5 it would still be a little verbose, but could get you a performance boost over the vectorized version.

cypher path with condition on relationship direction

I want to find all paths given a start node
MATCH path=(n)-[rels*1..10]-(m)
with the following 2 conditions on path inlcusion:
true if relationship between subsequent nodes in path has property PROP='true'
if type(relationship)=SENDS then true if direction of the relationship is outgoing (from one path node to the next node in the path)
Another way of phrasing this is that direction doesn't matter unless the relationship name is SENDS
I can do condition 1 with WHERE ALL (r IN rels WHERE r.PROP='true') however ive no idea how to do condition 2.
The only way I can think of to filter on relationship direction without declaring direction in the match pattern is by comparing the start node of each relationship in the path with the node at the corresponding index of the nodes() collection from the path. For this you need the relationship and node collections from the path, an index counter and some boolean evaluation equivalent to ALL(). One way to do it is to use REDUCE with a collection for the accumulator, so you can accumulate index and maintain a true/false value for the path at the same time. Here's an example, the accumulator starts at [0,1] where the 0 is the index for testing that startNode(r) equals the node at the corresponding index in the node collection (i.e. it's an outgoing relationship) and the 1 represents true, which signifies that the path has not yet failed your conditions. For each relationship the index value is incremented and the CASE/WHEN clause multiplies the 'boolean' with 1 if your conditions are satisfied, with 0 if not. The evaluation of the path is then the evaluation of the second value in the collection returned by REDUCE -- if 1 then yay, if 0 then boo.
MATCH path = (n)-[*1..10]-(m)
WITH path, nodes(path) as ns, relationships(path) as rs
WHERE REDUCE(acc = [0,1], r IN rs |
[acc[0]+1, CASE WHEN
r.PROP='true' AND
(type(r) <> "SENDS" OR startNode(r) = ns[acc[0]]) THEN acc[1]*1 ELSE acc[1]*0 END]
)[1] = 1
RETURN path
or maybe this is more readable
WHERE REDUCE(acc = [0,1], r IN rs |
CASE WHEN
r.PROP=true AND
(type(r) <> "SENDS" OR startNode(r) = ns[acc[0]])
THEN [acc[0]+1, acc[1]*1]
ELSE [acc[0]+1, acc[1]*0]
END
)[1] = 1
Here's a console: http://console.neo4j.org/?id=v3kgz9
For completeness I've answered the question using jjaderberg correct solution plus a condition to fix the start node and ensure that no zero length paths are included
MATCH p = (n)-[*1..10]-(m)
WHERE ALL(n in nodes(p) WHERE 1=length(filter(m in nodes(p) WHERE m=n)))
AND (id(n)=1)
WITH p, nodes(p) as ns, relationships(p) as rs
WHERE REDUCE(acc = [0,1], r IN rs | [acc[0]+1,
CASE WHEN r.PROP='true' AND (type(r) <> "SEND" OR startNode(r) = ns[acc[0]])
THEN acc[1]*1
ELSE acc[1]*0
END])[1] = 1
RETURN nodes(p);
Or my alternative answer based on jjaderbags answer but does not use accumulator but which is slightly slower
MATCH p=(n)-[rels*1..10]-(m)
WHERE ALL(n in nodes(p) WHERE 1=length(filter(m in nodes(p) WHERE m=n)))
AND( ALL (r IN rels WHERE r.PROP='true')
AND id(n)=1)
WITH p, range(0,length(p)-1) AS idx, nodes(p) as ns, relationships(p) as rs
WHERE ALL (i in idx WHERE
CASE type(rs[i])='SEND'
WHEN TRUE THEN startnode(rs[i])=ns[i]
ELSE TRUE
END)
RETURN nodes(p);

F# equals operator complexity

I have a question about default "=" (equals) operator in F#. It allows to compare user-defined union types. The question is: what's the complexity of it? For example, let's consider following type:
type Tree<'a> =
| Nil
| Leaf of 'a
| Node of Tree<'a> * Tree<'a>
and following trees:
let a : Tree<int> = Node (Node (Node (Leaf 1, Leaf 2), Node (Leaf 3, Node (Leaf 4, Leaf 5))), Node (Leaf 6, Nil))
let b : Tree<int> = Node (Node (Node (Leaf 1, Leaf 2), Node (Leaf 3, Node (Leaf 4, Leaf 5))), Node (Leaf 6, Nil))
let c : Tree<int> = Node (Node (Node (Leaf 1, Leaf 2), Nil), Node (Node (Leaf 3, Node (Leaf 4, Leaf 5)), Leaf 6))
It is obvious that this code:
printfn "a = b: %b" (a = b)
printfn "a = c: %b" (a = c)
printfn "a = a: %b" (a = a)
produces this output:
a = b: true
a = c: false
a = a: true
I expect that the "a = b" and "a = c" comparsions takes the linear time. But what about "a = a"? If it is constant what about more complex structures, like that one:
let d : Tree<int> = Node (a, c)
let e : Tree<int> = Node (a, c)
Will it go through whole d and e structure or will it stop at "a = a" and "c = c"?
F# uses structural equality whereas the default Equals implementation in .NET uses reference equality. This means, in the typical case, equality comparisons are O(N) where N is the number of fields in the object graphs being compared.
If you want to ensure a = a is optimized, you can override Equals to check for reference equality first, and fall back on structural equality otherwise. You'll need to annotate your type with [<CustomEquality>].
You can see the rather lengthy implementation of structural equality in the F# source code on github. To follow the call hierarchy start with GenericEqualityObj on line 1412.
EDIT: The original answer was wrong.
The usual implementation of Equals() in .Net works like this:
Compare the two instances by reference. If they both refer to the same object, return true.
Compare the runtime types of the two instances. If they are different, return false.
Compare each of the fields of the type pairwise for equality. If any are not equal, return false, else return true.
For some reason, F# skips the first step, which means the time complexity is always linear.
Since the compiler knows that a and b are the same and some subtrees of c are same as some subtrees of a, and it also knows that they are immutable, it could theoretically make a and b the same object and reuse some of their parts in c. The runtime does something similar with strings, called string interning. But (based on decompiled code) it seems the compiler currently doesn't do this.

Resources