
// Test3.java
// Andrew Davison, ad@coe.psu.ac.th, Feb 2020


/* Create sets of clauses consisting of parentOf/2 
   and livesAt/3 facts and a livesWith/2 rule.

   Test them with three goals:
      ?- parentOf(P, "jean").
      ?- parentOf(margaret,X), parentOf(X,holly).
      ?- livesWith(kim, X).
*/


import java.util.*;


public class Test3
{

  public static void main(String[] args)
  {
    Trail t = new Trail();

    // parentOf/2 predicate

    /*  parentOf(kim,holly).
        parentOf(margaret,kim).
        parentOf(margaret,kent).
        parentOf(esther,margaret).
        parentOf(herbert,margaret).
        parentOf(herbert,jean).
    */

    Functor kim = new Functor("kim");
    Functor holly = new Functor("holly");
    Functor margaret = new Functor("margaret");
    Functor kent = new Functor("kent");
    Functor esther = new Functor("esther");
    Functor herbert = new Functor("herbert");
    Functor jean = new Functor("jean");

    Clause cp1 = new Clause( new Functor("parentOf",kim,holly));
    Clause cp2 = new Clause( new Functor("parentOf",margaret,kim));
    Clause cp3 = new Clause( new Functor("parentOf",margaret,kent));
    Clause cp4 = new Clause( new Functor("parentOf",esther,margaret));
    Clause cp5 = new Clause( new Functor("parentOf",herbert,margaret));
    Clause cp6 = new Clause( new Functor("parentOf",herbert,jean));


    // livesAt/3 predicate

    /* livesAt(margaret, 9, "Bar Lane").
       livesAt(kim, 37, "Foo Street").
       livesAt(holly, 37, "Foo Street").
       livesAt(esther, 9, "Bar Lane").
       livesAt(herbert, 23, "PSU Village").
       livesAt(kent, 9, "Bar Lane").
       livesAt(bill, 23, "PSU Village").
       livesAt(john, 9, "Bar Lane").
    */
    Functor bill = new Functor("bill");
    Functor john = new Functor("john");

    Functor n9 = new Functor("9");
    Functor n23 = new Functor("23");
    Functor n37 = new Functor("37");

    Functor bar = new Functor("Bar Lane");
    Functor foo = new Functor("Foo Street");
    Functor psu = new Functor("PSU Village");

    Clause cv1 = new Clause( new Functor("livesAt",margaret, n9, bar));
    Clause cv2 = new Clause( new Functor("livesAt",kim, n37, foo));
    Clause cv3 = new Clause( new Functor("livesAt",holly, n37, foo));
    Clause cv4 = new Clause( new Functor("livesAt",esther, n9, bar));
    Clause cv5 = new Clause( new Functor("livesAt",herbert, n23, psu));
    Clause cv6 = new Clause( new Functor("livesAt",kent, n9, bar));
    Clause cv7 = new Clause( new Functor("livesAt",bill, n23, psu));
    Clause cv8 = new Clause( new Functor("livesAt",john, n9, bar));


    // livesWith/2 preducate
    /* livesWith(X, Y) :-
           livesAt(X, No, Addr), livesAt(Y, No, Addr).
    */
    Term vx = new Var("X", t);
    Term vy = new Var("Y", t);
    Term vNo = new Var("No", t);
    Term vAddr = new Var("Addr", t);

    ArrayList<Functor> rhs = new ArrayList<>();
    rhs.add( new Functor("livesAt",vx,vNo,vAddr));
    rhs.add( new Functor("livesAt",vy,vNo,vAddr));

    Clause lw1 = new Clause( new Functor("livesWith",vx,vy), rhs);


    List<Clause> cls = Arrays.asList(cp1, cp2, cp3, cp4, cp5, cp6,
             cv1, cv2, cv3, cv4, cv5, cv6, cv7, cv8,
             lw1  );

    // initialize engine
    Engine eng = new Engine(cls, t);




    // ----------------------------------------
    // 1st goal: ?- parentOf(P, "jean").
    Var vp = new Var("P", t);
    Functor goal1 = new Functor("parentOf", vp, jean);

    List<Var> vs = Arrays.asList(vp);

    eng.solve(goal1, vs);


    // ----------------------------------------
    // 2st goal: ?- parentOf(margaret,X), parentOf(X,holly).
    Var vgx = new Var("X", t);

    ArrayList<Functor> goal2 = new ArrayList<>();
    goal2.add( new Functor("parentOf", margaret, vgx));
    goal2.add( new Functor("parentOf", vgx, holly));

    vs = Arrays.asList(vgx);

    eng.solve(goal2, vs);


    // ----------------------------------------
    // 3rd goal: ?- livesWith(kim, X).
    Functor goal3 = new Functor("livesWith", kim, vgx);

    eng.solve(goal3, vs);

  }  // end of main()

}  // end of Test3 class

