Can I get a single answer in pydatalog ask? - logic-programming

I'm using pydatalog to solve a path-planning problem (just an example). I want one path from the begin state to the end state, i.e. one answer. As far as I can tell, ask() yields a list of all answers and I would like to generate the answers lazily.
A second question: notice I had to define member/2 where I thought I could say
(Z in Freesquares) and
~(Z in P1)
But I get the error
TypeError: argument of type 'bool' is not iterable
Any cleaner way to write that code?
Thanks!
# Defn of adjacent is missing. For example (r,c) is adjacent to (r+1,c), (r,c+1), (r-1,c), (r,c-1)
create_terms('path', 'Begin', 'Current', 'End', 'FreeSquares', 'Path', 'P1')
path(Begin, Current, End, FreeSquares, Path) <= adjacent(Current, End) & (Path==[])
path(Begin, Current, End, FreeSquares, Path) <= \
adjacent(Current, Z) & ~(Z == Begin) & ~(Z == End) & member(Z, FreeSquares) & \
path(Begin, Z, End, FreeSquares, P1) & ~member(Z, P1) & (Path == [Z] + P1)
ask('path((3,3), (3,3), (1,1), [(1,1), (1,2), (2,1), (2,2), (2,3), (3,1), (3,3)], X)').answers
[(((2, 3), (2, 2), (1, 2)),), (((2, 3), (2, 2), (2, 1)),)]

Related

How to do a cartesian product of a variable number of lists in Julia?

For each value j in the set {1, 2, ..., n} where the value of n can vary (it is some variable in my program that can be different depending on the inputs from the user), I have an array A_j. I would like to obtain the cartesian product of all the arrays A_j, so that I can then iterate through that cartesian product (taking one element from each A_1, A_2, ... A_n to get a tuple (a_1, a_2, ..., a_n) in A_1 x A_2 x ... x A_n). How would I accomplish this in Julia?
Use Iterators.product:
help?> Iterators.product
product(iters...)
Return an iterator over the product of several iterators. Each generated
element is a tuple whose ith element comes from the ith argument iterator.
The first iterator changes the fastest.
Examples
≡≡≡≡≡≡≡≡≡≡
julia> collect(Iterators.product(1:2, 3:5))
2×3 Matrix{Tuple{Int64, Int64}}:
(1, 3) (1, 4) (1, 5)
(2, 3) (2, 4) (2, 5)

Build array iterating over multiple indices in Julia

I want to obtain the following result with a more elegant syntax
julia> collect(Iterators.flatten([[(x,y) for y in 1:x] for x in 1:3]))
6-element Array{Tuple{Int64,Int64},1}:
(1, 1)
(2, 1)
(2, 2)
(3, 1)
(3, 2)
(3, 3)
I tried something like [(x,y) for y in 1:x, x in 1:3] but I get ERROR: UndefVarError: x not defined.
Just reverse the order of variables like this:
julia> [(x,y) for x in 1:3 for y in 1:x]
6-element Array{Tuple{Int64,Int64},1}:
(1, 1)
(2, 1)
(2, 2)
(3, 1)
(3, 2)
(3, 3)
I used to have also been struggled to remember the variable order. Until one day someone told me a secret: just treat the order of for loop in the list comprehension as usual except that the body is moved to the front.
For example, in normal order we write:
for x in 1:3
for y in 1:x
# do sth
end
end
Now we move the body part to the front and we have [ #= do sth =# for x in 1:3 for y in 1:x]

Read values and list of lists in Haskell

Before to mark this question as duplicated, I already read this topic: Haskell read Integer and list of lists from file and the solution doesn't solve my problem.
I'm trying to read the content in a File that contains this structure:
String, String, [(Int, Int, Int)]
The file looks something like this:
Name1 22/05/2018 [(1, 5, 10), (2, 5, 5), (3, 10, 40)]
Name2 23/05/2018 [(1, 10, 10), (2, 15, 5), (3, 50, 40),(4,20,5)]
Name3 22/05/2018 [(4, 2, 1), (5, 2, 2), (6, 50, 3), (1,2,3)]
Name4 23/05/2018 [(1, 3, 10), (2, 1, 5), (3, 2, 40), (6,20,20)]
In Haskell, I created this function to read the contents of the file and "convert" this content to my custom type.
rlist :: String -> [(Int, Int, Int)]
rlist = read
loadPurchases :: IO [(String, String, [(Int, Int, Int)])]
loadPurchases = do s <- readFile "tes.txt"
return (glpurch (map words (lines s)))
glpurch :: [[String]] -> [(String, String, [(Int, Int, Int)])]
glpurch [] = []
gplpurch ([name, dt, c]:r) = (name, dt, (rlist c)) : gplpurch r
But when I try to execute the "loadPurchases" function, I get this error:
Non-exhaustive patterns in function glpurch.
Using :set -Wall, I received this help message:
<interactive>:6:1: warning: [-Wincomplete-patterns]
Pattern match(es) are non-exhaustive
In an equation for `glpurch':
Patterns not matched:
([]:_:_)
([_]:_)
([_, _]:_)
((_:_:_:_:_):_)
My problem is how to create all these conditions.
I will be very grateful if anyone can help me create those conditions that are likely to determine the "stopping condition"
You are only matching lists of length 3 when in fact there are many more words on each line. Just try it in GHCi:
> words "Name1 22/05/2018 [(1, 5, 10), (2, 5, 5), (3, 10, 40)]"
["Name1","22/05/2018","[(1,","5,","10),","(2,","5,","5),","(3,","10,","40)]"]
You probably want to recombine all words past the first two:
glpurch ((name : dt : rest) :r) = (name, dt, (rlist $ unwords rest)) : gplpurch r
To solve my problem, I did what #Welperooni and #Thomas M. DuBuisson suggested.
I added this code to my function:
glpurch ((name: dt: c: _): r) = (name, dt, (read c :: [(Cod, Quant, Price)
And I removed the blanks that were in the list in my file, these spaces made the division of the text not done correctly.

Julia: Cannot append tuple to array

I would like to have an array of tuples. However it seems I cannot append a tuple to it. Here is a minimal code example that raises the error.
julia> a = [(1,1),(2,2)]
2-element Array{Tuple{Int64,Int64},1}:
(1, 1)
(2, 2)
julia> append!(a, (3,3) )
ERROR: MethodError: Cannot `convert` an object of type Int64 to an object of type Tuple{Int64,Int64}
This may have arisen from a call to the constructor Tuple{Int64,Int64}(...),
since type constructors fall back to convert methods.
Stacktrace:
[1] _append!(::Array{Tuple{Int64,Int64},1}, ::Base.HasLength, ::Tuple{Int64,Int64}) at ./array.jl:644
[2] append!(::Array{Tuple{Int64,Int64},1}, ::Tuple{Int64,Int64}) at ./array.jl:637
Is something wrong with my syntax? I don't get why it complains that it has to convert a number to a tuple. What gives?
append! adds all of the individual elements of another collection to the existing object. Julia raises the error here because (3, 3) is a collection of two integers and it cannot reconcile an individual integer of type Int64 with the array's Tuple{Int64,Int64} type.
The method you need is push!, which will add one or more individual items to an existing collection:
julia> push!(a, (3, 3))
3-element Array{Tuple{Int64,Int64},1}:
(1, 1)
(2, 2)
(3, 3)
The individual item, the tuple (3, 3), was successfully pushed onto the array a.
To accomplish the same task with append!, the tuple needs to be contained in a collection of some sort itself, such as an array:
julia> append!(a, [(4, 4)])
4-element Array{Tuple{Int64,Int64},1}:
(1, 1)
(2, 2)
(3, 3)
(4, 4)
This is documented on the collections page here.

How to use Data.List.iterate on tuple

The expression iterate (1+) 1 evaluates to [1, 2, 3, ...]
Can I do something like iterate ((1+) (1+)) (1, 1) so I can get [(1, 1), (2, 2), ... ] ? If yes, what is the syntax ?
This syntax should work fine:
iterate (\(x,y) -> (x+1, y+1)) (1, 1)
There are also many other ways to skin this cat:
iterate (bimap (1+) (1+)) (1, 1)
iterate ((1+) *** (1+)) (1, 1)
map (\x -> (x,x)) $ iterate (1+) 1
join (,) <$> iterate (1+) 1
[(x, x) | x <- [1..]]
...and many more.
Expanding on Daniel Wagner's answer -- Data.List's iterate takes a function as a first argument. The type signature of iterate is
(a -> a) -> a -> [a]
Meaning that the function in the first argument simply has to return the same type as it ingests. This can be an anonymous function, as show in Daniel's answer, or a function name. For example; his example could be rewritten using a named function like so:
import Data.List (iterate)
addOne (x, y) = (x + 1, y + 1)
iterate addOne (1, 1)

Resources