Declaration of Arrays in Z3 - z3

I am new to Z3. I am confused about what the following declaration of a one dimensional array in Z3 means
(declare-const a1 (Array t1 t2))
Is this a 1-D array of sort (type) t1 or of sort (type) t2?
Is one of t1 or t2 the type of the indexing in array a1?
Could you suggest a reference to understand Z3? I have been following the tutorial on http://z3.codeplex.com/.

Yes, t1 and t2 are index sort and element sort as defined by the SMT theory for arrays.
The Z3 Guide is probably the best place to start reading. It has a section on arrays too.

Related

Relational Algebra- fullouterjoin

The “left outer join” operation is an extension of
the relational join operation. The basic idea is that all tuples in the left relation always
appear in the “left outer join” result, irrespective of whether they join with any tuple in the
right relation. For example, consider two relations R(A, B), and S(B, C). Assume that R
has the following tuples: (1, 10), (1, 20), and S has the following tuples: (10, 75), (10, 85),
(30, 95). R LeftOuterJoin S will have the following tuples: (1, 10, 75), (1, 10, 85), (1, 20,
null). Note that the first two tuples are the result of a regular join operation between R and
S. The third tuple (1, 20, null) is added to the left outer join result because the tuple (1, 20)
in R (which is the left relation) does not join with any tuple in S; the S column values are
set to null in this case.
Note that the left outer join operation is not symmetric because tuples in the right relation
do not appear in the outer join result unless they join with a tuple in the left relation. In our
example, the tuple (30, 95) in S (the right relation) does not appear in the left outer join
result because it does not join with any tuple in R.
The RightOuterJoin is defined in a similar way except all tuples in S will show up in the
final result when we apply R RightOuterJoin S. In addition, we also define the full outer
join between two tables as :
R fullouterjoin S = (R Leftouterjoin S) ∪ (R Rightouterjoin S)
Given the above description of full outer join and assume T = R fullouterjoin S under an
arbitrary join condition, answer the following questions.
Therefore, T = R fullouterjoin S = (R Leftouterjoin S) ∪ (R Rightouterjoin S)
How can you recover the exact operands R and S from T? If yes, what is the function f? If not, why?
-> after searching online, i think the answer is that we can't. Can someone verify
I don't know the Hopkins book, so what does it say for Leftouterjoin where there's a tuple on the left with no match on the right? For example (1, 20) in R.
I expect it'll say that for attribute C there will be Null.
So this gives us a way to recover the original content of the operands:
If C is Null, the A, B must be in R only.
If A is Null, the B, C must be in S only.
If all attributes are non-Null, the A, B must be in R and the B, C must be in S.
Does the Hopkins text give a way to detect if an attribute is Null? There is no 'standard' Relational Algebra when it comes to detecting Null; indeed most variants of RA don't support Null at all, for a very good reason ...
Except: I'm making a big assumption, which is probably not valid. Are Nulls allowed in the base relations R, S? Then a Null in attribute C of the fullouterjoin might be because there was a tuple in R that didn't match to S, as I described above. Or might be because there there's a tuple in S with attribute C as Null.
This is just a small example of the logical incoherence in allowing Nulls. Don't do that; don't use outer joins; don't expect that you can recover the content of the operands from the result of an outer join. After all, most operators in logic or arithmetic lose information, why expect outer joins to be special?
A bigger incoherence is if there's tuples with attribute B as Null -- either in R or in S or in both. What does the Hopkins book say happens with outer joins? Does that behaviour make any sense to you?

neo4j: List of ints from plain string representation

Context
I would like to read from a csv-file into my database and create nodes and connections. For the to be created order nodes, one of the fields to read is a stuffed list of Products (relational key), i.e. looks like this "[123,456,789]" where the numbers are the product ids.
Now reading the data into the db I have no problem to create nodes for the Orders and the Products; going over another iteration I now want to create the edges by kind of unwinding the list of products in the Order and linking to the according products.
Best would be if I could at creation time of the Order-nodes convert the string containing the list into a list of ints, so that a simple loop over these values and matching the Product-nodes would do the trick (also for storage efficiency this would be better).
Problem
However I cannot figure out how to convert the said string into the said format of a list containing ints. All my attempts with coming up with a cypher for this failed miserably. I will post some of them below, starting from the string l:
WITH '[123,456,789]' as l
WITH split(replace(replace(l,'[',''),']',''),',') as s
UNWIND s as ss
COLLECT(toInteger(ss) ) as k
return k
WITH '[123,456,789]' as l
WITH split(replace(replace(l,'[',''),']',''),',') as s, [] as k
FOREACH(ss IN s| SET k = k + toInteger(ss) )
return k
both statements failing.
EDIT
I have found a partial solution, I am however not quite satisfied with as it applied only to my task at hand, but is not a solution to the more general problem of this list conversion.
I found out that one can create an empty list as an property of a node, which can be successively updated:
CREATE (o:Order {k: []})
WITH o, '[123,456]' as l
WITH o, split(replace(replace(l,'[',''),']',''),',') as s
FOREACH(ss IN s | SET o.k= o.k + toInteger(ss) )
RETURN o.k
strangly this will only work on properties of nodes, but not on bound variables (see above)
Since the input string looks like a valid JSON object, you can simple use the apoc.convert.fromJsonList function from the APOC library:
WITH "[123,456,789]" AS l
RETURN apoc.convert.fromJsonList(l)
You can use substring() to trim out the brackets at the start and the end.
This approach will allow you to create a list of the ints:
WITH '[123,456,789]' as nums
WITH substring(nums, 1, size(nums)-2) as nums
WITH split(nums, ',') as numList
RETURN numList
You can of course perform all these operations at once, and then UNWIND the subsequent list, convert them to ints, and match them to products:
WITH '[123,456,789]' as nums
UNWIND split(substring(nums, 1, size(nums)-2), ',') as numString
WITH toInteger(numString) as num
MATCH (p:Product {id:num})
...
EDIT
If you just want to convert this to a list of integers, you can use list comprehension to do this once you have your list of strings:
WITH '[123,456,789]' as nums
WITH split(substring(nums, 1, size(nums)-2), ',') as numStrings
WITH [str in numStrings | toInteger(str)] as nums
...

Check if a sequence exist in in collect in neo4j

Can somebody please tell how we can compare a sequence is present in the collection or not in Cypher / Neo4j?
Like if I say that while collect() is collecting the elements on traversal , can we check that this sequence is present when it has done collection [Element1, Element2, Element3]?
Depending if you allow gaps, you could either find the index of e1..e3 and see that they are ascending (with gaps) (apoc.coll.indexOf)
Or you could extract-3-element sublists and compare them.
WITH [1,2,3,4,5] as coll, [2,3,4] as seq
WHERE any(idx IN range(0,length(coll)-length(seq)) WHERE coll[idx..idx+length(seq)] = seq)
RETURN coll, seq

Neo4j : iterate through relationship

I'm using Neo4j 3.0.6 and I want to do something like that :
for k in keys(r):
if k >= `2015-01`:
sum(values(k)) as sum
I tried foreach but it doesn't work.
In the model, the key of my relationship is a pair of date and a criterion. Here is an example:
<id>... 2015-01,c:500 2015-02,c:23 2015-03,c:900 2015-01,r:56
The expected resulat :
sum
923
So, I'm looking to get the sum of the criterion c when it's greater than 2015-01
Thank you
MATCH (origin:AirportFR)
WHERE origin.code IN ['JFK', 'ATX']
MATCH (destination:AirportFR)
WHERE destination.code IN ['BUY', 'PUQ']
MATCH (origin) - [r] - (destination)
UNWIND [k IN KEYS(r) WHERE split(k, ',')[0] >= '2015-01' AND split(k, ',')[1] = 'c'| r[k] ] AS c_values
RETURN SUM(c_values)
SUM is an aggregation function that expects to collect data from several rows, so you have to get the property you want into rows. To generate these rows, you're going to have to UNWIND a filtered list of the keys for each row. But as mentioned below, seriously consider changing your data model so that you don't have to run string analysis on your keys.

My cypher WHERE clause is not filtering

I have a cypher query that is something like:
MATCH(e:ZOOT {id:100})
OPTIONAL MATCH(e)-[a1]->(X:QAZ)
OPTIONAL MATCH(e)-[a2]->(Y:WSX)
WHERE a1 is not null or a2 is not null
RETURN e, a1, a2
What I want is for rows producing neither a1 or a2 to be filtered away.
Yet my statement is returning rows in all cases, even of a1 and a2 are both null.
How does WHERE really work?
edit - clarification added to query
The reason you're seeing confusing results is because you're assuming the WHERE applies to the entire result before being pumped out by the RETURN. However, this isn't the case.
From the documentation on Cypher Structure:
WHERE: Not a clause in its own right, but rather part of MATCH,
OPTIONAL MATCH and WITH. Adds constraints to a pattern, or filters the
intermediate result passing through WITH.
So if I place parentheses to show how the clauses group together, it would look like this:
MATCH (e:ZOOT {id:100})
OPTIONAL MATCH(e)-[a1]->(X:QAZ)
(OPTIONAL MATCH(e)-[a2]->(Y:WSX)
WHERE a1 is not null or a2 is not null)
RETURN e, a1, a2
Your WHERE is only applying to that OPTIONAL MATCH (that particular OPTIONAL MATCH will only be included if a1 is not null or a2 is not null), which wasn't your intention. You want to apply it to the whole thing, so the easiest way to do that is to separate the queries with a WITH like so:
MATCH (e:ZOOT {id:100})
OPTIONAL MATCH(e)-[a1]->(:QAZ)
OPTIONAL MATCH(e)-[a2]->(:WSX)
WITH e, a1, a2
WHERE a1 is not null or a2 is not null
RETURN e, a1, a2
There's a way to optimize this query a bit if you're not really interested in the relationships themselves, and just want to know if your :ZOOT node has a match to either a QAZ node or a WSX node. You can use EXISTS() like so:
MATCH (e:ZOOT {id:100})
WHERE EXISTS((e)-->(:QAZ)) OR EXISTS((e)-->(:WSX))
RETURN e
Note that since you didn't provide the relationship type or use the X and Y variables bound to your end nodes, I'm assuming you aren't interested in them; I've removed them to avoid confusion from anyone reading your query.
you can change your query to this
match (e)-[r:a1|a2]-(x) return e,r,x
as for the WHERE clause i hate to state the obvious but read this :)

Resources