2012-04-24 8 views
8

Coq에서 Ackermann-Peters 함수를 정의하려고하는데 이해가 안되는 오류 메시지가 나타납니다. 보시다시피, 저는 Ackermann의 인수 a, b을 한 켤레에 포장합니다. ab; 인수에 대한 순서 지정 함수를 정의하는 순서를 제공합니다. 그런 다음 Function 양식을 사용하여 Ackermann 자체를 정의하고 ab 인수에 대한 정렬 함수를 제공합니다.Coq에서 Ackermann을 정의하는 중 오류가 발생했습니다.

Error: No such section variable or assumption: ack .

내가 COQ 귀찮게하지만, 인터넷 검색, 내가 제안 재귀를 사용하여 문제가있을 수 있습니다 찾았는지 확실하지 않다 :

Require Import Recdef.  
Definition ack_ordering (ab1 ab2 : nat * nat) := 
    match (ab1, ab2) with 
    |((a1, b1), (a2, b2)) => 
     (a1 > a2) \/ ((a1 = a2) /\ (b1 > b2)) 
    end. 
Function ack (ab : nat * nat) {wf ack_ordering} : nat := 
match ab with 
| (0, b) => b + 1 
| (a, 0) => ack (a-1, 1) 
| (a, b) => ack (a-1, ack (a, b-1)) 
end. 

내가 도착하면 다음과 같은 오류 메시지입니다 함수는 순서 부 또는 측정 값으로 정의되며 재귀 호출은 일치 항목 내에서 발생합니다. 그러나 투영 fstsndif-then-else을 사용하면 다른 오류 메시지가 생성됩니다. 누군가가 Coq에서 Ackermann을 정의하는 방법을 제안 할 수 있습니까?

+0

오늘 같은 문제가 발생했습니다. 해결책을 찾았습니까? –

+1

@AbhishekAnand 잠시 지났습니다 ... 아래에 '프로그램 고정 점'이 포함 된 솔루션을 제공했습니다. 'Function'으로 해결책을 찾았습니까? –

+0

아니, 나는하지 않았다. 귀하의 답변에 감사드립니다. –

답변

3

Function은이 문제를 해결할 수 없습니다. 그러나 그 사촌은 Program Fixpoint 수 있습니다.

Program Fixpoint ack (ab : nat * nat) {wf lexicographic_ordering ab} : nat := 
    match ab with 
    | (0, b) => b + 1 
    | (S a, 0) => ack (a, 1) 
    | (S a, S b) => ack (a, ack (S a, b)) 
    end. 
Next Obligation. 
    inversion Heq_ab; subst. left; auto. Defined. 
Next Obligation. 
    apply lexicographic_ordering_wf. Defined. 

일부 간단한 테스트는 우리가 ack으로 계산할 수 있음을 입증 :

Require Import Coq.Program.Wf. 
Require Import Coq.Arith.Arith. 

Definition lexicographic_ordering (ab1 ab2 : nat * nat) : Prop := 
    match ab1, ab2 with 
    | (a1, b1), (a2, b2) => 
     (a1 < a2) \/ ((a1 = a2) /\ (b1 < b2)) 
    end. 

(* this is defined in stdlib, but unfortunately it is opaque *) 
Lemma lt_wf_ind : 
    forall n (P:nat -> Prop), (forall n, (forall m, m < n -> P m) -> P n) -> P n. 
Proof. intro p; intros; elim (lt_wf p); auto with arith. Defined. 

(* this is defined in stdlib, but unfortunately it is opaque too *) 
Lemma lt_wf_double_ind : 
    forall P:nat -> nat -> Prop, 
    (forall n m, 
     (forall p (q:nat), p < n -> P p q) -> 
     (forall p, p < m -> P n p) -> P n m) -> forall n m, P n m. 
Proof. 
    intros P Hrec p. pattern p. apply lt_wf_ind. 
    intros n H q. pattern q. apply lt_wf_ind. auto. 
Defined. 

Lemma lexicographic_ordering_wf : well_founded lexicographic_ordering. 
Proof. 
    intros (a, b); pattern a, b; apply lt_wf_double_ind. 
    intros m n H1 H2. 
    constructor; intros (m', n') [G | [-> G]]. 
    - now apply H1. 
    - now apply H2. 
Defined. 

이제 우리는 ACKERMANN - 피터 함수를 정의 할 수 있습니다

이의 첫 잘 foundedness을 치료하는 몇 가지 보조 정리를 정의 할 수

Example test1 : ack (1, 2) = 4 := eq_refl. 
Example test2 : ack (3, 4) = 125 := eq_refl. (* this may take several seconds *) 
1

정의하는 동안 ack 함수를 참조하기 때문에이 오류가 발생합니다. 자체 참조는 Fixpoint (예 : 재귀 함수)에서만 허용되지만 Ackermann 함수가 원시 재귀 함수가 아니라는 것은 아시다시피 문제입니다.

자세한 내용은 Coq'Art section 4.3.2.2을 참조하십시오.

이렇게 정의하는 또 다른 방법은 두 번째 인수에 대해 구조적으로 재귀적인 두 번째 재귀 함수를 인라인하는 것입니다.

Fixpoint ack (n m : nat) : nat := 
    match n with 
    | O => S m 
    | S p => let fix ackn (m : nat) := 
       match m with 
       | O => ack p 1 
       | S q => ack p (ackn q) 
       end 
      in ackn m 
    end. 
+2

Fixpoint를 사용하지 않고 기능을 사용하고있었습니다.이것은 감소하는 인자를 가진 전체 함수들과 함께 동작하기로되어 있고, 계수 나 비교 중 하나를 사용해서 그렇게 할 수 있어야하고, 재귀 호출의 인자가 더 작은 값을 갖거나 원래 값보다 작다는 이론이 뒤 따른다. 인수는 비교 자당. 나는 Ackermann이 2 차 PR 인 것을 알고 있지만 분명히 PR의 PR 상태는 어떤 식 으로든 그것을 인코딩하는 것을 막지 못했다. 내가 궁금해하는 점은 내가 제공 한 인코딩에 무엇이 잘못된 것인가하는 것이고, 이것은 매뉴얼의 설명을 따르는 것으로 보인다. –

1

같은 일이 난 그냥 COQ 8.4으로 기능을 시도하고, 오류가 약간 다릅니다 :

Error: Nested recursive function are not allowed with Function 

내가 ACK로 내부 호출이 문제가 생각,하지만 난 몰라 왜.

희망이 도움이 조금 V.

PS : 나는 긍정 전선은 내부 fixpoint으로 쓴 것입니다 정의하는 일반적인 방법.