Repository: sympy/sympy

Issue:
InconsistentAssumptions sympy error
My program crushes with error. (you can find code here: https://github.com/jdmallo25/beam_deflection_computing/blob/main/program.py)
It happens in different moments (100 iterations - 200 iterations), but error is always the same.
This is 80th iteration. I start the program like this (previously ):  python d.py -lbi -274 -rbi 0
I would like to know what I did wrong. Thank you!
`
[13:24:42]       [0]     solve(24.0, -776.0, 10, 0.001)
[13:24:42]       [1]     solve(24.0, -774.6666666666666, 10, 0.001)
[13:24:42]       [2]     solve(24.0, -773.3333333333334, 10, 0.001)
[13:24:42]       [3]     solve(24.0, -772.0, 10, 0.001)
[13:24:44]       [0]     iteration #0
[13:24:44]       [3]     iteration #0
[13:24:44]       [2]     iteration #0
[13:24:45]       [1]     iteration #0
Exception in thread 3:
Traceback (most recent call last):
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\assumptions.py", line 462, in getit
    return self._assumptions[fact]
KeyError: 'zero'
[13:24:53]       [2]     iteration #1

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\assumptions.py", line 462, in getit
    return self._assumptions[fact]
KeyError: 'extended_real'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\assumptions.py", line 462, in getit
    return self._assumptions[fact]
KeyError: 'finite'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\assumptions.py", line 462, in getit
    return self._assumptions[fact]
KeyError: 'integer'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\threading.py", line 932, in _bootstrap_inner
    self.run()
  File "d.py", line 16, in run
[13:24:55]       [1]     [uw]    [8.85295568e-01 1.15775414e+00 1.00442109e+00 5.71818390e-01 2.68289195e-15 -5.71818390e-01 -1.00442109e+00 -1.15775414e+00 -8.85295568e-01 -4.14948517e-01 -7.52727968e-01 -9.96851869e-01 -1.14379881e+00 -1.19282330e+00 -1.14379881e+00 -9
.96851869e-01 -7.52727968e-01 -4.14948517e-01]
    self._return = self._target(*self._args, **self._kwargs)
[13:24:55]       [0]     iteration #1
  File "d.py", line 133, in solve
    f0 = sp.matrix2numpy(equations_matrix.subs(uw_tuples), dtype=np.float64)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\matrices\common.py", line 2417, in subs
    return self.applyfunc(lambda x: x.subs(*args, **kwargs))
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\matrices\common.py", line 2047, in applyfunc
    return self._eval_applyfunc(f)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\matrices\common.py", line 1987, in _eval_applyfunc
    out = self._new(self.rows, self.cols, [f(x) for x in self])
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\matrices\common.py", line 1987, in <listcomp>
    out = self._new(self.rows, self.cols, [f(x) for x in self])
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\matrices\common.py", line 2417, in <lambda>
    return self.applyfunc(lambda x: x.subs(*args, **kwargs))
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\basic.py", line 953, in subs
    rv = rv._subs(old, new, **kwargs)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\cache.py", line 72, in wrapper
    retval = cfunc(*args, **kwargs)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\basic.py", line 1067, in _subs
    rv = fallback(self, old, new)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\basic.py", line 1039, in fallback
    arg = arg._subs(old, new, **hints)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\cache.py", line 72, in wrapper
    retval = cfunc(*args, **kwargs)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\basic.py", line 1067, in _subs
    rv = fallback(self, old, new)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\basic.py", line 1044, in fallback
    rv = self.func(*args)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\cache.py", line 72, in wrapper
    retval = cfunc(*args, **kwargs)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\operations.py", line 85, in __new__
    c_part, nc_part, order_symbols = cls.flatten(args)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\mul.py", line 266, in flatten
    if not a.is_zero and a.is_Rational:
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\assumptions.py", line 466, in getit
    return _ask(fact, self)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\assumptions.py", line 509, in _ask
    a = evaluate(obj)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\add.py", line 691, in _eval_is_zero
    if a.is_extended_real:
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\assumptions.py", line 466, in getit
    return _ask(fact, self)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\assumptions.py", line 521, in _ask
    _ask(pk, obj)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\assumptions.py", line 521, in _ask
    _ask(pk, obj)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\assumptions.py", line 521, in _ask
    _ask(pk, obj)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\assumptions.py", line 509, in _ask
    a = evaluate(obj)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\mul.py", line 1458, in _eval_is_imaginary
    if self.is_finite is False:
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\assumptions.py", line 466, in getit
    return _ask(fact, self)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\assumptions.py", line 521, in _ask
    _ask(pk, obj)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\assumptions.py", line 509, in _ask
    a = evaluate(obj)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\mul.py", line 1635, in _eval_is_composite
    if not (arg.is_integer and arg.is_positive):
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\assumptions.py", line 466, in getit
    return _ask(fact, self)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\assumptions.py", line 501, in _ask
    assumptions._tell(fact, None)
  File "C:\Users\Andrey\AppData\Local\Programs\Python\Python38\lib\site-packages\sympy\core\facts.py", line 491, in _tell
    raise InconsistentAssumptions(self, k, v)
sympy.core.facts.InconsistentAssumptions: {
        algebraic: None,
        antihermitian: None,
        commutative: True,
        complex: True,
        composite: False,
        even: False,
        extended_negative: False,
        extended_nonnegative: True,
        extended_nonpositive: False,
        extended_nonzero: True,
        extended_positive: True,
        extended_real: True,
        finite: True,
        hermitian: True,
        imaginary: False,
        infinite: False,
        integer: False,
        irrational: None,
        negative: False,
        noninteger: True,
        nonnegative: True,
        nonpositive: False,
        nonzero: True,
        odd: False,
        positive: True,
        prime: False,
        rational: None,
        real: True,
        zero: False}, integer=None
[13:25:02]       [2]     [uw]    [8.84874443e-01 1.15725047e+00 1.00400082e+00 5.71583173e-01 -3.36461180e-16 -5.71583173e-01 -1.00400082e+00 -1.15725047e+00 -8.84874443e-01 -4.14440760e-01 -7.51819208e-01 -9.95657806e-01 -1.14243411e+00 -1.19140179e+00 -1.14243411e+00 -
9.95657806e-01 -7.51819208e-01 -4.14440760e-01]
[13:25:03]       [0]     [uw]    [8.85714798e-01 1.15825532e+00 1.00483919e+00 5.72052374e-01 -1.46025706e-15 -5.72052374e-01 -1.00483919e+00 -1.15825532e+00 -8.85714798e-01 -4.15455875e-01 -7.53636004e-01 -9.98044974e-01 -1.14516242e+00 -1.19424366e+00 -1.14516242e+00 -
9.98044974e-01 -7.53636004e-01 -4.15455875e-01]
Traceback (most recent call last):
  File "d.py", line 281, in <module>
    main()
  File "d.py", line 270, in main
    w_len = int(len(solution) / 2)
TypeError: object of type 'NoneType' has no len()
`


Discussion:
sympy-bot: 

Hi, I am the [SymPy bot](https://github.com/sympy/sympy-bot) (v162). I'm here to help you write a release notes entry. Please read the [guide on how to write release notes](https://github.com/sympy/sympy/wiki/Writing-Release-Notes).

:x: There was an issue with the release notes. **Please do not close this pull request;** instead edit the description after reading the [guide on how to write release notes](https://github.com/sympy/sympy/wiki/Writing-Release-Notes).

* The `<!-- BEGIN RELEASE NOTES -->` block was not found

<details><summary>Click here to see the pull request description that was parsed.</summary>

    <!-- 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. -->
    Partially Fixes : #22537

    #### Brief description of what is fixed or changed
    Assumptions code get crashed in multithreaded case.
    I have added some work around for that. I'm looking into the problem and will make a  PR for the complete fix.
    But till now, it will prevent the errors.
    #### Other comments
    Credit to : @oscarbenjamin 

</details><p>

github-actions[bot]: Benchmark results from GitHub Actions

Lower numbers are good, higher numbers are bad. A ratio less than 1
means a speed up and greater than 1 means a slowdown. Green lines
beginning with `+` are slowdowns (the PR is slower then master or
master is slower than the previous release). Red lines beginning
with `-` are speedups.

Significantly changed benchmark results (PR vs master)
```diff
       before           after         ratio
     [11eb2834]       [e9c7e29a]
+         552±5ns        839±300ns     1.52  core.arit.Time_Arit.time_pow2

```
Significantly changed benchmark results (master vs previous release)
```diff
       before           after         ratio
     [907895ac]       [11eb2834]
+     7.94±0.05ms         12.2±1ms     1.54  matrices.TimeMatrixPower.time_Case1
-      4.87±0.03s         327±10ms     0.07  polygon.PolygonArbitraryPoint.time_bench01

```
Full benchmark results can be found as artifacts in GitHub Actions
(click on checks at the top of the PR).
sympy-bot: ### 🟠

Hi, I am the [SymPy bot](https://github.com/sympy/sympy-bot) (v162). I've noticed that some of your commits add or delete files. Since this is sometimes done unintentionally, I wanted to alert you about it.

This is an experimental feature of SymPy Bot. If you have any feedback on it, please comment at https://github.com/sympy/sympy-bot/issues/75.

The following commits **add new files**:
* d96a3cd17872fce40974b8257722bb1f8cafd77f:
  - `h`

If these files were added/deleted on purpose, you can ignore this message.

oscarbenjamin: A file called "h" seems to have been accidentally added. The file is large so it should be removed and the commits squashed.
ayushbisht2001: Thanks oscar, for your support. I would like to know more about these issue. Like how can I trigger these type of issues which are ignored by the means of some work arounds. Some of them , I found. Also, from where do I start so that I can resolve these issues perfectly.
It's my pleasure to be part of this wonderful community by contributing in it.

Patch:
diff --git a/sympy/core/assumptions.py b/sympy/core/assumptions.py
index b8a8c1990d..34d5d51389 100644
--- a/sympy/core/assumptions.py
+++ b/sympy/core/assumptions.py
@@ -210,7 +210,7 @@
 
 """
 
-from .facts import FactRules, FactKB
+from .facts import FactRules, FactKB, InconsistentAssumptions
 from .core import BasicMeta
 from .sympify import sympify
 
@@ -515,7 +515,25 @@ def _ask(fact, obj):
 
     # Store None into the assumptions so that recursive attempts at
     # evaluating the same fact don't trigger infinite recursion.
-    assumptions._tell(fact, None)
+    #
+    # Potentially in a multithreaded context it is possible that the
+    # assumptions query for fact was already resolved in another thread. If
+    # that happens and the query was resolved as True or False then
+    # assumptions._tell will raise InconsistentAssumptions because of the
+    # attempt to replace True/False with None. In that case it should be safe
+    # to catch the exception and return the result that was computed in the
+    # other thread.
+    #
+    # XXX: Ideally this call to assumptions._tell would be removed. Its purpose
+    # is to guard against infinite recursion if a query for one fact attempts
+    # to evaluate a related fact for the same object. However really this is
+    # just masking bugs because a query for a fact about obj should only query
+    # the properties of obj.args and not obj itself. This is not easy to change
+    # though because it requires fixing all of the buggy _eval_is_* handlers.
+    try:
+        assumptions._tell(fact, None)
+    except InconsistentAssumptions:
+        return assumptions[fact]
 
     # First try the assumption evaluation function if it exists
     try:
diff --git a/sympy/functions/elementary/piecewise.py b/sympy/functions/elementary/piecewise.py
index b38944ff71..ce288fb916 100644
--- a/sympy/functions/elementary/piecewise.py
+++ b/sympy/functions/elementary/piecewise.py
@@ -8,7 +8,6 @@
 from sympy.functions.elementary.miscellaneous import Max, Min
 from sympy.logic.boolalg import (And, Boolean, distribute_and_over_or, Not,
     true, false, Or, ITE, simplify_logic, to_cnf, distribute_or_over_and)
-from sympy.polys.polyutils import illegal
 from sympy.utilities.iterables import uniq, sift, common_prefix
 from sympy.utilities.misc import filldedent, func_name
 
@@ -502,11 +501,9 @@ def handler(ipw):
                 sum = anti
             else:
                 sum = sum.subs(x, a)
-                e = anti._eval_interval(x, a, x)
-                if sum.has(*illegal) or e.has(*illegal):
-                    sum = anti
-                else:
-                    sum += e
+                if sum == Undefined:
+                    sum = 0
+                sum += anti._eval_interval(x, a, x)
             # see if we know whether b is contained in original
             # condition
             if b is S.Infinity:


Test patch:
diff --git a/sympy/functions/elementary/tests/test_piecewise.py b/sympy/functions/elementary/tests/test_piecewise.py
index f0f41ed8e3..40bdeac400 100644
--- a/sympy/functions/elementary/tests/test_piecewise.py
+++ b/sympy/functions/elementary/tests/test_piecewise.py
@@ -883,7 +883,7 @@ def test_holes():
     assert Piecewise((1, x < 2)).integrate(x) == Piecewise(
         (x, x < 2), (nan, True))
     assert Piecewise((1, And(x > 1, x < 2))).integrate(x) == Piecewise(
-        (nan, x < 1), (x, x < 2), (nan, True))
+        (nan, x < 1), (x - 1, x < 2), (nan, True))
     assert Piecewise((1, And(x > 1, x < 2))).integrate((x, 0, 3)) is nan
     assert Piecewise((1, And(x > 0, x < 4))).integrate((x, 1, 3)) == 2
 
@@ -1447,9 +1447,3 @@ def test_piecewise_eval():
         ) == (x >= -3) & (x <= oo)
     assert f(Piecewise((x, (Abs(arg(a)) <= 1) | (Abs(arg(a)) < 1)))
         ) == (Abs(arg(a)) <= 1) | (Abs(arg(a)) < 1)
-
-
-def test_issue_22533():
-    x = Symbol('x', real=True)
-    f = Piecewise((-1 / x, x <= 0), (1 / x, True))
-    assert integrate(f, x) == Piecewise((-log(x), x <= 0), (log(x), True))