在prolog中计算边颜色的出现次数

在prolog中计算边颜色的出现次数,prolog,graph-theory,shortest-path,Prolog,Graph Theory,Shortest Path,我有一个定义如下的图: edge(a1,c1,7,blue). edge(a1,d1,3,blue). edge(a1,l1,8,red). edge(b1,c1,11,blue). edge(d1,e1,2,red). .... colour(X,Y,C). 等等 我知道如何编写代码来检查是否有路径,并计算权重和最短路径但我想做的是输出2个整数:一个表示从X到Y的路径中的蓝色边数,一个表示红色边数。 本质上,我想要这样的东西: edge(a1,c1,7,blue). edge(a1,d1

我有一个定义如下的图:

edge(a1,c1,7,blue).
edge(a1,d1,3,blue).
edge(a1,l1,8,red).
edge(b1,c1,11,blue).
edge(d1,e1,2,red).
....
 colour(X,Y,C).
等等

我知道如何编写代码来检查是否有路径,并计算权重和最短路径但我想做的是输出2个整数:一个表示从X到Y的路径中的蓝色边数,一个表示红色边数。

本质上,我想要这样的东西:

edge(a1,c1,7,blue).
edge(a1,d1,3,blue).
edge(a1,l1,8,red).
edge(b1,c1,11,blue).
edge(d1,e1,2,red).
....
 colour(X,Y,C).
要么返回:

“蓝色”如果路径中的所有边都是蓝色(或红色表示所有红色)

如果存在混合边,则为“false”。

或者类似于:

蓝色:5红色:2如果有7条边


我不熟悉Prolog,如何创建“counter”类型变量非常混乱。

使用您显示的DB片段和库()


使用显示的DB片段和库():


对于
edge/4
谓词,还有两种方法可以计算相同颜色的边数:

1) 使用谓词查找所有解决方案,如:

\u
符号代表“匿名变量”,您不关心绑定的变量

此解决方案的缺点是它不是资源明智的:首先要传递所有
edge/4
事实(不可避免的成本),然后使用额外的内存存储
ListBlue
列表,然后必须遍历此列表

2) 在故障驱动循环中使用(见下文)和谓词(可以在运行时添加/删除谓词whore子句):

当从一个程序状态转换到另一个程序状态时,您可以做一些额外的事情,比如在为变量赋值的操作中打印文本(副作用)(直接作用)

强制回溯允许探索
边(,,,,Col)
查询的所有可能解决方案,从而找到所有蓝色边


我已经尝试过该代码,它很有效。

对于您的
边/4
谓词,可能还有两种方法可以计算相同颜色的边数:

1) 使用谓词查找所有解决方案,如:

\u
符号代表“匿名变量”,您不关心绑定的变量

此解决方案的缺点是它不是资源明智的:首先要传递所有
edge/4
事实(不可避免的成本),然后使用额外的内存存储
ListBlue
列表,然后必须遍历此列表

2) 在故障驱动循环中使用(见下文)和谓词(可以在运行时添加/删除谓词whore子句):

当从一个程序状态转换到另一个程序状态时,您可以做一些额外的事情,比如在为变量赋值的操作中打印文本(副作用)(直接作用)

强制回溯允许探索
边(,,,,Col)
查询的所有可能解决方案,从而找到所有蓝色边


我已经尝试了代码,并且成功了。

我想发布一些基准测试,这可能有助于比较@s0nata发布的两个更好的解决方案。这是一个额外的答案,主要是因为它对于注释来说太长了

Prolog是一种设计和运行基准测试的好语言,这也是因为一个查询可以很容易地描述大量基准测试

特设基准 例如,让我们使用以下查询对使用
findall/3
选项1进行基准测试:

?- length(_, E), N #= 2^E, portray_clause(E), forall(between(1, N, _), assertz(edge(x, y, 1, blue))), time(opt1), false. 为了进行比较,我们使用选项2

0. 'blue: '1 % 3,454 inferences, 0.001 CPU in 0.009 seconds (16% CPU, 2364134 Lips) 1. 'blue: '3 % 22 inferences, 0.000 CPU in 0.000 seconds (76% CPU, 785714 Lips) 2. 'blue: '7 % 26 inferences, 0.000 CPU in 0.000 seconds (74% CPU, 1181818 Lips) 3. 'blue: '15 % 34 inferences, 0.000 CPU in 0.000 seconds (77% CPU, 1478261 Lips) 4. 'blue: '31 % 50 inferences, 0.000 CPU in 0.000 seconds (79% CPU, 1851852 Lips) ... lines omitted ... 21. 'blue: '4194303 % 4,194,322 inferences, 1.301 CPU in 1.439 seconds (90% CPU, 3224179 Lips) ?- length(_, E), N #= 2^E, portray_clause(E), forall(between(1, N, _), assertz(edge(x, y, 1, blue))), time(opt2), false. 0. 'blue: '1 % 3,448 inferences, 0.001 CPU in 0.009 seconds (16% CPU, 2347175 Lips) 1. 'blue: '3 % 20 inferences, 0.000 CPU in 0.000 seconds (81% CPU, 769231 Lips) 2. 'blue: '7 % 32 inferences, 0.000 CPU in 0.000 seconds (80% CPU, 1142857 Lips) 3. 'blue: '15 % 56 inferences, 0.000 CPU in 0.000 seconds (84% CPU, 888889 Lips) 4. 'blue: '31 % 104 inferences, 0.000 CPU in 0.000 seconds (85% CPU, 1350649 Lips) ... lines omitted ... 21. 'blue: '4194303 % 12,582,920 inferences, 10.100 CPU in 10.305 seconds (98% CPU, 1245782 Lips) 此外,让我们引入以下辅助定义,以获得执行目标所需的walltime。这可能包括由于其他任务、垃圾收集等引起的轻微干扰,但重要的是要考虑执行目标所需的实际时间(不安全秒):

wall_time(Goal, T) :- statistics(walltime, [T0|_]), Goal, statistics(walltime, [T1|_]), T is (T1 - T0)/1000. 墙时间(目标,T):- 统计数据(walltime,[T0 |)), 目标, 统计数据(walltime,[T1 |),], T是(T1-T0)/1000。 现在让我们发布一个例子:

opt1(L) :- findall(_,edge(_,_,_,blue),ListBlue), length(ListBlue, L). opt2(NBlue) :- retractall(counter(_,_)), asserta(counter(blue,0)), count_edges(blue, NBlue). ?- format("~tE~t~5+~tNum~t~15+~tT1~10+~tT2~10+~n"), length(_, E), N #= 2^E, forall(between(1, N, _), assertz(edge(x, y, 1, blue))), wall_time(opt1(Num), T1), wall_time(opt2(Num), T2), format("~t~w~5+~t~w~15+~t~2f~10+~t~2f~10+~n", [E,Num,T1,T2]), false. ?-格式(“~tE~t~5+~tNum~t~15+~tT1~10+~tT2~10+~n”), 长度(u,E), N#=2^E, forall(在(1,N,u)之间),assertz(边(x,y,1,蓝色)), 墙时间(opt1(Num),T1), 墙时间(opt2(Num),T2), 格式(“~t~w~5+~t~w~15+~t~2f~10+~t~2f~10+~n”,[E,Num,T1,T2]), 错。 结果如下表所示:

E Num T1 T2 0 1 0.00 0.00 1 3 0.00 0.00 2 7 0.00 0.00 3 15 0.00 0.00 4 31 0.00 0.00 5 63 0.00 0.00 6 127 0.00 0.00 7 255 0.00 0.00 8 511 0.00 0.00 9 1023 0.00 0.00 10 2047 0.00 0.01 11 4095 0.00 0.01 12 8191 0.00 0.03 13 16383 0.01 0.04 14 32767 0.02 0.08 15 65535 0.02 0.16 16 131071 0.04 0.32 17 262143 0.09 0.64 18 524287 0.18 1.31 19 1048575 0.37 2.55 20 2097151 0.74 5.14 21 4194303 1.44 10.29 E数T1 T2 0 1 0.00 0.00 1 3 0.00 0.00 2 7 0.00 0.00 3 15 0.00 0.00 4 31 0.00 0.00 5 63 0.00 0.00 6 127 0.00 0.00 7 255 0.00 0.00 8 511 0.00 0.00 9 1023 0.00 0.00 10 2047 0.00 0.01 11 4095 0.00 0.01 12 8191 0.00 0.03 13 16383 0.01 0.04 14 32767 0.02 0.08 15 65535 0.02 0.16 16 131071 0.04 0.32 17 262143 0.09 0.64 18 524287 0.18 1.31 19 1048575 0.37 2.55 20 2097151 0.74 5.14 21 4194303 1.44 10.29 在比较这两种解决方案时,也请考虑这些实际基准。在Prolog中,杂质通常也会导致很多效率低下的问题


请注意,我们如何利用此机会验证两个选项是否产生相同的结果

我想发布一些基准,这可能有助于比较@s0nata发布的两个解决方案。这是一个额外的答案,主要是因为它对于注释来说太长了

Prolog是一种设计和运行基准测试的好语言,这也是因为一个查询可以很容易地描述大量基准测试

特设基准 例如,让我们对o进行基准测试 E Num T1 T2 0 1 0.00 0.00 1 3 0.00 0.00 2 7 0.00 0.00 3 15 0.00 0.00 4 31 0.00 0.00 5 63 0.00 0.00 6 127 0.00 0.00 7 255 0.00 0.00 8 511 0.00 0.00 9 1023 0.00 0.00 10 2047 0.00 0.01 11 4095 0.00 0.01 12 8191 0.00 0.03 13 16383 0.01 0.04 14 32767 0.02 0.08 15 65535 0.02 0.16 16 131071 0.04 0.32 17 262143 0.09 0.64 18 524287 0.18 1.31 19 1048575 0.37 2.55 20 2097151 0.74 5.14 21 4194303 1.44 10.29