6

Does anyone know of a replacement for NextPermutation in Combinatorica? The problem with loading Combinatorica is that it interferes with new functionality which I also want to use. I need to generate all the permutations of a list in lexicographic order one by one. Thanks for your help.

J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
EGME
  • 647
  • 3
  • 7
  • If you want all permutations in canonical order just use Permutations For

    perm = Permutations[{a, b, c, d, e, f, g}]; then

    OrderedQ[perm] evaluates to

    True

    – Bob Hanlon Oct 06 '19 at 15:11
  • 2
    @BobHanlon The problem with this approach is that you get all the permutations at once in memory, which I want to avoid ... I want to access them one by one, else there are too many ... there are close to 40 M permutations with lists that have 11 members, too many to have in memory, but it is possible with some time to look at each one of them and seek the property I want ... does this make sense? – EGME Oct 06 '19 at 15:17
  • Can you explain more about what do you need to do? (Not all people here might be familiar with the Combinatorica package). – TumbiSapichu Oct 06 '19 at 15:33
  • @TumbiSapichu Right: I would like to access each and all of the permutations of a list, one at a time. A function like Permutations that returns all the permutations is of no use, given the large number of permutations that I need to inspect. The logical way make sure you access each and every permutation is to do so in some order, say, the lexicographic order. Does this make sense? So the function NextPermutation applied to the list {1,2,3} would return {1,3,2} ... essentially I want a function that implements this ... it used to exist, in the Combinatorica package ... contd. – EGME Oct 06 '19 at 15:38
  • @TumbiSapichu The problem with loading Combinatorica is that it overlaps with functionality that has replaced some of what is in there ... – EGME Oct 06 '19 at 15:38
  • Possible duplicate: https://mathematica.stackexchange.com/q/1283/12 (not the question but some of the answers) – Szabolcs Oct 06 '19 at 17:19
  • @Szabolcs This problem arises for me in trying to access all the hamiltonian circuits of the complete graph one by one ... although FindHamiltonCycle and FindCycle work quite well, they don’t have this feature ... something worth considering for IGraph ... and the functions for finding paths are not that good ... – EGME Oct 07 '19 at 07:43
  • @EGME I understand the value of such a feature, I even wrote a post about it on Wolfram Community. Unfortunately, I have less and less time for IGraph/M and anything that's not directly related to my work is likely to proceed only at a snail's pace ... – Szabolcs Oct 07 '19 at 07:49
  • @Szabolcs Pity ... hope you don’t completely abandon IGraph ... indeed more is needed! All the best – EGME Oct 07 '19 at 07:50
  • @EGME No, I absolutely won't abandon it, but things are progressing slowly right now. – Szabolcs Oct 07 '19 at 07:54

5 Answers5

8

See page 57 of the book Computational Discrete Mathematics by Pemmaraju and Skiena.

NextPermutation[l_List] := Sort[l] /; (l === Reverse[Sort[l]])

NextPermutation[l_List] :=
   Module[{n = Length[l], i, j, t, nl = l},
      i = n - 1;
      While[Order[nl[[i]], nl[[i + 1]]] == -1, i--];
      j = n;
      While[Order[nl[[j]], nl[[i]]] == 1, j--];
      {nl[[i]], nl[[j]]} = {nl[[j]], nl[[i]]};
      Join[Take[nl, i], Reverse[Drop[nl, i]]]
   ]

For example:

NextPermutation[{8, 7, 6, 5, 4, 3, 2, 1}]

{1, 2, 3, 4, 5, 6, 7, 8}

NextPermutation[{7, 12, 4, 1, 3, 10, 5, 6, 8, 11, 2, 9}]

{7, 12, 4, 1, 3, 10, 5, 6, 8, 11, 9, 2}

KennyColnago
  • 15,209
  • 26
  • 62
  • Thank you, this is quite useful, not having the book - even if ideally, I want a “plug and play” replacement which is as fast as possible - thanks once again! – EGME Oct 07 '19 at 07:38
  • I should accept one of the two answers if nothing else comes, the problem is choosing one of the two! – EGME Oct 07 '19 at 07:39
  • 3
    Just as an extra remark: if you change the instances such as Order[x, y] == 1 (which doesn't compile) with OrderedQ[{x, y}] (which does), you can plonk the whole thing into Compile and get a much faster version for integers. – Sjoerd Smit Oct 07 '19 at 11:21
6

The best way for me to do what you are asking for is to, if I remember correctly from the last time I did something like this.

  1. Open up Combinatorica.m in a fresh notebook. It contains what looks like Mathematica code and Mathematica is happy to do this. The last time I looked the Combinatorica.m file is still there buried down inside the installed Mathematica files. Try searching your entire file system for the name if you can't find it.

  2. Scroll down and find the well written self contained definition of NextPermutation

  3. Scrape that definition into your clipboard

  4. Close the notebook without changing Combinatorica.m

  5. Open up your notebook

  6. Paste the definition into your notebook, along with credits, where it came from and how to find it and do this again if you need to

and you are ready to go with your own personal copy of NextPermutation in your notebook without any of the other definitions from combinatorica.m

Bill
  • 12,001
  • 12
  • 13
  • Thank you, this is also quite useful ... I haven’t tried it, but I think I will try it ... it solves a more general problem, and it is almost like plug and play, although this is not as optimized as might be ... as in the answer above, I would accept one of the two answers, were it not difficult to choose one, and waiting also for something else that might come around – EGME Oct 07 '19 at 07:41
  • Note that FindFile["Combinatorica`"] gives a hint where to look for the file. – Michael E2 Oct 07 '19 at 13:22
  • @EGME I don't assume that readers have a copy of "Computational Discrete Mathematics" on their shelves, although I've recommended that in the past. It seems more and more when I recommend looking in a book that the response is "Oh GAWD! Not a dead tree! Can't you just tell me where I can scrape the code." I'm not kidding, I've gotten that response from people. – Bill Oct 08 '19 at 15:28
  • @Bill Right ... I use libraries, or look for electronic copies of books ... many books now exist in electronic form ... maybe this one does, and I just didn’t look well enough. ... this one really seems like a book that ought to be in a shelf as you say, classics are worth getting even if in print, I think. – EGME Oct 08 '19 at 15:51
2

If you have a numeric list, we can get a substantial speedup by using Compile.

nextPerm = Compile[{{operm, _Integer, 1}},
  Module[{i, j, perm},
    perm = operm;
    j = Length[perm];
    i = j-1;
    While[i > 0 && perm[[i]] > perm[[i+1]], i--];
    If[i == 0, Return[Reverse[perm]]];
    While[perm[[j]] < perm[[i]], j--];
    perm[[{i, j}]] = perm[[{j, i}]];
    Join[perm[[1 ;; i]], perm[[-1 ;; i+1 ;; -1]]]
  ],
  CompilationTarget -> "C",
  RuntimeOptions -> "Speed"
];

Cycling through all permutations:

Nest[nextPerm, Range[11], 11!] // AbsoluteTiming
{29.7751, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}

Compare to Combinatorica:

<<Combinatorica`
Nest[NextPermutation, Range[11], 11!] // AbsoluteTiming
{637.568, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}
Greg Hurst
  • 35,921
  • 1
  • 90
  • 136
1

If you ever need a definition from an old function like this, you can try this trick to see if you can access the definition of the function directly:

<<Combinatorica`
GeneralUtilities`PrintDefinitions[NextPermutation]
Sjoerd Smit
  • 23,370
  • 46
  • 75
  • The source code of Combinatorica is available. It's better to read the source file, in case there are any comments. – Szabolcs Oct 07 '19 at 11:21
0

I have made use of commands from Combinatorica as well as more recent built-in commands, in the same code, and where their names have clashed, I have tried to differentiate between them by referring to them as, for example,

Combinatorica`SymmetricGroup

for the Combinatorica one, and

System`SymmetricGroup

for the more recent one, rather than just SymmetricGroup. This seems to have worked for me.

Simon
  • 1,415
  • 8
  • 13
  • 1
    I'd be curious to know what it is that you need from Combinatorica that you cannot get elsewhere. – Szabolcs Oct 07 '19 at 11:22
  • 2
    SetPartitions and RankSetPartition were two examples, I seem to remember, and I think that for some reason I preferred the Combinatorica version of SymmetricGroup, if indeed it's any different from the new one. – Simon Oct 07 '19 at 11:37
  • @Szabolcs I found a nasty graph related bug which calls for a replacement. However, I do not wish to post about bugs here, so I could send you a very short notebook with the example if you can be reached? By the way, why was this question closed ... I did not see parallel prior questions with these good answers, although it really doesn’t matter ... it has served its purpose, but that is not the reason given for its closure ... Apologies for asking, and thank you at the same time, I thought you might know, and also, be interested in the first issue ... – EGME Nov 29 '19 at 16:43