sympy/sympy — pull request #8295 by jcrist (2014-10-23 21:09:12+00:00)
Title: [WIP] Added `timeout` argument to `fu`

**Do not merge - proof of concept for discussion only**

## Rational

For the large expressions that we see in `mechanics`, calls to `simplify` can take an extremely long time. However, for simple expressions, simplification is desirable. Currently we don't simplify by default inside any of our library code, as it's impossible to tell whether the expression can be reasonably simplified or not. If a `timeout` argument was added to such functions though, one could simply run

```
>>> simplify(expr, timeout=some_reasonable_max_time)
```
and get the best of both worlds.

## Implementation

Just a proof of concept, still has lots of issues. `fu` isn't even the main culprit for time consuming operations, but it was self contained so I tried it here first. See [here](https://groups.google.com/forum/#!topic/sympy/qsPImy6WqcI) for some relevant discussion.

The `timeout` kwarg only implements a "pseudo-timeout". It relys on cooperative checking in each called function. Functions that don't implement timeout will result in blocking until a function with timeout gets control. Still, it works for simple test cases.

Actual timeouts can't easily be implemented robustly in a cross-platform way. The most common suggestion is to use `signal.alarm`, but that only works for `*NIX` systems. This is a (somewhat hackish) attempt at getting around that.

Another option is to use decorators and a global `TIMEOUT` parameter, but this will prevent using sympy in separate threads or setting different timeouts for different functions. It would be more composable though.

After some profiling, it seems that `expand` and friends are really the main culprit here. That would take some more work though, so I'd like to get some validation on this before working on that.