prolog - Make a predicate reversible -


i'm new prolog; i'm coming structured programming background, become obvious :)

i building prolog query involves reversing number; eg. reverse_num(123,x) results in x = 321. came following definition, works when provide number first parameter.

reverse_num(num, revnum) :-   number_chars(num, atoms),   reverse(revatoms, atoms),   number_chars(reversed, revatoms),   reversed = revnum. 

the number_chars/2 predicate doesn't unsubstantiated variable if do: reverse_num(x,123) (where i'm expecting x 321).

am trying hard make reverse_num shouldn't (should understood work number first parameter , variable second)?

or there easy / straight-forward way handle variable first parameter?

relational naming

before jumping coding, let's take step back. after all, idea in prolog define relations. name reverse_num/2 rather suggests actions, num_reversed/2 might better name.

determine relation

your definition not bad, let me rewrite to1:

num_reversed(num, reversed) :-    number_chars(num, chars),    reverse(chars, revchars),    number_chars(reversed, revchars).  ?- num_reversed(123,x). x = 321.  ?- num_reversed(1230,x). x = 321.  ?- num_reversed(12300,x). x = 321. 

do see pattern? numbers n*10^i have same result!

now, let's ask more:

?- num_reversed(num, 321). error: number_chars/2: arguments not sufficiently instantiated 

hm, did expect? actually, wanted 123*10^i printed. that's infinitely many solutions. above query, if correctly answered, require infinitely many solutions printed. if print them directly, take our universe's lifetime, , more!

it reason, prolog produces instantiation error instead. this, prolog states:

this goal general can make answer. maybe there infinitely many solutions, maybe not. know not. @ least indicate issuing error. remove error need instantiate arguments bit more.

so answer prolog produced not that bad @ all! in fact, better produce clean error to, say, fail incorrectly. in general, prolog's errors useful hint semantic problems might have. see all error classes how.

coroutining

as have other answers suggested, coroutining, using when/2 might solve problem. however, coroutining has many semantic problems. not without reason, systems xsb not offer it, due many problems related subsumption checking. implementation compatible unexpectedly inefficient.

but sake of point, make our definition more versatile querying like

 ?- when(nonvar(num), num_reversed(num, reversed)).  when(nonvar(num), num_reversed(num, reversed)). 

now answer query entered. known floundering. there is way represent infinitely may solutions in compact manner! however, comes @ rather high price: no longer know whether solution exists or not. think of:

?- when(nonvar(num), num_reversed(num, -1)). when(nonvar(num), num_reversed(num, -1)). 

others have suggested wait nonvar(reversed) correct if produce infinitely many answers - but, have seen - takes time.

coroutining looked promising road @ beginning of 1980s. however, has never caught on general programming methodology. of time floundering pain , more difficult handle than, instantiation errors.

however, more promising offspring of development constraints. there, mechanisms cleaner defined. practical purposes, programmers use existing libraries, clpfd, clpq, or chr. implementing own library extremely non-trivial project in own right. in fact might possible provide implementation of num_reversed/2 using library(clpfd) is, restricting relation integer case.

mode dependent conditionals

traditionally, many such problems solved testing instantiations explicitly. style perform exclusively nonvar/1 , ground/1 condition in when/2- other type test predicates lead errors exemplified another answer.

num_reversed(num, reversed) :-    (  nonvar(num)    -> original_num_reversed(num, reversed)    ;  original_num_reversed(reversed, base),       (  base =:= 0       -> num 0       ;  length(_, i),          num base*10^i       )    ). 

above code breaks floats using base 2 , later base 10. in fact, classical base 2 floats, relation not make sense.

as definition of number_chars/2, iso/iec 13211-1:1995 has following template , mode subclause:

8.16.7.2 template , modes

number_chars(+number, ?character_list)
number_chars(-number, +character_list)

the first case when first argument instantiated (thus nonvar). second case, when first argument not instantiated. in case, second argument has instantiated.

note, however, due similar problems, number_chars/2 not relation. example, chs = ['0','0'], number_chars(0, chs) succeeds, whereas number_chars(0, chs), chs = ['0','0'] fails.

very fine print

1 rewrite necessary, because in many prologs reverse/2 terminates if first argument known. , in swi rewrite necessary due idiosyncratic inefficiencies.


Comments

Popular posts from this blog

angularjs - ADAL JS Angular- WebAPI add a new role claim to the token -

php - CakePHP HttpSockets send array of paramms -

node.js - Using Node without global install -