I'm trying to identify unique arrays by comparing two lists, one which is growing in length. The number of elements in the list grows as 2^n^2, where n is the dimension of the array.
I'm not sure how to better optimize this code for speed, but it is very slow for arrays larger than 3x3, i.e. n=4in the code below. I suspect that the If and the AppendTo are slowing things down, and I don't believe I can use ParallelTable due to the nature of the search.
f[n_, i_] := Partition[IntegerDigits[i, 2, (n*n)], n, n]
g[n_, i_] := {f[n, i], Transpose[f[n, i]], J.f[n, i], Transpose[J.f[n, i]], J.f[n, i].J, Transpose[J.f[n, i].J], f[n, i].J, Transpose[f[n, i].J]}
h[n_, i_] := ContainsAny[uniqueArray, g[n, i]]
m[n_] := Table[If[h[n, i], , uniqueArray = AppendTo[uniqueArray, f[n, i]]], {i, 2^n^2}][[2^n^2]]
n = 2;
J = Reverse[IdentityMatrix[n]];
uniqueArray = {};
m[n]; // AbsoluteTiming
m[1]; // AbsoluteTiming
{0.000346, Null}
m[2]; // AbsoluteTiming
{0.001656, Null}
m[3]; // AbsoluteTiming
{0.061311, Null}
m[4]; // AbsoluteTiming
{169.272, Null}
This question builds on the following: A few tuples at a time?
EDIT Ok, I thought I could reduce the time of this search by doing some sorting before checking for uniqueness. For instance, an binary array with two 1's cannot be the same as an array with with three 1's, i.e. these cannot be the same:
MatrixForm[{{0,0},{1,1}}]
MatrixForm[{{0,1},{1,1}}]
So, it seems reasonable to only compares arrays of the same total. I amended the initial code in the following way:
f[n_, i_] := Partition[IntegerDigits[i, 2, (n*n)], n, n]
m[n_] := Table[
If[
ContainsAny[
uniqueArraySplit[[Total[Flatten[f[n, i]]] + 1]],
{f[n, i],
Transpose[f[n, i]],
J.f[n, i],
Transpose[J.f[n, i]],
J.f[n, i].J,
Transpose[J.f[n, i].J],
f[n, i].J,
Transpose[f[n, i].J]
}
],
Nothing,
AppendTo[uniqueArraySplit[[Total[Flatten[f[n, i]]] + 1]],
f[n, i]]
],
{i, 2^n^2}][[2^n^2]]
n = 4;
J = Reverse[IdentityMatrix[n]];
uniqueArraySplit = Table[{}, {p, n^2 + 1}];
m[n]; // AbsoluteTiming
m[4]; // AbsoluteTiming
{165.308, Null}
Now I'm stumped. I removed two functions, and I removed unnecessary searches, and yet it barely improved the timing... Any help would be greatly appreciated.
nto get? Even if you'd optimize theTablecalculation to do one iteration per nanosecond,n=8would take over 500 years. 2^n^2 simply grows very fast. Unless you come up with a different algorithm, anything above n=5 or maybe n=6 will take a very long time. – Niki Estner Mar 22 '16 at 06:18AppendTowith anAssociation, which should make insertion faster – Niki Estner Mar 22 '16 at 06:23n=6is essentially impossible. Perhaps there's a better algorithm, yet I haven't been able to think about one. Get the results forn=5andn=6would be a victory. Is there a syntax change needed to switchAppendTowithAssociation? When I substituted the latter it didn't write anything to the nested list. – dpholmes Mar 22 '16 at 13:07n=6, get a book like "Hackers Delight", translate the transpose/reverse operations to bit-twiddling operations, and learn C. Back-of-the envelope calculation suggests that it should be possible to run this forn=6in hours. But that it something you'd have to do yourself ;-) – Niki Estner Mar 23 '16 at 18:52