Nice that you fixed the actual bug here. Nevertheless, I think that the function fullratsimp should have protection against infinite loops. Something like:
(defmvar*max-fullratsimp-iterations*32"Maximum number of iterations allowed for fullratsimp before falling back.")(defmfun($fullratsimp:properties((evfunt)))(exp&restargl)"Repeatedly applies `ratsimp` to an exp until either (a) a fixpoint is reached (b) cycle is detected (A -> B -> C -> A -> ...), or (c) the number of iterations exceeds *max-fullratsimp-iterations*. For case 'a', the fixed point is returned; for cases 'b' & 'c', the expression with the least conssize is returned. The optional arguments (`argl`) are passed along to each `ratsimp` call."(labels((local-ratsimp(e)(simplify(apply#'$ratsimp (cons e argl)))))(let((seen(listexp))(currentexp)(next(local-ratsimpexp))(k*max-fullratsimp-iterations*))(loop;;Fixpointreached(expressionstoppedchanging)(when(alike1currentnext)(returncurrent));;Cycledetected(expressionstartedrepeating)ormaximumnumberofiterations;;exceeded--returnexpressionwithleastconssize.(when(or(membernextseen:test#'alike1) (< k 0))(return(reduce(lambda(ab)(if(<(conssizea)(conssizeb))ab))seen)))(pushnextseen)(decfk)(setfcurrentnextnext(local-ratsimpnext))))))
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
(defmvar*max-fullratsimp-iterations*32"Maximum number of iterations allowed for fullratsimp before falling back.")(defmfun($fullratsimp:properties((evfunt)))(exp&restargl)"Repeatedly applies `ratsimp` to `exp` until either (a) a fixpoint is reached, (b) a cycle is detected, or (c) the number of iterations exceeds *max-fullratsimp-iterations*."(labels((local-ratsimp(e)(simplify(apply#'$ratsimp e argl))))(let*((k*max-fullratsimp-iterations*)(seen(listexp))(currentexp)(next(local-ratsimpexp))(bestexp)(min-size(conssizeexp)))(loop;;Tracktheminimumsizeonthefly(let((sz(conssizenext)))(when(<szmin-size)(setfmin-sizeszbestnext)));;(a)Fixpointreached(when(alike1currentnext)(returnnext));orcurrent,theyarealike;;(b)Cycledetectedor(c)Maxiterationsexceeded(when(or(membernextseen:test#'alike1) (< k 0))(returnbest))(pushnextseen)(decfk)(setfcurrentnextnext(local-ratsimpnext))))))
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Most likely no. The iteration limit check is fast, but the cycle detection is slow. If we got rid of one check, maybe it should be the cycle detection?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Intuition about "fast" and "slow" in Maxima is often misleading, we'd have to measure. In the normal case, the new expression is not alike1 any previous, and I guess that alike1 aborts very quickly in the average case. I'll do some experiments soon.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Fixed by commit [a05a6b].
Related
Commit: [a05a6b]
Nice that you fixed the actual bug here. Nevertheless, I think that the function fullratsimp should have protection against infinite loops. Something like:
A better version:
Do we need an iteration limit if we detect cycles and abort then? I'd say no, intuitively.
Most likely no. The iteration limit check is fast, but the cycle detection is slow. If we got rid of one check, maybe it should be the cycle detection?
Intuition about "fast" and "slow" in Maxima is often misleading, we'd have to measure. In the normal case, the new expression is not
alike1any previous, and I guess thatalike1aborts very quickly in the average case. I'll do some experiments soon.