Структурная рекурсия по двум аргументам

#coq

#coq

Вопрос:

Я попытался создать функцию в Coq, которая имеет довольно сложный аргумент завершения. Чтобы упростить задачу, я могу написать функцию так, чтобы она имела натуральное число в качестве первого аргумента, так что либо число, либо аргумент после него структурно меньше.

При попытке вложенного подхода к исправлению рекурсии по двум аргументам Coq жалуется, что аргумент доказательства, содержащий семантику уменьшающегося числа, не является индуктивным типом.

Вероятно, я мог бы выполнить обоснованную рекурсию вручную, но я хотел бы использовать программную точку фиксации или уравнения. С помощью Program Fixpoint я получаю очень уродливую версию доказательства обоснованности. Ниже приведен минимальный пример кода, который демонстрирует уродство.

 Require Import Program Omega.

Inductive tuple_lt : (nat * nat) -> (nat * nat) -> Prop :=
  fst_lt : forall a b c d, a < c -> tuple_lt (a, b) (c, d).

Program Fixpoint f (a : nat) (b : nat) {measure (a, b) (tuple_lt)} :=
match a with
| 0 => 0
| S n => f n b
end.

Next Obligation.
apply fst_lt. auto.
Qed.

Next Obligation.
unfold well_founded. unfold MR.
 

Обязательство выглядит следующим образом:

 forall a : {_ : nat amp; nat}, Acc (fun x y : {_ : nat amp; nat} => tuple_lt (projT1 x, projT2 x) (projT1 y, projT2 y)) a
 

Могу ли я каким-то образом преобразовать доказательство Acc tuple_lt в это уродливое доказательство или избежать его генерации?

Есть ли в стандартной библиотеке доказательство для структурной рекурсии по двум аргументам?

Как мне вообще написать ручное доказательство WF с использованием уравнений? В руководстве это не упоминается.

Комментарии:

1. Я ответил на главный вопрос поста. Я не комментировал второй абзац, который я не понимаю, и я также не занимался уравнениями.

2. Что касается случая с уравнениями, у вас может быть что-то вроде следующего (не уверен, правильно ли я понял, но это ваше решение вашей исходной проблемы, верно?): Equations foo p1 p2 : return_type by wf (size1 p1 size2 p2) := Таким образом, в основном у вас есть меры для каждого параметра, который, по вашему мнению, уменьшится ( size1 и size2 ), и просто проверьте сумму (или вы можете сделать что-то более запутанное, если хотите …). Уравнения, как правило, автоматически проверяют, что рекурсивные вызовы в порядке (в противном случае вы должны это доказать).

Ответ №1:

В простых случаях, подобных этому, вам не нужно разворачивать определения, такие как well_founded и MR , а использовать соответствующие леммы.

Чтобы разобраться с MR этим, вы можете использовать лемму measure_wf в Program.Wf .

Чтобы доказать обоснованность tuple_lt , вы можете полагаться на леммы, показывающие обоснованность отношения, основанного на обоснованности другого отношения. Здесь мы можем использовать well_founded_lt_compat . В других случаях могут оказаться полезными другие леммы, такие как wf_inverse_image , well_founded_ltof или well_founded_gtof .

Доказательство обоснованности tuple_lt становится простым.

 Lemma tuple_lt_wf : well_founded tuple_lt.
Proof.
  apply well_founded_lt_compat with fst.
  intros ? ? []; assumption.
Defined.
 

То же самое относится и к доказательству второго обязательства.

 Next Obligation.
apply measure_wf. apply tuple_lt_wf.
Defined.
 

(Обратите внимание, что в обоих случаях вы должны заканчивать доказательства с Defined помощью вместо Qed , если вы хотите, чтобы ваша функция, определенная с помощью Program Fixpoint , вычислялась внутри Coq (в противном случае она застревает на непрозрачных доказательствах); кажется, вы можете закончить доказательство первого обязательства с Qed помощью , хотя).

Вы также можете использовать следующее более простое определение для tuple_lt :

 Definition tuple_lt (p1 p2 : nat * nat) := fst p1 < fst p2.
 

В этом случае доказательство обоснованности тривиально.

 Lemma tuple_lt_wf : well_founded tuple_lt.
Proof.
  apply well_founded_ltof.
Defined.
 

Комментарии:

1. Похоже, measure_wf было тем, чего мне не хватало. Я попробую это позже сегодня.

2. tuple_lt является сложным, потому что мой фактический код сравнивает обе стороны.

3. Вы также можете показать, что лексикографический порядок обоснован, учитывая, что два порядка, на которых он основан, также обоснованы.