0
$\begingroup$

I got stuck solving the following problem:

Table[Table[
  Table[
   g1Size = x; g2Size = y;
   vals = 
    FindInstance[(a1 - a2) - (b1 - b2) == z && a1 + b1 == g1Size && 
      a2 + b2 == g2Size && a1 + a2 == g1Size && b1 + b2 == g2Size && 
      a1 > 0 && a2 > 0 && b1 > 0 && b2 > 0, {a1, a2, b1, b2}, 
     Integers, 3];
   aa1 = a1 /. vals; aa2 = a2 /. vals; bb1 = b1 /. vals; 
   bb2 = b2 /. vals;
   {g1Size, g2Size, z, Flatten@{aa1, aa2, bb1, bb2}}
   , {z, 0, 10}], {x, 1, 10}], {y, 1, 10}]

I want to loop through different values of g1Size, g2Size and z and find the first solution to the system of equations. As soon as a solution for a combination of g1Size,g2size and z was found, I want to extract the values for a1,a2,b1,b2 and continue with the next loop. In other words, only print the values when vals is not empty and then stop the z-loop and switch to the next values of x and y.

But my output is like this:

{{{{1, 1, 0, {a1, a2, b1, b2}}, {1, 1, 1, {a1, a2, b1, b2}}, {1, 1, 
    2, {a1, a2, b1, b2}}, {1, 1, 3, {a1, a2, b1, b2}}, {1, 1, 
    4, {a1, a2, b1, b2}}, {1, 1, 5, {a1, a2, b1, b2}}, {1, 1, 
    6, {a1, a2, b1, b2}}, {1, 1, 7, {a1, a2, b1, b2}}, {1, 1, 
    8, {a1, a2, b1, b2}}, {1, 1, 9, {a1, a2, b1, b2}}, {1, 1, 
    10, {a1, a2, b1, b2}}}

plotting the names for a1,a2,b1,b2 when no solution was found.

My mathematica coding is a bit rust and this code seems far from elegant. And I hope it is clear what I mean :).

$\endgroup$
2
  • $\begingroup$ Why do you ask for 3 instances with the last argument to FindInstance, when you say that you want to switch to the next value of z "As soon as a solution for a combination of g1Size,g2size and z was found (...)"? Do you want 3 instances for each {g1Size, g2Size, z}, or just 1? $\endgroup$ Commented Sep 26, 2016 at 12:02
  • $\begingroup$ You are right, I forgot to change that :). $\endgroup$
    – holistic
    Commented Sep 26, 2016 at 12:07

2 Answers 2

1
$\begingroup$

Two points:

  1. If you don't know how many results a piece of code will give, you can use Reap and Sow to collect the results you want.

  2. If you want to break from the loop over z, simply use Break[] within an appropriate If test.

I would do the following:

ans = Reap[
   Do[
    Do[
     instances = 
      FindInstance[(a1 - a2) - (b1 - b2) == z && a1 + b1 == g1Size && 
        a2 + b2 == g2Size && a1 + a2 == g1Size && b1 + b2 == g2Size &&
         a1 > 0 && a2 > 0 && b1 > 0 && b2 > 0, {a1, a2, b1, b2}, 
       Integers];
     If[instances =!= {},
      Sow[{g1Size, g2Size, z, {a1, a2, b1, b2} /. instances}]; 
      Break[]
      ]
     , {z, 0, 10}]
    , {g1Size, 1, 10}, {g2Size, 1, 10}]
    ];

The results are found with ans[[2,1]], which gives a list that's a bit too long to reproduce here :)

$\endgroup$
1
  • $\begingroup$ Interesting solution, thank you! Didn't know about Reap and sow, so this works pretty well :) $\endgroup$
    – holistic
    Commented Sep 26, 2016 at 12:12
1
$\begingroup$

This may me done a bit faster (speed increases by factor 4; there may be potential for more increase) by doing it the functional way:

rangeX = rangeY = Range[10];

(* the function fz will find exactly on solution given z ∈ [0,10] if it exists *)
fz = Function[ {g1Size, g2Size},
    With[
      {
        sol = FindInstance[
          (a1 - a2) - (b1 - b2) == z
          && a1 + b1 == g1Size
          && a2 + b2 == g2Size
          && a1 + a2 == g1Size
          && b1 + b2 == g2Size
          && a1 > 0 && a2 > 0 && b1 > 0 && b2 > 0 &&  0 <= z <= 10,
          {z, a1, a2, b1, b2},
          Integers
        ]
      },
      If[ sol === {},
          (* then *)
          Nothing,
          (* else *)
          { g1Size, g2Size, z, {a1, a2, b1, b2}} /. sol 
      ]
    ]
];

solList = Outer[ fz[ #1, #2]&, rangeX, rangeY] // Flatten[ #, 2 ]&;

Short@solList

{{2,2,0,{1,1,1,1}},{2,3,1,{1,1,1,2}},<<77>>,{10,9,3,{6,4,4,5}},{10,10,0,{5,5,5,5}}}

References:

$\endgroup$
2
  • $\begingroup$ Since you are only interested in one instance of z you may include zin the FindInstance[...] expression so no additional loop needed. $\endgroup$
    – gwr
    Commented Sep 26, 2016 at 13:14
  • $\begingroup$ Insighful :), thank you! $\endgroup$
    – holistic
    Commented Sep 26, 2016 at 14:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.