Related
I'm trying to implement a cantor set using prolog. The problem is defined in this link. I have implemented the code like this.
create_cantor_set(X, Y, D, List):-
cantor(D, X, Y, Temp), % Depth, X, Y, temporary list
reverse(List, Temp).
% base condition
cantor(1, X, Y, [[X|Y]|_]).
cantor(D, X, Y, Temp):-
X1 is X + ((Y - X) / 3),
Y1 is Y - ((Y - X) / 3),
decrement(D, D1),
cantor(D1, X, X1, [[X|X1]|Temp]),
cantor(D1, Y1, Y, [[Y1|Y]|Temp]).
% Decrement helper
decrement(N, N1):-
N1 is N-1.
However, I'm getting an output like this:
List = [] ;
List = [_4770] ;
List = [_4770, _4776] ;
List = [_4770, _5442, _4776] ;
List = [_4770, _5442, _5448, _4776] ;
List = [_4770, _5442, _6114, _5448, _4776]
I'm not able to understand why it is giving placeholder variables rather than the actual values.
I'm trying to add the set [X|Y] when D = 0. The answer should be one final list. Thank you for your help.
EDIT:
sample query: create_cantor_set(0, 1, 2, List).
expected output: [[0, 0.333],[0.666, 1]]
div_interval(N, X-Y, Xn-Yn) :-
Xn is X/N, Yn is Y/N.
add_interval(A, X-Y, Xa-Ya) :-
Xa is X + A, Ya is Y + A.
step_cantor(Ii, Io) :-
maplist(div_interval(3), Ii, Io1),
maplist(add_interval(2/3), Io1, Io2),
union(Io1, Io2, Io).
cantor(0, [0-1]).
cantor(N, X) :-
N > 0, N1 is N - 1, cantor(N1, X1),
step_cantor(X1, X).
cantor_len(S, L) :-
foldl([X-Y, A, O]>>(O is (A+Y-X)), S, 0, L).
I am representing an interval [a, b] with a pair a-b.
?- cantor(0, X), cantor_len(X, Y).
X = [0-1],
Y = 1
?- cantor(1, X), cantor_len(X, Y).
X = [0-0.3333333333333333, 0.6666666666666666-1.0],
Y = 0.6666666666666666
?- cantor(2, X), cantor_len(X, Y).
X = [0-0.1111111111111111, 0.2222222222222222-0.3333333333333333, 0.6666666666666666-0.7777777777777777, 0.8888888888888888-1.0],
Y = 0.4444444444444444
I have a list with an unknown number of zeros at the beginning of it, for example [0, 0, 0, 1, 2, 0, 3]. I need this list to be stripped of leading zeros, so that it would look like [1, 2, 0 , 3].
Here's what I have:
lead([Head | _], _) :- Head =\= 0.
lead([0 | Tail], _) :-
lead(Tail, Tail).
The output of which is simply True. Reading the trace shows that it is running until it has a list with no leading zeros, but then the answer doesn't propagate back up the stack. I'm pretty new to Prolog, so I can't figure out how to make it do that.
Here is a solution that works in all directions:
lead([],[]).
lead([H|T],[H|T]) :-
dif(H,0).
lead([0|T],T2) :-
lead(T,T2).
Some queries:
?- lead([0,0,0,1,2,0,3], L).
L = [1, 2, 0, 3] ;
false.
?- lead(L, []).
L = [] ;
L = [0] ;
L = [0, 0] ;
L = [0, 0, 0] ;
...
?- lead(L0, L).
L0 = L, L = [] ;
L0 = L, L = [_G489|_G490],
dif(_G489, 0) ;
L0 = [0],
L = [] ;
L0 = [0, _G495|_G496],
L = [_G495|_G496],
dif(_G495, 0) ;
L0 = [0, 0],
L = [] ;
L0 = [0, 0, _G501|_G502],
L = [_G501|_G502],
dif(_G501, 0) ;
L0 = [0, 0, 0],
L = [] ;
...
EDIT This predicate actually doesn't work for e.g. lead(L0, [0,1,2]).
With library(reif):
:- use_module(reif).
remove_leading_zeros([], []).
remove_leading_zeros([H|T], Rest) :-
if_( H = 0,
remove_leading_zeros(T, Rest),
Rest = [H|T]).
Then:
?- remove_leading_zeros([0,0,0,1,2,0,3], R).
R = [1, 2, 0, 3].
?- remove_leading_zeros([2,0,3], R).
R = [2, 0, 3].
?- remove_leading_zeros(L, R).
L = R, R = [] ;
L = [0],
R = [] ;
L = [0, 0],
R = [] ;
L = [0, 0, 0],
R = [] . % and so on
Here is a solution that actually works for all possible inputs and doesn't leave unnecessary choice points:
lead(L0, L) :-
( nonvar(L),
L = [H|_] ->
dif(H,0)
;
true
),
lead_(L0, L).
lead_([], []).
lead_([H|T], L) :-
if_(H \= 0,
L = [H|T],
lead_(T,L)).
The initial check for nonvar(L) is the only solution I have been able to come up with that would prevent problems with e.g. lead(L0, [0,1,2,3]), while retaining the behavior of the predicate in all other situations.
This uses if_/3, part of library(reif)
if_(If_1, Then_0, Else_0) :-
call(If_1, T),
( T == true -> Then_0
; T == false -> Else_0
; nonvar(T) -> throw(error(type_error(boolean,T),
type_error(call(If_1,T),2,boolean,T)))
; throw(error(instantiation_error,instantiation_error(call(If_1,T),2)))
).
This also uses (\=)/3, that I came up with by simple modification of (=)/3 in library(reif).
\=(X, Y, T) :-
( X \= Y -> T = true
; X == Y -> T = false
; T = true, dif(X, Y)
; T = false,
X = Y
).
Some queries
?- lead([0,0,0,1,2,0,3],L). % No choice point
L = [1, 2, 0, 3].
?- lead([1,2,0,3],L).
L = [1, 2, 0, 3].
?- lead([0,0,0,0],L).
L = [].
?- lead([],L).
L = [].
?- lead(L0,[0,1,2,0,3]). % Correctly fails
false.
?- lead(L0,[1,2,0,3]).
L0 = [1, 2, 0, 3] ;
L0 = [0, 1, 2, 0, 3] ;
L0 = [0, 0, 1, 2, 0, 3] ;
…
?- lead(L0,L). % Exhaustively enumerates all cases:
L0 = L, L = [] ; % - LO empty
L0 = L, L = [_G2611|_G2612], % - L0 contains no leading 0
dif(_G2611, 0) ;
L0 = [0], % - L0 = [0]
L = [] ;
L0 = [0, _G2629|_G2630], % - L0 contains one leading 0
L = [_G2629|_G2630],
dif(_G2629, 0) ;
L0 = [0, 0], % - L0 = [0, 0]
L = [] ;
L0 = [0, 0, _G2647|_G2648], % - L0 contains two leading 0s
L = [_G2647|_G2648],
dif(_G2647, 0) ;
… % etc.
Here is a solution that doesn't generate any choice points. Its
using freeze/2, in a way that is not anticipated by dif/2. But using
freeze/2 here is quite appropriate, since one rule of thumb for freeze/2
is as follows:
Rule of Thumb for freeze/2: Use freeze/2 where the predicate would
generate uninstantiated solutions and a lot of choice points. The hope
is that a subsequent goal will specify the solution more, and the
freeze/2 will be woken up. Unfortunately doesn't work with CLP(FD) or
dif/2, since freeze/2 does not react to refinements implied by CLP(FD)
or dif/2, only unification will wake it up.
The code is thus:
lead(X, Y) :- var(X), !, freeze(X, lead(X,Y)).
lead([X|Y], Z) :- var(X), !, freeze(X, lead([X|Y],Z)).
lead([0|X], Y) :- !, lead(X, Y).
lead(X, X).
Here are some sample runs (SWI-Prolog without some import, Jekejeke Prolog use Minlog Extension and ?- use_module(library(term/suspend))):
?- lead([0,0,0,1,2,3], X).
X = [1, 2, 3].
?- lead([0,0|X], Y).
freeze(X, lead(X, Y)).
?- lead([0,0|X], Y), X = [0,1,2,3].
X = [0, 1, 2, 3],
Y = [1, 2, 3].
?- lead([Z,0|X], Y), X = [0,1,2,3].
X = [0, 1, 2, 3],
freeze(Z, lead([Z, 0, 0, 1, 2, 3], Y)).
?- lead([Z,0|X], Y), X = [0,1,2,3], Z = 0.
Z = 0,
X = [0, 1, 2, 3],
Y = [1, 2, 3].
In the above lead/2 implemetation only the first argument is handled. To handle multiple arguments simultaneously the predicate when/2 can be used. But for simplicity this is not shown here.
Also when using suspended goals, one might need a labeling like predicate at the end, since suspended goals cannot detect inconsistency among them.
The problem in your code is that the second parameter, your output, is specified as _, so your predicate is true for any output. What you want is a predicate that is true if and only if it is the input minus leading zeroes.
lead([], []).
lead([0 | Tail], Tail2) :- !, lead(Tail, Tail2).
lead([Head | Tail], [Head | Tail]) :- Head =\= 0.
The ! in the first line is optional. It prunes the search tree so Prolog does not consider the second line (which would fail) if the first line matches.
Here's how I'd phrase it. First, establish constraints: either X or Y must be bound to a list. Anything else fails.
If X is bound, we don't care about Y: it can be bound or unbound. We just strip any leading zeros from X and unify the results with Y. This path has a single possible solution.
If X is unbound and Y is bound, we shift into generative mode. This path has an infinite number of possible solutions.
The code:
strip_leading_zeros(X,Y) :- listish(X), !, rmv0( X , Y ) .
strip_leading_zeros(X,Y) :- listish(Y), !, add0( Y , X ) .
rmv0( [] , [] ) .
rmv0( [D|Ds] , R ) :- D \= 0 -> R = [D|Ds] ; rmv0(Ds,R) .
add0( X , X ) .
add0( X , Y ) :- add0([0|X],Y ) .
listish/1 is a simple shallow test for listish-ness. Use is_list/1 if you want to be pedantic about things.
listish( L ) :- var(L), !, fail.
listish( [] ) .
listish( [_|_] ) .
Edited to note: is_list/1 traverses the entire list to ensure that it is testing is a properly constructed list, that is, a ./2 term, whose right-hand child is itself either another ./2 term or the atom [] (which denotes the empty list). If the list is long, this can be an expensive operation.
So, something like [a,b,c] is a proper list and is actually this term: .(a,.(b,.(c,[]))). Something like [a,b|32] is not a proper list: it is the term .(a,.(b,32)).
List1=[(x,1),(y,1),(z,1)]
I'm attempting to split this list:
into two lists:
List3=[x,y,z]
List4=[1,1,1]
So I have written this predicate to try to do it:
splt([], [], []).
splt([X|Xs], [Y|Ys], [X,Y|Zs]) :-
splt(Xs,Ys,Zs).
However instead of the desired result, the predicate returns:
1 ?- splt([(x,1),(y,2),(z,3)],L3,L4).
L3 = [_G1760, _G1769, _G1778],
L4 = [ (z, 1), _G1760, (y, 2), _G1769, (z, 3), _G1778].
First, the term you have chosen. This: (a, b), is most definitely not how you would usually represent a "tuple" in Prolog. You almost always use a-b for a "pair", and pairs are used throughout the standard libraries.
So your initial list would look like this: [x-1, y-1, z-1].
This should also explain why you are having your problem. You write (a, b), but your predicate says a, b, and you consume two elements when you expect to get one ,(a,b) term. So, to fix your current predicate you would write:
split([], [], []).
split([X|Xs], [Y|Ys], [(X,Y)|XYs]) :-
split(Xs, Ys, XYs).
?- split(Xs, Ys, [(x,1), (y,1), (z,1)]).
Xs = [x, y, z],
Ys = [1, 1, 1].
But instead, using a more conventional name, term order, and Prolog pairs:
zip([], [], []).
zip([X-Y|XYs], [X|Xs], [Y|Ys]) :-
zip(XYs, Xs, Ys).
?- zip([x-1, y-1, z-1], Xs, Ys).
Xs = [x, y, z],
Ys = [1, 1, 1].
And of course, SWI-Prolog at least has a library(pairs), and it comes with a pairs_keys_values/3:
?- pairs_keys_values([x-1, y-1, z-1], Xs, Ys).
Xs = [x, y, z],
Ys = [1, 1, 1].
I find comfortable using library(yall):
?- maplist([(X,Y),X,Y]>>true, [(x,1),(y,2),(z,3)],L3,L4).
L3 = [x, y, z],
L4 = [1, 2, 3].
or, maybe clearer
?- maplist([A,B,C]>>(A=(B,C)), [(x,1),(y,2),(z,3)],L3,L4).
L3 = [x, y, z],
L4 = [1, 2, 3].
You're matching the tuple as a whole, rather than it's component parts.
You should match on [(X1,Y1)|XS], instead of [X|XS] and [Y|Ys].
splt([],[],[]).
splt([(X1,Y1)|Xs],[X1|T1],[Y1|T2]):-
splt(Xs,T1,T2).
Here the first term is used as input, the second and third as output.
Ideone example, using SWI-Prolog, here.
I'm trying to implement a lexicographic ordering constraint in BProlog using its CLP(FD).
As far as I can see from the manual BProlog doesn't provide a built-in lexLeq constraints (though there exist efficient propagation algorithms for this global constraint), so I'm trying to write my own and express the ordering as the following set of binary constraints:
X1 #=< Y1, (X1 #= Y1) #=> (X2 #=< Y2), (X1 #= Y1 #/\ X2 #= Y2) #=> (X3 #=< Y3), ..., (X1 #= Y1 #/\ ... #/\ XN #= YN) #=> (XN+1 #=< #YN+1)
To express the (A1 #/\ A2 #/\ ... #/\ AN) => AN+1 constraint I think I should be able to reify the Ais, so:
domain(B, 0, 1),
(X1 #= Y1) #<=> B
I then collect the Bs and to check that the conjunction is valid I simply do:
(sum(Bs) #= N) #=> AN+1
The idea leads to the following (probably very ugly) code:
lexLeq(Xs, Ys) :-
lexLeq(Xs, [], Ys, []).
lexLeq([X|Xs], [], [Y|Ys], []) :-
X #=< Y,
lexLeq(Xs, [X], Ys, [Y]).
lexLeq([X|Xs], [OldX|OldXs], [Y|Ys], [OldY|OldYs]) :-
makeAndConstr([OldX|OldXs], [OldY|OldYs], X, Y),
lexLeq(Xs, [X,OldX|OldXs], Ys, [Y, OldY|OldYs]).
lexLeq([], _, [], _).
makeAndConstr(Xs, Ys, X, Y) :-
length(Xs, N),
makeAndConstr(Xs, Ys, [], N, X, Y).
makeAndConstr([X|Xs], [Y|Ys], Bs, N, X, Y) :-
domain(B, 0, 1),
(X #= Y) #<=> B,
makeAndConstr(Xs, Ys, [B|Bs], N, X, Y).
makeAndConstr([], [], Bs, N, X, Y) :-
(sum(Bs) #= N) #=> (X #=< Y).
This partially works:
| ?- domain([A,B,C,D,E,F], 0, 1), lexLeq([A,B,C], [D, E, F]), labeling([A,B,C,$
A = 0
B = 0
C = 0
D = 0
E = 0
F = 0 ?;
A = 0
B = 0
C = 0
D = 1
E = 1
F = 1 ?;
A = 1
B = 1
C = 1
D = 1
E = 1
F = 1 ?;
no
as you can see all solutions produced do satisfy the constraint. The problem is that not all valid solutions are produced. It seems like the constraints I've describe also somehow imply that X1 #>= X2 #>= ... #>= XN or something like that, so that all variables are either 0 or 1,
while the above query should return also solutions like [0,1,0] vs [0,1,0] or [0,0,0] vs [0,1,0].
So, is there something wrong with my reasoning or is there a bug in the above definitions?
In the first clause of makeAndConstr/6, you use X for two different purposes, which causes the extra failures (same for Y). This renamed code works:
makeAndConstr([X1|Xs], [Y1|Ys], Bs, N, X, Y) :-
domain(B, 0, 1),
(X1 #= Y1) #<=> B,
makeAndConstr(Xs, Ys, [B|Bs], N, X, Y).
You could have found this by tracing a simple goal that you expected to succeed, e.g. lexLeq([0,1],[0,1]).
Simpler formulation of the lexicographic ordering constraint
I want to share with you an elegant solution that I was taught many years ago by my former colleague Warwick Harvey. It goes like this:
lex_le(Xs, Ys) :-
lex_le(Xs, Ys, 1).
lex_le([], [], 1).
lex_le([X|Xs], [Y|Ys], IsLe) :-
IsLe #<=> (X #< Y+RestIsLe),
lex_le(Xs, Ys, RestIsLe).
which is explained by observing that IsLe is 1 if
either X<Y (and the value of RestIsLe doesn't matter)
or X=Y and RestIsLe is 1.
Okay, I have found a possible, seemingly working, solution:
lexLeq([], []).
lexLeq([X|Xs], [Y|Ys]) :-
X #=< Y,
domain(B, 0, 1),
(X #= Y) #<=> B,
lexLeq(Xs, Ys, [B]).
lexLeq([X|Xs], [Y|Ys], Bs) :-
length(Bs, N),
(sum(Bs) #= N) #=> (X #=< Y),
domain(B, 0, 1),
(X #= Y) #<=> B,
lexLeq(Xs, Ys, [B|Bs]).
lexLeq([], [], _).
This is also much simpler than the above.
The difference is that in the first solution I created new Bs for every call to makeAndConstr, instead of reusing the same B already created.
Though I'm not really sure how this helps in avoid the bug; it should simply be more efficient.
I am trying to fill a list of given length N with numbers 1,2,3,...,N.
I thought this could be done this way:
create_list(N,L) :-
length(L,N),
forall(between(1,N,X), nth1(X,L,X)).
However, this does not seem to work. Can anyone say what I am doing wrong?
First things first: Use clpfd!
:- use_module(library(clpfd)).
In the following I present zs_between_and/3, which (in comparison to my previous answer) offers some more features.
For a start, let's define some auxiliary predicates first!
equidistant_stride([] ,_).
equidistant_stride([Z|Zs],D) :-
equidistant_prev_stride(Zs,Z,D).
equidistant_prev_stride([] ,_ ,_). % internal predicate
equidistant_prev_stride([Z1|Zs],Z0,D) :-
Z1 #= Z0+D,
equidistant_prev_stride(Zs,Z1,D).
Let's run a few queries to get a picture of equidistant_stride/2:
?- Zs = [_,_,_], equidistant_stride(Zs,D).
Zs = [_A,_B,_C], _A+D#=_B, _B+D#=_C.
?- Zs = [1,_,_], equidistant_stride(Zs,D).
Zs = [1,_B,_C], _B+D#=_C, 1+D#=_B.
?- Zs = [1,_,_], equidistant_stride(Zs,10).
Zs = [1,11,21].
So far, so good... moving on to the actual "fill list" predicate zs_between_and/3:
zs_between_and([Z0|Zs],Z0,Z1) :-
Step in -1..1,
Z0 #= Z1 #<==> Step #= 0,
Z0 #< Z1 #<==> Step #= 1,
Z0 #> Z1 #<==> Step #= -1,
N #= abs(Z1-Z0),
( fd_size(N,sup)
-> true
; labeling([enum,up],[N])
),
length(Zs,N),
labeling([enum,down],[Step]),
equidistant_prev_stride(Zs,Z0,Step).
A bit baroque, I must confess...
Let's see what features were gained---in comparison to my previous answer!
?- zs_between_and(Zs,1,4). % ascending consecutive integers
Zs = [1,2,3,4]. % (succeeds deterministically)
?- zs_between_and(Zs,3,1). % descending consecutive integers (NEW)
Zs = [3,2,1]. % (succeeds deterministically)
?- zs_between_and(Zs,L,10). % enumerates fairly
L = 10, Zs = [10] % both ascending and descenting (NEW)
; L = 9, Zs = [9,10]
; L = 11, Zs = [11,10]
; L = 8, Zs = [8,9,10]
; L = 12, Zs = [12,11,10]
; L = 7, Zs = [7,8,9,10]
...
?- L in 1..3, zs_between_and(Zs,L,6).
L = 3, Zs = [3,4,5,6]
; L = 2, Zs = [2,3,4,5,6]
; L = 1, Zs = [1,2,3,4,5,6].
Want some more? Here we go!
?- zs_between_and([1,2,3],From,To).
From = 1, To = 3
; false.
?- zs_between_and([A,2,C],From,To).
A = 1, From = 1, C = 3, To = 3 % ascending
; A = 3, From = 3, C = 1, To = 1. % descending
I don't have a prolog interpreter available right now, but wouldn't something like...
isListTo(N, L) :- reverse(R, L), isListFrom(N, R).
isListFrom(0, []).
isListFrom(N, [H|T]) :- M is N - 1, N is H, isListFrom(M, T).
reverse can be done by using e.g. http://www.webeks.net/prolog/prolog-reverse-list-function.html
So tracing isListTo(5, [1, 2, 3, 4, 5])...
isListTo(5, [1, 2, 3, 4, 5])
<=> isListFrom(5, [5, 4, 3, 2, 1])
<=> 5 is 5 and isListFrom(4, [4, 3, 2, 1])
<=> 4 is 4 and isListFrom(3, [3, 2, 1])
<=> 3 is 3 and isListFrom(2, [2, 1])
<=> 2 is 2 and isListFrom(1, [1])
<=> 1 is 1 and isListFrom(0, [])
QED
Since PROLOG will not only evaluate truth, but find satisfying solutions, this should work. I know this is a vastly different approach from the one you are trying, and apologize if your question is specifically about doing loops in PROLOG (if that is the case, perhaps re-tag the question?).
Here's a logically pure implementation of predicate zs_from_to/3 using clpfd:
:- use_module(library(clpfd)).
zs_from_to([],I0,I) :-
I0 #> I.
zs_from_to([I0|Is],I0,I) :-
I0 #=< I,
I1 #= I0 + 1,
zs_from_to(Is,I1,I).
Let's use it! First, some ground queries:
?- zs_from_to([1,2,3],1,3).
true.
?- zs_from_to([1,2,3],1,4).
false.
Next, some more general queries:
?- zs_from_to(Zs,1,7).
Zs = [1,2,3,4,5,6,7]
; false.
?- zs_from_to([1,2,3],From,To).
From = 1, To = 3.
Now, let's have some even more general queries:
?- zs_from_to(Zs,From,2).
Zs = [], From in 3..sup
; Zs = [2], From = 2
; Zs = [1,2], From = 1
; Zs = [0,1,2], From = 0
; Zs = [-1,0,1,2], From = -1
; Zs = [-2,-1,0,1,2], From = -2
...
?- zs_from_to(Zs,0,To).
Zs = [], To in inf.. -1
; Zs = [0], To = 0
; Zs = [0,1], To = 1
; Zs = [0,1,2], To = 2
; Zs = [0,1,2,3], To = 3
; Zs = [0,1,2,3,4], To = 4
...
What answers do we get for the most general query?
?- zs_from_to(Xs,I,J).
Xs = [], J#=<I+ -1
; Xs = [I], I+1#=_A, J#>=I, J#=<_A+ -1
; Xs = [I,_A], I+1#=_A, J#>=I, _A+1#=_B, J#>=_A, J#=<_B+ -1
; Xs = [I,_A,_B], I+1#=_A, J#>=I, _A+1#=_B, J#>=_A, _B+1#=_C, J#>=_B, J#=<_C+ -1
...
Edit 2015-06-07
To improve on above implementation of zs_from_to/3, let's do two things:
Try to improve determinism of the implementation.
Extract a more general higher-order idiom, and implement zs_from_to/3 on top of it.
Introducing the meta-predicates init0/3 and init1/3:
:- meta_predicate init0(2,?,?).
:- meta_predicate init1(2,?,?).
init0(P_2,Expr,Xs) :- N is Expr, length(Xs,N), init_aux(Xs,P_2,0).
init1(P_2,Expr,Xs) :- N is Expr, length(Xs,N), init_aux(Xs,P_2,1).
:- meta_predicate init_aux(?,2,+). % internal auxiliary predicate
init_aux([] , _ ,_ ).
init_aux([Z|Zs],P_2,I0) :-
call(P_2,I0,Z),
I1 is I0+1,
init_aux(Zs,P_2,I1).
Let's see init0/3 and init1/3 in action!
?- init0(=,5,Zs). % ?- numlist(0,4,Xs),maplist(=,Xs,Zs).
Zs = [0,1,2,3,4].
?- init1(=,5,Zs). % ?- numlist(1,5,Xs),maplist(=,Xs,Zs).
Zs = [1,2,3,4,5].
Ok, where do we go from here? Consider the following query:
?- init0(plus(10),5,Zs). % ?- numlist(0,4,Xs),maplist(plus(10),Xs,Zs).
Zs = [10,11,12,13,14].
Almost done! Putting it together, we define zs_from_to/2 like this:
z_z_sum(A,B,C) :- C #= A+B.
zs_from_to(Zs,I0,I) :-
N #= I-I0+1,
init0(z_z_sum(I0),N,Zs).
At last, let's see if determinism has improved!
?- zs_from_to(Zs,1,7).
Zs = [1,2,3,4,5,6,7]. % succeeds deterministically
If I understood correctly, the built-in predicate numlist/3 would do.
http://www.swi-prolog.org/pldoc/man?predicate=numlist/3