Как делать случаи с индуктивным типом в Coq - PullRequest
8 голосов
/ 26 июля 2011

Я хочу использовать тактику destruct, чтобы доказать утверждение делами.Я прочитал несколько примеров в Интернете, и я в замешательстве.Может ли кто-нибудь объяснить это лучше?

Вот небольшой пример (есть и другие способы решения, но попробуйте использовать destruct):

 Inductive three := zero 
                  | one 
                  | two.
 Lemma has2b2: forall a:three, a<>zero /\ a<>one -> a=two.

Теперь некоторые примеры в Интернете предлагают сделать следующее:

intros. destruct a.

В этом случае я получаю:

3 subgoals H : zero <> zero /\ zero <> one
______________________________________(1/3) 
zero = two

______________________________________(2/3) 
one = two

______________________________________(3/3) 
two = two

Итак, я хочу доказать, что первые два случая невозможны.Но машина перечисляет их как подцели и хочет, чтобы я ДОКАЗАЛ их ... что невозможно.

Резюме: Как точно отбросить невозможные случаи?

Я видел несколько примеров, используя inversion но я не понимаю процедуру.

Наконец, что произойдет, если моя лемма зависит от нескольких индуктивных типов, и я все еще хочу охватить ВСЕ случаи?

Ответы [ 2 ]

9 голосов
/ 26 июля 2011

Как отбросить невозможные случаи? Что ж, это правда, что первые два обязательства невозможно доказать, но обратите внимание, что они имеют противоречивые предположения (zero <> zero и one <> one, соответственно). Таким образом, вы сможете доказать эти цели с помощью tauto (есть также более примитивная тактика, которая поможет вам, если вы заинтересованы).

inversion - более продвинутая версия destruct. В дополнение к «разрушению» индуктивности, она иногда генерирует некоторые равенства (которые могут вам понадобиться). Само по себе это простая версия induction, которая дополнительно создаст для вас гипотезу индукции.

Если у вас есть несколько индуктивных типов в вашей цели, вы можете destruct/invert их один за другим.

Более подробное описание:

Inductive three := zero | one | two .

Lemma test : forall a, a <> zero /\ a <> one -> a = two.
Proof.
  intros a H.
  destruct H. (* to get two parts of conjunction *)
  destruct a. (* case analysis on 'a' *)
(* low-level proof *)
  compute in H. (* to see through the '<>' notation *)
  elimtype False. (* meaning: assumptions are contradictory, I can prove False from them *)
  apply H.
  reflexivity.
(* can as well be handled with more high-level tactics *)
  firstorder.
(* the "proper" case *)
  reflexivity.
Qed.
8 голосов
/ 26 июля 2011

Если вы видите невозможную цель, есть две возможности: либо вы допустили ошибку в своей стратегии доказательства (возможно, ваша лемма ошибочна), либо гипотезы противоречивы.

Если вы считаете, что гипотезыпротиворечиво, вы можете установить цель на False, чтобы немного усложнить ситуацию.elimtype False достигает этого.Часто вы доказываете False, доказывая предложение P и его отрицание ~P;Тактика absurd P выводит любую цель из P и ~P.Если есть конкретная гипотеза, которая является противоречивой, contradict H установит цель на ~H, или если гипотеза будет отрицанием ~A, тогда цель будет A (сильнее ~ ~A, но обычно более удобной),Если одна конкретная гипотеза явно противоречива, contradiction H или просто contradiction докажут какую-либо цель.

Существует множество тактик, включающих гипотезы индуктивных типов.Выяснение того, какой из них использовать, в основном зависит от опыта.Вот основные из них (но вы столкнетесь с случаями, которые здесь не рассматриваются в ближайшее время):

  • destruct просто разбивает гипотезу на несколько частей.Он теряет информацию о зависимостях и рекурсии.Типичным примером является destruct H, где H - это соединение H : A /\ B, которое разбивает H на две независимые гипотезы типов A и B;или дважды destruct H, где H - это дизъюнкция H : A \/ B, которая разбивает доказательство на две разные подпространства: одно с гипотезой A и одно с гипотезой B.
  • case_eqаналогично destruct, но сохраняет связи, которые гипотеза имеет с другими гипотезами.Например, destruct n, где n : nat разбивает доказательство на два подкрепления, одно для n = 0 и одно для n = S m.Если n используется в других гипотезах (т. Е. У вас есть H : P n), вам может потребоваться помнить, что уничтоженный вами n - это то же самое, что n, использованное в этих гипотезах: case_eq n делает это.
  • inversion выполняет анализ случая по типу гипотезы.Это особенно полезно, когда в типе гипотезы есть зависимости, которые destruct забудет.Обычно вы используете case_eq для гипотез в Set (где имеет место равенство) и inversion для гипотез в Prop (которые имеют очень зависимые типы).Тактика inversion оставляет много равных, и за ней часто следует subst для упрощения гипотез.Тактика inversion_clear - это простая альтернатива inversion; subst, но она теряет немного информации.
  • induction означает, что вы собираетесь доказать цель по индукции (= рекурсия) по данной гипотезе.Например, induction n, где n : nat означает, что вы выполните целочисленную индукцию и докажете базовый случай (n заменен на 0) и индуктивный случай (n заменен на m+1).

Ваш пример настолько прост, что вы можете доказать его как «очевидный по анализу кейсов на a».

Lemma has2b2: forall a:three, a<>zero/\a<>one ->a=two.
Proof. destruct a; tauto. Qed.

Но давайте посмотрим на кейсы, сгенерированные destructтактика, т.е. только после intros; destruct a..(Случай, когда a равен one, является симметричным; последний случай, когда a равен two, очевиден по рефлексивности.)

H : zero <> zero /\ zero <> one
============================
 zero = two

Цель выглядит невозможной.Мы можем сказать это Coq, и здесь он может обнаружить противоречие автоматически (zero=zero очевидно, а остальное - тавтология первого порядка, обработанная тактикой tauto).

elimtype False. tauto.

Inфакт tauto работает, даже если вы не начнете с того, что говорите Coq, чтобы он не беспокоился о цели, и написали tauto без elimtype False первым (IIRC это не делало в более старых версиях Coq).Вы можете увидеть, что делает Coq с тактикой tauto, написав info tauto.Coq скажет вам, какой сценарий доказательства генерирует тактика tauto.Это не очень легко понять, поэтому давайте посмотрим на ручное доказательство этого случая.Во-первых, давайте разделим гипотезу (которая является соединением) на две части.

destruct H as [H0 H1].

Теперь у нас есть две гипотезы, одна из которых zero <> zero.Это явно неверно, потому что это отрицание zero = zero, что совершенно верно.

contradiction H0. reflexivity.

Мы можем взглянуть еще более подробно на то, что делает тактика contradiction.(info contradiction покажет, что происходит под сценой, но опять же это не для новичков).Мы утверждаем, что цель верна, потому что гипотезы противоречивы, поэтому мы можем доказать что угодно.Итак, давайте установим промежуточную цель на False.

assert (F : False).

Запустите red in H0., чтобы увидеть, что zero <> zero действительно обозначение для ~(zero=zero), которое, в свою очередь, определяется как значение zero=zero -> False.Итак, False является выводом H0:

apply H0.

И теперь нам нужно доказать, что zero=zero, то есть

reflexivity.

Теперь мы доказали наше утверждениеFalse.Осталось доказать, что False подразумевает нашу цель.Ну, False подразумевает любую цель, это ее определение (False определяется как индуктивный тип с 0 регистром).

destruct F.
...