Yathartha Joshi Open Source Enthusiast

GSoC 2018 - Week 8 - Improving solving of logarithmic equations

Before the start of the week Amit and I discussed on a few points on:

Note: is_logarithmic() is an identifier helper for _transolve to determine whether the expression is logarithmic or not. and _solve_log() is a solving helper that returns the equation in a tractable form for solveset to better handle.

  • What should is_logarithmic() return?

While designing the method at first it returned a logcombined equation if found to be logarithmic, but we agreed upon having consistency among all the identifying helpers to return either True or False.

  • How _is_logarithmic() should work?

Next question was how it should work. We can implement it in two ways either to make the logcombined equation, if the expression reduces, it is obviously a logarithmic equation otherwise not. We also need to check whether the equation reduced has the variable to be solved in its free_symbols But logcombine possessed a problem that it unknowingly manipulates the equation, like log(x) - log(2*x) would reduce to log(1/2) for which the routine would return False as there are no symbol involved. So a more better way needs to be implemented.

  • How _solve_log() will handle removing unwanted solutions?

Simply reducing the logarithmic equation to a tractable form for solveset to handle would cause spurious solutions in the result. Therefore it becomes necessary to remove them. Take for example: solveset gives the result of log(x - 3) + log(x + 3) as {-sqrt(10), sqrt(10)}, but -sqrt(10) is not the solution in Real domain. Therefore one way to remove it was using checksol. Amit suggested on to have a look over the singularities and try incorporating the check in _solveset.

Things that I did during the week:

  • improved is_logarithmic()

Removed the logcombine way of checking the equation. As of now the _is_logarithm checks for every term to be logarithmic in terms of the variable to be solved, if so it returns True otherwise False

  • improved the _solve_log()

As per the current documentation of _transolve this routine is improved to return a modified form of the equation that solveset could better handle. Checking of the spurious solutions will take place in solveset itself.

  • Way to remove spurious solutions

To handle this scenario I have added a check in _solveset specifically for logarithmic equations to remove spurious solutions. The idea is based on the fact that natural log in undefined for negative and zero value, therefore this method gets each term of the expression, substitutes each solution to every term one by one and if for any term the value isn’t real that solution will not be included.

Why checksol() is not the appropriate way?

At first I thought of using the checksol(), but it possessed a problem. checksol unintensionally allows wrong solution to creep in. Take for example log(3*x) - log(-x + 1) - log(4*x + 1), solveset would give -1/2 and 1/2 as the solutions but the former isn’t a solution in real domain. Using checksol would not remove this as I*pi gets cancelled out during evaluating the expression therefore it returns True, which is not correct.

  • Addressing comments

Apart from this few changes have been done in the _transolve PR:

  • I have added a method that would return all the terms present in the expression: make_expr_args()

  • Made the expresssion remain unevaluated when doing lhs - rhs within _transolve.

Read this blog for better understanding of logarithmic solving.

Follow @Yathartha22