gpt4 book ai didi

parsing - 列表成员实例化时约束不会传播

转载 作者:行者123 更新时间:2023-12-02 14:21:14 26 4
gpt4 key购买 nike

我正在构建一个日期和时间的解析器和生成器。在普通的编程语言中,这些将被单独编写。在 Prolog+CLP(FD) 中,我可以编写 1 个谓词来完成这两个任务:-)

在我的用例中,解析多个数字并将其转换为整数,或者根据给定的整数生成多个数字通常是有意义的。

我的问题是,尽管我使用 clpfd:init_propagator/2 声明,但在实例化各个数字时,不会调用 clpfd:run_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 的值。

最佳答案

+1 表示在此任务中使用 CLP(FD) 约束!

forall/2 和约束不能很好地混合,因为回溯会撤销发布的约束。

您的示例按预期工作:

flip_init(Prop, D) :- clpfd:init_propagator(D, Prop)。

并使用maplist(flip_init(Prop), Ds)而不是forall/2

下一个问题是,digits_to_nonneg([1,2], N) 会失败,但这与实际的约束触发无关,这会按预期发生。 (顺便说一句:使用约束,您可以简化代码,以便可以在两个方向上使用单个谓词。)

此外,您还可以使用 in/2 代替 Between/3:D in 0..9。如果您想将其用作约束而不仅仅是测试,这通常很有用。

关于parsing - 列表成员实例化时约束不会传播,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30686706/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com