The short of this question: I need to find a bunch of n-tuples of {0,1} which do not fail to satisfy a set of (non-linear polynomial) equations, without hogging up all of my memory by trying to generate every possible n-tuple before eliminating the bad ones. This set of 'not bad' n-tuples should be substantially smaller than every possible n-tuple for the problem I am working on.
The long of this question:
I have a system of non-linear (polynomial) equations I want to solve; indeed, multiple such systems, each one corresponding to a separate case of interest to a larger problem. Simply using Mathematica's built-in Solve
function isn't very effective, as it quickly consumes memory and then run's at a snail's pace trying to work its way through the problem without consuming extra memory. Thankfully, the systems I'm working with have a couple of nice properties which give a more efficient workaround (indeed, my current method converts what could have taken days with Solve
into mere minutes).
The one of relevance here is that, if I call the variables in the system d[i]
, then it turns out there are a fair number of equations of the form d[i]^2==d[i]
, which means all of those variables have to be either 0's or 1's. I am currently using Tuples
to generate every possible substitution, and then proceeding to eliminate all of those which cannot satisfy the equations. However, this gets extremely memory intensive pretty fast. Even 'small examples' lead to insufficient memory errors at this stage, as they can have up to a few dozen of these squaring relations in each list of equations (and there can be half-dozen or more such lists in a 'small' example). There may be a number of ways to improve the efficiency of my code, as I'm still fairly new to advanced Mathematica programming, but mostly I am looking for ways to keep the memory demands down without drastically inflating computation time.
Before getting to this stage, I generate a nested list of equations I'm interested in, denoted CubeReduced2
(the equations end up being degree 2 multinomials; the reason for the 'cube' is not particularly germane here). The equations are all stored on the final level; the preceding levels effectively serve as markers of which case I'm looking at it, and do not store any other data. I am attempting to solve many possible systems without having to do them individually, especially when I have no advanced knowledge of how many systems there will be.
This is the code I am currently using to generate all possible combinations of 0/1 substitutions for these variables
SelfSquares = Flatten[Map[Reap[Do[If[MemberQ[#, d[i]^2 == d[i], Sow[i]],
{i, 1, varnum}]][[2]]&, CubeReduced2, {2}], {{1}, {2}, {3, 4}}];
SquarePossibilities =
ParallelTable[
Tuples[{0, 1}, Length[SelfSquares[[m]][[i]]]], {m, 1,
Length[CubeReduced2]}, {i, 1, Length[CubeReduced2[[m]]]}];
SquareReplaces =
ParallelTable[
Map[Table[
d[SelfSquares[[m]][[i]][[j]]]] -> #[[j]], {j, 1,
Length[SelfSquares[[m]][[i]]]}] &,
SquarePossibilities[[m]][[i]]], {m, 1, Length[SquarePossibilities]}, {i, 1,
Length[SquarePossibilities[[m]]]}];
The SquarePossibilities
stage is where my system memory quickly vanishes. I Remove
it after generating SquareReplaces, but when I can't even build the list that doesn't help any.
I would then use the following code to eliminate the tuples which definitely won't work:
SquareReplaces2 =
ParallelTable[
Select[SquareReplaces[[m]][[
i]], (And @@
Map[! TrueQ[# == False] &, ((CubeReduced2[[m]][[
i]]) /. (#))]) &], {m, 1, Length[CubeReduced2]}, {i, 1,
Length[CubeReduced2[[m]]]}];
There may be non-trivial equations left after apply the replacements, which will still need to be solved for. That's why I don't simply look for every equation to evaluate to True, but simply look for those tuples which don't produce a False. Hopefully this explanation is sufficient at this point to describe what I'm trying to accomplish.
I'd provide a sample list of equations I have applied this code to (succesfully), but right now my mathematica has the variables as $d_i$, which don't translate very well into an easy copy-paste. I'll try to fix that if a relevant example is desired.
Tuples[{1,0},n]
into twoTuples[{1,0},n/2]
lists and work through each combination of the two lists, joining elements as you go? $\endgroup$n
typically in your cases? I mean withn=30
you have2^30
tuples which is a number too large to do even the simplest loopDo[Null, {i, 2^30}];
. $\endgroup$n=30
is fairly easily achieved in 'small' examples. A particular example I've tried to compute that ran into a memory error had about n=24 to n=28 on each of 5 sets of equations. $\endgroup$d[i]
as your variable and have it formatted as a subscript. See this and perhaps point 4 in this. $\endgroup$