-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extend LinearStateSpace
class
#569
Conversation
Hello @shizejin! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:
Comment last updated at 2021-02-21 16:09:12 UTC |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shizejin Thanks for the PR! I'll check if it works for the Townsend lecture.
|
||
return mu_x_star, mu_y_star, Sigma_x_star, Sigma_y_star | ||
return mu_x, mu_y, Sigma_x, Sigma_y, Sigma_yx |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will probably break a significant amount of code using this function. An easy way around this is to use a keyword argument to optionally return Sigma_yx
. Otherwise, I'm guessing we'll need a PR to update multiple lectures.
r""" | ||
Reorder the states by shifting the constant terms to the | ||
top of the state vector. Then partition the linear state | ||
space model following Appendix C in RMT Ch2 such that the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this Appendix C in the latest version of RMT? In an older version, it seems that it was "Appendix B". If so, we might need a more precise reference.
quantecon/lss.py
Outdated
A_diag = np.diag(A) | ||
num_const = 0 | ||
for idx in range(n): | ||
if (A_diag[idx] == 1) and (C[idx, :] == 0).all(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem to be a sufficient condition for finding constants. For instance, consider:
A = np.array([[1., -0.1], [0.5, 0.9]])
C = np.array([[0.], [1.]])
This has no constants and A is apparently stable since:
np.absolute(np.linalg.eig(A)[0])
yields
array([0.97467943, 0.97467943])
Do we really need re-ordering, or can we ask the user to provide a system that takes the special form 2.C.1?
Detecting constants in general is tricky. Consider:
A = np.array([[0.5, 0.5], [0.5, 0.5]])
C = np.array([[0.], [0.]])
If the initial conditions are the same, then this produces constant processes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that this part is actually tricky. But I guess we need to do this inside the function so that we don't complicate the input format, with the same logic you mentioned above.
Essentially we want to detect those states associated with unity eigenvalues (we do not allow for eigenvalues strictly greater than 1). In addition to the current two conditions for finding the targeted states, I guess we can check np.linalg.norm(row_vec)==1
or we can compute the eigenvalues directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The second example I gave has eigenvalues 1 and 0, and none of the rows satisfy np.linalg.norm(row_vec)==1
. Besides, a row may satisfy np.linalg.norm(row_vec)==1
, but not be a vector containing one 1 and 0s otherwise.
I think the following procedure might be good enough, even if it doesn't cover all possible cases:
- Check whether the ith row is a vector with a 1 in the ith entry, and 0s otherwise. Store these rows as "constant" rows.
- Re-order the matrices based on 1.
- Verify that A_22 is stable by computing the modulus of eigenvalues. If the check fails, raise an error.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't step 1 equivalent to (A_diag[idx] == 1) and np.linalg.norm(row_vec)==1
? Sorry that I might not clear in my previous reply, I meant to add np.linalg.norm(row_vec)==1
"additionally". And (C[idx, :] == 0).all()
is also a necessary condition to check for a constant state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this looks good to me. I thought you meant only checking np.linalg.norm(row_vec)==1
.
This method works for the Townsend lecture -- thanks! |
Thanks @shizejin. @QBatista one you're happy with this PR would you be willing to @shizejin we will need to think of backward compatibility. Is this just two new methods (i.e. will it impact existing users of the function i.e. through an altered interface)? It seems to be modifying existing method interfaces etc. |
@mmcky Yes, sure. |
Yes @mmcky this PR is altering the existing method |
@shizejin It's not a big deal to change the lecture code to handle the extra output, although I do wonder if there are people using this routine in the wild who might be inconvenienced...? There are various alternatives, such as a flag like Overall, this seems to me like a valuable enhancement and it would be best to just change the lecture code to accommodate it. I'm happy to do that @mmcky and @oyamad . |
Thanks @mmcky and @jstac for very useful comments and suggestions. I will write down a clear note once I modify this PR adopting some suggestions from @QBatista . Thank you all! |
Add conditions for finding the constant term in the transition matrix.
I have modified the code according to the great suggestion by @QBatista. @mmcky would you please let me know if the following description looks clear enough to you? The two keyword arguments, We also make Therefore, the recommended use of mu_x, mu_y, Sigma_x, Sigma_y = lss.stationary_distributions(max_iter, tol) to mu_x, mu_y, Sigma_x, Sigma_y, Sigma_yx = lss.stationary_distributions() Please let me know if anything is unclear to you and if there is any information I could provide :) |
The code looks good to me. Thanks @shizejin ! |
Thanks @shizejin that would be great. |
Hi @mmcky could you please let me know if the two PRs look good to you? |
Thanks @shizejin -- looking good. I am holding off on merging this as we are in the middle of a migration for: python.quantecon.org to the new jupyter book system. Sorry for the delay. I will merge this PR next week and then issue a new release along with the additions to the lecture repos. |
I am going to release this now -- and then migrate the |
thanks @shizejin |
* update QuantEcon.py QuantEcon/QuantEcon.py#569 * catch execution errors for CI * TEST: test against new release of QuantEcon * add .git for install from quantecon.py@new-release * use correct branch name * update environment
Modify the
LinearStateSpace
class with two new features:to compute the steady state covariance matrix by solving a discrete Lyapunov equation rather than "iterating to convergence"
stationary_distributions
now does not take argumentsmax_iter
nortol
stationary_distributions
to use the Bartels-Stewart algorithm.adding a method that will compute the stationary covariance matrix
E (y_t - \mu_y) (x_t -\mu_x)' = G \Sigma_x(\infty).
stationary_distributions
methodSigma_yx