I trying my hand at core.logic which has always interested me but it has a steep learning curve. The domain I am mostly interested in is constraint satisfaction problems. For example if I have the following function, how can I translate this into a core.logic function that can be used in two ways.
Given some input return true or false (same as current impl)
Return a list of all combinations that would result in the function returning true. This is the true power of core.logic.
(defn my-exp
[a b c]
(and (= a "a") (= c "c")
(or (= b "b") (not= b "r"))))
My attempts at translating this involves nested conde. The problem with that is that the return values are not what I expect.
Update:
Here is one way I find some success but it feels strange to just put the original code inside project.
(l/run* [q a b c]
(l/membero a ["a" "r"])
(l/membero b ["b" "r" "a"])
(l/membero c ["a" "c"])
(l/project [a b c]
(l/== q (and (= a "a") (= c "c")
(or (= b "b") (not= b "r"))))
))
Sorry about the quality of this query. The example is just an example showing a type of expression I would like to be able to express. What im looking for is a generic way to translate logic expressions for some set of variables containing strings. The logic expressions contain the following operators (and not or = not=). What would be the generic way to think about such a transformation?
In the example the domain is just made up. I real life the domains will be a set of strings over which there are some constraints.
My example provide 2 solutions: ([true "a" "b" "c"] [true "a" "a" "c"])
The use of project here is probably not really needed?
(l/run* [a b c]
(l/membero a ["a" "r"])
(l/membero b ["b" "r" "a"])
(l/membero c ["a" "c"])
;; implicit AND by just adding expressions:
(l/== a "a")
(l/== c "c")
(l/conde ;; "OR"
[(l/== b "b")]
[(l/!= b "r")]))
gives:
(["a" "b" "c"] ["a" "b" "c"] ["a" "a" "c"])
But this is slighly confusing, since the clause b = “b” and the clause b != “r” is counted as two different clauses (solutions) but can reach satisfaction when b has the same values in two different cases.
Using conda or condu as the OR clause seems to work, because they terminate differently than conde.
(l/run* [a b c]
(l/membero a ["a" "r"])
(l/membero b ["b" "r" "a"])
(l/membero c ["a" "c"])
(l/== a "a")
(l/== c "c")
(l/condu
[(l/== b "b")]
[(l/!= b "r")]))