2013-03-05 14 views
8

w pliku teorii Isabelle, mogę pisać proste taktyki jednego wiersza, takich jak:Jak mogę łatwo napisać prostą taktykę na poziomie ML Isabelle?

apply (clarsimp simp: split_def split: prod.splits) 

Uważam jednak, kiedy zaczynam pisać kod ML zautomatyzować dowodów, w celu wytworzenia przedmiotu ML tactic, te jednej wkładki stać raczej gadatliwy:

clarsimp_tac (Context.proof_map (
    Simplifier.map_ss (fold Splitter.add_split @{thms prod.splits}) 
    #> Simplifier.map_ss (fn ss => ss addsimps [@{thm split_def}])) 
    @{context}) 1 

Czy istnieje prostszy sposób pisania prostych taktyk jedną linię na poziomie Isabelle/ml?

Na przykład, coś w stylu anty-oferty: @{tactic "clarsimp simp: split_def split: prod.splits"} produkującej funkcję typu context -> tactic, byłoby idealnym rozwiązaniem.

+0

Możesz zajrzeć do kodu 'try0'. AFAIK, podoba mi się to, co proponujesz z anty-cytatem. –

+0

@LarsNoschinski: 'try0' początkowo wyglądało obiecująco, ale niestety działa przy użyciu obiektów stanu dowodu (" stan "), które wciąż nie mogą być używane w sytuacji, w której wymagana jest' taktyka '. Możliwym rozwiązaniem może być wstrzyknięcie częściowo sprawdzonego "thm" w nowy obiekt stanu dowodu, zastosowanie do niego metody, a następnie wyodrębnienie wyniku; niestety wydaje się, że nie ma również oczywistego mechanizmu, aby to zrobić. – davidg

+0

Z kilkoma pytaniami, odpowiedziami i komentarzami rozłożonymi na nich, robi się nieco trudnym do naśladowania. Lepiej rozpoczynaj prostą dyskusję na liście dyskusyjnej w 'isabelle-users'. – Makarius

Odpowiedz

5

Widzę różne możliwości, zależy to trochę od kontekstu aplikacji, co jest najlepsze. Zauważ, że na ogół indywidualny kod ML dla dowodu zautomatyzowanego był zwykłym miejscem w dawnych czasach, ale dziś jest stosunkowo rzadki. Na przykład porównaj liczbę niestandardowych taktyk w raczej małym numerze HOL-Bali (rozpoczętym w 1997 r.) Z dużym JinjaThreads w AFP (rozpoczęty w 2007 r. I kontynuowany do niedawna).

Zagnieżdżanie antytokacji ML, takich jak @{tactic}, z zasady zadziałałoby, ale szybko natknąłbyś się na dalsze pytania, np. Co się stanie, jeśli argumenty teorematyczne będą znowu źródłem Isar lub ML.

Zamiast antiquoting taktyczne cegiełki w ml, bardziej podstawowe podejście jest cytatem dowód precedure w Isar poprzez nadanie mu regularne składni metody tak:

ML {* 
    (*foo_tac -- the payload of what you want to do, 
    note the dependency on ctxt: Proof.context*) 
    fun foo_tac ctxt = 
    let 
     val my_ctxt = 
     ctxt |> Simplifier.map_simpset 
     (fold Splitter.add_split @{thms prod.splits} #> 
      Simplifier.add_simp @{thm split_def}) 
    in ALLGOALS (clarsimp_tac my_ctxt) end 
*} 

method_setup foo = {* 
    (*concrete syntax like "clarsimp", "auto" etc.*) 
    Method.sections Clasimp.clasimp_modifiers >> 
    (*Isar method boilerplate*) 
    (fn _ => fn ctxt => SIMPLE_METHOD (CHANGED (foo_tac ctxt))) 
*} 

Tutaj mam pierwszy utworzyłem standardową definicję foo_tac w Isabelle/ML, a następnie zapakowałem ją w zwykły sposób Isar jako metodę sprawdzającą. To ostatnie oznacza, że ​​masz opakowania takie jak SIMPLE_METHOD, które zajmują się wypychaniem "przykutych faktów" do stanu docelowego, oraz CHANGED, aby zapewnić postęp procesu Isar (np. simp lub auto).

Przykład foo_tac zakłada, że ​​modyfikacja kontekstu (lub jego Simpset) jest stała, według sztywnych reguł podziału. Jeśli chcesz mieć dalsze parametry, możesz to uwzględnić w składni konkretnej metody. Zauważ, że Method.sections jest już dość wyrafinowany pod tym względem. Więcej podstawowych analizatorów argumentów podano w rozdziale "Definiowanie metod sprawdzania" w podręczniku isar-ref. Powinieneś także przyjrzeć się istniejącym przykładom, szukając źródeł dla method_setup (w Isabelle/Isar) lub Method.setup (w Isabelle/ML).

Jeśli nadal chcesz zrobić ML antiquotations zamiast konkretnej składni metody, można wypróbować wariant @{context} który pozwala modyfikatory tak:

@{context simp add: ...} 

To jest nieco spekulacyjny, wymyślone na poczekaniu, a może okazać się złą praktyką. Jak już powiedziałem, precyzyjne programowanie taktyki w Isabelle stało się w ostatnich latach nieco niecelowe, chociaż ML jest integralną częścią struktury Isabelle. Jeśli stawiasz bardziej konkretne pytanie z większą ilością kontekstu aplikacji, możemy ponownie rozważyć podejście antydotywacyjne.

+0

Nie jestem przyzwyczajony do używania anty-cytowania (jak dodawać argumenty ze zmiennych ML to dobry punkt), ale raczej szukam wygodnego sposobu na stworzenie natychmiastowej taktyki Isabelle (np. 'Clarsimp', 'auto', itp.) z kodu ML. Kontekstem jest projekt [AutoCorres] (http://ssrg.nicta.com.au/projects/TS/autocorres/), który musi generować wiele dowodów na podstawie kodu C użytkownika automatycznie. Pisanie/prototypowanie takich zautomatyzowanych metod może stać się dość uciążliwe przy użyciu interfejsu Isabelle ML, którego użyłem w moim pytaniu. – davidg

+0

Przykład "foo_tac' i metody' foo' powyżej miały być "wygodną instancją" clarsimp, auto. Zamiast wstawiać duże wyrażenia "taktyczne" ML, masz mieszankę pomocniczych taktyk ML i składni metody Isar. Możesz również przyjrzeć się src/HOL/Auth w źródłach Isabelle jako przykładowi wielu specyficznych taktyk ML i metod Isar w tym sensie (jest to zaktualizowana wersja klasycznej taktycznej aplikacji Isabelle z lat 90-tych). – Makarius

+0

'src/HOL/Auth' wydaje się być metodami craftingu, które pomagają rozwiązywać twierdzenia wewnątrz ręcznie pisanych plików teorii. W moim kontekście rozwiązuję twierdzenia, które zostały dynamicznie utworzone na podstawie wejściowego pliku C --- nie ma na dole skryptu proofa, ale mam do czynienia z obiektami 'thm' wygenerowanymi przez' Goal.init', które wymagają "taktyki" do przetworzenia. Opracowując taką taktykę, często po prostu chcę używać "wbudowanej" taktyki Isabelle, ale bez gadatliwości generowania odpowiednika ciała 'foo_tac' dla każdego takiego użycia. – davidg

1

Klasa Method wydają się zapewniać wystarczającą ilość interfejs do wyekstrahowania taktyki, poprzez cases_tactic następująco:

(* 
* Generate an ML tactic object of the given Isar string. 
* 
* For example, 
* 
* mk_tac "auto simp: field_simps intro!: ext" @{context} 
* 
* will generate the corresponding "tactic" object. 
*) 
fun mk_tac str ctxt = 
let 
    val parsed_str = Outer_Syntax.scan Position.start str 
     |> filter Token.is_proper 
     |> Args.name 
    val meth = Method.method (Proof_Context.theory_of ctxt) 
     (Args.src (parsed_str, Position.start)) ctxt 
in 
    Method.apply (K meth) ctxt [] #> Seq.map snd 
end 

lub alternatywnie jako anty-notowania:

(* 
* Setup an antiquotation of the form: 
* 
* @{tactic "auto simp: foo intro!: bar"} 
* 
* which returns an object of type "context -> tactic". 
* 
* While this doesn't provide any benefits over a direct call to "mk_tac" just 
* yet, in the future it may generate code to avoid parsing the tactic at 
* run-time. 
*) 
val tactic_antiquotation_setup = 
let 
    val parse_string = 
    ((Args.context -- Scan.lift Args.name) >> snd) 
     #>> ML_Syntax.print_string 
     #>> (fn s => "mk_tac "^s) 
     #>> ML_Syntax.atomic 
in 
    ML_Antiquote.inline @{binding "tactic"} parse_string 
end 

i konfiguracji w pliku teoretycznym:

setup {* 
    tactic_antiquotation_setup 
*} 

, które można następnie użyte w następujący sposób:

lemma "(a :: nat) * (b + 1) = (a * b) + a" 
    by (tactic {* @{tactic "metis Suc_eq_plus1 mult_Suc_right nat_add_commute"} @{context} *}) 

zgodnie z potrzebami.

1

Oprócz innych odpowiedzi, myślę, że warto wspomnieć, że istnieje nowy wysokopoziomowy język konstrukcji taktycznej/metody proof (podobny do Ltac w Coq) o nazwie Eisbach w Isabelle2015, który ma być łatwiejszy do zrozumienia i utrzymania .

Powiązane problemy