2
$\begingroup$

I want to restrict the outputs of Solve/Reduce/FindInstance, etc. to "simple" rationals, which I define as rationals of the form:

$$\pm \dfrac{a}{b}\; \text{ where } \; a, b \in \{1, 2, 3, 4, 5, 6\},$$

e.g., $ \tfrac{3}{5}$, $5$, $-\tfrac{4}{3}$, etc.

Since MMA associates the sign with the numerator, e.g.:

g = -3/4;
Numerator@g
Denominator@g

-3

4

... I believe restrictions on rationals can be represented as follows:

g = -3/4;
h = 5;
-6 <= Numerator@g <= 6 && 1 <= Denominator@g <= 6
0 <= Numerator@g <= 6 && 1 <= Denominator@g <= 6
0 <= Numerator@h <= 6 && Denominator@h == 1
-6 <= Numerator@h <= 6 && 2 <= Denominator@h <= 6

True

False

True

False

However, Solve, Reduce, and FindInstance don't recognize this. For example:

exprA = p + ρ + σ == 0 && -p + r + 2 ν - 3 ρ == 
0 && -2 p - ν - 2 σ == 1

enter image description here

FindInstance[
 exprA && -6 <= Numerator@σ <= 6 &&  1 <= Denominator@σ <= 6 
 && -6 <= Numerator@ν <= 6 &&  1 <= Denominator@ν <= 6 
 && -6 <= Numerator@r <= 6 && 1 <= Denominator@r <= 6 
 && -6 <= Numerator@p <= 6 && 1 <= Denominator@p <= 6 
 && -6 <= Numerator@ρ <= 6 && 1 <= Denominator@ρ <= 6,
 {σ, ν, r, p, ρ}, Rationals, 2]

enter image description here

With fewer variables (say, 3 instead of 5), I could instead brute-force the restriction by explicitly reformatting each variable as the ratio of sub-variables, applying value and domain restrictions to each—e.g., replacing the variable $r$ with $\frac{r_1}{r_2}$, where $-6 \leq r_1 \leq 6$, $1 \leq r_2 \leq 6$, $r_1\in \mathbb{Z}$ and $r_2\in \mathbb{Z}$. One can then use Table or Map to recombine the sub-variables in the output into rational solutions for the variables, and delete the duplicates. E.g.:

exprB = -((3 r1)/r2) - ν1/ν2 + σ1/σ2 == 0 && 
  r1/r2 + ν1/ν2 == 0 && -((2 ν1)/ν2) == 1

enter image description here

soln = Solve[
   exprB && {σ1, σ2, ν1, ν2, r1, r2} ∈ Integers && 
    And @@ Thread[-6 <= {σ1, σ2, ν1, ν2, r1, 
        r2} <= 6], {σ1, σ2, ν1, ν2, r1, r2}];
tab = DeleteDuplicates@
  Table[soln[[j, i, 2]]/soln[[j, i + 1, 2]], {j, 1, Length@soln}, {i, 
    1, Length@soln[[1]] - 1, 2}];
TableForm[tab, TableHeadings -> {None, {"σ", "ν", "r"}}]

enter image description here

However, this method doesn't work with exprA, since its five variables become 10, making the calculation take too long. [I stopped the following after it ran for 24 hours on my 2019 i9 iMac without producing a result.] Thus it would be nice if there were a way to apply the restrictions directly to the original rational-valued variables, rather than transforming them to ratios of integer-valued variables and thus doubling their number:

exprC = exprA /. {σ -> (σ1/σ2), ν -> (ν1/ν2), 
 r -> (r1/r2), p -> (p1/p2), ρ -> (ρ1/ρ2)}

enter image description here

soln = Solve[
  exprC && 
   And @@ Thread[-6 <= {σ1, σ2, ν1, ν2, r1, r2, 
       p1, p2, ρ1, ρ2} <= 
      6] && {σ1, σ2, ν1, ν2, r1, r2, p1, 
     p2, ρ1, ρ2} ∈ 
    Integers, {σ1, σ2, ν1, ν2, r1, r2, p1, 
   p2, ρ1, ρ2}]
tab = DeleteDuplicates@
   Table[soln[[j, i, 2]]/soln[[j, i + 1, 2]], {j, 1, Length@soln}, {i,
      1, Length@soln[[1]] - 1, 2}];
TableForm[tab, 
 TableHeadings -> {None, {"σ", "ν", "r", "p", "ρ"}}]
$\endgroup$
2
  • $\begingroup$ Why you not simply solve FindInstance[exprA, {\[Sigma], \[Nu], r, p, \[Rho]}, Rationals, 2]and then pick the solutions you want? $\endgroup$ Commented Jul 25, 2023 at 7:27
  • $\begingroup$ @DanielHuber I want all solutions that satisfy my constraints: All numbers are of of the form: $\pm \dfrac{a}{b}$, where a, b = {1, 2, 3, 4, 5, 6}. If you try runningFindInstance[exprA, {\[Sigma], \[Nu], r, p, \[Rho]}, Rationals, 2], you'll see it gives two solutions, neither of which satisfy my constraints: {{[Sigma] -> -(67/29), [Nu] -> 6, r -> -(78/29), p -> -(69/58), [Rho] -> 7/2}, {[Sigma] -> 101/34, [Nu] -> 137/34, r -> -6, p -> -(373/68), [Rho] -> 171/68}} $\endgroup$
    – theorist
    Commented Jul 25, 2023 at 16:36

1 Answer 1

3
$\begingroup$

Why Numerator and Denominator do not work in Solve or FindInstance?

Because for symbolic input, they get immediately evaluated:

Numerator[x]
(* x *)

Denominator[x]
(* 1 *)

Therefore, Solve and FindInstance don't even see them:

Solve[Numerator[x] == 3, x] // Trace // Column
(* {{Numerator[x],x},x==3}
   Solve[x==3,x]
   {{x->3}}
   {{x->3,x->3},{x->3}}
   {{x->3}} *)

This explains why some solutions may seem wrong at first sight:

FindInstance[Numerator[x] > 1 && Numerator[x] < 20, x, Rationals]
(* {{x -> 21/2}} *)

Given my explanation above (or using Trace), you can convince yourself that the code is actually equivalent to

FindInstance[x > 1 && x < 20, x, Rationals]

and the corresponding result $21/2$ is correct.

Alternative solution

Using Solve (or Reduce):

Solve[exprA]
(* {{ν -> 3 + 2 p - 2 r, ρ -> 2 + p - r, σ -> -2 - 2 p + r}} *)

we determine that there are only two independent variables ($p$ and $r$). Therefore, we can enumerate all possible $p$ and $r$, and then perform filtering on the other three variables:

sol1 = First@Solve[exprA];
fracs = DeleteDuplicates@Flatten@Table[m a/b, {m, {1, -1}}, {a, 1, 6}, {b, 1, 6}];
pqs = {p -> #1, r -> #2} & @@@ Tuples[fracs, {2}]; 
sols = {ν, ρ, σ, p, r} /. sol1 /. # & /@ pqs;

solsFiltered = Select[sols, ContainsAll[fracs, #] &]
(* {{3, 2, -3, 1, 1}, {1, 1, -2, 1, 2}, {2, 3/2, -(5/2), 1, 3/2}, ...} *)

Length[solsFiltered]
(* 234 *)
$\endgroup$
2
  • $\begingroup$ Nice use of algebra to make the problem tractable for MMA. Any idea why Solve, etc., don't accept Numerator or Denominator constraints as restrictions in equalities or inequalities? As I mentioned above, MMA does return True or False when those restrictions are applied outside of those functions. $\endgroup$
    – theorist
    Commented Jul 29, 2023 at 23:35
  • $\begingroup$ @theorist, please see my edit. $\endgroup$
    – Domen
    Commented Jul 30, 2023 at 11:25

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.