1

firstly look at following example:

?-  fp(X,[b,a,b]).  

false Ok, because second argument must be two-elements sorted list. (In my program I assume that a<b)

?-fp(X,[a,b,b]).
X = [a, b, b] ;
X = [b, a, b] ;
X = [b, b, a] ;
false.

Yeah, it is correct result.
However, for

?-fp ([b,a,b], X)
X = [a,b,b].

Yeah, it is expected result.
However, in case of

?-fp ([b,a,b], X)
X = [a,b,b];

Here is looping....

Is there exist way to deal with this looping ? I have thought a long time, but no success. Can you try to help me ?

fp(L, F) :-
   fp(L, [], [], F).

fp([], AccA, AccB, F):-
   append(AccA, AccB, F), !.
fp([a|L], AccA, AccB, F) :-
   append([a|AccA], _, F),
   fp(L, [a|AccA], AccB, F).
fp([b|L], AccA, AccB, F) :-
   append(_, [b|AccB], F),
   fp(L, AccA, [b|AccB], F).
lurker
  • 56,987
  • 9
  • 69
  • 103
  • 1
    Have you tried doing a `trace` to see what's going on? – lurker May 18 '16 at 12:26
  • Yes, I tried it. When we add `!` after `fp(L, AccA, [c|AccB], F).` it not looping, but it doesn't give correct (not all possibilites) when first argument is `X`. –  May 18 '16 at 12:28
  • 1
    In your last clause, `X` and `AccA` are singleton. Is that intentional? Also, the second clause to `fp/4` calls `fp([b|AccA], _, F)` (`fp/3`) which doesn't exist. – lurker May 18 '16 at 12:29
  • Ok, I made mistake during writing this post, I corrected it. –  May 18 '16 at 12:37
  • 1
    The code you are showing doesn't yield the results you are showing. – lurker May 18 '16 at 12:45
  • Look again, sorry for my errors. –  May 18 '16 at 13:00
  • `append(_, [b|AccB], F)` and `append([a|AccA], _, F)` are asking for trouble. There are a nearly endless number of solutions to these queries, which (if you look at your `trace`) is where your code is looping as it checks every one of them trying to find another solution. You want to think about refactoring to avoid these particular queries. – lurker May 18 '16 at 13:06
  • Please first remove the `!/0`: It destroys the logical meaning of your program. For example, try with the current version the query: `?- fp(L, F).`. You only obtain a *single* solution, `F = L = []`. Obviously there should be many more terms for which this relation holds! – mat May 18 '16 at 13:07
  • Avoiding `append` is not such easy.. –  May 18 '16 at 13:09
  • @HaskellFun yes, `append/3` is very handy and always tempting to use. Sometimes, though, a custom predicate that does more precisely what you want is more suitable, or sometimes there's a way to constrain the arguments for `append/3` so they are more bounded. Or, there might be a way to completely rethink the problem... – lurker May 18 '16 at 13:21

1 Answers1

1

The problem is that the query to append/3 with so many variables yields a very a nearly unbounded number of solutions to try. One way to constrain it is to ensure the list lengths are the same. And as @mat says, you get rid of the cut.

fp(L, F) :-
   same_length(L, F),
   fp(L, [], [], F).

fp([], AccA, AccB, F):-
   append(AccA, AccB, F).
fp([a|L], AccA, AccB, F) :-
   append([a|AccA], _, F),
   fp(L, [a|AccA], AccB, F).
fp([b|L], AccA, AccB, F) :-
   append(_, [b|AccB], F),

same_length/2 is defined in SWI Prolog already, but has a simple implementation:

same_length([], []).
same_length([_|T1], [_|T2]) :- same_length(T1, T2).

| ?- fp(X, [a,b,b,b]).

X = [a,b,b,b] ? a

X = [b,a,b,b]

X = [b,b,a,b]

X = [b,b,b,a]

(1 ms) no
| ?- fp([a,b,a], X).

X = [a,a,b] ? a

no
| ?-
lurker
  • 56,987
  • 9
  • 69
  • 103