src/HOL/Tools/Nitpick/nitpick_nut.ML
changeset 34936 c4f04bee79f3
parent 34288 cf455b5880e1
child 34982 7b8c366e34a2
equal deleted inserted replaced
34935:cb011ba38950 34936:c4f04bee79f3
    37     Not |
    37     Not |
    38     Finite |
    38     Finite |
    39     Converse |
    39     Converse |
    40     Closure |
    40     Closure |
    41     SingletonSet |
    41     SingletonSet |
       
    42     IsUnknown |
    42     Tha |
    43     Tha |
    43     First |
    44     First |
    44     Second |
    45     Second |
    45     Cast
    46     Cast
    46 
    47 
   156   Not |
   157   Not |
   157   Finite |
   158   Finite |
   158   Converse |
   159   Converse |
   159   Closure |
   160   Closure |
   160   SingletonSet |
   161   SingletonSet |
       
   162   IsUnknown |
   161   Tha |
   163   Tha |
   162   First |
   164   First |
   163   Second |
   165   Second |
   164   Cast
   166   Cast
   165 
   167 
   229 fun string_for_op1 Not = "Not"
   231 fun string_for_op1 Not = "Not"
   230   | string_for_op1 Finite = "Finite"
   232   | string_for_op1 Finite = "Finite"
   231   | string_for_op1 Converse = "Converse"
   233   | string_for_op1 Converse = "Converse"
   232   | string_for_op1 Closure = "Closure"
   234   | string_for_op1 Closure = "Closure"
   233   | string_for_op1 SingletonSet = "SingletonSet"
   235   | string_for_op1 SingletonSet = "SingletonSet"
       
   236   | string_for_op1 IsUnknown = "IsUnknown"
   234   | string_for_op1 Tha = "Tha"
   237   | string_for_op1 Tha = "Tha"
   235   | string_for_op1 First = "First"
   238   | string_for_op1 First = "First"
   236   | string_for_op1 Second = "Second"
   239   | string_for_op1 Second = "Second"
   237   | string_for_op1 Cast = "Cast"
   240   | string_for_op1 Cast = "Cast"
   238 
   241 
   565         | (Const (@{const_name Let}, T), [t1, Abs (s, T', t2)]) =>
   568         | (Const (@{const_name Let}, T), [t1, Abs (s, T', t2)]) =>
   566           Op3 (Let, nth_range_type 2 T, Any, BoundName (length Ts, T', Any, s),
   569           Op3 (Let, nth_range_type 2 T, Any, BoundName (length Ts, T', Any, s),
   567                sub t1, sub_abs s T' t2)
   570                sub t1, sub_abs s T' t2)
   568         | (t0 as Const (@{const_name Let}, T), [t1, t2]) =>
   571         | (t0 as Const (@{const_name Let}, T), [t1, t2]) =>
   569           sub (t0 $ t1 $ eta_expand Ts t2 1)
   572           sub (t0 $ t1 $ eta_expand Ts t2 1)
   570         | (Const (@{const_name unknown}, T), []) => Cst (Unknown, T, Any)
       
   571         | (@{const Unity}, []) => Cst (Unity, @{typ unit}, Any)
   573         | (@{const Unity}, []) => Cst (Unity, @{typ unit}, Any)
   572         | (Const (@{const_name Pair}, T), [t1, t2]) =>
   574         | (Const (@{const_name Pair}, T), [t1, t2]) =>
   573           Tuple (nth_range_type 2 T, Any, map sub [t1, t2])
   575           Tuple (nth_range_type 2 T, Any, map sub [t1, t2])
   574         | (Const (@{const_name fst}, T), [t1]) =>
   576         | (Const (@{const_name fst}, T), [t1]) =>
   575           Op1 (First, range_type T, Any, sub t1)
   577           Op1 (First, range_type T, Any, sub t1)
   639           end
   641           end
   640         | (Const (@{const_name ord_int_inst.less_int}, T), [t1, t2]) =>
   642         | (Const (@{const_name ord_int_inst.less_int}, T), [t1, t2]) =>
   641           Op2 (Less, bool_T, Any, sub t1, sub t2)
   643           Op2 (Less, bool_T, Any, sub t1, sub t2)
   642         | (Const (@{const_name ord_int_inst.less_eq_int}, T), [t1, t2]) =>
   644         | (Const (@{const_name ord_int_inst.less_eq_int}, T), [t1, t2]) =>
   643           Op1 (Not, bool_T, Any, Op2 (Less, bool_T, Any, sub t2, sub t1))
   645           Op1 (Not, bool_T, Any, Op2 (Less, bool_T, Any, sub t2, sub t1))
       
   646         | (Const (@{const_name unknown}, T), []) => Cst (Unknown, T, Any)
       
   647         | (Const (@{const_name is_unknown}, T), [t1]) =>
       
   648           Op1 (IsUnknown, bool_T, Any, sub t1)
   644         | (Const (@{const_name Tha}, Type ("fun", [_, T2])), [t1]) =>
   649         | (Const (@{const_name Tha}, Type ("fun", [_, T2])), [t1]) =>
   645           Op1 (Tha, T2, Any, sub t1)
   650           Op1 (Tha, T2, Any, sub t1)
   646         | (Const (@{const_name Frac}, T), []) => Cst (Fracs, T, Any)
   651         | (Const (@{const_name Frac}, T), []) => Cst (Fracs, T, Any)
   647         | (Const (@{const_name norm_frac}, T), []) => Cst (NormFrac, T, Any)
   652         | (Const (@{const_name norm_frac}, T), []) => Cst (NormFrac, T, Any)
   648         | (Const (@{const_name of_nat}, T as @{typ "nat => int"}), []) =>
   653         | (Const (@{const_name of_nat}, T as @{typ "nat => int"}), []) =>
   713     val x as (s, T) = (nickname_of v, type_of v)
   718     val x as (s, T) = (nickname_of v, type_of v)
   714     val R = (if is_abs_fun thy x then
   719     val R = (if is_abs_fun thy x then
   715                rep_for_abs_fun
   720                rep_for_abs_fun
   716              else if is_rep_fun thy x then
   721              else if is_rep_fun thy x then
   717                Func oo best_non_opt_symmetric_reps_for_fun_type
   722                Func oo best_non_opt_symmetric_reps_for_fun_type
   718              else if all_exact orelse is_skolem_name v
   723              else if all_exact orelse is_skolem_name v orelse
   719                      orelse member (op =) [@{const_name undefined_fast_The},
   724                     member (op =) [@{const_name undefined_fast_The},
   720                                            @{const_name undefined_fast_Eps},
   725                                    @{const_name undefined_fast_Eps},
   721                                            @{const_name bisim},
   726                                    @{const_name bisim},
   722                                            @{const_name bisim_iterator_max}]
   727                                    @{const_name bisim_iterator_max}]
   723                                           (original_name s) then
   728                            (original_name s) then
   724                best_non_opt_set_rep_for_type
   729                best_non_opt_set_rep_for_type
   725              else if member (op =) [@{const_name set}, @{const_name distinct},
   730              else if member (op =) [@{const_name set}, @{const_name distinct},
   726                                     @{const_name ord_class.less},
   731                                     @{const_name ord_class.less},
   727                                     @{const_name ord_class.less_eq}]
   732                                     @{const_name ord_class.less_eq}]
   728                                    (original_name s) then
   733                                    (original_name s) then
   744    -> nut list * rep NameTable.table *)
   749    -> nut list * rep NameTable.table *)
   745 fun choose_rep_for_nth_sel_for_constr (scope as {ext_ctxt, ...}) (x as (_, T)) n
   750 fun choose_rep_for_nth_sel_for_constr (scope as {ext_ctxt, ...}) (x as (_, T)) n
   746                                       (vs, table) =
   751                                       (vs, table) =
   747   let
   752   let
   748     val (s', T') = boxed_nth_sel_for_constr ext_ctxt x n
   753     val (s', T') = boxed_nth_sel_for_constr ext_ctxt x n
   749     val R' = if n = ~1 orelse is_word_type (body_type T)
   754     val R' = if n = ~1 orelse is_word_type (body_type T) orelse
   750                 orelse (is_fun_type (range_type T')
   755                 (is_fun_type (range_type T') andalso
   751                         andalso is_boolean_type (body_type T')) then
   756                  is_boolean_type (body_type T')) then
   752                best_non_opt_set_rep_for_type scope T'
   757                best_non_opt_set_rep_for_type scope T'
   753              else
   758              else
   754                best_opt_set_rep_for_type scope T' |> unopt_rep
   759                best_opt_set_rep_for_type scope T' |> unopt_rep
   755     val v = ConstName (s', T', R')
   760     val v = ConstName (s', T', R')
   756   in (v :: vs, NameTable.update (v, R') table) end
   761   in (v :: vs, NameTable.update (v, R') table) end
   796 (* nut -> nut *)
   801 (* nut -> nut *)
   797 fun optimize_unit u =
   802 fun optimize_unit u =
   798   if rep_of u = Unit then Cst (Unity, type_of u, Unit) else u
   803   if rep_of u = Unit then Cst (Unity, type_of u, Unit) else u
   799 (* typ -> rep -> nut *)
   804 (* typ -> rep -> nut *)
   800 fun unknown_boolean T R =
   805 fun unknown_boolean T R =
   801   Cst (case R of
   806   Cst (case R of Formula Pos => False | Formula Neg => True | _ => Unknown,
   802          Formula Pos => False
   807        T, R)
   803        | Formula Neg => True
       
   804        | _ => Unknown, T, R)
       
   805 
   808 
   806 (* op1 -> typ -> rep -> nut -> nut *)
   809 (* op1 -> typ -> rep -> nut -> nut *)
   807 fun s_op1 oper T R u1 =
   810 fun s_op1 oper T R u1 =
   808   ((if oper = Not then
   811   ((if oper = Not then
   809       if is_Cst True u1 then Cst (False, T, R)
   812       if is_Cst True u1 then Cst (False, T, R)
   952           else if member (op =) [Add, Subtract, Multiply, Divide, Gcd, Lcm]
   955           else if member (op =) [Add, Subtract, Multiply, Divide, Gcd, Lcm]
   953                          cst then
   956                          cst then
   954             let
   957             let
   955               val T1 = domain_type T
   958               val T1 = domain_type T
   956               val R1 = Atom (spec_of_type scope T1)
   959               val R1 = Atom (spec_of_type scope T1)
   957               val total = T1 = nat_T
   960               val total = T1 = nat_T andalso
   958                           andalso (cst = Subtract orelse cst = Divide
   961                           (cst = Subtract orelse cst = Divide orelse cst = Gcd)
   959                                    orelse cst = Gcd)
       
   960             in Cst (cst, T, Func (R1, Func (R1, (not total ? Opt) R1))) end
   962             in Cst (cst, T, Func (R1, Func (R1, (not total ? Opt) R1))) end
   961           else if cst = NatToInt orelse cst = IntToNat then
   963           else if cst = NatToInt orelse cst = IntToNat then
   962             let
   964             let
   963               val (dom_card, dom_j0) = spec_of_type scope (domain_type T)
   965               val (dom_card, dom_j0) = spec_of_type scope (domain_type T)
   964               val (ran_card, ran_j0) = spec_of_type scope (range_type T)
   966               val (ran_card, ran_j0) = spec_of_type scope (range_type T)
   965               val total = not (is_word_type (domain_type T))
   967               val total = not (is_word_type (domain_type T)) andalso
   966                           andalso (if cst = NatToInt then
   968                           (if cst = NatToInt then
   967                                     max_int_for_card ran_card >= dom_card + 1
   969                              max_int_for_card ran_card >= dom_card + 1
   968                                   else
   970                            else
   969                                     max_int_for_card dom_card < ran_card)
   971                              max_int_for_card dom_card < ran_card)
   970             in
   972             in
   971               Cst (cst, T, Func (Atom (dom_card, dom_j0),
   973               Cst (cst, T, Func (Atom (dom_card, dom_j0),
   972                                  Atom (ran_card, ran_j0) |> not total ? Opt))
   974                                  Atom (ran_card, ran_j0) |> not total ? Opt))
   973             end
   975             end
   974           else
   976           else
   977           (case gsub def (flip_polarity polar) u1 of
   979           (case gsub def (flip_polarity polar) u1 of
   978              Op2 (Triad, T, R, u11, u12) =>
   980              Op2 (Triad, T, R, u11, u12) =>
   979              triad (s_op1 Not T (Formula Pos) u12)
   981              triad (s_op1 Not T (Formula Pos) u12)
   980                    (s_op1 Not T (Formula Neg) u11)
   982                    (s_op1 Not T (Formula Neg) u11)
   981            | u1' => s_op1 Not T (flip_rep_polarity (rep_of u1')) u1')
   983            | u1' => s_op1 Not T (flip_rep_polarity (rep_of u1')) u1')
       
   984         | Op1 (IsUnknown, T, _, u1) =>
       
   985           let val u1 = sub u1 in
       
   986             if is_opt_rep (rep_of u1) then Op1 (IsUnknown, T, Formula Neut, u1)
       
   987             else Cst (False, T, Formula Neut)
       
   988           end
   982         | Op1 (oper, T, _, u1) =>
   989         | Op1 (oper, T, _, u1) =>
   983           let
   990           let
   984             val u1 = sub u1
   991             val u1 = sub u1
   985             val R1 = rep_of u1
   992             val R1 = rep_of u1
   986             val R = case oper of
   993             val R = case oper of
  1027             fun hybrid_case u =
  1034             fun hybrid_case u =
  1028               (* hackish optimization *)
  1035               (* hackish optimization *)
  1029               if is_constructive u then s_op2 Eq T (Formula Neut) u1' u2'
  1036               if is_constructive u then s_op2 Eq T (Formula Neut) u1' u2'
  1030               else opt_opt_case ()
  1037               else opt_opt_case ()
  1031           in
  1038           in
  1032             if liberal orelse polar = Neg
  1039             if liberal orelse polar = Neg orelse
  1033                orelse is_concrete_type datatypes (type_of u1) then
  1040                is_concrete_type datatypes (type_of u1) then
  1034               case (is_opt_rep (rep_of u1'), is_opt_rep (rep_of u2')) of
  1041               case (is_opt_rep (rep_of u1'), is_opt_rep (rep_of u2')) of
  1035                 (true, true) => opt_opt_case ()
  1042                 (true, true) => opt_opt_case ()
  1036               | (true, false) => hybrid_case u1'
  1043               | (true, false) => hybrid_case u1'
  1037               | (false, true) => hybrid_case u2'
  1044               | (false, true) => hybrid_case u2'
  1038               | (false, false) => non_opt_case ()
  1045               | (false, false) => non_opt_case ()
  1106              let
  1113              let
  1107                val table' = NameTable.update (u1, R1) table
  1114                val table' = NameTable.update (u1, R1) table
  1108                val u1' = aux table' false Neut u1
  1115                val u1' = aux table' false Neut u1
  1109                val u2' = aux table' false Neut u2
  1116                val u2' = aux table' false Neut u2
  1110                val R =
  1117                val R =
  1111                  if is_opt_rep (rep_of u2')
  1118                  if is_opt_rep (rep_of u2') orelse
  1112                     orelse (range_type T = bool_T andalso
  1119                     (range_type T = bool_T andalso
  1113                             not (is_Cst False
  1120                      not (is_Cst False (unrepify_nut_in_nut table false Neut
  1114                                         (unrepify_nut_in_nut table false Neut
  1121                                                             u1 u2
  1115                                                              u1 u2
  1122                                         |> optimize_nut))) then
  1116                                          |> optimize_nut))) then
       
  1117                    opt_rep ofs T R
  1123                    opt_rep ofs T R
  1118                  else
  1124                  else
  1119                    unopt_rep R
  1125                    unopt_rep R
  1120              in s_op2 Lambda T R u1' u2' end
  1126              in s_op2 Lambda T R u1' u2' end
  1121            | R => raise NUT ("Nitpick_Nut.aux.choose_reps_in_nut", [u]))
  1127            | R => raise NUT ("Nitpick_Nut.aux.choose_reps_in_nut", [u]))
  1129             in
  1135             in
  1130               if polar = Neut andalso is_opt_rep (rep_of u2') then
  1136               if polar = Neut andalso is_opt_rep (rep_of u2') then
  1131                 triad_fn (fn polar => gsub def polar u)
  1137                 triad_fn (fn polar => gsub def polar u)
  1132               else
  1138               else
  1133                 let val quant_u = s_op2 oper T (Formula polar) u1' u2' in
  1139                 let val quant_u = s_op2 oper T (Formula polar) u1' u2' in
  1134                   if def
  1140                   if def orelse
  1135                      orelse (liberal andalso (polar = Pos) = (oper = All))
  1141                      (liberal andalso (polar = Pos) = (oper = All)) orelse
  1136                      orelse is_complete_type datatypes (type_of u1) then
  1142                      is_complete_type datatypes (type_of u1) then
  1137                     quant_u
  1143                     quant_u
  1138                   else
  1144                   else
  1139                     let
  1145                     let
  1140                       val connective = if oper = All then And else Or
  1146                       val connective = if oper = All then And else Or
  1141                       val unrepified_u = unrepify_nut_in_nut table def polar
  1147                       val unrepified_u = unrepify_nut_in_nut table def polar
  1229               constr_spec datatypes (original_name (nickname_of (hd us')), T)
  1235               constr_spec datatypes (original_name (nickname_of (hd us')), T)
  1230             val opt = exists is_opt_rep Rs orelse not total
  1236             val opt = exists is_opt_rep Rs orelse not total
  1231           in Construct (map sub us', T, R |> opt ? Opt, us) end
  1237           in Construct (map sub us', T, R |> opt ? Opt, us) end
  1232         | _ =>
  1238         | _ =>
  1233           let val u = modify_name_rep u (the_name table u) in
  1239           let val u = modify_name_rep u (the_name table u) in
  1234             if polar = Neut orelse not (is_boolean_type (type_of u))
  1240             if polar = Neut orelse not (is_boolean_type (type_of u)) orelse
  1235                orelse not (is_opt_rep (rep_of u)) then
  1241                not (is_opt_rep (rep_of u)) then
  1236               u
  1242               u
  1237             else
  1243             else
  1238               s_op1 Cast (type_of u) (Formula polar) u
  1244               s_op1 Cast (type_of u) (Formula polar) u
  1239           end
  1245           end
  1240       end
  1246       end