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$ 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$ Commented Jul 29, 2023 at 23:35
  • $\begingroup$ @theorist, please see my edit. $\endgroup$ Commented Jul 30, 2023 at 11:25

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.