Skip to content

Commit

Permalink
v.1.0.6 in progress
Browse files Browse the repository at this point in the history
* make sure rank methods rank valid objects
* some more static methods split in two eg toGray, fromGray
  • Loading branch information
foo123 committed Jul 13, 2021
1 parent 8b676c9 commit 01c0211
Show file tree
Hide file tree
Showing 18 changed files with 2,585 additions and 2,523 deletions.
93 changes: 76 additions & 17 deletions src/js/Abacus.js
Original file line number Diff line number Diff line change
Expand Up @@ -20005,6 +20005,7 @@ Tensor = Abacus.Tensor = Class(CombinatorialIterator, {
add = Arithmetic.add, sub = Arithmetic.sub, mul = Arithmetic.mul,
index = Arithmetic.O, J = Arithmetic.J, nd, i;

if (!item) return J;
if ("partial" === type)
{
index = Arithmetic.num(find($.data, item, true));
Expand All @@ -20017,14 +20018,22 @@ Tensor = Abacus.Tensor = Class(CombinatorialIterator, {
if ("tuple" === type)
{
nd = n[0];
if (!nd) return J;
for (n=n[1],i=0; i<nd; i++) index = add(mul(index, n), item[i]);
if (!nd || nd !== item.length) return J;
for (n=n[1],i=0; i<nd; i++)
{
if (0 > item[i] || item[i] >= n) return J;
index = add(mul(index, n), item[i]);
}
}
else
{
nd = n.length;
if (!nd) return J;
for (i=0; i<nd; i++) index = add(mul(index, n[i]), item[i]);
if (!nd || nd !== item.length) return J;
for (i=0; i<nd; i++)
{
if (0 > item[i] || item[i] >= n[i]) return J;
index = add(mul(index, n[i]), item[i]);
}
}
}

Expand Down Expand Up @@ -20089,6 +20098,14 @@ Tensor = Abacus.Tensor = Class(CombinatorialIterator, {
dir = -1 === dir ? -1 : 1;
return 0 > dir ? igray(new Array(item.length), item, n) : gray(new Array(item.length), item, n);
}
,toGray: function(item, n) {
dir = -1 === dir ? -1 : 1;
return gray(new Array(item.length), item, n);
}
,fromGray: function(item, n) {
dir = -1 === dir ? -1 : 1;
return igray(new Array(item.length), item, n);
}
,inversion: function(inv) {
// assume inv is tensor component of dimensions: (1,2,..,n-1,n) in this order
var i, n = inv.length, perm = n ? [0] : [];
Expand Down Expand Up @@ -20216,7 +20233,7 @@ Permutation = Abacus.Permutation = Class(CombinatorialIterator, {
// random ordering for derangements / involutions / connecteds
// is based on random generation, instead of random unranking
$.rand = $.rand || {};
$.rand["involution"] = 1; $.rand["connected"] = 1;
$.rand["involution"] = 1;
if ("multiset" === $.type)
{
$.multiplicity = is_array($.multiplicity) && $.multiplicity.length ? $.multiplicity.slice() : array($.dimension, 1, 0);
Expand Down Expand Up @@ -20438,21 +20455,33 @@ Permutation = Abacus.Permutation = Class(CombinatorialIterator, {
I = Arithmetic.I, J = Arithmetic.J, N, M;

n = n || item.length;
if (!item || 0 > n) return J;
if (!item || 0 > n || n !== item.length) return J;
if (0===n) return index;

item = klass.DUAL(item, n, $);

if ("cyclic"=== type)
{
// O(1)
index = Arithmetic.num(item[0]);
// O(n)
ii = item[0];
for (i=0; i<n; i++)
{
x = item[(i+n-ii)%n];
if (x !== i) return J;
}
index = Arithmetic.num(ii);
}
else if ("connected" === type)
{
// O(nlgn)
if (n === item.length)
{
for (dict={},i=0; i<n; i++)
{
x = item[i];
if (0 > x || x >= n || 1 === dict[x]) return J;
dict[x] = 1;
}
item = permutation2cycles(item)[0];
if (n !== item.length) return J;
k = item.indexOf(n-1);
Expand Down Expand Up @@ -20501,6 +20530,14 @@ Permutation = Abacus.Permutation = Class(CombinatorialIterator, {
// adapted from https://github.com/WoDoInc/FindMultisetRank
// O(nm) ~ O(n^2) TODO construct O(nlgn) algorithm
M = $.multiplicity.slice();
for (i=0; i<n; i++)
{
x = item[i];
if (0 > x || x >= M.length || 0 >= M[x]) return J;
M[x]--;
}
if (0 !== M.filter(function(x){return x !== 0;}).length) return J;
M = $.multiplicity.slice();
N = $ && null!=$.count ? $.count : factorial(n,M);
for (m=n-1,i=0; i<m && Arithmetic.gt(N, I); i++)
{
Expand Down Expand Up @@ -21217,20 +21254,25 @@ Combination = Abacus.Combination = Class(CombinatorialIterator, {
,rank: function(item, n, $) {
var klass = this, Arithmetic = Abacus.Arithmetic,
add = Arithmetic.add, sub = Arithmetic.sub,
mul = Arithmetic.mul, O = Arithmetic.O, I = Arithmetic.I,
index = O, i, c, j, k = n[1], N, binom,
mul = Arithmetic.mul, O = Arithmetic.O, I = Arithmetic.I, J = Arithmetic.J,
index = O, i, c, j, k = n[1], N, binom, x, dict,
order = $ && null!=$.order ? $.order : LEX,
type = $ && $.type ? $.type : "combination"/*"unordered"*/;

if (0 > n[0] || 0 > n[1]) return Arithmetic.J;
if (!item || 0 > n[0] || 0 > n[1] || k !== item.length) return J;

if (0===k) return O;
item = klass.DUAL(item, n, $);

if (("ordered+repeated" === type) || ("variation+repeated" === type) || ("repeated+variation" === type))
{
// O(k)
N = n[0];
for (i=0; i<k; i++) index = add(mul(index, N), item[i]);
for (i=0; i<k; i++)
{
if (0 > item[i] || item[i] >= N) return J;
index = add(mul(index, N), item[i]);
}
}
else if (("repeated" === type) || ("combination+repeated" === type))
{
Expand All @@ -21241,6 +21283,7 @@ Combination = Abacus.Combination = Class(CombinatorialIterator, {
// "Algorithms for Unranking Combinations and Other Related Choice Functions", Zbigniew Kokosi´nski 1995 (http://riad.pk.edu.pl/~zk/pubs/95-1-006.pdf)
// adjust the order to match MSB to LSB
// reverse of wikipedia article http://en.wikipedia.org/wiki/Combinatorial_number_system
if (0 > item[i-1] || item[i-1] >= n[0] || (i<k && item[i-1] > item[i])) return J;
c = N-1-item[i-1]-i+1; j = k+1-i;
if (j <= c) index = add(index, factorial(c, j));
}
Expand All @@ -21251,7 +21294,13 @@ Combination = Abacus.Combination = Class(CombinatorialIterator, {
// "Efficient Algorithms to Rank and Unrank Permutations in Lexicographic Order", Blai Bonet (http://ldc.usb.ve/~bonet/reports/AAAI08-ws10-ranking.pdf)
// rank(ordered) = rank(k-n-permutation)
// O(klgk)
N = n[0]; item = permutation2inversion(null, item, N);
N = n[0];
for (dict={},i=0; i<k; i++)
{
if (0 > item[i] || item[i] >= N || 1 === dict[item[i]]) return J;
dict[item[i]] = 1;
}
item = permutation2inversion(null, item, N);
for (i=0; i<k; i++) index = add(mul(index, N-i), item[ i ]);
}
else//if (("combination" === type) || ("unordered" === type) || ("binary" === type))
Expand All @@ -21264,6 +21313,7 @@ Combination = Abacus.Combination = Class(CombinatorialIterator, {
// "Algorithms for Unranking Combinations and Other Related Choice Functions", Zbigniew Kokosi´nski 1995 (http://riad.pk.edu.pl/~zk/pubs/95-1-006.pdf)
// adjust the order to match MSB to LSB
// reverse of wikipedia article http://en.wikipedia.org/wiki/Combinatorial_number_system
if (0 > item[i-1] || item[i-1] >= N || (i<k && item[i-1] >= item[i])) return J;
c = N-1-item[i-1]; j = k+1-i;
if (j <= c) index = add(index, factorial(c, j));
}
Expand Down Expand Up @@ -21358,6 +21408,12 @@ Combination = Abacus.Combination = Class(CombinatorialIterator, {
,binary: function(item, n, dir) {
return -1 === dir ? binary2subset(item, n) : subset2binary(item, n);
}
,toBinary: function(item, n) {
return subset2binary(item, n);
}
,fromBinary: function(item, n) {
return binary2subset(item, n);
}
,pick: function(a, k, type) {
return (0 < k) && a.length ? pick(a, k, ("ordered+repeated"!==type)&&("variation+repeated"!==type)&&("repeated+variation"!==type)&&("ordered"!==type)&&("variation"!==type), ("ordered+repeated"===type)||("variation+repeated"===type)||("repeated"===type)||("combination+repeated"===type), new Array(k)) : [];
}
Expand Down Expand Up @@ -21764,6 +21820,7 @@ Subset = Abacus.Powerset = Abacus.Subset = Class(CombinatorialIterator, {
{
item = (is_binary && !is_reflected) || (is_reflected && !is_binary) ? item.slice(n-item[n],n) : item.slice(0,item[n]);
}
if ($.mindimension > item.length || $.maxdimension < item.length) return J;
if (0 === n)
{
index = O;
Expand Down Expand Up @@ -22632,6 +22689,8 @@ Partition = Abacus.Partition = Class(CombinatorialIterator, {
{
item = REFLECTED & order ? item.slice(LEN-item[LEN][0],LEN) : item.slice(0,item[LEN][0]);
}
if ($.mindimension > item.length || $.maxdimension < item.length) return J;

//if (REFLECTED & order) item = item.slice().reverse();
item = klass.DUAL(item.slice(), n, $, -1);

Expand All @@ -22643,7 +22702,7 @@ Partition = Abacus.Partition = Class(CombinatorialIterator, {
index = O;
if (W && M === W)
{
return null == K || stdMath.floor(n/M) === K ? O : J;
return (null == K || n === K*M) && 0 === item.filter(function(x){return x !== M;}).length ? O : J;
}
for (w=0,m=0,i=0; 0<n && i<item.length; i++)
{
Expand All @@ -22654,15 +22713,15 @@ Partition = Abacus.Partition = Class(CombinatorialIterator, {
if (M === x) m++;
n -= x;
}
if (0 !== n) return J;
if (0 !== n || i !== item.length) return J;
if (REVERSED & order) index = Arithmetic.sub(last, index);
}
else
{
index = last;
if (W)
{
if (M === W) return null == K || stdMath.floor(n/M) === K ? O : J;
if (M === W) return (null == K || n === K*M) && 0 === item.filter(function(x){return x !== M;}).length ? O : J;
n -= W; if (K) K--;
}
for (i=0; 0<n && i<item.length; i++)
Expand All @@ -22673,7 +22732,7 @@ Partition = Abacus.Partition = Class(CombinatorialIterator, {
index = Arithmetic.sub(index, M && 0 === i ? O : part_rank(n, x, W, M, K ? K-i : null));
n -= x;
}
if (0 !== n) return J;
if (0 !== n || i !== item.length) return J;
if (!(REVERSED & order)) index = Arithmetic.sub(last, index);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/js/Abacus.min.js

Large diffs are not rendered by default.

30 changes: 15 additions & 15 deletions test/combinations.txt
Original file line number Diff line number Diff line change
Expand Up @@ -159,28 +159,28 @@ o.order("colex,reversed")
0,1,3
0,1,2
o.order("random")
2,4,5
1,2,5
0,1,3
0,1,2
0,2,5
2,3,5
0,4,5
0,2,4
0,1,4
1,3,4
2,3,4
1,2,3
1,2,4
1,4,5
0,2,5
0,1,3
0,3,4
2,4,5
1,3,4
1,2,5
0,2,3
0,1,5
2,3,4
0,3,5
1,4,5
3,4,5
0,1,5
0,2,4
1,3,5
0,3,4
1,2,3
3,4,5
0,4,5
0,1,2
o.random()
1,3,5
1,3,4
o.order("colex").range(-5, -1)
2,3,5
0,4,5
Expand Down
96 changes: 48 additions & 48 deletions test/combinations_repeats.txt
Original file line number Diff line number Diff line change
Expand Up @@ -411,64 +411,64 @@ o.order("colex,reversed")
0,0,1
0,0,0
o.order("random")
0,2,5
1,3,3
2,4,4
1,1,5
1,2,4
2,3,5
1,2,5
3,4,4
4,4,4
5,5,5
0,4,5
1,1,1
2,3,4
2,4,5
3,5,5
2,2,4
2,3,3
3,3,4
0,0,2
0,2,2
0,1,5
4,5,5
0,5,5
1,2,2
3,3,5
1,1,3
0,1,4
0,3,3
0,3,5
3,5,5
3,3,3
0,0,1
3,4,5
4,4,5
0,0,4
0,2,4
2,5,5
1,1,2
2,3,5
0,4,4
0,2,3
2,5,5
0,0,0
0,1,3
0,0,3
1,2,3
0,3,5
2,2,5
0,3,4
0,1,2
0,1,1
2,2,3
2,2,2
0,0,1
0,2,4
1,5,5
1,3,5
1,2,3
1,4,5
1,3,4
2,3,4
0,0,4
1,4,4
1,1,2
4,5,5
1,2,4
0,3,3
0,1,4
0,0,3
1,1,1
0,2,3
1,2,2
0,5,5
0,4,5
0,2,5
1,1,5
2,4,4
0,0,5
0,3,4
0,1,1
0,2,2
2,4,5
0,1,2
1,1,4
1,3,5
1,2,5
0,0,2
2,3,3
0,1,5
5,5,5
3,3,4
2,2,4
0,1,3
1,3,3
1,3,4
4,4,5
4,4,4
3,4,5
3,4,4
2,2,2
2,2,5
2,2,3
3,3,5
o.random()
1,1,2
1,3,3
o.order("colex").range(-5, -1)
1,5,5
2,5,5
Expand Down
Loading

0 comments on commit 01c0211

Please sign in to comment.