Skip to content

ENH: Add informative ValueError for LQMarkov DARE non-convergence when beta=1#831

Open
HG-Cheng wants to merge 3 commits into
QuantEcon:mainfrom
HG-Cheng:main
Open

ENH: Add informative ValueError for LQMarkov DARE non-convergence when beta=1#831
HG-Cheng wants to merge 3 commits into
QuantEcon:mainfrom
HG-Cheng:main

Conversation

@HG-Cheng

@HG-Cheng HG-Cheng commented May 4, 2026

Copy link
Copy Markdown

References

Fixes #508

Description

This PR addresses the cryptic ValueError: Convergence failed issue when instantiating LQMarkov with a discount factor beta = 1.0.

Mathematical Context:
When beta = 1.0, the Bellman operator for the discrete algebraic Riccati equation (DARE) loses its strict contraction mapping property. Consequently, the value function iteration transitions from exponential convergence to extremely slow, sublinear convergence.

The Fix:
Instead of modifying the initial Ps = np.eye(n) (which is necessary to ensure convergence to the stabilizing positive definite solution rather than a pseudo-solution), this PR implements a graceful degradation strategy.

When beta == 1.0 and convergence fails within max_iter, the code now raises a highly informative context-aware ValueError. It explains the mathematical limitation (loss of strict contraction) and explicitly guides the user to significantly increase max_iter, saving hours of debugging time for future users.

All existing unit tests in test_lqcontrol.py continue to pass smoothly.

@HG-Cheng

Copy link
Copy Markdown
Author

Hello maintainers,

I noticed the CI pipeline failed on the macos-latest runner.

Looking closely at the logs, the failure is entirely isolated to quantecon/util/tests/test_timing.py (ACTUAL: 0.203895 vs DESIRED: 0.05). It appears to be a transient flaky test caused by CI runner CPU load fluctuation, as this PR only modifies a string message in _matrix_eqn.py and does not touch any timing utility logic.

Just leaving a note here for visibility. Looking forward to your review on the core changes!

@oyamad

oyamad commented May 30, 2026

Copy link
Copy Markdown
Member

@HG-Cheng Thank you for the contribution!

Do you know what is known to happen when beta > 1? (The current code does not prohibit beta > 1.)
I think it is better to either change if beta == 1.0 to if beta >= 1.0 or reject beta > 1 upon construction.

@HG-Cheng

Copy link
Copy Markdown
Author

@oyamad "Thanks for the review!
You are right, $\beta > 1$ doesn't make economic sense in this context. I agree that rejecting $\beta > 1$ upon construction is the cleaner approach. I will update the PR to include this validation and push the changes shortly."

@oyamad

oyamad commented May 31, 2026

Copy link
Copy Markdown
Member

@HG-Cheng Next question is: what is known to happen when beta = 1?

For the instance in #508 (comment), it does not converge even with max_iter=1_000_000:

ValueError: Convergence failed after 1000000 iterations.

@HG-Cheng

Copy link
Copy Markdown
Author

Hi @oyamad,Thanks for running that test! That actually makes perfect sense mathematically.If $\beta = 1$, there is absolutely no discounting. This means future costs don't decay over time. If we sum them up over an infinite horizon, the total simply diverges to infinity.Because the mathematical result is infinite, the underlying Riccati solver is essentially trying to compute a finite limit that doesn't exist. That's exactly why it spins endlessly and fails even after 1,000,000 iterations—it's looking for a convergent solution where there isn't one.Given this, I have updated the validation from if beta > 1.0: to if beta >= 1.0: in the latest commit. This way, we can "fail-fast" and reject $\beta = 1$ upon construction as well, preventing the solver from wasting compute time on an endless loop.Let me know if you agree and if we are good to merge!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ValueError: LQMarkov with beta=1

2 participants