Convert logical combinations from Reduce to a usable function
Perhaps the following. It has the traditional output of Solve
when no solution exists.
ClearAll[getTriangle];
Apply[SetDelayed,
Hold[getTriangle[v_, s_, u_], Solve["eq", {p, q, r}]] /. "eq" -> mysol
]
Triangle exists:
getTriangle[-1, -2, -1]
(* {{p -> 5/3, q -> 5, r -> 2/9}} *)
Triangle does not exist:
getTriangle[-1, -2, 1]
(* {} *)
Alternative definition:
Unevaluated[getTriangle[v_, s_, u_] := Solve[mysol, {p, q, r}]] /.
HoldPattern[mysol] -> mysol
If we change the parameters of Reduce
we can get this:
Reduce[(u s - r v) == -r (p s + r v + u q - p v - u s - r q) &&
2 p + 3 r + 4 u == 0 && 2 q + 3 s + 4 v == 0 && u < 0 && 0 < r < 1 && p > 0 &&
s < 0 && q > 0, {r, p, q}, Reals, Backsubstitution -> True]
(v <= 0 && s < 0 && u < -(1/6) && r == 2/9 && p == 1/3 (-1 - 6 u) && q == 1/2 (-3 s - 4 v)) || (v > 0 && s < -((4 v)/3) && u < -(1/6) && r == 2/9 && p == 1/3 (-1 - 6 u) && q == 1/2 (-3 s - 4 v))
From which we can make a direct definition, eliminating Solve
and producing solutions some two orders of magnitude faster than Michael's solution.
tri[v_, s_, u_ /; u < -1/6] :=
{{p -> 1/3 (-1 - 6 u), q -> 1/2 (-3 s - 4 v), r -> 2/9}} /;
(v <= 0 && s < 0) || (v > 0 && s < -((4 v)/3))
tri[_, _, _] = {};
Test:
res1 = Array[getTriangle, {11, 11, 11}, -5]; // RepeatedTiming
res2 = Array[tri, {11, 11, 11}, -5]; // RepeatedTiming
res1 === res2
{0.74, Null} {0.00482, Null} True
Inspired by Michael's comment regarding Solve
, here is another approach:
sol = Solve[(u s - r v) == -r (p s + r v + u q - p v - u s - r q) &&
2 p + 3 r + 4 u == 0 && 2 q + 3 s + 4 v == 0 && u < 0 && 0 < r < 1 && p > 0 &&
s < 0 && q > 0, {p, q, r}, Reals] // FullSimplify;
{p, q, r} /. sol[[1]];
Thread[%, ConditionalExpression];
MapAt[Apply[And], %, 2]
ConditionalExpression[{-(1/3) - 2 u, -((3 s)/2) - 2 v, 2/9}, (s < 0 && u < -(1/6) && v < 0) || (u < -(1/6) && v > 0 && 3 s + 4 v < 0)]