Принцип индукции, генерируемый Coq, ведет себя не так, как я хочу
Отредактировано для понятности
Я пытаюсь доказать свойства дерева особого типа. Это дерево похоже на следующее. Проблема в том, что принцип индукции, сгенерированный Coq, недостаточен для доказательства свойств дерева. Для более простого примера, скажем, следующий тип описывает все мои "деревья":
Inductive prv_tree(E:BES) : statement -> Prop :=
| REFL (G:propVar_relation)(a:Prop) :
prv_tree E (G |- a ---> a)
| TRA (G:propVar_relation) (a b c:Prop) :
prv_tree E (G |- a ---> b) -> prv_tree E (G |- b ---> c) ->
prv_tree E (G |- a ---> c).
Затем, чтобы доказать правильность всех деревьев (скажем, для импликации), мне нужно доказать следующую лемму:
Lemma soundness: forall E:BES, forall f g:Prop, forall R G:propVar_relation,
(prv_tree E (G |- f ---> g)) -> (E,G,R |= f --> g).
Для чего мне нужно применить индукцию на структуру дерева. Однако, если я сделаю intros;induction H.
тогда первая подзадача (E,G,R |= f --> g)
т.е. информация о требуемой структуре f и g теряется (хотелось бы (E,G,R |= a --> a)
). (Также для индуктивного случая гипотеза индукции утверждает, (E,G,R |= f --> g)
что странно для меня).
Еще один подход, который я попробовал, это вспомнить (G |- f ---> g)
, чтобы сохранить структуру f и g доступной. Доказательство тогда продолжается как intros;remember (G |- f --> g) as stmt in H.induction H.
Затем я получаю цели и условия, которые я ожидаю для своих базовых случаев. Однако для доказательства случая TRA я получаю следующий контекст доказательства:
H : prv_tree E (G0 |- a --> b)
H0 : prv_tree E (G0 |- b --> c)
IHprv_tree1 : G0 |- a --> b = G |- f --> g -> (E,G,R |= f --> g)
IHprv_tree2 : G0 |- b --> c = G |- f --> g -> (E,G,R |= f --> g)
В то время как я ожидаю, что гипотеза индукции будет
IHprv_tree1 : prv_tree E (G0 |- a --> b) -> (E,G,R |= a --> b)
IHprv_tree2 : prv_tree E (G0 |- b --> c) -> (E,G,R |= b --> c)
СТАРЫЙ ТЕКСТ
Я пытаюсь доказать свойства дерева особого типа. Это дерево может быть построено с использованием 21 различных правил (которые я не буду повторять здесь). Проблема в том, что принцип индукции, сгенерированный Coq, недостаточен для доказательства свойств дерева.
Дерево строится следующим образом
Inductive prv_tree (E:BES): (*BES ->*) statement -> Prop := .... (*constructors go here*).
Один из этих конструкторов
CTX: forall a b c:propForm, forall x:propVar, forall G:propVar_relation, (prv_tree E (makeStatement G a b) -> (prv_tree E (makeStatement G (replace c x a) (replace c x b))))
Моя цель - доказать
Lemma soundness: forall E:BES, forall f g:propForm, forall G:propVar_relation, forall tree:prv_tree E (makeStatement G f g), rel_cc_on_propForm E (cc_max E) G f g.
Для этого я помню
makeStatement G f g
в противном случае я теряю информацию о структуре f и g. Затем я применяю индукцию к дереву. Я доказал все случаи как отдельные леммы, которые я могу успешно использовать для базовых случаев. Однако для индуктивных случаев гипотеза об индукции, представленная мне Коком, непригодна.Например, для упомянутого выше конструктора CTX я получаю следующую индукционную гипотезу:
IHP {| context := G; stm_l := a; stm_r := b |} = {| context := empty_relation; stm_l := replace c x a; stm_r := replace c x b |} -> E, cc_max E |- replace c x a <,_ empty_relation replace c x b
который я не могу использовать. Вместо этого я хочу что-то вроде
IHP prv_tree E {| context := G; stm_l := a; stm_r := b |} -> E, cc_max E |- replace c x a <,_ empty_relation replace c x b
Может кто-нибудь объяснить мне, как это исправить? До сих пор я пытался определить свой собственный принцип индукции на prv_tree, однако это приводит к тем же проблемам, так что, возможно, я сделал это неправильно?
Утверждение для CTX в моем собственном принципе индукции следующее:
(forall a b c:propForm, forall x:propVar, forall G:propVar_relation, (prv_tree E {| context := G; stm_l := a; stm_r := b |} ) -> P {| context := G; stm_l := replace c x a; stm_r := replace c x b |})
2 ответа
Я думаю, что я понял вашу проблему, но мне пришлось заполнить весь ваш вопрос. Было бы проще, если бы вы придумали самостоятельный пример, как предложил @ejgallego.
Вот как я смоделировал вашу проблему:
Axiom BES : Type.
Axiom propVar_relation : Type.
Inductive statement :=
| Stmt : propVar_relation -> Prop -> Prop -> statement.
Notation "G |- a ---> b" := (Stmt G a b) (at level 50).
Inductive prv_tree(E:BES) : statement -> Prop :=
| REFL (G:propVar_relation)(a:Prop) :
prv_tree E (G |- a ---> a)
| TRA (G:propVar_relation) (a b c:Prop) :
prv_tree E (G |- a ---> b) -> prv_tree E (G |- b ---> c) ->
prv_tree E (G |- a ---> c).
Lemma soundness: forall (E: BES) (f g:Prop) (R G:propVar_relation),
(prv_tree E (G |- f ---> g)) -> R = R.
Действительно, мы сталкиваемся с теми же проблемами, что и те, которые вы описали в своем вопросе. Решение состоит в том, чтобы revert
после запоминания и перед выполнением индукции.
intros.
remember (G |- f ---> g) as stmt. revert f g R G Heqstmt.
induction H; intros.
Теперь гипотезы индукции все еще странные, но они должны работать.
Спасибо за помощь. В конце концов я нашел решение сам. Хитрость заключалась в определении вспомогательной функции h:statement -> Prop
, как и следовало ожидать по принципу индукции, и использовать эту функцию вместо (E,G,R |= f --> g)
,