Wenn ich Function
verwende, um eine nicht strukturell rekursive Funktion in Coq zu definieren, verhält sich das resultierende Objekt merkwürdig, wenn eine bestimmte Berechnung angefordert wird. Anstatt das Ergebnis direkt anzugeben, gibt die Eval compute in ...
-Direktive einen ziemlich langen (typischerweise 170.000 Zeilen) Ausdruck zurück. Es scheint, dass Coq nicht alles auswerten kann und daher einen vereinfachten (aber langen) Ausdruck anstelle nur eines Werts zurückgibt.Mit einer rekursiven Funktion berechnen, die durch wohldefinierte Induktion definiert ist
Das Problem scheint von der Art und Weise zu kommen, wie ich die Verpflichtungen von Function
generiert zu beweisen. Zuerst dachte ich, das Problem käme von den undurchsichtigen Begriffen, die ich benutzt habe, und ich habe alle Lemmas in transparente Konstanten umgewandelt. Gibt es übrigens eine Möglichkeit, die in einem Begriff auftretenden undurchsichtigen Begriffe aufzulisten? Oder eine andere Möglichkeit, undurchsichtige Lemmas in transparente zu verwandeln?
Ich bemerkte dann, dass das Problem genauer aus dem Beweis kam, dass die verwendete Reihenfolge begründet ist. Aber ich habe seltsame Ergebnisse.
Zum Beispiel definiere ich log2
auf die natürlichen Zahlen durch wiederholtes Anwenden div2
. Hier ist die Definition:
Function log2 n {wf lt n} :=
match n with
| 0 => 0
| 1 => 0
| n => S (log2 (Nat.div2 n))
end.
Ich bekomme zwei Beweispflichten. Der erste prüft, ob n
die Relation lt
in den rekursiven Aufrufen berücksichtigt und leicht zu beweisen ist.
forall n n0 n1 : nat, n0 = S n1 -> n = S (S n1) -> Nat.div2 (S (S n1)) < S (S n1)
intros. apply Nat.lt_div2. apply le_n_S. apply le_0_n.
Der zweite überprüft, dass lt
eine fundierte Bestellung ist. Dies ist bereits in der Standardbibliothek nachgewiesen. Das entsprechende Lemma ist Coq.Arith.Wf_nat.lt_wf
.
Wenn ich diesen Beweis verwende, verhält sich die resultierende Funktion normal. Eval compute in log24 10.
gibt 3
zurück.
Aber wenn ich den Beweis selbst machen will, bekomme ich nicht immer dieses Verhalten. Erstens, wenn ich den Beweis mit Qed
anstelle von Defined
beende, ist das Ergebnis der Berechnung (selbst bei kleinen Zahlen) ein komplexer Ausdruck und keine einzelne Zahl. Also verwende ich Defined
und versuche nur transparente Lemmas zu verwenden.
Hier ist Lemma1 ein Beweis für die fundierte Induktion der natürlichen Zahlen. Auch hier kann ich bereits existierende Lemmas verwenden, wie lt_wf_ind
, lt_wf_rec
, lt_wf_rec1
, die sich in Coq.Arith.Wf_nat
oder sogar well-founded lt
befinden. Das erste funktioniert nicht, es scheint, weil es undurchsichtig ist. Die drei anderen arbeiten.
Ich versuchte, es direkt unter Verwendung der Standardinduktion auf den natürlichen Zahlen, nat_ind
zu beweisen. Dies ergibt:
Lemma lemma1 : forall n (P:nat -> Prop),
(forall n, (forall p, p < n -> P p) -> P n) -> P n.
Proof.
intros n P H. pose proof (nat_ind (fun n => forall p, p < n -> P p)).
simpl in H0. apply H0 with (n:=S n).
- intros. inversion H1.
- intros. inversion H2.
+ apply H. exact H1.
+ apply H1. assumption.
- apply le_n.
Defined.
Mit diesem Beweis (und einigen Varianten davon), log2
hat das gleiche seltsame Verhalten. Und dieser Beweis scheint nur transparente Objekte zu verwenden, also ist das Problem vielleicht nicht da.
Wie kann ich einen Function
definieren, der verständliche Ergebnisse zu bestimmten Werten liefert?
Mit 'Opaque Dependencies drucken log2' können die in' log2' verwendeten undurchsichtigen Begriffe aufgelistet werden. – eponier