2015-05-11 6 views
5

Ho problemi con la formalizzazione delle definizioni del modulo seguente: definire un numero intero tale che alcune proprietà siano valide.Definizione per proprietà in coq

Diciamo che ho formalizzato la definizione della struttura:

Definition IsGood (x : Z) : Prop := ... 

Ora bisogno di una definizione della forma:

Definition Good : Z := ... 

supponendo che ho dimostrato che un numero intero con la proprietà esiste e è unico nel suo genere:

Lemma Lemma_GoodExistsUnique : exists! (x : Z), IsGood x. 

c'è un modo semplice di definire Good utilizzando IsGood e Lemma_GoodExistsUnique?

Poiché la proprietà è definita su numeri interi, sembra che non debbano essere necessari ulteriori assiomi. In ogni caso, non vedo come aggiungere qualcosa come l'assioma di scelta possa aiutare con la definizione.

Inoltre, sto avendo difficoltà con formalizzare definizioni della forma seguente (ho il sospetto questo è legato al problema che ho descritto sopra, ma si prega di indicare se questo non è il caso): per ogni x, esiste y, e questi y sono diversi per diversi x. Come, ad esempio, come definire che ci sono N distinti numeri buoni interi utilizzando IsGood:

Definition ThereAreNGoodIntegers (N : Z) (IsGood : Z -> Prop) := ...? 

In matematica del mondo reale, le definizioni del genere si verificano di tanto in tanto, quindi questo non dovrebbe essere difficile per formalizzare se Coq è destinato ad essere adatto per la matematica pratica.

risposta

7

La risposta breve alla tua prima domanda è: in generale, non è possibile, ma nel tuo caso particolare, sì.

Nella teoria di Coq, le proposizioni (vale a dire, Prop s) e le loro dimostrazioni hanno uno stato molto speciale. In particolare, in generale non è possibile scrivere un operatore di scelta che estrae il testimone di una prova di esistenza. Questo viene fatto per rendere la teoria compatibile con certi assiomi e principi, come la prova dell'irrilevanza, che dice che tutte le prove di una determinata proposizione sono uguali tra loro. Se vuoi essere in grado di farlo, devi aggiungere questo operatore di scelta come un assioma aggiuntivo alla tua teoria, come nel caso standard library.

Tuttavia, in alcuni casi particolari, è è possibile estrarre un testimone da una prova di esistenza astratta senza ricorrere a ulteriori assiomi. In particolare, è possibile farlo per tipi numerabili (come Z) quando la proprietà in questione è decidibile. Ad esempio, è possibile utilizzare l'interfaccia choiceType nella libreria Ssreflect per ottenere esattamente ciò che si desidera (cercare la funzione xchoose).

Detto questo, di solito consiglierei contro di fare cose con questo stile, perché porta a una complessità non necessaria. È probabilmente più semplice definire Good direttamente, senza ricorrere alla prova dell'esistenza, e quindi provare separatamente che Good ha la proprietà ricercata.

Definition Good : Z := (* ... *) 
Definition IsGood (z : Z) : Prop := (* ... *) 

Lemma GoodIsGood : IsGood Good. 
Proof. (* ... *) Qed. 

Lemma GoodUnique : forall z : Z, IsGood z -> z = Good. 

Se si vuole assolutamente definire Good con una prova di esistenza, è anche possibile modificare la prova della Lemma_GoodExistsUnique utilizzare un connettivo Type invece di Prop, in quanto permette di estrarre il testimone direttamente utilizzando la funzione proj1_sig :

Lemma Lemma_GoodExistsUnique : {z : Z | Good z /\ forall z', Good z' -> z' = z}. 
Proof. (* ... *) Qed. 

Per quanto riguarda la seconda domanda, sì, è un po 'correlata al primo punto. Ancora una volta, ti raccomanderei di annotare una funzione y_from_x con tipo Z -> Z che calcolerà dato x e poi dimostrerà separatamente che questa funzione mette in relazione ingressi e uscite in un modo particolare. Quindi, è possibile affermare che gli s sono diversi per x s provando che y_from_x è iniettivo.

D'altra parte, non sono sicuro di come il tuo ultimo esempio si riferisce a questa seconda domanda. Se ho ben capito che cosa si vuole fare in modo corretto, è possibile scrivere qualcosa di simile a

Definition ThereAreNGoodIntegers (N : Z) (IsGood : Z -> Prop) := 
    exists zs : list Z, 
    Z.of_nat (length zs) = N 
    /\ NoDup zs 
    /\ Forall IsGood zs. 

Qui, Z.of_nat : nat -> Z è l'iniezione canonica da naturali a numeri interi, NoDup è un predicato affermando che una lista non contiene elementi ripetuti, e Forall è un predicato di ordine superiore che asserisce che un dato predicato (in questo caso, IsGood) contiene tutti gli elementi di un elenco.

Come nota finale, consiglierei di non usare Z per cose che possono riguardare solo numeri naturali. Nel tuo esempio, utilizzi un numero intero per parlare della cardinalità di un set e questo numero è sempre un numero naturale.