I'm getting unexpected results from a core.logic expression:
(let [input (mapv (partial mapv #(lvar % false))
'((0 1)
(0 1 2 3 4 5 6)
(0 1 2 3 4 5)
(0 1 2 3 4 5)
(0 1 2 3)
(0 1 2 3 4)
(0 1 2 3 4 5)
(0 1 2 3 4)
(0 1 2 3 4)
(0 1 2)))
model [[:a :b :c :e :f :g]
[:c :f]
[:a :c :d :e :g]
[:a :c :d :f :g]
[:b :c :d :f]
[:a :b :d :f :g]
[:a :b :d :e :f :g]
[:a :c :f]
[:a :b :c :d :e :f :g]
[:a :b :c :d :f :g]]]
(->> (run* [q]
(everyg (fn [s] (membero s model)) input)
(== q input)) ))
I would like to solve:
"For all values from 0 to 9 in input , what is the corresponding value from :ato :f ?" (e.g: (0 1) can only map to [:c :f] because it is the only length 2 collection.)
Is that what I'm expressing as goals in run*? Or am I expressing something else?its not a great problem for logic/relational programming, things defined in terms of counting are tricky
Are you sure? I think I'm pretty much using logic programming when I'm trying to solve it myself
yes
what do you mean by counting exactly though?
you are defining the correspondence relation based on the count (the size, the length) of collections
Oh yeah
Isn't it supposed to work with permuteo though? I updated it:
(run* [q]
(everyg (fn [s]
(or*
(map (partial permuteo s)
model)))
input)
(== q input))
But still unsuccessfulI guess I'll try something else
if you define it in some way that isn't based on counting it will go much better
like say, all rows are the same length, but have some pattern of true, false
so if you replace all you vectors of letters with things like [false false true false false true false] which would correspond to [:c :f] because those positions are true
I see
input in your example is just kind of bogus
I am not sure even what you are trying to do with it
there are reasons to call the lvar constructor with arguments, but basically you never need to
Well [0 1] => [:c :f], [0 1 2 3] => [:b :c :d :f] (permutable), because they uniquely got the same length. The rest should follow with the the numbers mapped to the letters.
Because 0 should be the same across all the input
0 in the first element of input should be the same than in the second
So from [0 1] => `[:c :f]` , we can deduce that (or (and 0 => c, 1=> f) (and 0 => f, 1 => c)
thats not how it works though, like, you are saying the vars are members of the lists, 2 vars can be members of 3 element list just as easy as they can be members of a 2 element list
and you have no kind of unique constraints
so 2 vars can be members of a 1 element list easily as well
I'm not sure I understand
if X and Y are members of L
if L is just (1) then X a and Y, absent other constraints, are both 1
Oh, that makes sense.
I think that's why I'm getting some kind of factorial of all possibilities as a result
but even then, if you can, it is best to avoid membero, because membero is at best a linear search in a list, so combinatorial is bad
I think that linear search is pretty much required by the problem itself
maybe, hard to tell from the code and description given
there is search through the space of all possibilities, then there is search through data structures for the right things to unify
I see.
like, the code you shared has no branching of the search tree, other then the recursive cases for membero
so outside the is this lvar the first, the second, the third, ..., etc member of this list, there are no branches
so its not like it is considering all the model or inputs as different searches or something
Do you think I should give up on core.logic? It's an advent of code exercise and I thought it was a nice way to learn core.logic
I dunno, there is definitely a significant hump to get over
core.logic is kind of a bare bones logic programming environment, so figuring out how to represent problems in a way that works can be tricky
I see
and because core.logic is a dsl embedded in clojure, often the way to do things is with clojure as a meta/macro language for constructing core.logic programs, which is also tricky to get the hang of sometimes (see all the troubles people get into learning macros)
my understanding of logic programming comes in large part from sitting down with the minikanren paper and implementing it in go, and then writing solvers for a bunch of logic riddles in it as tests, not from working with core.logic a lot