# Optimize while loop with several conditions

I am trying to generate several random numbers according to some conditions, but the way I have it implemented, it won't run.

The conditions are:

CheckConditions[\[Lambda]1_, \[Lambda]2_, \[Lambda]6_, \[Lambda]7_, \
\[Lambda]8_, \[Lambda]3_, \[Lambda]4_, \[Lambda]5_, v1_, v2_, v1s_,
v2s_, vS_] :=
Module[{cond1, cond2, cond3, cond4, cond5, cond6, cond7, cond8,
cond9, cond10, cond11},
cond1 = \[Lambda]1 > 0 && \[Lambda]2 > 0 && \[Lambda]6 > 0;
cond2 = Sqrt[Abs[\[Lambda]1  \[Lambda]6]] + \[Lambda]7 > 0;
cond3 = Sqrt[Abs[\[Lambda]2  \[Lambda]6]] + \[Lambda]8 > 0;
cond4 =
Sqrt[Abs[\[Lambda]1  \[Lambda]2]] + \[Lambda]3 +
Min[\[Lambda]4 - Abs[\[Lambda]5], 0] > 0;
cond5 = \[Lambda]7 + Sqrt[Abs[\[Lambda]1/\[Lambda]2]]  \[Lambda]8 >=
0;
cond6 = \[Lambda]2 \[Lambda]6 >= \[Lambda]8^2;
cond7 =
Sqrt[Abs[\[Lambda]1  \[Lambda]6]] > -\[Lambda]7 >=
Sqrt[Abs[\[Lambda]1/\[Lambda]2]]  \[Lambda]8;
cond8 =
Sqrt[Abs[(\[Lambda]7^2 - \[Lambda]1  \[Lambda]6)  (\[Lambda]8^2 - \
\[Lambda]2  \[Lambda]6)]] > \[Lambda]7 \[Lambda]8 - (Min[\[Lambda]4 -
Abs[\[Lambda]5], 0] + \[Lambda]3) \[Lambda]6;
cond9 = v1^2 + v2^2 == 246^2;
cond10 = v1s^2 + v2s^2 == 246^2;
cond11 = 1 <= vS <= 3*10^3;
cond1 && cond2 && cond3 && cond4 && cond5 && cond6 && cond7 &&
cond8 && cond9 && cond10 && cond11]


And the part of the code regarding the generation is:

ParameterGenerator[] :=
Module[{\[Lambda]1, \[Lambda]2, \[Lambda]3, \[Lambda]4, \[Lambda]5, \
\[Lambda]6, \[Lambda]7, \[Lambda]8, v1, v2, v1s, v2s, vS, m12, m11,
m22, mS, VwithVS, VwithoutVS, diff, conditions},

(*Generate parameters and check conditions until they are satisfied*)
While[True,
{\[Lambda]1, \[Lambda]2, \[Lambda]6} = RandomReal[{0, 1}, 3];
{\[Lambda]7, \[Lambda]8, \[Lambda]3, \[Lambda]4, \[Lambda]5} =
RandomReal[{-1, 1}, 5];
v1 = RandomReal[{0, 246}];
v2 = Sqrt[246^2 - v1^2];
v1s = RandomReal[{0, 246}];
v2s = Sqrt[246^2 - v1s^2];
vS = RandomReal[{1, 3*10^3}];
m12 = RandomReal[{0, Sqrt[5*10^5]}];
(*Check if the generated parameters satisfy the conditions*)
conditions =
CheckConditions[\[Lambda]1, \[Lambda]2, \[Lambda]6, \[Lambda]7, \
\[Lambda]8, \[Lambda]3, \[Lambda]4, \[Lambda]5, v1, v2, v1s, v2s,
vS];
Print["Conditions: ", conditions];
If[conditions,
Print["Parameters: ", {\[Lambda]1, \[Lambda]2, \[Lambda]6, \
\[Lambda]7, \[Lambda]8, \[Lambda]3, \[Lambda]4, \[Lambda]5, v1, v2,
v1s, v2s, vS}];
Break[];];

];


This function has more code afterwards, but that is not relevant to the matter. I have tried without the while True part, but it wouldn't agree with the conditions.Is there any way to optimize this loop?

• Remove the Print statements; that will make things much faster. Commented Aug 3 at 15:31
• Afterwards, you can try to use Compile. Without the Print statements, this can basically be run in a small external library with almost no callbacks to Mathematica's main kernel. You better inline CheckConditions manually, though. Commented Aug 3 at 15:35
• And try to write it into a short-circuiting way. Currently, all the conditions are evaluated. Try to order them by the cost of evaluation. Then put them all directly into a big And. And evaluates its arguments from left to right; as soon as one argument is False, it returns False without evaluating the other ones. That's also what the compiler will do. Commented Aug 3 at 15:37
• Since And shortcircuits, you'd probably get better performance if you didn't precompute all of the conditions before applying And to them. Once you change that, you can remove some of the redundant checks. For example, after you've already checked that l1 and l6 are positive you don't need the Abs in Sqrt[Abs[l1 l6]] + l7 > 0. Or another example is the bit of redundancy between cond3 and cons6, which I assume you can clean/simplify. But even after all of that, you're stuck with the fact that cond5 and cond7 force you into having l7 and l8 be 0. Commented Aug 3 at 15:40
• In other words, I think it's taking a long time because it might just be very rare to choose random values that can satisfy all of your constraints. If l7 and l8 aren't 0, then nothing else matters, and it's unlikely that you'll randomly choose both of those to be 0. Commented Aug 3 at 15:42

Elevating my (corrected, hopefully) comment because I think you overlooked it and the consequences. Here are some of your conditions (replacing \[Lambda] with plain L):

cond1 = L1 > 0 && L2 > 0 && L6 > 0;
cond5 = L7 + Sqrt[Abs[L1/L2]]   L8 >= 0;
cond7 = Sqrt[Abs[L1   L6]] > -L7 >= Sqrt[Abs[L1/L2]]   L8;


Let's simplify this to just focus on four critical variables:

cond1x = L1 > 0 && L2 > 0;
cond5 = L7 + Sqrt[Abs[L1/L2]]   L8 >= 0;
cond7x = -L7 >= Sqrt[Abs[L1/L2]]   L8;


In your While loop, you are generating random values for these four variables (L1, L2, L7, L8). Notice that cond5 and cond7x together require that

condZ = L7 + Sqrt[Abs[L1/L2]]   L8 == 0


The probability that 4 randomly chosen values will satisfy condZ is zero. Assuming my reasoning is correct, your code is going into an infinite loop since it is virtually impossible for these 4 variables to align correctly.

Caveat: I'm just making this argument from inspecting your code. I haven't tried to develop a formal proof or empirical data to support it. Maybe I've made a logical error. If I were you, I'd actually create a simpler version of CheckConditions that focuses on this specific piece of the condition and test whether my conclusions are correct or not.

• You are absolutely right. I made a mistake. It was supposed to be some conditions OR other conditions, and not every condition at the same time. By correcting that, it has worked out. Thank you for your help Commented Aug 3 at 20:42