Skip to content
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

Functions with %*% cannot be differentiated.... #16

Open
Non-Contradiction opened this issue May 28, 2018 · 11 comments
Open

Functions with %*% cannot be differentiated.... #16

Non-Contradiction opened this issue May 28, 2018 · 11 comments

Comments

@Non-Contradiction
Copy link
Owner

This is because of the operator %*% in R is only S4 generic but not S3 generic, so %*% on JuliaObject can't be overloaded currently....
From the R documentation of matmult, %*%

This operator is S4 generic but not S3 generic. S4 methods need to be written for a function of two arguments named x and y.

Currently I can think of two ways to deal with the problem, one way is to make JuliaObject an S4 again, and it will occur some additional overloading.
The other one is to define some new operator like %x% to be used instead of %*%.

@Non-Contradiction
Copy link
Owner Author

Currently an operator %x% is defined.

@randy3k
Copy link

randy3k commented Jun 1, 2018

You also need to define it for regular R objects?

a = matrix(1:4, 2, 2)
b = 1:2
a %x% b  # it should work, otherwise calling a function with matrix miiltiplication won’t work

@Non-Contradiction
Copy link
Owner Author

Oh, my fault.
I should have noticed that %x% already means Kronecker product in R.
So need to find another symbol for the purpose.

@Non-Contradiction
Copy link
Owner Author

And the behavior of R matrix multiplication also doesn't match the behavior of Julia matrix multiplication.
For example, in R, the result of a matrix multiplies a vector is a matrix, but in Julia the result is a vector, (which makes more sense?). Need to think carefully about this... Maybe need to define own function in Julia to match the R behavior.....

@randy3k
Copy link

randy3k commented Jun 1, 2018

A vector is mathematically equivalent to a n by 1 matrix. Julia handles this quite well, but it is not the case in R. It is more a question for JuliaCall and RCall.

@randy3k
Copy link

randy3k commented Jun 4, 2018

@Non-Contradiction
Copy link
Owner Author

I have considered this kind of approach for %*%, other internal generics and non-generic functions.

The problem is that if users use this method in the REPL after library(autodiffr), then it is fine,
but if users want to use automatic differentiation on some function from other packages, or the function definition is based on some function from other packages (even like base!) and the function use %*%, then everything is broken,
because that definition of %*% in other packages (like base) is not modified by autodiffr.

And I also think once it is broken, users will be very confused because all they see is %*% but from different namespaces, unless they already know this kind of thing, to debug this will be a nightmare.

@Non-Contradiction
Copy link
Owner Author

There are tricky ways to deal with the problem.

The best way I can think of is that for every function that is passed to gradient, hessian..., you define a slightly modified function: the function should have the same function body but different environment with the original function, before all the way to base environment, you add one environment that contains the changed definition of %*% or whatever that is needed, so every call of %*% will come to the new definition.
I don't think the extreme complexity worth it....

@randy3k
Copy link

randy3k commented Jun 4, 2018

but if users want to use automatic differentiation on some function from other packages, or the function definition is based on some function from other packages (even like base!) and the function use %%, then everything is broken,
because that definition of %
% in other packages (like base) is not modified by autodiffr

I assume the package would depend on autodiffr or JuliaCall, so the package will understand the exported %*% method. It may be an issue, however, if another package also exports the S3 method %*%.default.

@Non-Contradiction
Copy link
Owner Author

If the package depends on autodiffr, then it also understands the new operator being defined.
Defining a new operator is inconvenient for users, but if users are aware of it, then it will be very clear when they encounter errors regarding %*%. Redefining an existing operator is convenient, but once users have problems with %*%, they will be confused.

And it is also a general issue with other internal generics and non-generics. Should we redefine them? Or should we introduce other new functions to use instead?

@nashjc
Copy link
Collaborator

nashjc commented Jun 6, 2018

This is an important enough issue that I think it worthwhile to start a vignette to show what goes wrong, using examples. I suggest creating numbered functions for different tries, e.g., JuliaObject1, JuliaObject2, ... with JuliaObject itself reserved for the latest (and hopefully best) solution.

Having such a vignette (possibly like a "history" of attempts, with explanations -- need not be terribly tidy) will allow us to ask others for help. Possibly Duncan Murdoch can give some insight.

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

No branches or pull requests

3 participants