From windley@cheetah  Wed Nov 22 14:46:48 1989
Received: by iris (5.57/3.14)
        id AA26797; Wed, 22 Nov 89 14:46:48 PST
Received: from cheetah.ucdavis.edu by clover.ucdavis.edu (5.59/UCD.EECS.1.11)
        id AA13927; Wed, 22 Nov 89 14:49:57 PST
Received: by cheetah.ucdavis.edu (AIX  2.1.2/3.14)
        id AA01903; Wed, 22 Nov 89 14:47:45 PST
Message-Id: <8911222247.AA01903@cheetah.ucdavis.edu>
To: info-hol@clover
Subject: association lists in HOL
Date: Wed, 22 Nov 89 14:47:44 -0800
From: Phil Windley <windley@cheetah>


I'm verifying a CPU that will have a rather large microstore and decided to
represent it as an association list.  The verification is done by symbolic
execution at times and thus it is important to be able to process the list
quickly.  To this end I defined a conversion that does a reasonable job.  I
decided to post them so that others can use them.  Here is the definition
of ASSOC:

let ASSOC =
     new_recursive_definition false list_Axiom `ASSOC`
      "(ASSOC NIL (x:*) (y:**) = y) /\
       (!(h:*#**) t .
           ASSOC (CONS h t) x (y:**) =
                 ((x = (FST h)) => (SND h)
                                 | (ASSOC t x y)))";;


I couldn't get the type package to accept it in the form I wanted, so here
is a theorem that IS in the coorect form (Tom, am I doing something wrong
or does the type package not like pairs as variables?):

let ASSOC_THM = prove_thm
   (`ASSOC_THM`,
    "! x y h1 h2 t .
     (ASSOC NIL x y = y) /\
     (ASSOC (CONS (h1,h2) t) x y =
            ((x = h1) => h2
                       | (ASSOC t x y)))",
    REPEAT GEN_TAC
    THEN REWRITE_TAC [ASSOC]
   );;

The conversion works in time linear to the length of the association list.
My ML style is self-taught, so if you can do it better, send me the
improvements. (Mild laughter allowed.)  Here is the conversion:

let ASSOC_CONV conv t = (
    let cond_lemma_1 = GEN_ALL (CONJUNCT1 (SPEC_ALL COND_CLAUSES))) in
    let cond_lemma_2 = GEN_ALL (CONJUNCT2 (SPEC_ALL COND_CLAUSES))) in
    let (t1, [lst;x;y]) = strip_comb t in
    let thm = (SPEC_ALL ASSOC_THM) in
    if lst = "NIL:^(type_of lst)" then
        (SPECL [x; y]
           (INST_TYPE [(type_of x,":*");(type_of y,":**")]
              (GEN_ALL (CONJUNCT1 thm)))) else
    let t2,lst1 = strip_comb lst in
    let ((h1, h2), t3) = (dest_pair (hd lst1), hd (tl lst1)) in
    let lemma = conv "^x = ^h1" in
    let rule1 = (\z.
         SUBS [SPECL [h2;"ASSOC ^t3 ^x ^y"]
            (INST_TYPE [(type_of y,":*")] z)]
          (SUBS [lemma]
             (SPECL [h1;h2;t3;x;y]
                   (INST_TYPE [(type_of x,":*");(type_of y,":**")]
                        (GEN_ALL (CONJUNCT2 thm)))))) in
    if ((snd o dest_eq o concl) lemma = "T")  then
       rule1 cond_lemma_1
    else
       rule1 cond_lemma_2
   ) ? failwith `ASSOC_CONV`;;

Note that the association takes a conversion as an argument.  The
argument is used to determine the (in)equalities.  In my application these
were large (by HOL standards) decimal numbers, so I used DEC_EQ_CONV, from
my decimal arithmetic package.

So, for example,

(TOP_DEPTH_CONV (ASSOC_CONV DEC_EQ_CONV))
    "ASSOC
       [(0, I0000_mc);
        (1, I0001_mc);
        (2, I0002_mc);
        (lodd, lodd1_mc);
        (lodd, lodd2_mc);
        (tab_stod, stod1_mc);
        (stod, stod2_mc);
        (stod+1, stod3_mc);
        (tab_addd, addd1_mc);
        (addd, addd2_mc);
        (tab_push, push1_mc);
        (push, push2_mc);
        (tab_pop, pop1_mc);
        (pop, pop2_mc);
        (pop+1, pop3_mc);
       ] 2 noop_mc";;

yields

    |- ASSOC
       [(0, I0000_mc);(1, I0001_mc);(2, I0002_mc);(4, lodd1_mc);
        (30, lodd2_mc);(5, stod1_mc);(32, stod2_mc);
        (33, stod3_mc);(6, addd1_mc);(34, addd2_mc);
        (21, push1_mc);(70, push2_mc);(22, pop1_mc);
        (71, pop2_mc);(72, pop3_mc)] 2 noop_mc =
       I0002_mc

On a Sun3/160, the conversion takes about 4 seconds times the position in
the list, so the above calculation takes about 12 seconds.  Not lightening
fast, but better than the hour that it took using a stupid rewrite and then
check for (in)equalities strategy.  (Note that the hard numbers in the
above term are actually symbolic to the human, only the machine actually
sees the real numbers).

Hope that this is of use to somebody else.

--phil--

Phil Windley                          |  windley@cheetah.ucdavis.edu
Division of Computer Science          |  ucbvax!ucdavis!cheetah!windley
College of Engineering                |  (916) 752-6452 (or 3168)
University of California, Davis       |  Davis, CA 95616

