Buduję parser i generator dla dat i godzin. W zwykłym języku programowania będą one pisane osobno. W Prolog + CLP (FD) mogę napisać 1 predykat, który wykonuje oba :-)Ograniczenie nie jest propagowane po utworzeniu elementów listy
W moim przypadku użycia często ma sens parsować liczbę cyfr i konwertować na liczbę całkowitą lub generować liczbę cyfr na podstawie danej liczby całkowitej.
Mój problem polega na tym, że clpfd:run_propagator/2
nie jest wywoływany, gdy tworzone są pojedyncze cyfry, pomimo moich deklaracji z użyciem clpfd:init_propagator/2
. Czy istnieje sposób, aby to zrobić, czy też popełniam błąd w mojej definicji clpfd_digits/2
?
Kod realizowane w 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).
Przykład zastosowania:
?- string_codes("12", Cs), phrase(day(D), Cs).
Cs = [49, 50],
clpfd_digits(D, [1, 2]).
Jak widać ograniczenie nie jest obliczana w celu uzyskania wartości D
.
Zobacz [tę odpowiedź] (http://stackoverflow.com/a/28442760/772868) dla metody clpfd, aby rozwiązać powiązany problem. – false
Co spodziewasz się zyskać w porównaniu do 'when ((ziemia (kody), nonvar (N)), liczba_znaków (N, kody))'? Oba są słabe, a nie relacje - o to chodzi. – false
@false To przychodzi dość blisko! Jednak nie zajmuje się zerami dopełnienia, np. 'Fraza (dzień (2)," 02 ")'. –