【发布时间】:2015-06-07 04:20:34
【问题描述】:
我正在为日期和时间构建解析器和生成器。在普通的编程语言中,这些将单独编写。在 Prolog+CLP(FD) 中,我可以编写 1 个同时执行这两种操作的谓词 :-)
在我的用例中,解析多个数字并将其转换为整数或根据给定整数生成多个数字通常是有意义的。
我的问题是 clpfd:run_propagator/2 在实例化单个数字时不会被调用,尽管我使用 clpfd:init_propagator/2 声明。有没有办法做到这一点,还是我对clpfd_digits/2 的定义有误?
在 SWI-Prolog 中实现的代码:
:- use_module(library(apply)).
:- use_module(library(clpfd)).
:- multifile(clpfd:run_propagator/2).
day(D) --> {clpfd_digits(D, [D1,D2])}, digit(D1), digit(D2).
digit(D) --> [C], {code_type(C, digit(D))}.
clpfd_digits(N, Ds):-
clpfd:make_propagator(clpfd_digits(N, Ds), Prop),
clpfd:init_propagator(N, Prop),
clpfd:init_propagator(Ds, Prop),
forall(
member(D, Ds),
clpfd:init_propagator(D, Prop)
),
clpfd:trigger_once(Prop).
clpfd:run_propagator(clpfd_digits(N, Ds), MState):-
( maplist(is_digit0, Ds)
-> clpfd:kill(MState),
digits_to_nonneg(Ds, N)
; integer(N)
-> clpfd:kill(MState),
nonneg_to_digits(N, Ds)
; true
).
digits_to_nonneg([], 0):- !.
digits_to_nonneg(Ds, N):-
maplist(char_weight, Chars, Ds),
number_chars(N, Chars).
char_weight(Char, D):-
char_type(Char, digit(D)).
nonneg_to_digits(0, []):- !.
nonneg_to_digits(N, Ds):-
atom_chars(N, Chars),
maplist(char_weight, Chars, Ds).
is_digit0(D):- integer(D), between(0, 9, D).
使用示例:
?- string_codes("12", Cs), phrase(day(D), Cs).
Cs = [49, 50],
clpfd_digits(D, [1, 2]).
如您所见,约束没有计算为在 D 的值处派生。
【问题讨论】:
-
请参阅this answer 了解解决相关问题的 clpfd 方法。
-
与
when((ground(Codes);nonvar(N)), number_codes(N,Codes))相比,您期望获得什么?两者都是弱关系而不是关系 - 就此而言。 -
@false 非常接近!但是它不处理填充零,例如,
phrase(day(2), "02")。 -
我看不出这个目标有什么问题,前提是
set_prolog_flag(double_quotes, codes)。 -
错误在于code_type:它失败了:
code_type(C,digit(N)),N=0.但成功了N=0, code_type(C,digit(N)).