Coq में प्रूफ प्रूफ


10

पृष्ठभूमि

मैं अपने दम पर सहायता, Coq सीख रहा हूं। अब तक, मैंने यव्स बर्टोट के कोक एक हूर्री में पढ़ना पूरा कर लिया है । अब, मेरा लक्ष्य प्राकृतिक संख्या से संबंधित कुछ बुनियादी परिणामों को साबित करना है, तथाकथित विभाजन एल्गोरिथ्म के साथ समापन। हालाँकि, मुझे उस लक्ष्य की ओर अपने रास्ते में कुछ असफलताओं का सामना करना पड़ा है। विशेष रूप से, दो निम्नलिखित परिणाम साबित हुए हैं (उद्देश्य) मैं शुरू में कल्पना की तुलना में कोक में साबित करना अधिक कठिन था। वास्तव में, मेरे पास कई फलहीन प्रयासों के बाद, उन्हें हाथ से साबित करने के लिए सहारा लिया (जैसा कि नीचे दिखाया गया है)। यह स्पष्ट रूप से मुझे कोक को संभालने में अधिक कुशल बनने में मदद नहीं कर रहा है; जिसके कारण मैं इस मंच की ओर रुख करता हूं। मेरी आशा है कि इस साइट पर कोई सक्षम और इच्छुक हैनीचे मेरे सबूतों का अनुवाद करने में मेरी मदद करने के लिए एक सबूत जिसे Coq स्वीकार करता है। सभी मदद ईमानदारी से की सराहना की है!

प्रमेय ए

सभी सबूत:x,yN

x<S(y)x<yI(N,x,y)

मान लीजिए । इसलिए साथ _ है इसलिए (पीनो 1 बी और 3)x<S(y)zN

(*)I(N,x+S(z),S(y))
I(N,x+z,y)

एक पूर्व निर्धारित

Q(u):=(I(N,x+u,y)x<yI(N,x,y)

यह दिखाने के लिए पर्याप्त है । हम इसे पर इंडक्शन द्वारा सिद्ध करते हैं । देखने के लिए , नहीं ethat अगर तो रखती है Peano 1 ए से सच है। इस प्रकार, । अब, हम सिद्ध करते हैं : मान लीजिए कि । इस परिभाषा से हमारे पास और इस प्रकार भी इस मामले में हैं। अंत में, Peano का पांचवा स्वयंसिद्ध और द्वारा हमें । Q(z)zQ(0)I(N,x+0,y)I(N,x,y)x<yI(n,x,y)Q(S(v))I(N,x+S(v),y)x<yx<yI(N,x,y)Q(z)()x<yI(N,x,y)

()

प्रमेय बी

सभी सबूत:x,yN

x<yI(N,x,y)y<x

यदि तो परिभाषा द्वारा, और यदि तो भी परिभाषा द्वारा। यदि और तो ट्रांज़िटिविटी और रिफ्लेक्सिटी के द्वारा, हमारे पास , जो एक विरोधाभास है। नतीजतन, बयानों में से एक से अधिक सच नहीं है।x<y¬I(N,x,y)x>y¬I(N,x,y)x>y y>xI(N,x,y)

हम स्थिर रखते हैं और पर शामिल करते हैं । जब हमारे पास सभी के लिए है, जो आधार मामला साबित होता है। अगला, मान लीजिए कि प्रमेय लिए रखता है ; अब हम लिए प्रमेय सिद्ध करना चाहते हैं । लिए ट्राइकोटॉमी से , तीन मामले हैं: , और । यदि , तो स्पष्ट रूप से । यदि , तो (as सभी )। अंत में, मान लीजिएyxI(N,0,y)0<yI(N,0,y)yxS(x)xx<y,I(N,x,y)x>yx>yS(x)>yI(N,x,y)S(x)>yS(x)>xxNx<yफिर, प्रमेय A द्वारा हमारे पास या , और किसी भी स्थिति में हम किए जाते हैं। S(x)<yI(N,S(x),y)

()

जिन प्रमेयों को मैं प्रमाणित करना चाहता हूं, उन्हें Coq में निम्न प्रकार से व्यक्त किया जा सकता है।

Lemma less_lem (xy: N): कम x (succ y) -> या (कम xy) (IN xy)।

प्रमेय Ntrichotomy: (forall xy: N, या (xy कम) (या (xy) (कम yx))।

उपयोगी परिणाम

यहां, मैंने कुछ ऐसे परिणामों को इकट्ठा किया है जिन्हें मैंने परिभाषित किया है, और इस बिंदु तक साबित किया है। ये वे हैं जिनका मैं ऊपर उल्लेख करता हूं। * यह वह कोड है जिसे मैंने अब तक लिखने में कामयाब रहा है, ध्यान दें कि अधिकांश में परिभाषाएं शामिल हैं। *

(* Sigma types *)


Inductive Sigma (A:Set)(B:A -> Set) :Set :=
  Spair: forall a:A, forall b : B a,Sigma A B.

Definition E (A:Set)(B:A -> Set)
  (C: Sigma A B -> Set)
  (c: Sigma A B)
  (d: (forall x:A, forall y:B x, 
      C (Spair A B x y))): C c :=

match c as c0 return (C c0) with
| Spair a b => d a b
end. 


(* Binary sum type *)

Inductive sum' (A B:Set):Set := 
inl': A -> sum' A B | inr': B -> sum' A B.

Print sum'_rect.

Definition D (A B : Set)(C: sum' A B -> Set)
(c: sum' A B)
(d: (forall x:A, C (inl' A B x)))
(e: (forall y:B, C (inr' A B y))): C c :=

match c as c0 return C c0 with
| inl' x => d x
| inr' y => e y
end.

(* Three useful finite sets *)

Inductive N_0: Set :=.

Definition R_0
  (C:N_0 -> Set)
  (c: N_0): C c :=
match c as c0 return (C c0) with
end.

Inductive N_1: Set := zero_1:N_1.

Definition R_1 
  (C:N_1 -> Set)
  (c: N_1)
  (d_zero: C zero_1): C c :=
match c as c0 return (C c0) with
  | zero_1 => d_zero
end.

Inductive N_2: Set := zero_2:N_2 | one_2:N_2.

Definition R_2 
  (C:N_2 -> Set)
  (c: N_2)
  (d_zero: C zero_2)
  (d_one: C one_2): C c :=
match c as c0 return (C c0) with
  | zero_2 => d_zero
  | one_2  => d_one
end.


(* Natural numbers *)

Inductive N:Set :=
zero: N | succ : N -> N.

Print N. 

Print N_rect.

Definition R 
  (C:N -> Set)
  (d: C zero)
  (e: (forall x:N, C x -> C (succ x))):
  (forall n:N, C n) :=
fix F (n: N): C n :=
  match n as n0 return (C n0) with
  | zero => d
  | succ n0 => e n0 (F n0)
  end.

(* Boolean to truth-value converter *)

Definition Tr (c:N_2) : Set :=
match c as c0 with
  | zero_2 => N_0
  | one_2 => N_1
end.

(* Identity type *)

Inductive I (A: Set)(x: A) : A -> Set :=
r :  I A x x.

Print I_rect.

Theorem J 
  (A:Set)
  (C: (forall x y:A, 
              forall z: I A x y, Set))
  (d: (forall x:A, C x x (r A x)))
  (a:A)(b:A)(c:I A a b): C a b c.
induction c.
apply d.
Defined.

(* functions are extensional wrt
  identity types *)

Theorem I_I_extensionality (A B: Set)(f: A -> B):
(forall x y:A, I A x y -> I B (f x) (f y)).
Proof.
intros x y P.
induction P.
apply r.
Defined.


(* addition *)

Definition add (m n:N) : N 
 := R (fun z=> N) m (fun x y => succ y) n.

(* multiplication *)

Definition mul (m n:N) : N 
 := R (fun z=> N) zero (fun x y => add y m) n.


(* Axioms of Peano verified *)

Theorem P1a: (forall x: N, I N (add x zero) x).
intro x.
(* force use of definitional equality
  by applying reflexivity *)
apply r.
Defined.


Theorem P1b: (forall x y: N, 
I N (add x (succ y)) (succ (add x y))).
intros.
apply r.
Defined.


Theorem P2a: (forall x: N, I N (mul x zero) zero).
intros.
apply r.
Defined.


Theorem P2b: (forall x y: N, 
I N (mul x (succ y)) (add (mul x y) x)).
intros.
apply r.
Defined.

Definition pd (n: N): N :=
R (fun _=> N) zero (fun x y=> x) n.

(* alternatively
Definition pd (x: N): N :=
match x as x0 with
  | zero => zero
  | succ n0 => n0
end.
*)

Theorem P3: (forall x y:N, 
I N (succ x) (succ y) -> I N x y).
intros x y p.
apply (I_I_extensionality N N pd (succ x) (succ y)).
apply p.
Defined.

Definition not (A:Set): Set:= (A -> N_0).

Definition isnonzero (n: N): N_2:=
R (fun _ => N_2) zero_2 (fun x y => one_2) n.


Theorem P4 : (forall x:N, 
not (I N (succ x) zero)).
intro x.
intro p.

apply (J N (fun x y z => 
    Tr (isnonzero x) -> Tr (isnonzero y))
    (fun x => (fun t => t)) (succ x) zero)
.
apply p.
simpl.
apply zero_1.
Defined.

Theorem P5 (P:N -> Set):
P zero -> (forall x:N, P x -> P (succ x))
   -> (forall x:N, P x).
intros base step n.
apply R.
apply base.
apply step.
Defined.

(* I(A,-,-) is an equivalence relation *)

Lemma Ireflexive (A:Set): (forall x:A, I A x x).
intro x.
apply r.
Defined.

Lemma Isymmetric (A:Set): (forall x y:A, I A x y -> I A y x).
intros x y P.
induction P.
apply r.
Defined.

Lemma Itransitive (A:Set): 
(forall x y z:A, I A x y -> I A y z -> I A x z).
intros x y z P Q.
induction P.
assumption.
Defined.


Lemma succ_cong : (forall m n:N, I N m n -> I N (succ m) (succ n)).
intros m n H.
induction H.
apply r.
Defined.

Lemma zeroadd: (forall n:N, I N (add zero n) n).
intro n.
induction n.
simpl.
apply r.
apply succ_cong.
auto.

Defined.

Lemma succadd: (forall m n:N, I N (add (succ m) n) (succ (add m n))).
intros.
induction n.
simpl.
apply r.
simpl.
apply succ_cong.
auto.

Defined.

Lemma commutative_add: (forall m n:N, I N (add m n) (add n m)).
intros n m; elim n.
apply zeroadd.
intros y H; elim (succadd m y).
simpl.
rewrite succadd.
apply succ_cong.
assumption.


Defined.

Lemma associative_add: (forall m n k:N, 
I N (add (add m n) k) (add m (add n k))).
intros m n k.
induction k.
simpl.
apply Ireflexive.
simpl.
apply succ_cong.
assumption.
Defined.

Definition or (A B : Set):= sum' A B.


Definition less (m n: N) :=
 Sigma N (fun z => I N (add m (succ z)) n).



Lemma less_lem (x y:N) : 
less x (succ y) -> or (less x y) (I N x y).
intro.
destruct H.
right.

(* Here is where I'm working right now *)

Defined.


Theorem Ntrichotomy: (forall x y:N, 
or (less x y) (or (I N x y) (less y x))).

3
यह समझने के लिए कि आपको कितनी दूर मिली है, यह मदद करेगा यदि आप अपना Coq कोड अब तक पोस्ट करेंगे, ताकि हम इसे लोड कर सकें और जांच सकें कि हम आपकी परिभाषाओं के लिए क्या काम करते हैं।
गिल्स एसओ- बुराई को रोकना '

1
टिप्पणियों और स्पष्ट प्रश्नों की एक जोड़ी: - क्या यह आपके उद्देश्यों के लिए पर्याप्त होगा कि मैं (एन, एक्स, वाई) के बजाय सिंटिक समानता ("=" कोक में) का उपयोग करूं? क्या आपके द्वारा इसे परिभाषित करने के तरीके का उपयोग करने का कोई कारण है? Coq (ठीक है, Coq के लिए बुनियादी पुस्तकालयों) में अभिव्यक्ति का एक तरीका तार्किक असंतोष है जो सबूत के कुछ अच्छे पहलुओं की सुविधा देता है। इसी तरह 'कम' को परिभाषित करने का एक तरीका है जो आपके लिए अधिक व्यावहारिक हो सकता है। इसके लिए आप सॉफ़्टवेयर फ़ाउंडेशन के शुरुआती अध्यायों पर एक नज़र डालना चाहते हैं । जबकि पुस्तक का अंत ...
ल्यूक मैथिसन

... कार्यक्रमों आदि का सत्यापन करने के बारे में है, शुरुआत कोक के लिए एक अच्छा परिचय है, और आपके पास अभ्यास और उदाहरणों की तरह प्रमेय हैं। यह मुफ़्त है, और यह वास्तव में सभी कोक स्क्रिप्ट के रूप में लिखा गया है, इसलिए आप अभ्यास कर सकते हैं और उन्हें संकलित कर सकते हैं जैसे आप पढ़ रहे हैं। आप यहाँ क्या कर रहे हैं, इसके लिए अध्यायों में दिलचस्प बिट्स और टुकड़े हैं। मूल बातें, इंडक्शन, प्रोप और लॉजिक - और शायद बिट इनबेटीइन से कुछ निर्भरताएँ।
ल्यूक मैथिसन

1
एक और नोट, Thm P5 (आगमनात्मक सिद्धांत) कोक में एक मजबूत रूप (संरचनात्मक प्रेरण) के लिए बनाया गया है, इसलिए आपको स्पष्ट रूप से एक स्वयंसिद्ध रूप में लेने की आवश्यकता नहीं है।
ल्यूक मैथिसन

मैंने अभी तक जो Coq कोड लिखे हैं, उन्हें मैंने पोस्ट किया है।
user11942

जवाबों:


7

कोक कागज के प्रमाणों की तुलना में थोड़ा अधिक क्रूर है: जब आप लिखते हैं "और हम कागज़ के प्रमाण में" या "स्पष्ट रूप से" किए जाते हैं, तो कोक को समझाने के लिए अक्सर बहुत कुछ करना पड़ता है।

अब मैंने आपके कोड को थोड़ा साफ कर दिया, जबकि उसी भावना में रखने की कोशिश कर रहा था। आप इसे यहाँ पा सकते हैं ।

कई टिप्पणियाँ:

  1. मैंने डेटाटाइप्स और परिभाषाओं में निर्मित का उपयोग किया, जहां मुझे लगा कि यह आपके इरादे को चोट नहीं पहुंचाएगा। ध्यान दें कि अगर मैंने इसके बजाय अंतर्निहित समानता का उपयोग किया था identityऔर "कम-से-कम" संबंध में बनाया गया था, तो सबूत बहुत आसान हो जाते थे, क्योंकि आपके कई नींबू ज्ञात प्रमेयों के डेटाबेस में हैं, जिन्हें आपके प्रत्येक कॉल पर जांचा जाता है।

    auto with arith.
    
  2. मैंने कुछ ऐसे टैक्टिक्स का इस्तेमाल किया जिनके बारे में आप शायद नहीं जानते, लेकिन एक "वास्तविक" कोक सुपर-यूज़र के हाथ में बहुत अधिक शक्तिशाली रणनीति होगी और नौकरी को आसान बनाने के लिए उसने खुद की रणनीति लिखी। मैं हमेशा CPDT को एक शक्तिशाली तरीके से रणनीति का उपयोग करने के बारे में जानने के लिए सलाह देता हूं ।

  3. मैंने पठनीयता में सुधार करने के लिए नोटेशन और टैबिंग का इस्तेमाल किया और मिलान inductionऔर फिर से कारक को आसान बनाने के लिए मिलान और रणनीति जैसे निर्माणों का निर्माण किया । विशेष रूप से, आपकी परिभाषा के lessसाथ काम करना कठिन था, आप देख सकते हैं कि कैसे मैंने इसे से समतुल्य रूप से संशोधित किया है के बराबर (लेकिन उपयोग करने में आसान) इस तरह का "डेफिनिशन ट्विकिंग" औपचारिक प्रमाणों में बहुत कुछ होता है ।

    x, m+(x+1)=n
    x, (x+m)+1=n
  4. जब आप यहां इस प्रकार के प्रश्नों के उत्तर प्राप्त कर सकते हैं, तो मैं आपको अत्यधिक सलाह देता हूं कि आप अपने काम को कोक-क्लब में प्रस्तुत करें, जो इस प्रकार के प्रश्नों के उत्तर देने के उद्देश्य से बनाया गया था।


1
महान जवाब कोडी! यह सीखना अद्भुत है कि आप जैसे उदार लोग वहाँ हैं, जो दूसरों की ज़रूरत में मदद करने को तैयार हैं। मैं ईमानदारी से इसकी सराहना करता हूं! मैं निश्चित रूप से सीपीडीटी और कोक-क्लब पर एक नज़र डालूंगा; इन दोनों की मुझे निकट भविष्य में सबसे अधिक आवश्यकता होगी क्योंकि मैं Coq में डिवीजन एल्गोरिदम को साबित करने की दिशा में काम करना जारी रखूंगा।
user11942

धन्यवाद! ध्यान दें कि इसे अक्सर "यूक्लिडियन डिवीजन" कहा जाता है और पहले से ही कुछ पुस्तकालयों में मौजूद है (हालांकि पूर्णांक से अधिक)
कोडी

यह मुझे आश्चर्यचकित नहीं करता है, मैंने जिन कॉक्स पुस्तकालयों को देखा है उनमें उल्लेखनीय रूप से परिभाषाओं, नींबू और प्रमेयों के साथ अच्छी तरह से स्टॉक किया गया है। मैं कल तक एक प्रश्न के रूप में यूक्लिडियन डिवीजन एल्गोरिथ्म में अपना दृष्टिकोण पोस्ट करना चाहूंगा।
user11942

4

कोडी का उत्तर उत्कृष्ट है, और अपने सबूत कोक में अनुवाद करने के बारे में आपके प्रश्न को पूरा करता है। उसी के पूरक के रूप में, मैं एक ही परिणाम जोड़ना चाहता था, लेकिन एक अलग मार्ग का उपयोग करके साबित कर दिया, मुख्य रूप से कुछ बिट्स कॉक के चित्रण के रूप में और यह प्रदर्शित करने के लिए कि आप बहुत कम अतिरिक्त काम के साथ वाक्यविन्यास साबित कर सकते हैं। हालांकि यह दावा नहीं है कि यह सबसे छोटा रास्ता है - बस एक अलग है। सबूतों में केवल एक अतिरिक्त सहायक लम्मा शामिल है, और केवल मूल परिभाषाओं पर भरोसा करते हैं, मैं इसके अलावा गुणन, या उनके किसी भी गुण, या कार्यात्मक बाह्यता का परिचय नहीं देता हूं, और केवल Peano स्वयंसिद्ध <= b -> का एक सरल रूप है हेल्पर लेम्मा (सिर्फ सी = 1) और संरचनात्मक प्रेरण में ए + सी <= बी + सी, जो वैसे भी मुफ्त में आगमनात्मक प्रकार के साथ आता है।

कोडी की तरह, जहां मुझे लगा कि इससे कोई फर्क नहीं पड़ता, मैंने पूर्वनिर्धारित प्रकारों आदि का इस्तेमाल किया, इसलिए सबूत से पहले, मैं उन का वर्णन करूंगा:

  • मैंने नैट प्रकार में प्राकृतिक नंबरों के लिए उपयोग किया है, जिसमें आपके पास एक ही परिभाषा (सटीक नामकरण तक) है:

आगमनात्मक nat: सेट: = O: nat | स: नट -> नट

  • मैंने बिल्ट एंड लेट का उपयोग क्रमशः और उससे कम या बराबर और उससे कम के लिए किया है, जिसमें पठनीयता के लिए "<=" और "<" उल्लेखनीय रूप से शॉर्टहैंड हैं। उन्हें परिभाषित किया गया है:

आगमनात्मक ले: nat -> nat -> Prop: =
| le_n: forall n, le nn
| le_S: forall nm, (le nm) -> (le n (S m))।

तथा

परिभाषा lt (nm: nat): = le (S n) m।

  • ईक (शॉर्टहैंड "=") में निर्मित सिंटैक्टिक समानता है और आपके "आई" के समान ही काम करता है, एक निर्माणकर्ता के साथ जो बस कुछ भी कहता है वह स्वयं के बराबर है। सममित और सकर्मक गुण वहाँ से आसान साक्ष्य हैं, लेकिन हमें इस मामले में उनकी आवश्यकता नहीं होगी। नीचे eq के लिए परिभाषा में बनाया गया संकेतन है।

आगमनात्मक eq (A: टाइप) (x: A): A -> Prop: = eq_refl: x = x

  • अंत में, मैंने प्रस्ताव (या शॉर्टहैंड "\ /" - जो कि बैकस्लैश फॉरवर्डलैश है) का उपयोग किया है, जिसमें दो निर्माता हैं, मूल रूप से या तो आपके पास बाएं तर्क के लिए सबूत हैं, या सही तर्क हैं। Coq में कुछ शॉर्टहैंड टैक्टिक्स भी हैं, बाएं और दाएं, जिसका मतलब है "क्रमशः or_introl" और "apply or_intror"।

आगमनात्मक या (AB: प्रोप): Prop: =
or_introl: A -> A / B | or_intror: बी -> ए / बी

अब इस प्रकार मेरे प्रमाण हैं, सिद्धांत रूप में, यदि मार्कअप रास्ते में नहीं आता है, तो आपको इसे Coq .v फ़ाइल में बस कट और पेस्ट करने में सक्षम होना चाहिए और यह काम करेगा। मैंने दिलचस्प बिट्स को नोट करने के लिए टिप्पणियां शामिल की हैं, लेकिन वे (* *) सीमांकक हैं, इसलिए आपको उन्हें निकालना नहीं चाहिए।

Theorem lt_or_eq: forall (n m : nat),
  n < S m -> n < m \/ n = m.
Proof.
(*
  This proof is just a case analysis on n and m, whether they're zero or
  a successor of something.
*)
destruct n as [|n']; destruct m as [|m']. 

(*n = 0, m = 0*)
intros.
  right. reflexivity.

(*n = 0, m = S m'*)
intros H.
  inversion H.
  inversion H1.
  left. unfold lt. constructor.
  (*The constructor tactic tries to match the goal to a constructor
    that's in the environment.*) 
  left. unfold lt. constructor. assumption.
  (*Assumption tries to match the goal to something that's in the
    current context*)

(*n = S n', m = 0
  This case is false, so we can invert our way out of it.*)
intros.
  inversion H. inversion H1.

(*n = S n', m = S m'*)
intros.
  inversion H.
    right. reflexivity.
    left. unfold lt. assumption.
Qed.


(*
  The following lemma with be useful in the proof of the trichotomy theorem,
  it's pretty obviously true, and easy to prove. The interesting part for
  anyone relatively new to Coq is that the induction is done on the
  hypothesis "a <= b", rather than on either a or b.
*)
Lemma a_le_b_implies_Sa_le_Sb: forall a b, a <= b -> S a <= S b.
Proof.
  intros a b Hyp.
  induction Hyp.
  constructor.
  constructor.
  apply IHHyp.
Qed.

(*
  The proof of the trichotomy theorem is a little more involved than the
  last one but again we don't use anything particularly tricky. 
  Other than the helper lemma above, we don't use anything other than the
  definitions.

  The proof proceeds by induction on n, then induction on m.  My personal
  feeling is that this can probably be shortened.  
*)
Theorem trich: forall (n m : nat),
  n < m \/ n = m \/ m < n.
Proof.
  induction n.
    induction m.
      right. left. reflexivity.
        inversion IHm.
          left. unfold lt. constructor. unfold lt in H. assumption.
          inversion H.
          left. unfold lt. subst. constructor.
          inversion H0.     
    induction m.
      assert (n < 0 \/ n = 0 \/ 0 < n).
      apply IHn.
      inversion H.
      inversion H0.
      inversion H0.
      right. right. subst. unfold lt. constructor.
      right. right. unfold lt. constructor. assumption.
      inversion IHm. unfold lt in H.
      left. unfold lt. constructor. assumption.
      inversion H; subst.
      left. unfold lt. constructor.
      inversion H0.
      right. left. reflexivity.
      right. right. apply lt_or_eq in H0.

      inversion H0.
      apply a_le_b_implies_Sa_le_Sb. assumption.
      subst. unfold lt. apply a_le_b_implies_Sa_le_Sb. assumption.
Qed.

(*
  The following is just to show what can be done with some of the tactics
  The omega tactic implements a Pressburger arithmetic solver, so anything
  with natural numbers, plus, multiplication by constants, and basic logic
  can just be solved. Not very interesting for practicing Coq, but cool to
  know.
*)

Require Import Omega.

Example trich' : forall (n m : nat),
  n < m \/ n = m \/ m < n.
Proof.
  intros.
  omega.
Qed.

एक और अद्भुत जवाब! आपने मेरे प्रश्न का उत्तर देने में जो समय और मेहनत लगाई है, उसके लिए मैं वास्तव में आपका आभारी हूं।
user11942
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.