2

I am trying to understand the usage of existentially quantifying. What I know by now is this technique is used with setof, findall, bagof. Further, I found a tutorial. However, I am not sure when and how I do the Vars^Goal (existentially quantifying) in Prolog.

Here is the example, my goal is to find two employees who know each other but work at different companies, binding the result with L showing Name1-Name2:

company('Babbling Books', 500, 10000000).
company('Crafty Crafts', 5, 250000).
company('Hatties Hats', 25, 10000).

employee(mary, 'Babbling Books').
employee(julie, 'Babbling Books').
employee(michelle, 'Hatties Hats').
employee(mary, 'Hatties Hats').
employee(javier, 'Crafty Crafts').

knows(javier, michelle).

My first instinct is to use the query

?-employee(N1,C1),employee(N2,C2),C1\=C2,knows(N1,N2).

The query found the answer but doesn't render it into the correct format. The correct one is:

?-setof(N1-N2, (C1,C2)^(employee(N1,C1),employee(N2,C2),C1\=C2,knows(N1,N2)), L).

How could I understand the (C1,C2)^(employee(N1,C1),employee(N2,C2),C1\=C2,knows(N1,N2)) ? And what's the concept of it? Thanks.

Guy Coder
  • 24,501
  • 8
  • 71
  • 136
Woden
  • 1,054
  • 2
  • 13
  • 26
  • 1
    What is "the correct format"? – Scott Hunter Jun 10 '21 at 18:11
  • The answer is `L = [javier-michelle].`. – Woden Jun 10 '21 at 18:13
  • Of interest: [Use setof/3 when goal not exported from module with existential (caret) operator (^)](https://swi-prolog.discourse.group/t/use-setof-3-when-goal-not-exported-from-module-with-existential-caret-operator/3292) – Guy Coder Jun 10 '21 at 18:19
  • @GuyCoder Thank you. Using the square bracket is the convention, right? Since using parathesis gives me the same answer. – Woden Jun 10 '21 at 18:20
  • 3
    Any term that groups the existentially-qualified variables can be used: `(C1,C2)`, `[C1,C2]`, `v(C1,C2)`, ... all work assuming a standards compliant implementation of `bagof/3`. – Paulo Moura Jun 10 '21 at 18:58
  • 3
    @GuyCoder I am curious where did you get that the convention is to use square brackets. I have always seen `Var1^Var2^...^VarN^Goal` and the link of interest you posted has SWI creator state also that the convention is to use Var^Var2...^Goal – gusbro Jun 10 '21 at 18:58
  • @gusbro `where did I get that the convention is to use square bracket?` I seriously can not remember. `the link of interest you posted has SWI creator state also that the convention is to use Var^Var2...^Goal` Yes. I changed it, forgot that is the convention and needed a reminder to fix the page. Thanks. :) – Guy Coder Jun 10 '21 at 19:47
  • As @gusbro notes and I fixed in the link, the convention is to use `C1^C2^(employee(N1,C1),employee(N2,C2),C1\=C2,knows(N1,N2))`. I have been using the square brackets for so long I can't recall them ever not working, but now having been prompted will remember to do it with `A^B^ ... ^(query(A,B,C,D))` – Guy Coder Jun 10 '21 at 19:52
  • 1
    This has been [cross posted](https://swi-prolog.discourse.group/t/the-existentially-quantifying/4052?u=ericgt) at the SWI-Prolog Discourse forum. – Guy Coder Jun 11 '21 at 13:33

1 Answers1

1

I am not sure when and how I do the Vars^Goal (existentially quantifying) in Prolog.

The easiest answer is: Don't do it, ever. You can always introduce an auxiliary predicate that captures exactly the query you want, exposing exactly the arguments you want and nothing else (that would require quantification), and with a nice self-documenting name.

In your example, you can define:

different_company_acquaintances(N1, N2) :-
    employee(N1, C1),
    employee(N2, C2),
    C1 \= C2,
    knows(N1, N2).

and then express your setof query as:

?- setof(N1-N2, different_company_acquaintances(N1, N2), L).
L = [javier-michelle].

This is easier to read because of the predicate name and because it hides the irrelevant implementation details. Note that in the predicate definition the arguments are only the data the caller cares about (the employees), and there are no arguments for the data the caller doesn't care about (the companies).

How could I understand the (C1,C2)^(employee(N1,C1),employee(N2,C2),C1\=C2,knows(N1,N2)) ?

The ^ syntax, whatever the exact correct form is, is meant to signal variables that, if you wrote out a separate predicate definition, would only occur in the predicate's body, not as its arguments. This tells setof and friends that every time it tries to execute the goal (employee(N1,C1),employee(N2,C2),C1\=C2,knows(N1,N2)) it should do so with unbound variables C1 and C2. In other words, it should not try to retain the values of C1 and C2 from one attempt to the next.

Isabelle Newbie
  • 9,258
  • 1
  • 20
  • 32