Supponiamo di voler rappresentare numeri interi come: integer:Sign:[FirstDigit,SecondDigit,...]
. Ad esempio, 42 sarebbe rappresentato come integer:positive:[4,2]
.Elenco di numeri interi e loop infinito in Prolog CLPFD
Ho bisogno di un predicato che generi il valore del numero intero basato su questa rappresentazione e viceversa.
Ecco quello che mi si avvicinò con:
integer_value_('integer':Sign:[H],E) :-
H in 0..9,
(
Sign = 'positive',
E #= H
;
Sign = 'negative',
E #= -H
).
integer_value_('integer':Sign:[H,I|T],E) :-
H in 0..9,
length([I|T],L),
(
Sign = 'positive',
E #= F + H * 10^L
;
Sign = 'negative',
E #= F - H * 10^L
),
integer_value_('integer':Sign:[I|T],F).
Questo funziona come previsto. Tuttavia, ha la sfortunata proprietà di accettare cose come integer:positive:[0,1]
, cioè zero iniziali all'inizio della lista. Questo è particolarmente problematico quando enumero tutti i possibili numeri interi usando integer_value_(I,J), label([J]).
: anche quelli con zero iniziale vengono visualizzati.
Allora ho tentato di correggere questo usando integer_value_
solo per tutti, ma la prima cifra, e utilizzando integer_value
per la prima (tenendo presente che abbiamo bisogno di accogliere per 0 essere rappresentato con una lista che contiene solo 0):
integer_value('integer':Sign:[H],E) :-
abs(E) #< 10,
abs(E) #> -1,
integer_value_('integer':Sign:[H],E).
integer_value('integer':Sign:[H,I|T],E) :-
H in 1..9,
length([I|T],L),
(
Sign = 'positive',
E #= F + H * 10^L
;
Sign = 'negative',
E #= F - H * 10^L
),
integer_value_('integer':Sign:[I|T],F).
Tuttavia ora non si comporta correttamente. Ad esempio, integer_value(I,-19).
restituisce I = integer:negative:[1, 9]
, ma se chiediamo un'altra risposta, Prolog entra in un ciclo infinito per motivi che non capisco (dovrebbe dire falso, o già sapere che non ci sono altre risposte).
Questo problema non si verifica con la query "opposta" integer_value(integer:negative:[1,9],Z).
che restituisce Z = 19
e quindi false, né si verifica quando entrambi gli argomenti sono variabili (enumera i numeri correttamente, senza zeri iniziali), il che è sorprendente per me.
Qualche idea su cosa si verifichi questo loop infinito e se esiste un modo semplice per risolverlo?
+1 per un caso di utilizzo molto interessante e appropriato dei vincoli CLP (FD)! Ho un piccolo commento riguardo le virgolette singole: puoi omettere il '' 'per tutti gli atomi che non hanno bisogno di virgolette come' positivo', 'negativo',' intero' ecc. Puoi semplicemente scrivere tutti questi atomi direttamente , come 'Segno = positivo',' Segno = negativo' e 'intero: Segno: [I | T]'. – mat
@mat Lo so, ma dal momento che non sono un programmatore Prolog trovo abbastanza brutto avere atomi del genere: p – Fatalize