Why does introducing numbero in minikanren cause the failure of valid unifications? - logic-programming

I am using Racket v8.5, with the packages for minikanren and
minikanren/numbers required. Why does introducing the numbero
constraint cause previously valid unifications to fail?
> (run 1 (q) (<lo '(1) q))
'((_.0 _.1 . _.2))
> (run 1 (q) (<lo '(1) q) (numbero q))
'()
> (run 1 (q) (numbero q) (<lo '(1) q))
'()
> (run 1 (q) (<lo q '(1)))
'(())
> (run 1 (q) (<lo q '(1)) (numbero q))
'()
> (run 1 (q) (numbero q) (<lo q '(1)))
'()

Because the numbero constraint enforces that a term is consistent with a number in the host language (Racket in this case). Think of numbero as the constraint equivalent of Racket's number? predicate: (numbero 5) succeeds. However, you are using Kisleyov's relational arithmetic system, in which numerals are represented as little-endian lists of binary digits: (numbero '(1 0 1)) fails, just as (number? '(1 0 1)) returns #f in Racket.

Related

Counting the times of recursion in Haskell

I am writing a small school assignment in Haskell to determine the distance between two given dates. I wrote a crude function to cycle through dates but I can't wrap my head around how to write loops in a Functional Programming way. I have only done procedural- and OOP-programming before. I somehow need to store the information of how many times I've called the nextDate-function but Haskell doesn't allow me to introduce a variable inside a function. Here is the code I've come up so far. It is not very Haskelly at all...
nextDate year month day =
if day + 1 < 31
then (year,month, day+1)
else if month + 1 < 12
then (year, month + 1, 1)
else (year +1,1,1)
calculateDifference year month day year2 month2 day2 =
let x = 0
if year == year2 && month == month2 && day == day2 then x
else
nextDate(year, month, day)
x = x + 1
-- How I would do it in Python
-- x = 0
-- while((tuple1) != (year2, month2, day2)):
-- x += 1
-- tuple1 = nextDate(tuple1)
-- print(x)
If you want to track how many times the function is called, you need to provide that as an input. There's no other way to do this, because Haskell only lets you work with arguments that are passed into the function.
For example, let's say I wanted to compute a factorial, but I wanted to track how many steps it took. My function signature could look like this:
factorial :: Int -> (Int, Int) -- Takes a number, returns the number and recursion count
factorialInternal :: (Int, Int) -> (Int, Int) -- This actually does the recursion
and then the definitions could look like this:
factorial n = factorialInternal (n, 0)
factorialInternal (1, n) = (1, n + 1)
factorialInternal (x, n) = let (y, z) = factorialInternal (x-1, n) in (x * y, z + 1)
Essentially, the parameter tracking the amount of recursion is incremented at each level, and then becomes part of the output of factorial.
It definitely helps to create an interface function so that you don't have to manually input the starting recursion level when using the function (which is always zero, anyway). An example of what your function signatures could look like:
-- The function you call
calculateDifference :: (Int, Int, Int) -> (Int, Int, Int) -> Int
-- What the calculateDifference function calls (the third parameter is the recursion counter)
calculateDifferenceInternal :: (Int, Int, Int) -> (Int, Int, Int) -> Int -> Int
From here, you should be able to figure out how to implement calculateDifference and calculateDifferenceInternal.
EDIT: As amalloy pointed out, a better solution is to just output the counter, not take one in: so instead of factorialInternal :: (Int, Int) -> (Int, Int), factorialInternal Int -> (Int, Int) would work. The definition would then look like:
factorialInternal 1 = (1, 0)
factorialInternal n = let (x, y) = factorialInternal (n - 1) in (n * x, y + 1)

Query Cypher node A does not have relation with node B with conditions on B

I'm trying to build a Cypher to check if node A does not have a relation with a node B with specific attributes
node (A)
does not have relation (X)
with node (B) where B.date > 5
I've tried this and fails if there are relations with B nodes where B.date = 3
START u = node:users("id:123123")
MATCH (u)-[r1?:X]->(e1)
WHERE (NOT ((e1.date! > 5)))
OR r1 IS NULL
RETURN (u), e1
I'm using Neo4j 1.9.4
I think you need to check every node B that is related to A, and only if none of them has attribute date that satisfies B.date > 5, then the A is the desired node.
Start u = node:users("id:123123")
Match u-[:DEPENDS_ON]->e1
With u, collect(e1) as ecol
Where None (e in ecol where e.date > 5)
RETURN (u), ecol

PyDatalog: list of values in answer

In PyDatalog I have defined the following assertions:
#stations
assert_fact('station', 'A' ,'yellow')
assert_fact('station', 'B' ,'yellow')
assert_fact('station', 'C' ,'yellow')
assert_fact('station', 'D' ,'yellow')
#sections
assert_fact('stretch', 'A' ,'B')
assert_fact('stretch', 'B' ,'C')
assert_fact('stretch', 'C', 'D')
And I would like to ask the database if there is a way to get to D from A.
The following code should work, because it answers set([()]) if there is a way, and None if there isn't. But it doesn't give me the result of the different evaluations of Z. I would like to know also the route, for example: A B C D
load("""
route(X,Y) <= stretch(X,Y)
route(X,Y) <= stretch(X,Z) & route(Z,Y)
""")
I have tried with unbound values, but it only gives me the result of the first iteration:
load("""
route(X,Y,P) <= stretch(X,Y) & (P==Y)
route(X,Y,P) <= stretch(X,P) & route(P,Y,Z)
""")
I think that the problem is that it only takes P in the first iteration. Or should I use aggregation functions? I don't understand very well how I could use concat...
Thanks in advance.
You need a predicate with a variable that contains the nodes between the 2 end points. You could use the following definition of route():
load("""
route(X,P, Y) <= stretch(X,Y) & (P==[])
route(X,P, Y) <= stretch(X,Z) & route(Z,P1,Y) & ~(Z in P1) & (P==[Z]+P1)
""")
print(pyDatalog.ask("route('A', P, 'D')"))
# prints set([(('B', 'C'),)])
Lists are supported since pyDatalog 0.13.

A PostgreSQL query with 'ANY' is not working

SELECT "Ticket_id" FROM "Tickets"
WHERE "Status" = 1 AND ("Ticket_id" != ANY(array[1,2,3])) Limit 6
And the result is 1,2,3,4,5,6
You want to use ALL, not ANY. From the fine manual:
9.21.3. ANY/SOME (array)
expression operator ANY (array expression)
[...] The left-hand expression is evaluated and compared to each element of the array using the given operator, which must yield a Boolean result. The result of ANY is "true" if any true result is obtained.
So if we say this:
1 != any(array[1,2])
then we'll get true since (1 != 1) or (1 != 2) is true. ANY is essentially an OR operator. For example:
=> select id from (values (1),(2),(3)) as t(id) where id != any(array[1,2]);
id
----
1
2
3
(3 rows)
If we look at ALL, we see:
9.21.4. ALL (array)
expression operator ALL (array expression)
[...] The left-hand expression is evaluated and compared to each element of the array using the given operator, which must yield a Boolean result. The result of ALL is "true" if all comparisons yield true...
so if we say this:
1 != all(array[1,2])
then we'll get false since (1 != 1) and (1 != 2) is false and we see that ALL is essentially an AND operator. For example:
=> select id from (values (1),(2),(3)) as t(id) where id != all(array[1,2]);
id
----
3
(1 row)
If you want to exclude all values in an array, use ALL:
select "Ticket_id"
from "Tickets"
where "Status" = 1
and "Ticket_id" != all(array[1,2,3])
limit 6
Do you mean:
"Ticked_id" NOT IN (1,2,3)

Counting Existing Facts in the RHS of Clips Rules

How do you test for fact existence in the RHS of rules in Clips? I'm trying to
design a rule that will "score" the current state by counting how many goal facts exist. It's obvious how to test for facts in the LHS, but I can't find how to do the equivalent in the RHS.
I want to do something like this, albeit this isn't valid Clips code:
(defrule score-state ""
?score <- (score (value ?value))
=>
(modify ?score (value (+ (exists (goal-1)) (exists (goal-2)) (exists (goal-3))))))
So that if none of the goal states exist, then there would exist the fact (score (value 0)). Conversely, if all the goal states existed, then there would exist the fact (score (value 3)).
The reference manual mentions the function fact-existp, but this seems to require it's passed a fact address. I tried using it like (fact-existp (goal-1)), but Clips gives me a syntax error.
(deftemplate score
(slot value))
(deftemplate goal-1)
(deftemplate goal-2)
(deftemplate goal-3)
(deffacts start
(score (value undefined))
(goal-1)
(goal-3))
(deffunction ecount (?g)
(if (any-factp ((?f ?g)) TRUE)
then (return 1)
else (return 0)))
(defrule score-state ""
?score <- (score (value undefined))
=>
(modify ?score (value (+ (ecount goal-1) (ecount goal-2) (ecount goal-3)))))

Resources