Vince, I think you just explained to me that I've been misunderstanding HOL all 
along!  What I'd been asking about environment and scope of variable sounds now 
like the simple fact that HOL allows free variables.  I think that means that 
FOL is actually quite different than the way mathematicians think, even though 
it amounts to the same proofs.

   I still don't understand why you want to avoid preterms.

Let me answer this question, and then explain my HOL misunderstanding, by going 
back to my earlier post about quotexpander.  It's worth going through again to 
highlight John's related preterm code.  

You proposed a modification of quotexpander in system.ml using "." at the start 
indicate a preterm.  I got a lot out of your proposal, and came up with my own 
modification, where  "\"" at the start indicates a string: 

let quotexpander s =
  if s = "" then failwith "Empty quotation" else
  let c = String.sub s 0 1 in
  if c = "\"" then 
  "\""^(String.escaped (String.sub s 1 (String.length s - 1)))^"\"" else
  if c = ":" then
    "parse_type \""^
    (String.escaped (String.sub s 1 (String.length s - 1)))^"\""
  else if c = ";" then "parse_qproof \""^(String.escaped s)^"\""
  else "parse_term \""^(String.escaped s)^"\"";;

Modify quotexpander this way and then start a new HOL Light process by 
ocaml
#use "hol.ml";; 
Then the code included below works.  The definitions of consider and case_split 
there are quite simple.  

But I can also define case_split using preterms, with this code: 

let parse_qproof s = (fst o parse_preterm o lex o explode) 
  (String.sub s 1 (String.length s - 1));;

let case_split sDestruct pretermDisjlist tac =
  let disjthm = (term_of_preterm o (retypecheck [])) (end_itlist 
    (fun pt1 pt2 -> (Combp (Combp (`;\/`, pt1), pt2))) pretermDisjlist) in 
  SUBGOAL_TAC "" disjthm tac THEN FIRST_X_ASSUM
  (DESTRUCT_TAC sDestruct);;

I think that's a lot more complicated than my string version below, and I could 
not define consider using preterms.  

However, I realized last night that John did more complicated preterm stunts in 
Examples/mizar.ml

(* ------------------------------------------------------------------------- *)
(* Some preterm operations we need.                                          *)
(* ------------------------------------------------------------------------- *)

let rec split_ppair ptm =
  match ptm with
    Combp(Combp(Varp(",",dpty),ptm1),ptm2) -> ptm1::(split_ppair ptm2)
  | _ -> [ptm];;

let pmk_conj(ptm1,ptm2) =
  Combp(Combp(Varp("/\\",dpty),ptm1),ptm2);;

let pmk_exists(v,ptm) =
  Combp(Varp("?",dpty),Absp(v,ptm));;

John's version of consider there is better than mine, but it's a lot more 
complicated.  BTW let me say that John's mizar.ml predates Freek's Mizar-like 
code written, and it's only 682 lines long, and I counted 160 of those lines as 
defining John's Mizar-like by justification, and I don't want that.   So that's 
only 522 of code that I have to understand.  I can't believe it's that hard to 
understand?

   Maybe I don't get your question here, because it looks more complex
   than I thought.

Maybe I've been misunderstanding HOL Light!  I've been thinking that various 
occurences of the same variable had the same value, but maybe I had it all 
wrong.  Let's go through the code below, which is my version of the tutorial 
proof of the irrationality of sqrt.  

After the first 3 lines, we have fixed the variables p & q (of type num), the 
goal is 

q = 0

and we have two labeled assumptions

  0 [`!m. m < p ==> (!q. m * m = 2 * q * q ==> q = 0)`] (A)
  1 [`p * p = 2 * q * q`] (B)

Now a mathematicians would think this means that we have chosen arbitrary 
elements of the set that num denotes, and that the variables p and q will refer 
to these fixed, but arbitrary, elements from now on.  But I think that's not 
what HOL is doing!  I think HOL is just saying that the assumptions and the 
goals are now written in terms of the free variables p & q.  And I guess HOL 
and FOL are designed this way because that's the way math works, but I never 
saw that before.  

The next SUBGOAL_TAC command uses assumption B and easily gives as a new 
assumption

  2 [`EVEN (p * p) <=> EVEN (2 * q * q)`]

The next SUBGOAL_TAC command uses this last assumption, theorems ARITH and 
EVEN_MULT to prove the new assumption 

  3 [`EVEN p`]

I guess that's true for any free variables p & q of type num!  The next 
consider command fixes the variable m of type num and gives us the labeled 
assumption

  4 [`p = 2 * m`] (C)

Basically MESON proved that such an m exists using theorem EVEN_EXISTS.  So now 
we have three free variables p, q, and m which all have type num, and 5 
assumptions about p, q, and m, but I think now that p, q, and m are just free 
variables.  Now I have a question for you:

I bet the information that p, q, and m have type num is stored somewhere.  I 
know we can infer the type num from the assumptions, but that's not always 
true.  Can you tell me where this type information is stored?

Now I do 

e(case_split "qp | pq" [`"(q:num) < p`; `"p <= q`] [ARITH_TAC]);;

This gives two cases, with labels qp and pq, and I can do this because 
ARITH_TAC proves that for all p & q of type num, either q < p or p <= q.  I 
think now that there's no connection here between this p & q and the p & q 
above that I think are "fixed".  Since my proof is interactive, I now work the 
first case, which has a new assumption 

  5 [`q < p`] (qp)

The next SUBGOAL_TAC command gives us the new assumption 

  6 [`q * q = 2 * m * m ==> m = 0`]

I think MESON's proof only needs the two free variables p and q and the 
assumptions qp and A.  I think MESON just instantiates the !m. m < p of 
assumption A with m = q, which is true by assumption qp.  Then the consequent 
of assumption A becomes, after an alpha conversion

(!z. q * q = 2 * z * z ==> z = 0)

and MESON can then instantiate z with m to get our assumption 6 above.  Note 
that this entire argument has nothing to do with any "fact" that p, q and m 
denote fixed elements of the set denoted by the type num.  It's just FOL using 
the free variables p, q & m, promoted to HOL by the typing, and assumptions qp 
and A.  Wow.  How could I have misunderstood this all along!  

Let's see how the next NUM_RING_thmTAC command proves the goal q = 0 using 
these 3 assumptions:

  1 [`p * p = 2 * q * q`] (B)
  4 [`p = 2 * m`] (C)
  6 [`q * q = 2 * m * m ==> m = 0`]

We have free variables p, q and m and these 3 statements.  B and C give p^2 = 
2q^2 and p = 2m, so

4 m^2 = 2 q^2

q^2 = 2 m^2 

Assumption 6 then gives m = 0.  By C, p = 0 and then by B, 

2 q^2 = 0, 

so q = 0.  NUM_RING can perform this sort of nonlinear deduction.  Now we're 
working the other case

  5 [`p <= q`] (pq)

The next SUBGOAL_TAC command uses this last assumption and the theorem LE_MULT2 
to prove 

  6 [`p * p <= q * q`]

and surely this is true for any free variables p and q of type num.  There's no 
reason to think that HOL Light is remembering that p and q denote fixed natural 
numbers that we've been using all along!

The next SUBGOAL_TAC command deduces

  7 [`q * q = 0`]

from this last assumption and B:

  1 [`p * p = 2 * q * q`] (B)
  6 [`p * p <= q * q`]

That is, ARITH_TAC can prove that for any free variables p & q, that if 

2 q^2 <= q^2 

then q = 0.  Nothing about HOL Light is remembering our fixed natural numbers p 
& q!

Now NUM_RING proves the goal.  But surely we believe that for any free variable 
q of type num that 
q = 0 
if q^2 = 0.  

-- 
Best,
Bill 

let consider vars_t prfs lab =
  let len = String.length vars_t in
  let rec findSuchThat = function
      n -> if String.sub vars_t n 9 = "such that" then n
      else findSuchThat (n + 1) in
  let n = findSuchThat 1 in
  let vars = String.sub vars_t 0 (n - 1) and
  t = String.sub vars_t (n + 9) (len - n - 9) in
  let tm = parse_term ("?" ^ vars ^ ". " ^ t) in
  match prfs with
   p::ps -> (warn (ps <> []) "Consider: additional subproofs ignored";
   SUBGOAL_THEN tm (DESTRUCT_TAC ("@" ^ vars ^ "." ^ lab))
   THENL [p; ALL_TAC])
   | [] -> failwith "Consider: no subproof given";;

let case_split sDestruct sDisjlist tac =
  let rec list_mk_string_disj = function
      [] -> ""
    | s::[] -> "(" ^ s ^ ")"
    | s::ls -> "(" ^ s ^ ") \\/ " ^ list_mk_string_disj ls in
  let disjthm =  parse_term (list_mk_string_disj sDisjlist) in
  SUBGOAL_TAC "" disjthm tac THEN FIRST_X_ASSUM
  (DESTRUCT_TAC sDestruct);;

let TACtoThmTactic tac = fun  ths -> MAP_EVERY MP_TAC ths THEN tac;;
let NUM_RING_thmTAC = TACtoThmTactic (CONV_TAC NUM_RING);;
let ARITH_thmTAC = TACtoThmTactic ARITH_TAC;;
let so = fun tac -> FIRST_ASSUM MP_TAC THEN tac;;

g `!p q. p * p = 2 * q * q ==> q = 0`;;
e(MATCH_MP_TAC num_WF);;
e(INTRO_TAC "!p; A; !q; B");;
e(SUBGOAL_TAC "" `EVEN(p * p) <=> EVEN(2 * q * q)` 
  [HYP MESON_TAC "B" []]);;
e(SUBGOAL_TAC "" `EVEN(p)` [so (MESON_TAC [ARITH; EVEN_MULT])]);;
e(consider `"m such that p = 2 * m` 
  [so (MESON_TAC [EVEN_EXISTS])] "C");;
e(case_split "qp | pq" [`"(q:num) < p`; `"p <= q`] [ARITH_TAC]);;
e(SUBGOAL_TAC "" `q * q = 2 * m * m ==> m = 0` [HYP MESON_TAC "qp A" []]);;
e(so (HYP NUM_RING_thmTAC "B C" []));;
e(SUBGOAL_TAC "" `p * p <= (q:num) * q` [so (MESON_TAC [LE_MULT2 ])]);;
e(SUBGOAL_TAC "" `q * q = 0` [so (HYP ARITH_thmTAC "B" [])]);;
e(so (NUM_RING_thmTAC []));;
let NSQRT_2 = top_thm();;

------------------------------------------------------------------------------
Try New Relic Now & We'll Send You this Cool Shirt
New Relic is the only SaaS-based application performance monitoring service 
that delivers powerful full stack analytics. Optimize and monitor your
browser, app, & servers with just a few lines of code. Try New Relic
and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_apr
_______________________________________________
hol-info mailing list
hol-info@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/hol-info

Reply via email to