On Thu, 30 Jun 2022 at 23:27, Chris Smith <
smi...@gmail.com> wrote:
>
> Nearly from the beginning, `solve` has recognized the `undetermined coefficients` case wherein a single equation is solved for a set of symbols which will simultaneously set it equal to zero. This is different than the normal use of `solve`, however, and might be considered a bug or feature. As an example, consider:
>
> [in1] solve(a*x + b - (2*x + 4), (a, b)) # solve for a and b
> {a: 2, b: 4}
> [in2] solve(a*x + b - (2*x + 4), exclude=[x]) # solve for as many as possible, but not x
> {a: 2, b: 4}
> [in3] solve(a*x + b - (2*x + 4), a) # solve for a
> [(-b + 2*x + 4)/x]
> [in4] solve(a*x + b - (2*x + 4)) # solve for anything and tell me what you did
> [{a: (-b + 2*x + 4)/x}]
>
> The "undetermined coefficients" case is returned from inputs 1 and 2 while the more usual "solution" is returned from 3 and 4.
>
> The request for comment is whether this feature should be removed from `solve` so a better defined equation set is provided rather than building that equation set automatically when this case is detected as one-equation-many-symbols.
>
> To me it feels natural to get the undetermined coefficients solution when I ask for many symbols from one equation. If I want sympy to pick any variable other than some I would use `exclude=some` (where `some` is a list or set of things to ignore). But not everyone feels this way and refusing the temptation to guess is important, too.
It does not feel natural to me at all that solve should arbitrarily
decide to get an undetermined coefficients solution. Also solve is
just flat out inconsistent:
In [7]: a, b, x = symbols('a, b, x')
In [8]: eq = a + x*b
In [9]: solve([eq], [a, b])
Out[9]: {a: -b⋅x}
In [10]: nonlinsolve([eq], [a, b])
Out[10]: {(-b⋅x, b)}
In [11]: linsolve([eq], [a, b])
Out[11]: {(-b⋅x, b)}
Okay so far so good but what happens to solve if I change [eq] to eq:
In [12]: solve([eq], [a, b])
Out[12]: {a: -b⋅x}
In [13]: solve(eq, [a, b])
Out[13]: {a: 0, b: 0}
Firstly there should be no distinction between eq and [eq] here.
Secondly in Out[13] solve has arbitrarily decided to completely
reinterpret the problem that was set. The problem is: compute the set
of solutions for a and b to the equation system involving a and b that
is parametrised by a symbol x and give expressions for the solutions
that are valid for almost all possible values of the parameter x.
That is what {a: -b*x} is. The return value {a:0, b:0} implies that
there is a unique solution for a and b when it is clear that there is
not a unique solution for this underdetermined system. If you
substitute values for x then you get different results:
In [17]: solve(eq.subs(x, 0), [a, b])
Out[17]: [(0, b)]
In [18]: solve(eq, [a, b])
Out[18]: {a: 0, b: 0}
Why are these even different types? One is a list of tuples and the
other is a dict...
The return from solve(eq, [a, b]) should be valid for different values
of the parameter x i.e. ideally these should be equivalent:
solve(eq.subs(x, value), [a, b])
solve(eq, [a, b]).subs(x, xvalue)
(Although it isn't actually possible to use subs directly on the
returned output like that.)
> Since this behavior is described in the docstring and has been present for many years it feels like a regression of this feature to me (though to others it feels like a bug fix). If you use this feature and/or have comments, please let us know your thoughts on this:
I don't think this is a feature:
1. I doubt that anyone even realises that this is intentional behaviour.
2. The docstring of solve is impossible to understand.
3. This feature hardly works because there isn't any way to make solve
consistently behave like this.
> 1) should it be kept?
The output should just be changed to be consistent with the
mathematical definition of computing a parametrised solution set.
> 2) if removed, should there be deprecation?
It isn't possible to deprecate this. The output just needs to be made
correct. What is possible is adding a separate function that does
undetermined coefficients solving more directly.
--
Oscar