-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
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
chold! doesn't act as expected #1374
Comments
It's not possible to change the type of something in-place, so the behavior expecting isn't actually feasible. Perhaps this is an indication that |
cc: @timholy |
"its value stays as an array": CholeskyDense is a composite of two objects, and Array and a Bool. In that output, you're seeing those two components (note the "true" at the end). What's possibly confusing is that that CholeskyDense is designed to act as a decomposition of A, in other words be interchangeable for A when used in linear algebra. For example: julia> Ac = copy(A)
5x5 Float64 Array:
6.4692 2.17151 -3.92343 -3.83961 -0.393393
2.17151 4.54112 -3.09598 -1.09211 -0.745708
-3.92343 -3.09598 12.3281 0.280427 -0.148782
-3.83961 -1.09211 0.280427 6.62379 -1.92005
-0.393393 -0.745708 -0.148782 -1.92005 4.46919
julia> C = chold!(A, true)
CholeskyDense{Float64}(5x5 Float64 Array:
2.54346 0.853761 -1.54255 -1.5096 -0.154668
0.0 1.95249 -0.91115 0.100757 -0.314295
0.0 0.0 3.01968 -0.647885 -0.223115
0.0 0.0 0.0 1.97863 -1.14545
0.0 0.0 0.0 0.0 1.72762 ,true)
julia> C\b
5-element Float64 Array:
-0.189731
-0.419205
-0.250393
-0.222415
-0.419997
julia> Ac\b
5-element Float64 Array:
-0.189731
-0.419205
-0.250393
-0.222415
-0.419997 In other words, this test shows that it's working as intended. If you want the Cholesky factor, used |
Ah, clever. So the |
I get the decomposition thing---that's really quite useful---I guess I just expected |
I see your point, and it's a good one. (It took me a little to understand that was probably your thinking, sorry about that.) But as Stefan said, it's not possible. I guess ! also means "caution!" in this context :-). ! is actually pretty ambiguous: some functions have "dummy" inputs that really serve as outputs, for others (like I just noticed that your comments also point out that |
So does that mean |
Correct. |
Indeed, I should say that |
It depends. If Note that I was very careful to completely avoid the word "variable." |
An alternative would be to use a type to indicate that an object is allowed to be destroyed:
The exclamation mark could then be reserved for functions that do in-place modifications such as |
That's not a bad idea. I'm a bit used to knowing that ! means I'd better read the documentation on a function, so I don't think this is essential, but it might mean fewer trips to the docs. That certainly has merit. What do others think? |
My attitude was much like yours, @timholy. The To me it is a sign to the casual user that such functions should be avoided. The expert user who has read the docs can employ such functions to overwrite arrays thereby saving storage and enhancing performance but they should not complain about subtle bugs in their code introduced by the contents of arrays being changed. So I think that the |
Yes, I think you're right about the
(Although maybe this example is a bit far-fetched.) |
Right. That's a different but related convention, which is that when you give constructors an array, they "own" it. Of course, this is to avoid having to make copies of everything, but it can definitely be a usability issue. |
As an inner constructor the function All the Factorization types eventually call Lapack subroutines to generate the decomposition. These subroutines always overwrite some of their arguments, hence the option for overwriting is available. Saving memory allocation and garbage collection by overwriting is not important when dealing with arrays with tens or hundreds of elements. It is important when dealing with arrays having tens or hundreds of millions of elements. I write code that performs iterative optimization of parameters in models that can have matrices of this size in their representation and these arrays need to be updated at each evaluation of the objective function. I really want to do that updating in place. In fact, in the R code for these models that I currently have available, I go to a lot of trouble and complication linking compiled code with R code and passing objects that should not be modified but are, exactly to allow for in-place updating. In early versions of that code (the lme4 package for R) users had the experience of getting models fit and then having R fail because it is unable to allocate memory to construct the object to be returned from the model-fitting function. In other words, the results were calculated but could not be returned because of a copy operation. They weren't happy. |
I think David's point is that you could, if you chose, have the following behavior: However, I agree with Stefan it's probably a good convention that when you pass things to a constructor, you're passing control of them to the new object. I think I follow that pretty naturally in my coding, but I suppose this is yet another chance to ask whether we need more documentation. |
@timholy, that's indeed what I meant. The convention of passing control of the arguments in a type constructor to the type does seem to make a lot of sense, however. Adding Destroy methods everywhere would probably be too verbose. |
If I have a triangular matrix, is there a way to construct a This could be useful for sampling from Wishart (and inverse Wishart) distributions, which can be done via a Bartlett decomposition. |
@simonbyrne At present the Actually, now that I think of it there is no need to match the size of the matrix used to create ``cld` with the size of the matrix you replace the factor by. However, it is probably much easier to just call |
@daviddelaat Regarding adding Destroy methods everywhere, I think it make much more sense to call |
@dmbates Thanks. You can actually call However, perhaps it would be better if the constructor for This would have the benefit of being consistent with some of the other |
Actually, I just realised |
As I understand it,
chold!
is supposed to return an in-placeCholeskyDense
: it outputs such a type, but its value stays asArray
. Also, only the upper diagonal elements are changed, the lower diagonal elements are those of the original matrix.The text was updated successfully, but these errors were encountered: