Skip to content

DomainCondition disagrees with the value for five nodes #2256

Open

Description

@Rafael-SOWNet

DomainCondition is where an expression has a value, and Simplify relies on it: a rewrite that hides a singularity adds a provided from it. A new workspace harness, work/domaincheck, compares the condition at exact points with the value there. Each function is checked alone, and then in random compositions. Five nodes disagree. Each one lets Simplify give a value where there is none, or none where there is one. 2.6.0 and master are the same:

  • The factorial and the gamma function require a real argument: "x!".ToEntity().DomainCondition is x in RR and (x >= 0 or not x in ZZ). i! is 0.498 - 0.155i, and the only poles are the negative integers. "x!/x!".ToEntity().Simplify() is 1 provided x in RR and (x >= 0 or not x in ZZ), which has no value at i.
  • max and min hold everywhere, but they have no value at a complex argument. max(i, i) is NaN, as the node is read over the reals. "max(x, x)".ToEntity().Simplify() is x, which has a value at i.
  • arctan and arccot hold at their poles: arctan(i) is +oo i. "arctan(x) - arctan(x)".ToEntity().Simplify() is 0 there. The tangent's condition excludes its poles, and the logarithm's excludes 0, where it is -oo.
  • lambertw has the same condition over the reals as over the complex numbers. "lambertw(0, x)".ToEntity().DomainConditionIn(Domain.Real) is True, but W_0 is real only for x >= -1/e, and W_(-1) only on [-1/e, 0).
  • DomainConditionIn of a piecewise asks every case to be defined. DomainCondition asks only the case that applies (A piecewise's domain condition asks every case's predicate to be defined #1817). tan(piecewise(pi / x provided x > 0, x / 2)) is 0 at 0, but its condition over the reals, piecewise((not cos(pi / x) = 0 and not x = 0 and x in RR) provided (x > 0), (not cos(x / 2) = 0 and not x = 0 and x in RR) provided True), fails there.

Two disagreements are evaluation's, not the conditions': #2253 (Im(1/0) is 0) and #2255 (log(0, 2) is 0). The power's condition is left permissive for a symbolic exponent on purpose, which Powf explains, so x^x at -1/2 over the reals is not listed.

Activity

  1. added this to the 2.7.0 milestone on Oct 30, 2026
  2. Rafael-SOWNet commented on Oct 30, 2026

    @Rafael-SOWNet
    MemberAuthor

    The factorial is #2260 and max/min is #2261.

    arctan and arccot are measured and held. The condition not 1 + x^2 = 0 (or not x^2 = -1) is right, and the arctan(x) - arctan(x) case passes with it. But ten integration tests change. An integrator that builds p ln(...) + q arctan(...) and finds q = 0 leaves 0 * arctan(...), and the zero product keeps arctan's condition. So integral(x/(x^2 + 1), x) comes out as (1/2 ln(x^2 + 1) provided not 1 + (2 x / 2)^2 = 0) + C, which is redundant, since ln(x^2 + 1) excludes the same two points. Five answers in the trigonometric-substitution tests gain a provided, and one passes its size bound. 48 places build an arctan.

    The fix that costs nothing is #1019's engine, which carries conditions beside a candidate and drops whatever the input's own domain already implies. Patching the integrators one by one is the wrong layer. I'll leave this box unchecked until then.

    🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions