Skip to content

Commit a9c2abf

Browse files
authored
Merge pull request #803 from Mathics3/combinatorica-91
Use recently-found V0.91 version
2 parents acb3265 + 285ffad commit a9c2abf

File tree

2 files changed

+124
-128
lines changed

2 files changed

+124
-128
lines changed

mathics/packages/DiscreteMath/CombinatoricaV0.9.m

Lines changed: 113 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
350 Bridge Parkway, Redwood City CA 94065. ISBN 0-201-50943-1.
1515
For ordering information, call 1-800-447-2226.
1616
17-
These programs can be obtained on Macintosh and MS-DOS disks by sending
18-
$15.00 to Discrete Mathematics Disk, Wolfram Research Inc.,
19-
PO Box 6059, Champaign, IL 61826-9905. (217)-398-0700.
17+
These (and related) programs are available by anonymous ftp.cs.sunysb.edu
18+
in the pub/Combinatorica directory. They can also be obtained on
19+
Macintosh and MS-DOS disks by sending $15.00 to Discrete Mathematics Disk,
20+
Wolfram Research Inc., PO Box 6059, Champaign, IL 61826-9905. (217)-398-0700.
2021
2122
Any comments, bug reports, or requests to get on the Combinatorica
2223
mailing list should be forwarded to:
@@ -32,13 +33,13 @@
3233
*)
3334
(* :Context: DiscreteMath`Combinatorica`
3435
*)
35-
(* :Package Version: .9 (2/29/92 Beta Release)
36-
*)
36+
(* :Package Version: .91 (3/23/95 Beta Release)
37+
*)
3738

3839
(**** Note: some very small changes have been made to make this
39-
to work with Mathics 1.1.1 ****)
40+
to work with Mathics3 ****)
4041

41-
(* :Copyright: Copyright 1990, 1991, 1992 by Steven S. Skiena
42+
(* :Copyright: Copyright 1990--1995 by Steven S. Skiena
4243
4344
This package may be copied in its entirety for nonprofit purposes only.
4445
Sale, other than for the direct cost of the media, is prohibited. This
@@ -54,6 +55,7 @@
5455
incidental, or consequential damages.
5556
*)
5657
(* :History:
58+
Version .9 by Steven S. Skiena, February 1992.
5759
Version .8 by Steven S. Skiena, July 1991.
5860
Version .7 by Steven S. Skiena, January 1991.
5961
Version .6 by Steven S. Skiena, June 1990.
@@ -77,13 +79,10 @@
7779
and Graph Theory with Mathematica",
7880
Addison-Wesley Publishing Co.
7981
*)
80-
(* :Mathematica Version: 0.9.0 for Mathics
81-
This is Mathematica Version 0.9 adapted for Mathics.
82+
(* :Mathematica Version: 2.3
8283
*)
8384

84-
BeginPackage["DiscreteMath`CombinatoricaV0.9`"]
85-
Unprotect[All]
86-
Unprotect[Subsets]
85+
BeginPackage["DiscreteMath`CombinatoricaV0.91`"]
8786

8887
Graph::usage = "Graph[g,v] is the header for a graph object where g is an adjacency matrix and v is a list of vertices."
8988

@@ -137,7 +136,7 @@
137136

138137
ChromaticNumber::usage = "ChromaticNumber[g] computes the chromatic number of the graph, the fewest number of colors necessary to color the graph."
139138

140-
ChromaticPolynomial::usage = "ChromaticPolynomial[g,z] returns the chromatic polynomial P(z) of graph g, which counts the number of ways to color g with exactly z colors."
139+
ChromaticPolynomial::usage = "ChromaticPolynomial[g,z] returns the chromatic polynomial P(z) of graph g, which counts the number of ways to color g with at most z colors."
141140

142141
CirculantGraph::usage = "CirculantGraph[n,l] constructs a circulant graph on n vertices, meaning the ith vertex is adjacent to the (i+j)th and (i-j)th vertex, for each j in list l."
143142

@@ -599,6 +598,8 @@
599598

600599
(* Section 1.1.1 Lexicographically Ordered Permutions, Pages 3-4 *)
601600

601+
LexicographicPermutations[{}] := {{}}
602+
602603
LexicographicPermutations[{l_}] := {{l}}
603604

604605
LexicographicPermutations[{a_,b_}] := {{a,b},{b,a}}
@@ -626,30 +627,16 @@
626627
RankPermutation[p_?PermutationQ] := (p[[1]]-1) (Length[Rest[p]]!) +
627628
RankPermutation[ Map[(If[#>p[[1]], #-1, #])&, Rest[p]] ]
628629

629-
(* UP, and UnrankPermutation come from the V2.1 code.
630-
There is some problem in the v0.9 code and rather than try to fix that
631-
we use the newer version
632-
*)
633-
UP[r_Integer, n_Integer] :=
634-
Module[{r1 = r, q = n!, i},
635-
Table[r1 = Mod[r1, q];
636-
q = q/(n - i + 1);
637-
Quotient[r1, q] + 1,
638-
{i, n}
639-
]
640-
]
641-
UnrankPermutation[r_Integer, {}] := {}
642-
UnrankPermutation[r_Integer, l_List] :=
643-
Module[{s = l, k, t, p = UP[Mod[r, Length[l]!], Length[l]], i},
644-
Table[k = s[[t = p[[i]] ]];
645-
s = Delete[s, t];
646-
k,
647-
{i, Length[ p ]}
648-
]
649-
]
650-
UnrankPermutation[r_Integer, n_Integer?Positive] :=
651-
UnrankPermutation[r, Range[n]]
652-
NthPermutation[r_Integer, l_List] := UnrankPermutation[r, l]
630+
NthPermutation[n1_Integer,l_List] :=
631+
Block[{k, n=n1, s=l, i},
632+
Table[
633+
n = Mod[n,(i+1)!];
634+
k = s [[Quotient[n,i!]+1]];
635+
s = Complement[s,{k}];
636+
k,
637+
{i,Length[l]-1,0,-1}
638+
]
639+
]
653640

654641
NextPermutation[p_?PermutationQ] :=
655642
NthPermutation[ RankPermutation[p]+1, Sort[p] ]
@@ -658,7 +645,7 @@
658645

659646
(*** FIXME:
660647
ListPlot[ RandomPermutation1[30]]
661-
shows that RandomPermutaion1 isn't good. Therefore we use RandomPermutation2
648+
shows that RandomPermutaiton1 isn't good. Therefore we use RandomPermutation2
662649
for RandomPermutation.
663650
****)
664651

@@ -675,6 +662,7 @@
675662
p
676663
]
677664

665+
(* rocky: RandomPermutation1 not random, so use RandomPermutation2 *)
678666
RandomPermutation[n_Integer?Positive] := RandomPermutation2[n]
679667

680668
(* Section 1.1.4 Permutation from Transpostions, Page 11 *)
@@ -723,6 +711,8 @@
723711
Solution[space_List,index_List,count_Integer] :=
724712
Module[{i}, Table[space[[ i,index[[i]] ]], {i,count}] ]
725713

714+
DistinctPermutations[s_List] := Permutations[s] /; (Length[s] == 1)
715+
726716
DistinctPermutations[s_List] :=
727717
Module[{freq,alph=Union[s],n=Length[s]},
728718
freq = Map[ (Count[s,#])&, alph];
@@ -797,7 +787,7 @@
797787
ReflexiveQ[r_?SquareMatrixQ] :=
798788
Module[{i}, Apply[And, Table[(r[[i,i]]!=0),{i,Length[r]}] ] ]
799789

800-
TransitiveQ[r_?SquareMatrixQ] := TransitiveQ[ Graph[v,RandomVertices[Length[r]]] ]
790+
TransitiveQ[r_?SquareMatrixQ] := TransitiveQ[ Graph[r,RandomVertices[Length[r]]] ]
801791
TransitiveQ[r_Graph] := IdenticalQ[r,TransitiveClosure[r]]
802792

803793
SymmetricQ[r_?SquareMatrixQ] := (r === Transpose[r])
@@ -904,7 +894,8 @@
904894

905895
(* 1.3.1 Inversion Vectors, Page 27 *)
906896
FromInversionVector[vec_List] :=
907-
Block[{n=Length[vec]+1,i,p={n}},
897+
Module[{n=Length[vec]+1,i,p},
898+
p={n};
908899
Do [
909900
p = Insert[p, i, vec[[i]]+1],
910901
{i,n-1,1,-1}
@@ -1040,8 +1031,7 @@
10401031
Join[ prev, Map[(Append[#,First[l]])&,Reverse[prev]] ]
10411032
]
10421033

1043-
(* We have a builtin that does this.
1044-
GrayCode doesn't work?
1034+
(* rocky hacked: is already in Mathics3
10451035
Subsets[l_List] := GrayCode[l]
10461036
Subsets[n_Integer] := GrayCode[Range[n]]
10471037
*)
@@ -1095,7 +1085,7 @@
10951085
]
10961086
]
10971087
]]
1098-
]
1088+
] /; (k <= Length[set])
10991089

11001090
PartitionQ[p_List] := (Min[p]>0) && Apply[And, Map[IntegerQ,p]]
11011091

@@ -1133,14 +1123,16 @@
11331123
Show[
11341124
Graphics[
11351125
Join[
1136-
{PointSize[ Min[0.04,1/(2 Max[p])] ]},
1126+
{PointSize[ Min[0.05,1/(2 Max[p])] ]},
11371127
Table[Point[{i,j}], {j,n}, {i,p[[j]]}]
11381128
],
11391129
{AspectRatio -> 1, PlotRange -> All}
11401130
]
11411131
]
11421132
]
11431133

1134+
TransposePartition[{}] := {}
1135+
11441136
TransposePartition[p_List] :=
11451137
Module[{s=Select[p,(#>0)&], i, row, r},
11461138
row = Length[s];
@@ -1176,32 +1168,23 @@
11761168
]
11771169
]
11781170

1171+
(* from Paul Chase *)
1172+
11791173
RandomPartition[n_Integer?Positive] :=
1180-
Module[{mult = Table[0,{n}],j,d,m = n},
1181-
While[ m != 0,
1182-
{j,d} = NextPartitionElement[m];
1183-
m -= j d;
1184-
mult[[d]] += j;
1185-
];
1186-
Flatten[Map[(Table[#,{mult[[#]]}])&,Reverse[Range[n]]]]
1187-
]
1188-
1189-
NextPartitionElement[n_Integer] :=
1190-
Module[{d=0,j,m,z=RandomInteger[] n PartitionsP[n],done=False,flag},
1191-
While[!done,
1192-
d++; m = n; j = 0; flag = False;
1193-
While[ !flag,
1194-
j++; m -=d;
1195-
If[ m > 0,
1196-
z -= d PartitionsP[m];
1197-
If[ z <= 0, flag=done=True],
1198-
flag = True;
1199-
If[m==0, z -=d; If[z <= 0, done = True]]
1200-
];
1201-
];
1202-
];
1203-
{j,d}
1204-
]
1174+
Module[{mult = Table[0, {n}], j, d, r=n, z},
1175+
While[ (r > 0),
1176+
d = 1; j = 0;
1177+
z = Random[] r PartitionsP[r];
1178+
While [z >= 0,
1179+
j++;
1180+
If [r-j*d < 0, {j=1; d++;}];
1181+
z -= j*PartitionsP[r-j*d];
1182+
];
1183+
r -= j d;
1184+
mult[[j]] += d;
1185+
];
1186+
Reverse[Flatten[Table[Table[j, {mult[[j]]}], {j, Length[mult]}]]]
1187+
]
12051188

12061189
NumberOfCompositions[n_,k_] := Binomial[ n+k-1, n ]
12071190

@@ -1250,10 +1233,11 @@
12501233

12511234
ShapeOfTableau[t_List] := Map[Length,t]
12521235

1236+
(* Section 2.3.1 Insertion and Deletion, Page 64 *)
12531237
InsertIntoTableau[e_Integer,{}] := { {e} }
12541238

12551239
InsertIntoTableau[e_Integer, t1_?TableauQ] :=
1256-
Module[{item=e,row=0,col,t=t1},
1240+
Block[{item=e,row=0,col,t=t1},
12571241
While [row < Length[t],
12581242
row++;
12591243
If [Last[t[[row]]] <= item,
@@ -2693,25 +2677,67 @@
26932677
Graph[reduction,Vertices[g]]
26942678
]
26952679

2696-
HasseDiagram[g_Graph] :=
2697-
Module[{r,rank,m,stages,freq=Table[0,{V[g]}]},
2698-
r = TransitiveReduction[ RemoveSelfLoops[g] ];
2699-
rank = RankGraph[
2700-
MakeUndirected[r],
2701-
Select[Range[V[g]],(InDegree[r,#]==0)&]
2702-
];
2703-
m = Max[rank];
2704-
rank = MapAt[(m)&,rank,Position[OutDegree[r],0]];
2705-
stages = Distribution[ rank ];
2706-
Graph[
2707-
Edges[r],
2708-
Table[
2709-
m = ++ freq[[ rank[[i]] ]];
2710-
{(m-1) + (1-stages[[rank[[i]] ]])/2, rank[[i]]},
2711-
{i,V[g]}
2680+
(*thanks Christoph Strnadl*)
2681+
2682+
HasseDiagram[g_,fak_:1] :=
2683+
Module[{r, rank, m, stages, freq=Table[0,{V[g]}],
2684+
adjm, first},
2685+
r = TransitiveReduction[ RemoveSelfLoops[g] ];
2686+
adjm = ToAdjacencyLists[r];
2687+
rank = Table[ 0,{ V[g]} ];
2688+
first = Select[ Range[ V[g]], InDegree[r,#]==0& ];
2689+
rank = MakeLevel[ first, 1, adjm, rank];
2690+
first = Max[rank];
2691+
stages = Distribution[ rank ];
2692+
Graph[
2693+
Edges[r],
2694+
Table[
2695+
m = ++ freq[[ rank[[i]] ]];
2696+
{ ((m-1) + (1-stages[[rank[[i]] ]])/2) fak^(first-rank[[i]]),
2697+
rank[[i]] },
2698+
{i, V[g]}
27122699
]
27132700
]
2714-
] /; AcyclicQ[RemoveSelfLoops[g],Directed]
2701+
] /; AcyclicQ[ RemoveSelfLoops[g],Directed ]
2702+
2703+
(*
2704+
* SetLevel[{p1,p2,...},lvl,rank] sets the positions p1, p2,.. of
2705+
* list rank to the level lvl, if the old entry at that position
2706+
* is less than level.
2707+
*)
2708+
SetLevel[l_List,lvl_,rank_List] :=
2709+
Module[ {r=rank},
2710+
If[ r[[#]] < lvl, r[[#]] = lvl ] & /@ l;
2711+
r
2712+
]
2713+
2714+
(*
2715+
* MakeLevel[l,level,adjm,rank] constructs recursively the ranks of
2716+
* each vertex according to the adjacency matrix adjm of the graph.
2717+
* rank is the current ranking, level the new level to assign and
2718+
* l = {v1,v2,..} the list of vertices to be set to level.
2719+
*)
2720+
MakeLevel[{},_,_,rank_] := rank
2721+
2722+
MakeLevel[l_List,lvl_,adjm_List,r_List] :=
2723+
Module[ {rank=r, v, lst=l },
2724+
rank = SetLevel[lst,lvl,rank]; (* make this level ready *)
2725+
While[ lst != {},
2726+
v = First[lst];
2727+
rank = MakeLevel[adjm[[v]], lvl+1,adjm,rank];
2728+
lst = Rest[lst];
2729+
];
2730+
rank
2731+
]
2732+
2733+
(*
2734+
* HasseDiagram[g] renders a graph corresponding to the HasseDiagram of
2735+
* the partial order induced by the directed graph g.
2736+
* HasseDiagram[g,fac] renders the HasseDiagram in which each vertex'
2737+
* position is stretched by factor fac. In each stage that factor
2738+
* is taken to the power of the distance to the 1 element.
2739+
*)
2740+
27152741

27162742
TopologicalSort[g_Graph] :=
27172743
Module[{g1 = RemoveSelfLoops[g],e,indeg,zeros,v},
@@ -3180,38 +3206,6 @@
31803206
(aj < Max[b])
31813207
]
31823208

3183-
KSetPartitions::usage = "KSetPartitions[set, k] returns the list of set partitions of set with k blocks. KSetPartitions[n, k] returns the list of set partitions of {1, 2, ..., n} with k blocks. If all set partitions of a set are needed, use the function SetPartitions."
3184-
KSetPartitions[{}, 0] := {{}}
3185-
KSetPartitions[s_List, 0] := {}
3186-
KSetPartitions[s_List, k_Integer] := {} /; (k > Length[s])
3187-
KSetPartitions[s_List, k_Integer] := {Map[{#} &, s]} /; (k === Length[s])
3188-
KSetPartitions[s_List, k_Integer] :=
3189-
Block[{$RecursionLimit = Infinity},
3190-
Join[Map[Prepend[#, {First[s]}] &, KSetPartitions[Rest[s], k - 1]],
3191-
Flatten[
3192-
Map[Table[Prepend[Delete[#, j], Prepend[#[[j]], s[[1]]]],
3193-
{j, Length[#]}
3194-
]&,
3195-
KSetPartitions[Rest[s], k]
3196-
], 1
3197-
]
3198-
]
3199-
] /; (k > 0) && (k < Length[s])
3200-
3201-
KSetPartitions[0, 0] := {{}}
3202-
KSetPartitions[0, k_Integer?Positive] := {}
3203-
KSetPartitions[n_Integer?Positive, 0] := {}
3204-
KSetPartitions[n_Integer?Positive, k_Integer?Positive] := KSetPartitions[Range[n], k]
3205-
3206-
SetPartitions::usage = "SetPartitions[set] returns the list of set partitions of set. SetPartitions[n] returns the list of set partitions of {1, 2, ..., n}. If all set partitions with a fixed number of subsets are needed use KSetPartitions."
3207-
3208-
SetPartitions[{}] := {{}}
3209-
SetPartitions[s_List] := Flatten[Table[KSetPartitions[s, i], {i, Length[s]}], 1]
3210-
3211-
SetPartitions[0] := {{}}
3212-
SetPartitions[n_Integer?Positive] := SetPartitions[Range[n]]
3213-
3214-
32153209
End[]
32163210

32173211
Protect[

0 commit comments

Comments
 (0)