|
| 1 | + |
1 | 2 | (* :Title: Combinatorica |
2 | 3 | *) |
3 | 4 | (* :Author: |
|
14 | 15 | 350 Bridge Parkway, Redwood City CA 94065. ISBN 0-201-50943-1. |
15 | 16 | For ordering information, call 1-800-447-2226. |
16 | 17 |
|
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. |
| 18 | +These (and related) programs are available by anonymous ftp.cs.sunysb.edu |
| 19 | +in the pub/Combinatorica directory. They can also be obtained on |
| 20 | +Macintosh and MS-DOS disks by sending $15.00 to Discrete Mathematics Disk, |
| 21 | +Wolfram Research Inc., PO Box 6059, Champaign, IL 61826-9905. (217)-398-0700. |
20 | 22 |
|
21 | 23 | Any comments, bug reports, or requests to get on the Combinatorica |
22 | 24 | mailing list should be forwarded to: |
|
32 | 34 | *) |
33 | 35 | (* :Context: DiscreteMath`Combinatorica` |
34 | 36 | *) |
35 | | -(* :Package Version: .9 (2/29/92 Beta Release) |
36 | | -*) |
| 37 | +(* :Package Version: .91 (3/23/95 Beta Release) |
| 38 | + *) |
37 | 39 |
|
38 | 40 | (**** Note: some very small changes have been made to make this |
39 | | -to work with Mathics 1.1.1 ****) |
| 41 | +to work with Mathics3 ****) |
40 | 42 |
|
41 | | -(* :Copyright: Copyright 1990, 1991, 1992 by Steven S. Skiena |
| 43 | +(* :Copyright: Copyright 1990--1995 by Steven S. Skiena |
42 | 44 |
|
43 | 45 | This package may be copied in its entirety for nonprofit purposes only. |
44 | 46 | Sale, other than for the direct cost of the media, is prohibited. This |
|
54 | 56 | incidental, or consequential damages. |
55 | 57 | *) |
56 | 58 | (* :History: |
| 59 | + Version .9 by Steven S. Skiena, February 1992. |
57 | 60 | Version .8 by Steven S. Skiena, July 1991. |
58 | 61 | Version .7 by Steven S. Skiena, January 1991. |
59 | 62 | Version .6 by Steven S. Skiena, June 1990. |
|
77 | 80 | and Graph Theory with Mathematica", |
78 | 81 | Addison-Wesley Publishing Co. |
79 | 82 | *) |
80 | | -(* :Mathematica Version: 0.9.0 for Mathics |
81 | | - This is Mathematica Version 0.9 adapted for Mathics. |
| 83 | +(* :Mathematica Version: 2.3 |
82 | 84 | *) |
83 | 85 |
|
84 | | -BeginPackage["DiscreteMath`CombinatoricaV0.9`"] |
85 | | -Unprotect[All] |
86 | | -Unprotect[Subsets] |
| 86 | +BeginPackage["DiscreteMath`CombinatoricaV0.91`"] |
87 | 87 |
|
88 | 88 | 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." |
89 | 89 |
|
|
137 | 137 |
|
138 | 138 | ChromaticNumber::usage = "ChromaticNumber[g] computes the chromatic number of the graph, the fewest number of colors necessary to color the graph." |
139 | 139 |
|
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." |
| 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 at most z colors." |
141 | 141 |
|
142 | 142 | 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." |
143 | 143 |
|
|
599 | 599 |
|
600 | 600 | (* Section 1.1.1 Lexicographically Ordered Permutions, Pages 3-4 *) |
601 | 601 |
|
| 602 | +LexicographicPermutations[{}] := {{}} |
| 603 | + |
602 | 604 | LexicographicPermutations[{l_}] := {{l}} |
603 | 605 |
|
604 | 606 | LexicographicPermutations[{a_,b_}] := {{a,b},{b,a}} |
|
626 | 628 | RankPermutation[p_?PermutationQ] := (p[[1]]-1) (Length[Rest[p]]!) + |
627 | 629 | RankPermutation[ Map[(If[#>p[[1]], #-1, #])&, Rest[p]] ] |
628 | 630 |
|
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] |
| 631 | +NthPermutation[n1_Integer,l_List] := |
| 632 | + Module[{k, n=n1, s=l, i}, |
| 633 | + Table[ |
| 634 | + n = Mod[n,(i+1)!]; |
| 635 | + k = s [[Quotient[n,i!]+1]]; |
| 636 | + s = Complement[s,{k}]; |
| 637 | + k, |
| 638 | + {i,Length[l]-1,0,-1} |
| 639 | + ] |
| 640 | + ] |
653 | 641 |
|
654 | 642 | NextPermutation[p_?PermutationQ] := |
655 | 643 | NthPermutation[ RankPermutation[p]+1, Sort[p] ] |
656 | 644 |
|
657 | 645 | (* Section 1.1.3 RandomPermutations, Pages 6-7 *) |
658 | 646 |
|
659 | | -(*** FIXME: |
660 | | - ListPlot[ RandomPermutation1[30]] |
661 | | -shows that RandomPermutaion1 isn't good. Therefore we use RandomPermutation2 |
662 | | -for RandomPermutation. |
663 | | - ****) |
664 | | - |
665 | 647 | RandomPermutation1[n_Integer?Positive] := |
666 | 648 | Map[ Last, Sort[ Map[({RandomInteger[],#})&,Range[n]] ] ] |
667 | 649 |
|
|
675 | 657 | p |
676 | 658 | ] |
677 | 659 |
|
678 | | -RandomPermutation[n_Integer?Positive] := RandomPermutation2[n] |
| 660 | +RandomPermutation[n_Integer?Positive] := RandomPermutation1[n] |
679 | 661 |
|
680 | 662 | (* Section 1.1.4 Permutation from Transpostions, Page 11 *) |
681 | 663 | MinimumChangePermutations[l_List] := |
|
723 | 705 | Solution[space_List,index_List,count_Integer] := |
724 | 706 | Module[{i}, Table[space[[ i,index[[i]] ]], {i,count}] ] |
725 | 707 |
|
| 708 | +DistinctPermutations[s_List] := Permutations[s] /; (Length[s] == 1) |
| 709 | + |
726 | 710 | DistinctPermutations[s_List] := |
727 | 711 | Module[{freq,alph=Union[s],n=Length[s]}, |
728 | 712 | freq = Map[ (Count[s,#])&, alph]; |
|
797 | 781 | ReflexiveQ[r_?SquareMatrixQ] := |
798 | 782 | Module[{i}, Apply[And, Table[(r[[i,i]]!=0),{i,Length[r]}] ] ] |
799 | 783 |
|
800 | | -TransitiveQ[r_?SquareMatrixQ] := TransitiveQ[ Graph[v,RandomVertices[Length[r]]] ] |
| 784 | +TransitiveQ[r_?SquareMatrixQ] := TransitiveQ[ Graph[r,RandomVertices[Length[r]]] ] |
801 | 785 | TransitiveQ[r_Graph] := IdenticalQ[r,TransitiveClosure[r]] |
802 | 786 |
|
803 | 787 | SymmetricQ[r_?SquareMatrixQ] := (r === Transpose[r]) |
|
904 | 888 |
|
905 | 889 | (* 1.3.1 Inversion Vectors, Page 27 *) |
906 | 890 | FromInversionVector[vec_List] := |
907 | | - Block[{n=Length[vec]+1,i,p={n}}, |
| 891 | + Module[{n=Length[vec]+1,i,p}, |
| 892 | + p={n}; |
908 | 893 | Do [ |
909 | 894 | p = Insert[p, i, vec[[i]]+1], |
910 | 895 | {i,n-1,1,-1} |
|
1040 | 1025 | Join[ prev, Map[(Append[#,First[l]])&,Reverse[prev]] ] |
1041 | 1026 | ] |
1042 | 1027 |
|
1043 | | -(* We have a builtin that does this. |
1044 | | -GrayCode doesn't work? |
| 1028 | +(* rocky hacked: is already in Mathics3 |
1045 | 1029 | Subsets[l_List] := GrayCode[l] |
1046 | 1030 | Subsets[n_Integer] := GrayCode[Range[n]] |
1047 | 1031 | *) |
|
1095 | 1079 | ] |
1096 | 1080 | ] |
1097 | 1081 | ]] |
1098 | | - ] |
| 1082 | + ] /; (k <= Length[set]) |
1099 | 1083 |
|
1100 | 1084 | PartitionQ[p_List] := (Min[p]>0) && Apply[And, Map[IntegerQ,p]] |
1101 | 1085 |
|
|
1133 | 1117 | Show[ |
1134 | 1118 | Graphics[ |
1135 | 1119 | Join[ |
1136 | | - {PointSize[ Min[0.04,1/(2 Max[p])] ]}, |
| 1120 | + {PointSize[ Min[0.05,1/(2 Max[p])] ]}, |
1137 | 1121 | Table[Point[{i,j}], {j,n}, {i,p[[j]]}] |
1138 | 1122 | ], |
1139 | 1123 | {AspectRatio -> 1, PlotRange -> All} |
1140 | 1124 | ] |
1141 | 1125 | ] |
1142 | 1126 | ] |
1143 | 1127 |
|
| 1128 | +TransposePartition[{}] := {} |
| 1129 | + |
1144 | 1130 | TransposePartition[p_List] := |
1145 | 1131 | Module[{s=Select[p,(#>0)&], i, row, r}, |
1146 | 1132 | row = Length[s]; |
|
1176 | 1162 | ] |
1177 | 1163 | ] |
1178 | 1164 |
|
| 1165 | +(* from Paul Chase *) |
| 1166 | + |
1179 | 1167 | 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 | | - ] |
| 1168 | + Module[{mult = Table[0, {n}], j, d, r=n, z}, |
| 1169 | + While[ (r > 0), |
| 1170 | + d = 1; j = 0; |
| 1171 | + z = Random[] r PartitionsP[r]; |
| 1172 | + While [z >= 0, |
| 1173 | + j++; |
| 1174 | + If [r-j*d < 0, {j=1; d++;}]; |
| 1175 | + z -= j*PartitionsP[r-j*d]; |
| 1176 | + ]; |
| 1177 | + r -= j d; |
| 1178 | + mult[[j]] += d; |
| 1179 | + ]; |
| 1180 | + Reverse[Flatten[Table[Table[j, {mult[[j]]}], {j, Length[mult]}]]] |
| 1181 | + ] |
1205 | 1182 |
|
1206 | 1183 | NumberOfCompositions[n_,k_] := Binomial[ n+k-1, n ] |
1207 | 1184 |
|
|
2693 | 2670 | Graph[reduction,Vertices[g]] |
2694 | 2671 | ] |
2695 | 2672 |
|
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]} |
| 2673 | +(*thanks Christoph Strnadl*) |
| 2674 | + |
| 2675 | +HasseDiagram[g_,fak_:1] := |
| 2676 | + Module[{r, rank, m, stages, freq=Table[0,{V[g]}], |
| 2677 | + adjm, first}, |
| 2678 | + r = TransitiveReduction[ RemoveSelfLoops[g] ]; |
| 2679 | + adjm = ToAdjacencyLists[r]; |
| 2680 | + rank = Table[ 0,{ V[g]} ]; |
| 2681 | + first = Select[ Range[ V[g]], InDegree[r,#]==0& ]; |
| 2682 | + rank = MakeLevel[ first, 1, adjm, rank]; |
| 2683 | + first = Max[rank]; |
| 2684 | + stages = Distribution[ rank ]; |
| 2685 | + Graph[ |
| 2686 | + Edges[r], |
| 2687 | + Table[ |
| 2688 | + m = ++ freq[[ rank[[i]] ]]; |
| 2689 | + { ((m-1) + (1-stages[[rank[[i]] ]])/2) fak^(first-rank[[i]]), |
| 2690 | + rank[[i]] }, |
| 2691 | + {i, V[g]} |
2712 | 2692 | ] |
2713 | 2693 | ] |
2714 | | - ] /; AcyclicQ[RemoveSelfLoops[g],Directed] |
| 2694 | + ] /; AcyclicQ[ RemoveSelfLoops[g],Directed ] |
| 2695 | + |
| 2696 | +(* |
| 2697 | + * SetLevel[{p1,p2,...},lvl,rank] sets the positions p1, p2,.. of |
| 2698 | + * list rank to the level lvl, if the old entry at that position |
| 2699 | + * is less than level. |
| 2700 | + *) |
| 2701 | +SetLevel[l_List,lvl_,rank_List] := |
| 2702 | + Module[ {r=rank}, |
| 2703 | + If[ r[[#]] < lvl, r[[#]] = lvl ] & /@ l; |
| 2704 | + r |
| 2705 | + ] |
| 2706 | + |
| 2707 | +(* |
| 2708 | + * MakeLevel[l,level,adjm,rank] constructs recursively the ranks of |
| 2709 | + * each vertex according to the adjacency matrix adjm of the graph. |
| 2710 | + * rank is the current ranking, level the new level to assign and |
| 2711 | + * l = {v1,v2,..} the list of vertices to be set to level. |
| 2712 | + *) |
| 2713 | +MakeLevel[{},_,_,rank_] := rank |
| 2714 | + |
| 2715 | +MakeLevel[l_List,lvl_,adjm_List,r_List] := |
| 2716 | + Module[ {rank=r, v, lst=l }, |
| 2717 | + rank = SetLevel[lst,lvl,rank]; (* make this level ready *) |
| 2718 | + While[ lst != {}, |
| 2719 | + v = First[lst]; |
| 2720 | + rank = MakeLevel[adjm[[v]], lvl+1,adjm,rank]; |
| 2721 | + lst = Rest[lst]; |
| 2722 | + ]; |
| 2723 | + rank |
| 2724 | + ] |
| 2725 | + |
| 2726 | +(* |
| 2727 | + * HasseDiagram[g] renders a graph corresponding to the HasseDiagram of |
| 2728 | + * the partial order induced by the directed graph g. |
| 2729 | + * HasseDiagram[g,fac] renders the HasseDiagram in which each vertex' |
| 2730 | + * position is stretched by factor fac. In each stage that factor |
| 2731 | + * is taken to the power of the distance to the 1 element. |
| 2732 | + *) |
| 2733 | + |
2715 | 2734 |
|
2716 | 2735 | TopologicalSort[g_Graph] := |
2717 | 2736 | Module[{g1 = RemoveSelfLoops[g],e,indeg,zeros,v}, |
|
3180 | 3199 | (aj < Max[b]) |
3181 | 3200 | ] |
3182 | 3201 |
|
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 | | - |
3215 | 3202 | End[] |
3216 | 3203 |
|
3217 | 3204 | Protect[ |
|
0 commit comments