如何在Coq中将命题公式转换为DNF

时间:2016-02-19 14:38:42

标签: normalization coq

我已经将我的命题公式定义如下:

Inductive propForm : Set :=
| top : propForm
| bot : propForm
| var : propVar -> propForm
| orp : propForm -> propForm -> propForm
| andp : propForm -> propForm -> propForm.

我正在尝试定义一个函数,用于将命题公式转换为DNF中的一个。为此,我定义了一个使用分配律来分配术语的函数:

Fixpoint distribute (f:propForm) : propForm -> propForm :=
fix distribute1 (g:propForm) : propForm :=
match f with
| f1 \/p f2 => match g with
            | g1 \/p g2 => distribute1 g1 \/p distribute1 g2
            | _ => distribute f1 g \/p distribute f2 g
            end
| _ => match g with
       | g1 \/p g2 => distribute1 g1 \/p distribute1 g2
       | _ => f /\p g
       end
end.

此功能正常。但是,我仍然需要定义一个将命题公式转换为DNF的函数。以下函数可以实现我想要的功能,但Coq不接受它,因为对于最后一种情况,函数在f'中的结构没有减少。任何提示和技巧将不胜感激。

Fixpoint toDNF (f':propForm):propForm :=
match f' with
| top => f'
| bot => f'
| var _ => f'
| f1 \/p f2 => toDNF f1 \/p toDNF f2
| f1 /\p f2 => toDNF (distribute f1 f2)
end.

1 个答案:

答案 0 :(得分:2)

您的函数是从半环中规范化表达式的特殊情况。我写了一个post解释如何使用Ssreflect和MathComp库在算术表达式的情况下这样做,但我会在这里包含一个更直接的答案。

一个想法是使用列表列表来表示DNF中的公式:毕竟,它们只是一个析取列表的组合,它们只是文字列表。然后,您可以重用列表库来编写函数:

Module Sol1.

Require Import Coq.Lists.List.
Import ListNotations.

Notation propVar := nat.

Inductive propAtom :=
| top | bot | var :> propVar -> propAtom.

Inductive propForm : Set :=
| atom :> propAtom -> propForm
| orp : propForm -> propForm -> propForm
| andp : propForm -> propForm -> propForm.

Definition dnfForm := list (list propAtom).

Fixpoint andd (f1 f2 : dnfForm) : dnfForm :=
  match f1 with
  | [] =>
    (* false && f2 = false *)
    []
  | cf :: f1 =>
    (* (cf || f1) && f2 = cf && f2 || f1 && f2 *)
    map (app cf) f2 ++ andd f1 f2
  end.

Fixpoint toDNF (f : propForm) : dnfForm :=
  match f with
  | atom a => [[a]]
  | orp f1 f2 => toDNF f1 ++ toDNF f2
  | andp f1 f2 => andd (toDNF f1) (toDNF f2)
  end.

Compute (toDNF (andp (orp 3 4) (orp 1 2))).

End Sol1.

这里有两点需要注意。首先,我将变量和常量分解为单独的propAtom类型,并且我调用了distribute andd,因为您可以将其视为计算DNF中两个表达式的AND。

这是另一种基于原始代码的解决方案。您的distribute函数似乎保留了在DNF中的不变性;也就是说,如果f1f2在DNF中,那么distribute f1 f2也是如此。因此,您只需按顺序拨打电话:

Module Sol2.

Notation propVar := nat.

Inductive propForm : Set :=
| top : propForm
| bot : propForm
| var :> propVar -> propForm
| orp : propForm -> propForm -> propForm
| andp : propForm -> propForm -> propForm.

Fixpoint distribute (f:propForm) : propForm -> propForm :=
fix distribute1 (g:propForm) : propForm :=
match f with
| orp f1 f2 => match g with
            | orp g1 g2 => orp (distribute1 g1) (distribute1 g2)
            | _ => orp (distribute f1 g) (distribute f2 g)
            end
| _ => match g with
       | orp g1 g2 => orp (distribute1 g1) (distribute1 g2)
       | _ => andp f g
       end
end.

Fixpoint toDNF (f':propForm):propForm :=
match f' with
| top => f'
| bot => f'
| var _ => f'
| orp f1 f2 => orp (toDNF f1) (toDNF f2)
| andp f1 f2 => distribute (toDNF f1) (toDNF f2)
end.

Compute (toDNF (andp (orp 3 4) (orp 1 2))).

End Sol2.