我已经将我的命题公式定义如下:
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.
答案 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中的不变性;也就是说,如果f1
和f2
在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.