Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Hereditary Harrop Formulas (Papers We Love Boston)

Hereditary Harrop Formulas (Papers We Love Boston)

Slides about Hereditary Harrop Formulas from Papers We Love Boston: https://youtu.be/RwBiHLoQ3E4

nikomatsakis

May 29, 2018
Tweet

More Decks by nikomatsakis

Other Decks in Programming

Transcript

  1. 3 Basic idea of Prolog: parent(zeus, athena). parent(chronos, zeus). parent(rhea,

    zeus). Define CLAUSES (“X is true if Y and Z are true”). ancestor(A, B) :- parent(A, B). ancestor(A, C) :- parent(A, B), ancestor(B, C). “facts” = clauses
 with no conditions. ?- ancestor(P, athena). P = zeus. P = chronos. P = rhea. Use CLAUSES to solve GOALS (or QUERIES):
  2. 5 parent(zeus, athena). parent(chronos, zeus). parent(rhea, zeus). ancestor(A, B) :-

    parent(A, B). ancestor(A, C) :- parent(A, B), ancestor(B, C). ?- ancestor(P, athena). ancestor(P, athena) :- parent(P, athena) A = P B = athena
  3. 6 parent(zeus, athena). parent(chronos, zeus). parent(rhea, zeus). ancestor(A, B) :-

    parent(A, B). ancestor(A, C) :- parent(A, B), ancestor(B, C). ?- ancestor(P, athena). ancestor(P, athena) :- parent(P, athena) parent(zeus, athena) P = zeus Unifications
  4. 7 parent(zeus, athena). parent(chronos, zeus). parent(rhea, zeus). ancestor(A, B) :-

    parent(A, B). ancestor(A, C) :- parent(A, B), ancestor(B, C). ?- ancestor(P, athena). ancestor(P, athena) :- parent(P, athena) parent(zeus, athena) P = zeus Unifications Answer 0: ancestor(zeus, athena)
  5. 8 parent(zeus, athena). parent(chronos, zeus). parent(rhea, zeus). ancestor(A, B) :-

    parent(A, B). ancestor(A, C) :- parent(A, B), ancestor(B, C). ?- ancestor(P, athena). ancestor(P, athena) :- parent(P, athena) parent(zeus, athena) P = zeus Unifications Answer 0: ancestor(zeus, athena) ancestor(P, athena) :- parent(P, Q), ancestor(Q, athena).
  6. 9 parent(zeus, athena). parent(chronos, zeus). parent(rhea, zeus). ancestor(A, B) :-

    parent(A, B). ancestor(A, C) :- parent(A, B), ancestor(B, C). ?- ancestor(P, athena). Unifications ancestor(P, athena) :- parent(P, Q), ancestor(Q, athena). parent(zeus, athena) P = zeus Q = athena
  7. 10 parent(zeus, athena). parent(chronos, zeus). parent(rhea, zeus). ancestor(A, B) :-

    parent(A, B). ancestor(A, C) :- parent(A, B), ancestor(B, C). ?- ancestor(P, athena). Unifications ancestor(P, athena) :- parent(P, Q), ancestor(Q, athena). parent(zeus, athena) P = zeus Q = athena ancestor(athena, athena)
  8. 11 parent(zeus, athena). parent(chronos, zeus). parent(rhea, zeus). ancestor(A, B) :-

    parent(A, B). ancestor(A, C) :- parent(A, B), ancestor(B, C). ?- ancestor(P, athena). Unifications ancestor(P, athena) :- parent(P, Q), ancestor(Q, athena). parent(zeus, athena) P = zeus Q = athena ancestor(athena, athena)
  9. 12 parent(zeus, athena). parent(chronos, zeus). parent(rhea, zeus). ancestor(A, B) :-

    parent(A, B). ancestor(A, C) :- parent(A, B), ancestor(B, C). ?- ancestor(P, athena). Unifications ancestor(P, athena) :- parent(P, Q), ancestor(Q, athena). parent(zeus, athena) P = zeus Q = athena ancestor(athena, athena) parent(athena, athena)?
  10. 13 parent(zeus, athena). parent(chronos, zeus). parent(rhea, zeus). ancestor(A, B) :-

    parent(A, B). ancestor(A, C) :- parent(A, B), ancestor(B, C). ?- ancestor(P, athena). Unifications ancestor(P, athena) :- parent(P, Q), ancestor(Q, athena). parent(zeus, athena) P = zeus Q = athena ancestor(athena, athena)
  11. 14 “Backward chaining” and “Unification” Unifications P = zeus Q

    = athena Goals ancestor(..) parent(..) Program Clauses parent(zeus, athena). parent(chronos, zeus). parent(rhea, zeus). ancestor(A, B) :- … ancestor(A, C) :- …
  12. 15 ( Unifications Goals Program Clauses D, {G}, Θ )

    M = (D, {G}, Θ) M1 -> M2 Machine state Transition between states
  13. 16 ( Unifications Goals Program Clauses D, {G}, Θ )

    (D, {ancestor(P, athena)}, {}) (D, {parent(P, athena)}, {}) (D, { parent(P, Q), ancestor(Q, athena) }, {}) Branches in our search space: implementation must try both
  14. 17 Horn Clauses G ::= A | G and G

    | G or G | exists<T> { G } D ::= A | A :- G | D and D | forall<T> { D } (zeus) An “atom” A (zeus). A clause D ::= A (X) :- (X). A clause D ::= forall<X> { … }
  15. 18 G ::= A | G and G | G

    or G | exists<T> { G } Prove an atom A using clauses given by the user. Proving these other goals is “built in”. (D, {(G1 and G2)}, Θ) (D, {G1, G2}, Θ) (D, {(G1 or G2)}, Θ) (D, {G1}, Θ) (D, {G2}, Θ) Same as when proving an atom against many program clauses.
  16. 19 G ::= A | G and G | G

    or G | exists<T> { G } (D, {exists<T> { G }}, Θ) (D, {[T -> X] G}, Θ) “Replace T with some fresh variable X” …exists<G> { (G) }… …(Y)… Same as a “forall” clause like forall<G> { (G) :- (G) }
  17. 20 Horn Clauses G ::= A | G and G

    | G or G | exists<T> { G } D ::= A | A :- G | D and D | forall<T> { D } “What about me?” => Can’t have a clause that says “either Foo or Bar is true but I don’t know which”.
  18. 21 Prolog’s Awesomeness Expressive logical language Simple solver Yet: Sound

    and complete! Caveat: “If it terminates…” “If it terminates, the solver will find all possible answers.”
  19. 22 Prolog’s Limitations Always working with “concrete atoms” ?- forall<G>

    { (G) } ?- (G). ∃G. (G) ? We might want to be more generic…
  20. 24 Prolog’s Limitations Always working with a fixed set of

    facts/rules We’d like to able to add hypotheses if (C) { G } ?- forall<G> { if ((G)) { (G) } } “For any god G… …assuming they have lightning… are they scary?” “If we assume C is true, is G provable?”
  21. 26 fn foo<T>(a: T, b: T) where T: Ord {

    a == b // requires T: Eq<T> } forall<T> { if (Implemented(T: Ord)) { Implemented(T: Eq<T>) } }
  22. 29 Hereditary Harrop Clauses G ::= A | G and

    G | G or G | exists<T> { G } | forall<T> { G } | if(D) { G } D ::= A | A :- G | D and D | forall<T> { D } These two are new
  23. 30 How to implement “if”? ( Unifications Goals Program Clauses

    D, {(D, G)}, Θ ) Each goal now carries a list of hypotheses along with it
  24. 31 (D, {(true, (athena) => (athena))}, {}) (D, {(true &&

    (athena), (athena))}, {}) Hypotheses New goal
  25. 32 Now, when we want to prove an atom (D,

    A): Check each program clauses from the user, as before Also check the hypotheses D G ::= A | G and G | G or G | exists<T> { G } | forall<T> { G } | if(D) { G } D ::= A | A :- G | D and D | forall<T> { D } G => D D => G
  26. 33 How to implement “forall”? U0 U1 “Universe” — a

    set of names U0 — all the global names, like `athena`, `zeus`. U1 — all the global names, and then one more, `!U1`
  27. 34 U0 U1 U2 U3 U4 U2 can name !U2,

    !U1, and the root names
  28. 35 (D, {forall<T> { G }}, Θ) (D, {[T ->

    !U] G}, Θ) “Replace T with !U with the next universe U” …forall<G> { (G) }… …(!U1)… (zeus). (G) :- (G). “!U1 is not zeus” But G can be any name, even U1
  29. 36 Really? ANY name? forall<A> { exists<E> { A =

    E } } Sure, E = A (or E = !U1) exists<E> { forall<A> { A = E } } No! E = A doesn’t work, A is not in scope.
  30. 37 Idea: give each variable a universe forall<A> { exists<E>

    { A = E } } Here, E is in universe U1, so it can name !U1 exists<E> { forall<A> { A = E } } Here, E is in universe U0, so it cannot. U0 U1 U0 U1
  31. 38 M = (D, {(D,G,I)}, L, Θ) Program clauses. Hypotheses

    Goal to prove Current universe counter; starts out at U0 Labels: what universe is each variable in Substitution
  32. 39 U0 U1 U2 U3 U4 Why just a counter?

    e.g., what about U1 and U4? How do we know that U1 is not U4’s parent?
  33. 40 G={exists<E> { forall<A> { E = A } and

    forall<B> { E = B } }} G={forall<A> { E = A } and forall<B> { E = B }} L=() L=(E: U0) G={forall<A> { E = A }, forall<B> { E = B }} L=(E: U0) G={E = !U1, forall<B> { E = B }} L=(E: U0) !U1 and !U2 are siblings — never directly interact
  34. 41 Thanks! If you enjoyed this, consider joining the Traits

    Working Group. Help us rework Rust’s trait system implementation in these terms. (Also, this book is really good.)