mathnet / mathnet-symbolics

Math.NET Symbolics
http://symbolics.mathdotnet.com
MIT License
341 stars 66 forks source link

SymbolicExpression.Parse freeze for "29^11^7" #64

Open ghost opened 5 years ago

ghost commented 5 years ago

Using C# nuget package MathNet.Symbolics, ver 0.20.0

Parsing this expression "29^11^7" leads to freeze. Tried with Infix.ParseOrUndefined("29^11^7"); and SymbolicExpression.Parse("29^11^7")

When tried to put parenthesis it works fine "(29^11)^7"

FoggyFinder commented 5 years ago

I think it's just trying to calculate:

"29^(11^7)"

that's very big number. So, put a parentheses is a good idea.

Happypig375 commented 5 years ago

Yes. Exponentiation is right-associative, which means that it is evaluated right-to-left.

This is because (29^11)^7 can be written as 29^(11*7) while the other cannot be easily simplified.

Happypig375 commented 5 years ago

I think large number detection can be done to avoid hangs. (Using power rules while calculating instead of expanding to a very big number)

ghost commented 5 years ago

Yes, it sounds reasonable. The problem in my case with this expression is that it is entered by user and I don't have control over what he can enter. Is there a way to handle this?

Happypig375 commented 5 years ago

Evaluate asynchronously, show an activity indicator and provide a cancel button?

ghost commented 5 years ago

Evaluate asynchronously, show an activity indicator and provide a cancel button?

This is not possible, because my code is in web service invoked by other applications.

Happypig375 commented 5 years ago

Setting a default timeout so that each request will not take too much time?

ghost commented 5 years ago

This is not an option too, because I have to return meaningful result in short time. I have to somehow handle expressions like this without affecting the whole functionality. For now my workaround is to run it in separate thread and wait for specified number of milliseconds, but I prefer to have better way to do it.

cdrnet commented 5 years ago

I guess we could have a global Control instance like in Numerics to control how a few operations like power behave on very large input (or expected very large output or expensive operation). Ugly, but usually good enough.

Any proposals on what good rules would be for power? Should the limitation be opt-in or opt-out?

MovGP0 commented 3 years ago

Instead of a default timeout, there should be

Using a CancellationToken allows for scenarios with cancel buttons, web requests, as well as timeouts (via the CancellationTokenSource).

Example

let expression = 9Q ** (9Q ** 9Q);
expression ==> "9^(9^9)"
use cts = new CancellationTokenSource (TimeSpan.FromSeconds 5)
try
    Expression.simplifyAsync expression cts.Token
with
| :? TaskCanceledException as e => // ...