Skip to content

Support parametric solutions #212

Open

Description

@Happypig375

2x-4y=12 => x=6+2t and y=t

Activity

  1. Happypig375 commented on Sep 21, 2020

    @Happypig375
    MemberAuthor

    Especially for EquationSystems where there are infinite solutions.

  2. MomoDeve commented on Sep 26, 2020

    @MomoDeve
    Member

    x = (12 + 4y) / 2 = 6 + 2y
    y = t => x = 6 + 2t
    whats the point? Its the same as solving the system for some variable and then replacing it by a new one
    Please find a better example, I didn't get it

  3. Happypig375 commented on Sep 28, 2020

    @Happypig375
    MemberAuthor

    The parameters are the inputs to get solutions. They can be any number, which differentiates them from the original variables in the equation system, where there may be non-free variables.

  4. Happypig375 commented on Sep 28, 2020

    @Happypig375
    MemberAuthor
    ⎧  𝑥₁ + 2𝑥₂ + 4𝑥₃ +  𝑥₄ -  𝑥₅ =  1
    ⎨ 2𝑥₁ + 4𝑥₂ + 8𝑥₃ + 3𝑥₄ - 4𝑥₅ =  2
    ⎩  𝑥₁ + 3𝑥₂ + 7𝑥₃       + 3𝑥₅ = -2
    𝑥₁ = 2𝑠 + 3𝑡 + 7
    𝑥₂ = -3𝑠 - 2𝑡 - 3
    𝑥₃ = 𝑠
    𝑥₄ = 2𝑡
    𝑥₅ = 𝑡
    
  5. added
    AcceptedFor proposals, which were approved and will be implemented
    on Aug 11, 2026
  6. Rafael-SOWNet commented on Aug 16, 2026

    @Rafael-SOWNet
    Member

    Still open, and the current behaviour is worth recording: an underdetermined system does not decline, it throws.

    Measured on master at a45a7256:

    MathS.Equations("2*x - 4*y - 12").Solve("x", "y")
    // WrongNumberOfArgumentsException

    That is @Happypig375's own example from the body — 2x - 4y = 12, wanting x = 6 + 2t, y = t. One equation over two variables is exactly the shape this issue exists for, and the API's answer to it is an exception rather than "no closed-form answer" or a parametric one.

    I think that is worth separating from the feature itself. Whatever happens to parametric solutions, throwing WrongNumberOfArgumentsException for a system that is well-formed but underdetermined reads as "you called this wrongly" when the caller did nothing wrong — the system simply has infinitely many solutions. AGENTS.md's line applies: not answering is a legitimate answer, and this is not currently spelled as one.

    So there are two things here:

    1. The feature — parametric solutions, with the free variables named and returned. That is the issue as filed and it is real work: it needs a representation for "a solution family" that Matrix does not currently provide, which is probably why @MomoDeve's question in the thread ("what's the point? it's the same as solving for some variable") never resolved — the point is precisely that the answer type has nowhere to put the parameter.
    2. The refusal — until (1) exists, an underdetermined system could decline rather than throw.

    (2) is small and independent. Say the word and I will do it; I have not, because turning an exception into a null is a change to what the API promises and that is yours to decide.

  7. Rafael-SOWNet commented on Sep 3, 2026

    @Rafael-SOWNet
    Member

    Part of this is done, in #1148.

    MathS.Equations("2*x - 4*y - 12").Solve("x", "y")
    
    was  WrongNumberOfArgumentsException: Number of equations must be equal to that of vars
    is   [[6 + 2 * t_1, t_1]]
    

    which is x = 6 + 2t, y = t — the body's own example. @Happypig375's five-unknown system from the
    thread comes back matching the working posted here in 2020, term for term:

    his:   x1 = 2s + 3t + 7   x2 = -3s - 2t - 3   x3 = s   x4 = 2t   x5 = t
    now:   [[7 + 2*t_1 + 3*t_2, -3 + (-3)*t_1 + (-2)*t_2, t_1, 2*t_2, t_2]]
    

    The answer type did not have to change, which is why this was smaller than the thread
    expected. A solution has always been a row whose i-th entry is the i-th unknown's value, and
    nothing said those entries may not mention a variable — the same device already carries the
    constant of integration out of the ODE solver, and InSolveSystem already minted one t for the
    single case where its recursion bottoms out unconstrained (#550). @MomoDeve's question above —
    "what's the point? it's the same as solving for some variable and then replacing it" — is
    answered by exactly that: the point is that the answer type had somewhere to put the parameter all
    along.

    What is not done

    The parameters are not named in the result. The issue asks for the free variables to be
    identified; they are only discoverable by looking at which variables appear in the answer that
    were not among the unknowns. Giving them a place of their own is an API-shape question this thread
    has not settled, so I have not chosen one.

    Only a short count is taken. equations.Count < vars.Length is precisely the shape that
    raised, so nothing else changed behaviour: a determined system, an overdetermined one, and a
    rank-deficient square one all answer exactly as before — the last through the eliminator, which
    has handled it since #550.

    The system must be linear in the unknowns, with rational coefficients on them. x^2 + y^2 = 1
    and x*y = 1 fail a linearity check that is made rather than assumed, and a*x + y = 1 is refused
    because a row reduction has to decide whether a pivot is zero and the general test available is
    structural — Matrix.ReducedRowEchelonForm asks a == 0, whose own comment records that an
    expression which is zero everywhere without being written 0 is not recognised. Choosing such a
    pivot divides by zero and yields a wrong family rather than no answer. The constant term is
    unrestricted, being never a pivot, so 2x - 4y = k is answered with k symbolic.

    A contradictory short system is null — the same as a contradictory square one, and still
    meaning there are no solutions rather than no answer was found.

    The exception is unchanged for what this declines. My comment above split this issue into the
    feature and the refusal, and said the refusal was yours to decide because turning
    WrongNumberOfArgumentsException into something else changes what the API promises. That is still
    where it stands: the systems this path cannot take still raise it.

  8. Happypig375 commented on Sep 3, 2026

    @Happypig375
    MemberAuthor

    Accepting new equation forms and stopping throwing exceptions is fine

  9. added this to the 2.7.0 milestone on Sep 18, 2026
  10. Rafael-SOWNet commented on Oct 26, 2026

    @Rafael-SOWNet
    Member

    #2124 takes the rest of the shapes that raised. A system with more or fewer equations than unknowns is now answered or declined as null, and never raises WrongNumberOfArgumentsException:

    MathS.Equations("x^2 + y^2 - 1").Solve("x", "y")
    was  WrongNumberOfArgumentsException
    is   [[t_1, sqrt(-(t_1 ^ 2 + -1))], [t_1, -sqrt(-(t_1 ^ 2 + -1))]]
    
    MathS.Equations("a*x + y - 1").Solve("x", "y")    [[t_1, -(a * t_1 + -1)]]
    MathS.Equations("sin(x)", "x").Solve("x")         [0]
    MathS.Equations("sqrt(y) - x").Solve("x", "y")    null
    

    Each family is put back into every equation, and the system is declined unless each one simplifies to 0. That is why sqrt(y) = x is null and not (t, t^2), which fails for a negative t.

    Still open here:

    • The parameters are not named in the result, as above.
    • A family with an integer parameter is declined: sin(x) - 1/2 in x, y is null.

    The square path had the same missing check, and answers sqrt(y) - x, x + 1 with [[-1, 1]]. That is #2123.

    🤖 Generated with Claude Code

    https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura

  11. Happypig375 commented on Oct 26, 2026

    @Happypig375
    MemberAuthor

    consider provided clauses for sqrt(y)=x?

  12. Rafael-SOWNet commented on Oct 26, 2026

    @Rafael-SOWNet
    Member

    Yes. The solver already does this for abs and floor: abs(x) = a is { a * e ^ (i * r_1) provided r_1 in RR and a >= 0 }. A fractional power has no condition, so the single equation sqrt(y) = x is { x ^ 2 } today, which is also wrong for a negative x. The system's family comes from that solve.

    The condition is the range of the principal square root, and there is no Re, Im or arg node to write it with. Options:

    1. provided sqrt(x ^ 2) = x. Exact for every complex x, but it restates the equation, and Simplify leaves it as it is.
    2. provided x in RR and x >= 0. What a reader expects, but it drops x = i, where sqrt(-1) = i, so the answer is no longer every solution.
    3. An arg node, so the condition is x = 0 or -pi/2 < arg(x) <= pi/2. Exact and readable, but a new function.

    I'd attach it in the power's inversion, as abs does, so sqrt(y) = x gets the condition as a single equation and the system answers [[t_1, t_1 ^ 2 provided ...]]. That changes the answer of every solve through a fractional power with a symbolic side, so it gets a BREAKING-CHANGES.md entry. Which condition do you want?

    🤖 Generated with Claude Code

    https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura

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

    AcceptedFor proposals, which were approved and will be implemented

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions