mozart-oz中有限域编程读书笔记

 

mozart-oz自带文档:

《Finite Domain Constraint Programming in Oz. A Tutorial.》读书笔记

http://www.mozart-oz.org/documentation/fdt/index.html

watercloud @ xfocus.org 2004-4

先考虑据说是爱因斯坦在20世纪初出的这个谜语。他说世界上有98%的
人答不出来。

1、在一条街上,有5座房子,喷了5种颜色。
2、每个房里住着不同国籍的人
3、每个人喝不同的饮料,抽不同品牌的香烟,养不同的宠物。

问题是:谁养鱼?

提示: 1、英国人住红色房子
2、瑞典人养狗
3、丹麦人喝茶
4、绿色房子在白色房子左面
5、绿色房子主人喝咖啡
6、抽Pall Mall 香烟的人养鸟
7、黄色房子主人抽Dunhill 香烟
8、住在中间房子的人喝牛奶
9、 挪威人住第一间房
10、抽Blends香烟的人住在养猫的人隔壁
11、养马的人住抽Dunhill 香烟的人隔壁
12、抽Blue Master的人喝啤酒
13、德国人抽Prince香烟
14、挪威人住蓝色房子隔壁
15、抽Blends香烟的人有一个喝水的邻居

这个题在oz中非常容易就能获得答案!!!!!


约束编程中存在两个基本问题:约束传播和约束分配。
有限域中处理的通常为非负数,并且此类问题中oz中能处理的最大
数字为:134 217 726。

oz中用过程描述域限定,然后使用oz提供的搜索工具即可找到解。
过程规范如下:
proc {Script Root}
%% declare variables
in
%% post constraints
%% specify distribution strategy
end
其中Root代表问题的解存放变量,如果问题的解由多个变量构成,则
Root为record。
约束描述语法包括: ::: 指定记录中所有元素的取值范围; :: 指定
变量范围(用n#m表示);
=: 指定等式约束 ; =: 指定不等约束; >: <: >=: =<: ,
这些表达式都是FD模块中的部分功能的快捷方式。

过程中发布约束到问题解上用如下方法:
{FD.distribute ff Root} ff为最常用的发布策略,发布策略可参
考手册。 Root为问题解。

问题求解有下面两个oz标准过程实现:
{SearchAll Script ?Solutions}
{SearchOne Script ?Solutions}

查看搜索过程可用
{ExploreOne Script }
{ExploreAll Script }
来查看。
(Explor图中的图标可双击以查看搜索情况,三角形图标可展开)


3.2 问题:
变量D E M N O R S Y都是0-9的数字, 求其值使得如下等式成立:
SEND+MORE=MONEY

解:
declare Script Root in
proc {Script Root}
S E N D M O R Y in
sol(s:S e:E n:N d:D m:M o:O r:R y:Y)=Root
Root ::: 0#9
S =: 0
M =: 0
S*1000 + E*100 + N*10 + D + M*1000 + O*100 + R*10 + E
=: M*10000 + O*1000 + N*100 + E*10 +Y
{FD.distribute ff Root}
end
/* {ExploreAll Script} */
{Browse {SearchAll Script}}
这将获得一系列的答案,如:[sol(d:7 e:5 m:1 n:6 o:0 r:8 s:9 y:2)]


通过完整的FD模块约束传播定义上面的脚本等价于;
proc {Money Root}
S E N D M O R Y
in
Root = sol(s:S e:E n:N d:D m:M o:O r:R y:Y)
{FD.dom 0#9 Root}
{FD.distinct Root}
{FD.sum [S] '=:' 0}
{FD.sum [M] '=:' 0}
{FD.sumC
[1000 100 10 1 1000 100 10 1 ~10000 ~1000 ~100 ~10 ~1]
[ S E N D M O R E M O N E Y]
'=:'
0}
{FD.distribute ff Root}
end


first-class space是有限域计算的顶层空间,有点类似oz语

言执行中的top-level space,唯一不同的是top.. space在约

束条件不一致时时产成违例,而first-class space中则仅仅

产成一个普通的没有解的事件;另外first-classspace不能

写其父空间中的变量。


FD.distinct (creates a propagator)
FD.distribute (creates a distributor)

oz中支持 %注释一行 和 /* */构成的大段注释

最开始的问题和下面这个是等同的,4.3节:
Five men with different nationalities live in the first five
houses of a street. There are only houses on one side of the
street. The men practice distinct professions, and each of
them has a favorite drink and a favorite animal, all of them
different. The five houses are painted with different colors.
The following facts are known:
The Englishman lives in a red house.
The Spaniard owns a dog.
The chinese is a painter.
The Italian drinks tea.
The Norwegian lives in the first house.
The owner of the green house drinks coffee.
The green house comes after the white one.
The sculptor breeds snails.
The diplomat lives in the yellow house.
Milk is drunk in the third house.
The Norwegian's house is next to the blue one.
The violinist drinks juice.
The fox is in the house next to that of the doctor.
The horse is in the house next to that of the diplomat.
The zebra is in the white house.
One of the men drinks water.
Who lives where?

求解:
proc {Zebra Nb}
Groups = [ [english spanish chinese italian norwegian]
[green red yellow blue white]
[painter diplomat violinist doctor sculptor]
[dog zebra fox snails horse]
[juice water tea coffee milk] ]
Properties = {FoldR Groups Append nil}
proc {Partition Group}
{FD.distinct {Map Group fun {$ P} Nb.P end}}
end
proc {Adjacent X Y}
{FD.distance X Y '=:' 1}
end
in
%% Nb maps all properties to house numbers
{FD.record number Properties 1#5 Nb}
{ForAll Groups Partition}
Nb.english = Nb.red
Nb.spanish = Nb.dog
Nb.chinese = Nb.painter
Nb.italian = Nb.tea
Nb.norwegian = 1
Nb.green = Nb.coffee
Nb.green >: Nb.white
Nb.sculptor = Nb.snails
Nb.diplomat = Nb.yellow
Nb.milk = 3
{Adjacent Nb.norwegian Nb.blue}
Nb.violinist = Nb.juice
{Adjacent Nb.fox Nb.doctor}
{Adjacent Nb.horse Nb.diplomat}
Nb.zebra = Nb.white
{FD.distribute ff Nb}
end
求解结果为:
number(
blue:2 coffee:5 diplomat:3 doctor:4
dog:3 english:4 fox:5 green:5
horse:4 italian:2 chinese:5 juice:1
milk:3 norwegian:1 painter:5 red:4
sculptor:2 snails:2 spanish:3 tea:2
violinist:1 water:4 white:1 yellow:3
zebra:1
)

约束问题中得脚本也可以是由过程或函数返回的过程。

增加冗余的约束很多时候都能提高搜索性能。

X*X =: Y约束要求X和Y都必须在约束域中才能工作,

作为替代可以用FD.times


=====================================

翻译部分《参考手册》中系统模块部分的有限域模块

内容如下:

5.4 Telling domains
X :: 1#10 相当于 {FD.int 1#10 X}
sol(X Y Z) ::: 1#10 相当于: {FD.dom 1#10 sol(X Y Z)}
{FD.list I spec Ds} I: 列表中要约束的元素长度 spec为范围,
如1#10,Ds为列表变量
{FD.tuple L I spec Dt} L为tuple的label
{FD.record L Ls spec Dr} LS为feature list
{FD.decl D} 相当于: {FD.int 0$FD.sup D}

FD.inf 为约束域的最低值:0
FD.sup ... 大值:目前为:134 217 726


5.7 Generic Propagators
{FD.sum *Dv +A *D}
调用格式如:{FD.sum [ X Y Z ] '>:' 8} Dv为操作数,A为约束

,D为目标值
sum操作为求列表的累加值。
{FD.sumC +Iv *Dv +A *D} :约束累加 Ii * Di 后的值
{FD.sumCN +Iv *Dvv +A *D} Dvv为多维列表,约束 累加 Ii*(Dij j=1..Max)
{FD.sumAC +Iv *Dv +A *D} sumAC中A指绝对值 C值称值
{FD.sumACN +Iv *Dvv +A *D} sumACN中 N指多维列表
FD.sumD和FD.sumCD指支持 '=:'和 '=:'操作。

{FD.distinct *Dv} 所有Dv中的元素都互为不同
distinctB和distinctD效果和distinct相同,但内部使用了不同的算法。
{FD.distinctOffset *Dv +Iv} 所有的Di+Ii结果都不能相同
{FD.distinct2 *Dv1 +Iv1 *Dv2 +Iv2}等价于:
or Dv1.i + IV1.i =<: Dv1.j
[] Dv1.j + IV1.j =<: Dv1.i
[] Dv2.i + IV2.i =<: Dv2.j
[] Dv2.j + IV2.j =<: Dv2.i
end
主要用来表示两个四边形不要相互覆盖,此时Dv1存储

X坐标,Dv2存Y坐标Iv1和 IV2分别存放宽度和高度
{FD.atMost *D *Dv +I} 相当于Dv中最多有D个元素值为I
{FD.atLeast *D *Dv +I} 至少
{FD.exactly *D *Dv +I} 刚好
{FD.element *D1 +Iv *D2} Iv中第D1个元素等于D2中对应元素,如:
{FD.int [1 3] X} {FD.element X [5 6 7 8] Y}
will constrain Y to [5 7] .


5.9 0/1 Propagators
{FD.conj $D1 $D2 $D3} $D3为$D1和$D2的与
{FD.disj $D1 $D2 $D3} 或
{FD.exor $D1 $D2 $D3} 异或
{FD.nega $D1 $D2} 非
{FD.impl $D1 $D2 $D3} 推导,D3 is the implication of D2 by D1 (``'').
{FD.equi $D1 $D2 $D3} D3 is the equivalence of D1 by D2 (``'').

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值