Mercurial > octave
comparison scripts/specfun/perms.m @ 31031:8629bb61ef17
maint: perms.m: Copyedit docstring and comments to match Octave codestyle
perms.m: Copyedit docstring, add some spacing, remove commented-out fprintf.
author | Arun Giridhar <arungiridhar@gmail.com> |
---|---|
date | Thu, 26 May 2022 13:12:31 -0400 |
parents | f03e1eebf46d |
children | b949f8a631e2 |
comparison
equal
deleted
inserted
replaced
31030:ded93e72418d | 31031:8629bb61ef17 |
---|---|
28 ## @deftypefnx {} {@var{P} =} perms (@var{v}, "unique") | 28 ## @deftypefnx {} {@var{P} =} perms (@var{v}, "unique") |
29 ## Generate all permutations of vector @var{v} with one row per permutation. | 29 ## Generate all permutations of vector @var{v} with one row per permutation. |
30 ## | 30 ## |
31 ## Results are returned in inverse lexicographic order. The result has size | 31 ## Results are returned in inverse lexicographic order. The result has size |
32 ## @code{factorial (@var{n}) * @var{n}}, where @var{n} is the length of | 32 ## @code{factorial (@var{n}) * @var{n}}, where @var{n} is the length of |
33 ## @var{v}. Any repetitions are included in the output. | 33 ## @var{v}. Any repeated elements are included in the output. |
34 ## | 34 ## |
35 ## If the optional second argument is the string "unique", then only unique | 35 ## If the optional argument "unique" is given, then only unique permutations |
36 ## permutations are returned, using a method that uses less memory than | 36 ## are returned, using less memory and generally taking less time than calling |
37 ## @code{unique (perms (@var{v}), "rows")} and can be faster for | 37 ## @code{unique (perms (@var{v}), "rows")}. In this case, the results are |
38 ## certain inputs. In this case, the results are not guaranteed to be in any | 38 ## not guaranteed to be in any particular order. |
39 ## particular order. | |
40 ## | 39 ## |
41 ## Example 1 | 40 ## Example 1 |
42 ## @example | 41 ## @example |
43 ## @group | 42 ## @group |
44 ## perms ([1, 2, 3]) | 43 ## perms ([1, 2, 3]) |
64 ## 1 2 1 2 | 63 ## 1 2 1 2 |
65 ## 1 1 2 2 | 64 ## 1 1 2 2 |
66 ## @end group | 65 ## @end group |
67 ## @end example | 66 ## @end example |
68 ## | 67 ## |
69 ## Programming Notes: If the "unique" argument is not used, the length of | 68 ## Programming Note: If the "unique" option is not used, the length of @var{v} |
70 ## @var{v} should be no more than 10-12 to limit memory consumption. To get | 69 ## should be no more than 10-12 to limit memory consumption. Even with |
71 ## unique results, test both @code{perms (@var{v}, "unique")} and | 70 ## "unique", there should be no more than 10-12 unique elements in @var{v}. |
72 ## @code{unique (perms (@var{v}), "rows")} to compare speed and | |
73 ## memory usage. | |
74 ## @seealso{permute, randperm, nchoosek} | 71 ## @seealso{permute, randperm, nchoosek} |
75 ## @end deftypefn | 72 ## @end deftypefn |
76 | 73 |
77 ## FIXME: In principle it should be more efficient to do indexing using uint8 | 74 ## FIXME: In principle it should be more efficient to do indexing using uint8 |
78 ## type. However, benchmarking shows doubles are faster. If this changes in | 75 ## type. However, benchmarking shows doubles are faster. If this changes in |
159 for i = ulen:-1:1 | 156 for i = ulen:-1:1 |
160 freq (i) = nnz (v == uvec(i)); | 157 freq (i) = nnz (v == uvec(i)); |
161 endfor | 158 endfor |
162 | 159 |
163 ## Performance is improved by handling the most frequent elements first. | 160 ## Performance is improved by handling the most frequent elements first. |
164 ## This can mess with the output order though. Currently we do not promise | 161 ## This can change the output order though. Currently we do not promise |
165 ## the results will be in any specific order. | 162 ## the results will be in any specific order. |
166 [freq, order] = sort (freq, "descend"); | 163 [freq, order] = sort (freq, "descend"); |
167 uvec = uvec (order); | 164 uvec = uvec (order); |
168 | 165 |
169 ## Call nchoosek for each choice and do a Cartesian set product, | 166 ## Call nchoosek for each choice and do a Cartesian set product, |
181 tmp = tmp (all (tmp ~= k, 2), :); | 178 tmp = tmp (all (tmp ~= k, 2), :); |
182 endfor | 179 endfor |
183 | 180 |
184 r = rows (tmp); | 181 r = rows (tmp); |
185 c = columns (tmp); | 182 c = columns (tmp); |
186 if (pos + r > rows(new)) # allocate more memory on the fly | 183 if (pos + r > rows(new)) # Allocate more memory on the fly |
187 new (pos+r+1e5, 1) = 0; | 184 new (pos + r + 1e5, 1) = 0; |
188 endif | 185 endif |
189 | 186 |
190 new ((pos+1):(pos+r), 1:c) = tmp; | 187 new ((pos+1):(pos+r), 1:c) = tmp; |
191 new ((pos+1):(pos+r), (c+1):end) = repmat (this(j,:), r, 1); | 188 new ((pos+1):(pos+r), (c+1):end) = repmat (this(j,:), r, 1); |
192 pos += r; | 189 pos += r; |
193 | |
194 # fprintf (1, "%d\t%d\t%d\t%d\t%d\t%f\n", i, j, r, pos, rows(new), toc); | |
195 endfor | 190 endfor |
196 indx = new (1:pos, :); | 191 indx = new (1:pos, :); |
197 endfor | 192 endfor |
198 clear new tmp this # clear large variables before building P | 193 clear new tmp this # Clear large variables before building P |
199 | 194 |
200 indx = (indx-1) * rows (indx) + (1:rows (indx))'; | 195 indx = (indx-1) * rows (indx) + (1:rows (indx))'; |
201 | 196 |
202 ## Initialize P to be the same size as indx with the same class as v. | 197 ## Initialize P to be the same size as indx with the same class as v. |
203 P = repmat (v, rows(indx), 1); | 198 P = repmat (v, rows(indx), 1); |