Trying to translate into logic expression into core.logic

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.

  1. Given some input return true or false (same as current impl)
  2. 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"))))
             ))

Your original function example only has one possible combination though. Is there an example where this is not the case?

Further, what are the domains of the variables? Where does the selection of [“a” “r”] etc. come from?

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")]))

gives

(["a" "b" "c"] ["a" "a" "c"])

which seems to be what you are looking for!

1 Like