15 val algebra_tac: thm list -> thm list -> Proof.context -> int -> tactic |
15 val algebra_tac: thm list -> thm list -> Proof.context -> int -> tactic |
16 end |
16 end |
17 |
17 |
18 structure Groebner: GROEBNER = |
18 structure Groebner: GROEBNER = |
19 struct |
19 struct |
20 open Normalizer; |
20 |
21 open Misc; |
21 open Conv Misc Normalizer; |
22 |
22 |
23 fun assocd x al d = case AList.lookup (op =) al x of SOME y => y | NONE => d; |
|
24 val rat_0 = Rat.zero; |
23 val rat_0 = Rat.zero; |
25 val rat_1 = Rat.one; |
24 val rat_1 = Rat.one; |
26 val minus_rat = Rat.neg; |
25 val minus_rat = Rat.neg; |
27 val denominator_rat = Rat.quotient_of_rat #> snd #> Rat.rat_of_int; |
26 val denominator_rat = Rat.quotient_of_rat #> snd #> Rat.rat_of_int; |
28 fun int_of_rat a = |
27 fun int_of_rat a = |
329 (* Turn proof into a certificate as sum of multipliers. *) |
328 (* Turn proof into a certificate as sum of multipliers. *) |
330 (* *) |
329 (* *) |
331 (* In principle this is very inefficient: in a heavily shared proof it may *) |
330 (* In principle this is very inefficient: in a heavily shared proof it may *) |
332 (* make the same calculation many times. Could put in a cache or something. *) |
331 (* make the same calculation many times. Could put in a cache or something. *) |
333 (* ------------------------------------------------------------------------- *) |
332 (* ------------------------------------------------------------------------- *) |
334 fun assoc x l = snd(find (fn p => fst p = x) l); |
|
335 |
|
336 fun resolve_proof vars prf = |
333 fun resolve_proof vars prf = |
337 case prf of |
334 case prf of |
338 Start(~1) => [] |
335 Start(~1) => [] |
339 | Start m => [(m,[(rat_1,map (K 0) vars)])] |
336 | Start m => [(m,[(rat_1,map (K 0) vars)])] |
340 | Mmul(pol,lin) => |
337 | Mmul(pol,lin) => |
343 | Add(lin1,lin2) => |
340 | Add(lin1,lin2) => |
344 let val lis1 = resolve_proof vars lin1 |
341 let val lis1 = resolve_proof vars lin1 |
345 val lis2 = resolve_proof vars lin2 |
342 val lis2 = resolve_proof vars lin2 |
346 val dom = distinct (op =) ((map fst lis1) union (map fst lis2)) |
343 val dom = distinct (op =) ((map fst lis1) union (map fst lis2)) |
347 in |
344 in |
348 map (fn n => let val a = ((assoc n lis1) handle _ => []) (* FIXME *) |
345 map (fn n => let val a = these (AList.lookup (op =) lis1 n) |
349 val b = ((assoc n lis2) handle _ => []) in (* FIXME *) |
346 val b = these (AList.lookup (op =) lis2 n) |
350 (n,grob_add a b) end) dom end; |
347 in (n,grob_add a b) end) dom end; |
351 |
348 |
352 (* ------------------------------------------------------------------------- *) |
349 (* ------------------------------------------------------------------------- *) |
353 (* Run the procedure and produce Weak Nullstellensatz certificate. *) |
350 (* Run the procedure and produce Weak Nullstellensatz certificate. *) |
354 (* ------------------------------------------------------------------------- *) |
351 (* ------------------------------------------------------------------------- *) |
355 fun grobner_weak vars pols = |
352 fun grobner_weak vars pols = |
386 fun transform_polynomial q = fold_rev (grob_add o transform_monomial) q [] |
383 fun transform_polynomial q = fold_rev (grob_add o transform_monomial) q [] |
387 val cert' = map (fn (c,q) => (c-1,transform_polynomial q)) |
384 val cert' = map (fn (c,q) => (c-1,transform_polynomial q)) |
388 (filter (fn (k,_) => k <> 0) cert) in |
385 (filter (fn (k,_) => k <> 0) cert) in |
389 (d,l,cert') end; |
386 (d,l,cert') end; |
390 |
387 |
391 fun string_of_pol vars pol = |
|
392 foldl (fn ((c,m),s) => ((Rat.string_of_rat c) |
|
393 ^ "*(" ^ |
|
394 (snd (foldl |
|
395 (fn (e,(i,s)) => |
|
396 (i+ 1, |
|
397 (nth vars i |
|
398 |>cterm_of (the_context()) (* FIXME *) |
|
399 |> string_of_cterm)^ "^" |
|
400 ^ (Int.toString e) ^" * " ^ s)) (0,"0") m)) |
|
401 ^ ") + ") ^ s) "" pol; |
|
402 |
|
403 |
388 |
404 (* ------------------------------------------------------------------------- *) |
389 (* ------------------------------------------------------------------------- *) |
405 (* Overall parametrized universal procedure for (semi)rings. *) |
390 (* Overall parametrized universal procedure for (semi)rings. *) |
406 (* We return an ideal_conv and the actual ring prover. *) |
391 (* We return an ideal_conv and the actual ring prover. *) |
407 (* ------------------------------------------------------------------------- *) |
392 (* ------------------------------------------------------------------------- *) |
455 |
440 |
456 val mk_object_eq = fn th => th COMP meta_eq_to_obj_eq; |
441 val mk_object_eq = fn th => th COMP meta_eq_to_obj_eq; |
457 val bool_simps = @{thms "bool_simps"}; |
442 val bool_simps = @{thms "bool_simps"}; |
458 val nnf_simps = @{thms "nnf_simps"}; |
443 val nnf_simps = @{thms "nnf_simps"}; |
459 val nnf_conv = Simplifier.rewrite (HOL_basic_ss addsimps bool_simps addsimps nnf_simps) |
444 val nnf_conv = Simplifier.rewrite (HOL_basic_ss addsimps bool_simps addsimps nnf_simps) |
460 val weak_dnf_conv = Simplifier.rewrite (HOL_basic_ss addsimps (@{thms "weak_dnf_simps"})); |
445 val weak_dnf_conv = Simplifier.rewrite (HOL_basic_ss addsimps @{thms "weak_dnf_simps"}); |
461 val initial_conv = |
446 val initial_conv = |
462 Simplifier.rewrite |
447 Simplifier.rewrite |
463 (HOL_basic_ss addsimps nnf_simps |
448 (HOL_basic_ss addsimps nnf_simps |
464 addsimps [not_all, not_ex] addsimps map (fn th => th RS sym) (ex_simps @ all_simps)); |
449 addsimps [not_all, not_ex] addsimps map (fn th => th RS sym) (ex_simps @ all_simps)); |
465 |
450 |
466 val specl = fold_rev (fn x => fn th => instantiate' [] [SOME x] (th RS spec)); |
451 val specl = fold_rev (fn x => fn th => instantiate' [] [SOME x] (th RS spec)); |
467 |
452 |
468 val cTrp = @{cterm "Trueprop"}; |
453 val cTrp = @{cterm "Trueprop"}; |
469 val cConj = @{cterm "op &"}; |
454 val cConj = @{cterm "op &"}; |
470 val (cNot,false_tm) = (@{cterm "Not"}, @{cterm "False"}); |
455 val (cNot,false_tm) = (@{cterm "Not"}, @{cterm "False"}); |
471 val ASSUME = mk_comb cTrp #> assume; |
456 val assume_Trueprop = mk_comb cTrp #> assume; |
472 val list_mk_conj = list_mk_binop cConj; |
457 val list_mk_conj = list_mk_binop cConj; |
473 val conjs = list_dest_binop cConj; |
458 val conjs = list_dest_binop cConj; |
474 val mk_neg = mk_comb cNot; |
459 val mk_neg = mk_comb cNot; |
475 |
460 |
476 |
461 |
605 val neq_01 = prove_nz (rat_1); |
590 val neq_01 = prove_nz (rat_1); |
606 fun neq_rule n th = [prove_nz n, th] MRS neq_thm; |
591 fun neq_rule n th = [prove_nz n, th] MRS neq_thm; |
607 fun mk_add th1 = combination(Drule.arg_cong_rule ring_add_tm th1); |
592 fun mk_add th1 = combination(Drule.arg_cong_rule ring_add_tm th1); |
608 |
593 |
609 fun refute tm = |
594 fun refute tm = |
610 if tm aconvc false_tm then ASSUME tm else |
595 if tm aconvc false_tm then assume_Trueprop tm else |
611 let |
596 let |
612 val (nths0,eths0) = List.partition (is_neg o concl) (conjuncts(ASSUME tm)) |
597 val (nths0,eths0) = List.partition (is_neg o concl) (HOLogic.conj_elims (assume_Trueprop tm)) |
613 val nths = filter (is_eq o Thm.dest_arg o concl) nths0 |
598 val nths = filter (is_eq o Thm.dest_arg o concl) nths0 |
614 val eths = filter (is_eq o concl) eths0 |
599 val eths = filter (is_eq o concl) eths0 |
615 in |
600 in |
616 if null eths then |
601 if null eths then |
617 let |
602 let |
618 val th1 = end_itlist (fn th1 => fn th2 => idom_rule(conji th1 th2)) nths |
603 val th1 = end_itlist (fn th1 => fn th2 => idom_rule(HOLogic.conj_intr th1 th2)) nths |
619 val th2 = Conv.fconv_rule |
604 val th2 = Conv.fconv_rule |
620 ((arg_conv #> arg_conv) |
605 ((arg_conv #> arg_conv) |
621 (binop_conv ring_normalize_conv)) th1 |
606 (binop_conv ring_normalize_conv)) th1 |
622 val conc = th2 |> concl |> Thm.dest_arg |
607 val conc = th2 |> concl |> Thm.dest_arg |
623 val (l,r) = conc |> dest_eq |
608 val (l,r) = conc |> dest_eq |
633 val (l,cert) = grobner_weak vars pols |
618 val (l,cert) = grobner_weak vars pols |
634 in (vars,l,cert,neq_01) |
619 in (vars,l,cert,neq_01) |
635 end |
620 end |
636 else |
621 else |
637 let |
622 let |
638 val nth = end_itlist (fn th1 => fn th2 => idom_rule(conji th1 th2)) nths |
623 val nth = end_itlist (fn th1 => fn th2 => idom_rule(HOLogic.conj_intr th1 th2)) nths |
639 val (vars,pol::pols) = |
624 val (vars,pol::pols) = |
640 grobify_equations(list_mk_conj(Thm.dest_arg(concl nth)::map concl eths)) |
625 grobify_equations(list_mk_conj(Thm.dest_arg(concl nth)::map concl eths)) |
641 val (deg,l,cert) = grobner_strong vars pols pol |
626 val (deg,l,cert) = grobner_strong vars pols pol |
642 val th1 = Conv.fconv_rule((arg_conv o arg_conv)(binop_conv ring_normalize_conv)) nth |
627 val th1 = Conv.fconv_rule((arg_conv o arg_conv)(binop_conv ring_normalize_conv)) nth |
643 val th2 = funpow (Integer.machine_int deg) (idom_rule o conji th1) neq_01 |
628 val th2 = funpow (Integer.machine_int deg) (idom_rule o HOLogic.conj_intr th1) neq_01 |
644 in (vars,l,cert,th2) |
629 in (vars,l,cert,th2) |
645 end) |
630 end) |
646 (* val _ = writeln ("Translating certificate to HOL inferences") *) |
631 (* val _ = writeln ("Translating certificate to HOL inferences") *) |
647 val cert_pos = map (fn (i,p) => (i,filter (fn (c,m) => c >/ rat_0) p)) cert |
632 val cert_pos = map (fn (i,p) => (i,filter (fn (c,m) => c >/ rat_0) p)) cert |
648 val cert_neg = map (fn (i,p) => (i,map (fn (c,m) => (minus_rat c,m)) |
633 val cert_neg = map (fn (i,p) => (i,map (fn (c,m) => (minus_rat c,m)) |
654 end_itlist mk_add |
639 end_itlist mk_add |
655 (map (fn (i,p) => Drule.arg_cong_rule (mk_comb ring_mul_tm p) |
640 (map (fn (i,p) => Drule.arg_cong_rule (mk_comb ring_mul_tm p) |
656 (nth eths (Integer.machine_int i) |> mk_meta_eq)) pols) |
641 (nth eths (Integer.machine_int i) |> mk_meta_eq)) pols) |
657 val th1 = thm_fn herts_pos |
642 val th1 = thm_fn herts_pos |
658 val th2 = thm_fn herts_neg |
643 val th2 = thm_fn herts_neg |
659 val th3 = conji(mk_add (symmetric th1) th2 |> mk_object_eq) noteqth |
644 val th3 = HOLogic.conj_intr(mk_add (symmetric th1) th2 |> mk_object_eq) noteqth |
660 val th4 = Conv.fconv_rule ((arg_conv o arg_conv o binop_conv) ring_normalize_conv) |
645 val th4 = Conv.fconv_rule ((arg_conv o arg_conv o binop_conv) ring_normalize_conv) |
661 (neq_rule l th3) |
646 (neq_rule l th3) |
662 val (l,r) = dest_eq(Thm.dest_arg(concl th4)) |
647 val (l,r) = dest_eq(Thm.dest_arg(concl th4)) |
663 in implies_intr (mk_comb cTrp tm) |
648 in implies_intr (mk_comb cTrp tm) |
664 (equal_elim (Drule.arg_cong_rule cTrp (eqF_intr th4)) |
649 (equal_elim (Drule.arg_cong_rule cTrp (eqF_intr th4)) |
694 val rawvars = fold_rev grobvars (tm::tms) [] |
679 val rawvars = fold_rev grobvars (tm::tms) [] |
695 val vars = sort ord (distinct (fn (x,y) => (term_of x) aconv (term_of y)) rawvars) |
680 val vars = sort ord (distinct (fn (x,y) => (term_of x) aconv (term_of y)) rawvars) |
696 val pols = map (grobify_term vars) tms |
681 val pols = map (grobify_term vars) tms |
697 val pol = grobify_term vars tm |
682 val pol = grobify_term vars tm |
698 val cert = grobner_ideal vars pols pol |
683 val cert = grobner_ideal vars pols pol |
699 in map (fn n => let val p = assocd n cert [] in holify_polynomial vars p end) |
684 in map (fn n => these (AList.lookup (op =) cert n) |> holify_polynomial vars) |
700 (map Integer.int (0 upto (length pols - 1))) |
685 (map Integer.int (0 upto (length pols - 1))) |
701 end |
686 end |
702 in (ring,ideal) |
687 in (ring,ideal) |
703 end; |
688 end; |
704 |
689 |
731 | SOME (res as (theory, {is_const, dest_const, mk_const, conv = ring_eq_conv})) => |
716 | SOME (res as (theory, {is_const, dest_const, mk_const, conv = ring_eq_conv})) => |
732 fst (ring_and_ideal_conv theory |
717 fst (ring_and_ideal_conv theory |
733 dest_const (mk_const (Thm.ctyp_of_term tm)) (ring_eq_conv ctxt) |
718 dest_const (mk_const (Thm.ctyp_of_term tm)) (ring_eq_conv ctxt) |
734 (semiring_normalize_wrapper ctxt res)) form)); |
719 (semiring_normalize_wrapper ctxt res)) form)); |
735 |
720 |
736 fun algebra_tac add_ths del_ths ctxt i = ObjectLogic.full_atomize_tac i |
721 fun algebra_tac add_ths del_ths ctxt i = ObjectLogic.full_atomize_tac i |
737 THEN (simp_tac (fst (NormalizerData.get ctxt) delsimps del_ths addsimps add_ths) i) |
722 THEN (simp_tac (fst (NormalizerData.get ctxt) delsimps del_ths addsimps add_ths) i) |
738 THEN (fn st => |
723 THEN (fn st => |
739 case try (nth (cprems_of st)) (i - 1) of |
724 case try (nth (cprems_of st)) (i - 1) of |
740 NONE => no_tac st |
725 NONE => no_tac st |
741 | SOME p => let val th = ring_conv ctxt (Thm.dest_arg p) |
726 | SOME p => let val th = ring_conv ctxt (Thm.dest_arg p) |
742 in rtac th i st end |
727 in rtac th i st end |
743 handle TERM _ => no_tac st |
728 handle TERM _ => no_tac st |
744 | THM _ => no_tac st |
729 | THM _ => no_tac st |
745 | ERROR _ => no_tac st |
730 | ERROR _ => no_tac st (* FIXME !? *) |
746 | CTERM _ => no_tac st); |
731 | CTERM _ => no_tac st); |
747 |
732 |
748 end; |
733 end; |