Repository: sympy/sympy
Pull request: minor changes in mod(a, b)
<!-- Your title above should be a short description of what
was changed. Do not include the issue number in the title. -->

#### References to other Issues or PRs
<!-- If this pull request fixes an issue, write "Fixes #NNNN" in that exact
format, e.g. "Fixes #1234" (see
https://tinyurl.com/auto-closing for more information). Also, please
write a comment on that issue linking back to this pull request once it is
open. -->
Fixes #26016

#### Brief description of what is fixed or changed


#### Other comments


#### Release Notes

<!-- Write the release notes for this release below between the BEGIN and END
statements. The basic format is a bulleted list with the name of the subpackage
and the release note for this PR. For example:

* solvers
  * Added a new solver for logarithmic equations.

* functions
  * Fixed a bug with log of integers. Formerly, `log(-x)` incorrectly gave `-log(x)`.

* physics.units
  * Corrected a semantical error in the conversion between volt and statvolt which
    reported the volt as being larger than the statvolt.

or if no release note(s) should be included use:

NO ENTRY

See https://github.com/sympy/sympy/wiki/Writing-Release-Notes for more
information on how to write release notes. The bot will check your release
notes automatically to see if they are formatted correctly. -->

<!-- BEGIN RELEASE NOTES -->
* core
  * minor changes in mod as mentioned in [commnet](https://github.com/sympy/sympy/issues/26016#issuecomment-1873374064)
<!-- END RELEASE NOTES -->


Problem statement:
i think mod(a,b) are considering only integers solutions
Hello guys, i have a simplification of my code which is:

```
import sympy as sp
import itertools

Zp = range(3)
Zq = range(3) 
sextetos = itertools.product(Zp, Zp, Zp, Zq, Zq, Zq)


x, y, z, w = sp.symbols('x y z w', real=True)
system = []
#it will test the generic form: B(a,b) = x*a1*b1+y*a1*b2+z*a2*b1+w*a2*b2, for all pairs a= (a1,a2), b=(b1,b2) e c=(c1,c2)
#both mapping axioms, and return the set of conditions that x, y, z e w must satisfy.

for a1, b1, c1, a2, b2, c2 in sextetos:
 d1 = (b1 + c1) % p
 d2 = (b2 + c2) % q   
 if (a1, b1, c1, a2, b2, c2) != (0, b1, c1, 0, b2, c2):
    print(a1,b1,c1,a2,b2,c2)
    eq1 = ((x * (a1 * b1+b1 * a1)+y * (a1 * b2+b1 * a2)+z * (a2*b1+b2 * a1)+w * (a2 * b2+a2 * b2))) % 2
    system.append(eq1)
    eq2 = (x * (a1 * ((b1+c1)%p))+y * (a1 * ((b2+c2)%q))+z * (a2 * ((b1+c1)%p))+w * (a2*((b2+c2)%q)) - (x * a1 * (b1+c1)+y * a1 * (b2+c2)+z * a2*(b1+c1)+w * a2 * (b2+c2))) % 2
    eq2 = (x * a1 * (sp.Mod(b1+c1,p)-(b1+c1))+y * a1 * (sp.Mod(b2+c2,q)-(b2+c2))+z * a2 * (sp.Mod(b1+c1,p)-(b1+c1))+w * a2 * (sp.Mod(b2+c2,q)-(b2+c2))) % 2
    print(eq1)
    print(eq2)
    input()
vars = [x, y, z, w]
print(sp.nonlinsolve(system, vars)) 
```

I was feeling something was a litte bit wrong with this code, because the conditionset it returns has some rules that i know that doesnt exist, like for the sexteto (a1,b1,c1,a2,b2,c2) = (0,0,0,1,1,2), eq2 should be w * 1 * (-3) % 2. Or, with sp tools: Eq(3*Mod(w,2),0), considering the possibility of w = 2/3 (example). However, the code returns me just Eq(Mod(w,2),0), and i just cant understand why...

Important that: the error is before the nonlinsolve function. If u just put a print(eq2) with the equations.append(eq2), it will return (Eq(Mod(w,2),0). 

If someone have an ideia of what is happening, please give me a hand. 

Merry Christmas, gifhubbers :D

Hints from issue discussion:
You haven't defined what p and q are. 
oops, sorry, it was an input, and Zp, Zq was two ranges based on p and q. I decided to send with p and q = 3 to make it more specific, but i forgot to switch all the p and q with the number 3. Sorry.
@joaorrmattos 
I think the following code is a simplified version which removes unnecessary calculations and aligns with the length of respective changes, please have a look at it!

```
import sympy as sp
import itertools

p = 3  # Define the value of p
q = 3  # Define the value of q
Zp = range(p)
Zq = range(q)
sextetos = itertools.product(Zp, Zp, Zp, Zq, Zq, Zq)

x, y, z, w = sp.symbols('x y z w', real=True)
system = []

for a1, b1, c1, a2, b2, c2 in sextetos:
    if (a1, b1, c1, a2, b2, c2) != (0, 0, 0, 1, 1, 2):
        eq1 = ((x * (a1 * b1 + b1 * a1) + y * (a1 * b2 + b1 * a2) + z * (a2 * b1 + b2 * a1) + w * (a2 * b2 + a2 * b2))) % 2
        system.append(eq1)

        mod_val_p = sp.Mod(b1 + c1, p)
        mod_val_q = sp.Mod(b2 + c2, q)
        eq2 = (x * a1 * mod_val_p + y * a1 * mod_val_q + z * a2 * mod_val_p + w * a2 * mod_val_q - (x * a1 * (b1 + c1) + y * a1 * (b2 + c2) + z * a2 * (b1 + c1) + w * a2 * (b2 + c2))) % 2
        system.append(eq2)

vars = [x, y, z, w]
solutions = sp.nonlinsolve(system, vars)
print(solutions)
``` 
hmmm unfortunately it doesnt work. 

1: i put (a1, b1, c1, a2, b2, c2) != (0,b1,c1,0,b2,c2) because if a1 and a2 equals 0, both eq1 and eq2 goes to 0.

2: its important to analyse  (a1, b1, c1, a2, b2, c2) = (0, 0, 0, 1, 1, 2), because it shows us the problem very quick.

Ur idea was really good, but it keeps turning the equation Eq(Mod(3*w, 2,), 0) to Eq(Mod(w, 2), 0), considering the only the possibility of w to be integer. 

:/


If I understand correctly then the question is why this happens:
```
In [1]: Mod(3*x, 2)
Out[1]: x mod 2

In [2]: (3*x) % 2
Out[2]: x mod 2
```
This simplification assumes that `x` is an integer which is not necessarily the case if no assumptions are set on `x`:
```
In [3]: (3*(S(2)/3)) % 2
Out[3]: 0
```
yes, thats correct. I have an alternative that is: keep my equations without mod app, then only %2 when i already switched the variables with the values i want to verify. The bad thing is: it takes more time than it would with Mod(a,b)... Thats why i asked for a solution... If there is nothing to do with it, ie, the simplification will assume that x is intenger everytime when it is a variable, i accept it ahahaha. Thanks for the explanation! Happy new year!
This is my suggested fix:
```diff
diff --git a/sympy/core/mod.py b/sympy/core/mod.py
index 873e815cb2..3f0e07a561 100644
--- a/sympy/core/mod.py
+++ b/sympy/core/mod.py
@@ -164,8 +164,10 @@ def number_eval(p, q):
                 return prod_non_mod*cls(net, q)
 
             if q.is_Integer and q is not S.One:
-                non_mod_l = [i % q if i.is_Integer and (i % q is not S.Zero) else i for
-                             i in non_mod_l]
+                if all(t.is_integer for t in p.args):
+                    non_mod_l = [i % q if i.is_Integer else i for i in p.args]
+                    if any(iq is S.Zero for iq in non_mod_l):
+                        return S.Zero
 
             p = Mul(*(non_mod_l + mod_l))
```
Then
```python
In [1]: x = symbols('x')

In [2]: Mod(3*x, 2)
Out[2]: 3⋅x mod 2

In [3]: x = symbols('x', integer=True)

In [4]: Mod(3*x, 2)
Out[4]: x mod 2
```

Commit message: Adding test cases

Patch to review:
diff --git a/sympy/core/mod.py b/sympy/core/mod.py
index 873e815cb227..3f0e07a5612c 100644
--- a/sympy/core/mod.py
+++ b/sympy/core/mod.py
@@ -164,8 +164,10 @@ def number_eval(p, q):
                 return prod_non_mod*cls(net, q)
 
             if q.is_Integer and q is not S.One:
-                non_mod_l = [i % q if i.is_Integer and (i % q is not S.Zero) else i for
-                             i in non_mod_l]
+                if all(t.is_integer for t in p.args):
+                    non_mod_l = [i % q if i.is_Integer else i for i in p.args]
+                    if any(iq is S.Zero for iq in non_mod_l):
+                        return S.Zero
 
             p = Mul(*(non_mod_l + mod_l))
 
diff --git a/sympy/core/tests/test_args.py b/sympy/core/tests/test_args.py
index 6e5ab8fdd025..cd5a2575c8e6 100644
--- a/sympy/core/tests/test_args.py
+++ b/sympy/core/tests/test_args.py
@@ -682,6 +682,7 @@ def test_sympy__core__function__WildFunction():
 def test_sympy__core__mod__Mod():
     from sympy.core.mod import Mod
     assert _test_args(Mod(x, 2))
+    assert _test_args(Mod(3*x, 2))
 
 
 def test_sympy__core__mul__Mul():


Code review comments:
diff_hunk: @@ -682,6 +682,7 @@ def test_sympy__core__function__WildFunction():
 def test_sympy__core__mod__Mod():
     from sympy.core.mod import Mod
     assert _test_args(Mod(x, 2))
+    assert _test_args(Mod(3*x, 2))
path: sympy/core/tests/test_args.py
text: @user1:
This test would pass without the changes here. This does not really test anything useful and should be removed.

Tests should be added in `sympy/core/tests/test_arit.py`.