Question: I am having trouble getting my ipython to work after a regular python upgrade.
If I type: 

```
ipython notebook --pylab inline

```

I get the following error:

```
-bash: /usr/local/bin/ipython: No such file or directory

```

If I type:

```
which ipython

```

I get no response, just the command line prompt.
if I type:

```
which python

```

I get

```
/usr/bin/python

```

if I type:

```
ipython --version

```

I get the following error:

```
-bash: /usr/local/bin/ipython: No such file or directory

```

When I inspect my system I see that my Ipython is installed in:

```
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Ipython

```

**What should I do to make my ipython function again?** I had to fix the links for pip and easy\_install to get them to work after the python installation. I just can't seem to get ipython working again.

Answer: 
Here is a version of `bubble/3` that is deterministic if the first argument is instantiated, so that tail call optimisation (and, more specifically, tail recursion optimisation) applies:

```
bubble([L|Ls0], Ls, Max) :- phrase(bubble_(Ls0, L, Max), Ls).

bubble_([], Max, Max) --> [].
bubble_([L0|Ls0], Max0, Max) -->
        elements_max(L0, Max0, Max1),
        bubble_(Ls0, Max1, Max).

elements_max(X, Y, Max) -->
        { compare(C, X, Y) },
        c_max(C, X, Y, Max).

c_max(<, X, Y, Y) --> [X].
c_max(=, X, Y, Y) --> [X].
c_max(>, X, Y, X) --> [Y].

```

Example usage, with the rest of the program unchanged (running times depend on the random list, which is bad if you want to reproduce these results - hint: introduce the random seed as argument to fix this):

```
?- generate_list(100, 10_000, Ls), time(bubble_sort(Ls, Ls1)).
% 200,099,991 inferences, 29.769 CPU in 34.471 seconds
...

```

For testing different versions, please use a version of the query that you can use to reliably reproduce the same initial list, such as:

```
?- numlist(1, 10_000, Ls0), time(bubble_sort(Ls0, Ls)).

```

The nice thing is: If you just use `zcompare/3` from `library(clpfd)` instead of `compare/3`, you obtain a version that can be used in all directions:

```
?- bubble(Ls0, Ls, Max).
Ls0 = [Max],
Ls = [] ;
Ls0 = [Max, _G677],
Ls = [_G677],
_G677#=<Max+ -1,
zcompare(<, _G677, Max) ;
Ls0 = [Max, _G949, _G952],
Ls = [_G949, _G952],
_G952#=<Max+ -1,
_G949#=<Max+ -1,
zcompare(<, _G952, Max),
zcompare(<, _G949, Max) ;
etc.

```

This describes the relation in general terms between integers.
Disclaimer: following the hint by @mat could be more rewarding...

I've played a bit with your code, in my experiment the local stack overflow was thrown with a list length near 2500. Then I've placed some cut:

```
%% bubble(L, Ls, max):- insert list L and get max member of list by
%% swapping members from the start of L.
bubble([Z], [], Z).
bubble([X,Y|L], [R|Ls], Z):-
 ( X =< Y -> (R,T)=(X,Y) ; (R,T)=(Y,X) ),
 bubble([T|L], Ls, Z).

%% bubble_sort(List, Accumulator, Sorted_List)
bubblesort([X], Ls, [X|Ls]) :- !.
bubblesort(L, Accumulate, Result):-
 bubble(L, Ls, Max),
 !, bubblesort(Ls, [Max|Accumulate], Result).

```

and I get 

```
?- time(generate_list(100,10000,L)),time(bubble_sort(L,S)).
% 60,000 inferences, 0.037 CPU in 0.037 seconds (99% CPU, 1618231 Lips)
% 174,710,407 inferences, 85.707 CPU in 86.016 seconds (100% CPU, 2038460 Lips)
L = [98, 19, 80, 24, 16, 59, 70, 39, 22|...],
S = [0, 0, 0, 0, 0, 0, 0, 0, 0|...] 
.

```

so, it's working, but very slowly, showing the quadratic complexity...