-
-
Notifications
You must be signed in to change notification settings - Fork 191
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
Feature/issue 123 complex numbers with vars #789
Feature/issue 123 complex numbers with vars #789
Conversation
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.
Thanks for contributing. It'd be great to get some basic support for complex numbers. Is this intended to be something that eventually makes its way to the Stan language?
The first step needs to be a functional spec for what is being proposed---this doesn't look like it's still on the same course as the issue #123. Then a wider group can look at the spec and make sure it's going to work with al the various moving pieces of Stan.
We have very strict dependency requirements that this is violating. We do not allow files in the var
path to include fvar
, for example. I'm not sure where all of this is documented. I don't see anything in the math repo readme or Wiki.
I have a hard time imagining we're going to be able to get away with imaginary and real components being of different types. The problem is what happens when they combine with each other. But I take the point in the comments about type inference and templates---we run into that all the time. In general, you dont need to doc the language---assume the code reader is very familiar with C++, so that you only need to comment when you violate standard idioms.
Here is one page with some information sort of like this: /~https://github.com/stan-dev/stan/wiki/Code-Quality Anyone know if we have a single page we can link new devs to? @syclik maybe? Edit: Here are some pages that are decent to skim: |
I see, what I was looking for (description of code layout and dependencies) is here: /~https://github.com/stan-dev/stan/wiki/Contributing-New-Functions-to-Stan We need to prioritize getting that single getting-started page for new contributors. |
I swear I’ve written it out before, but I can’t find it.
I think we should have separate ones for Stan and Math.
… On Mar 7, 2018, at 4:17 PM, Bob Carpenter ***@***.***> wrote:
I see, what I was looking for (description of code layout and dependencies) is here:
/~https://github.com/stan-dev/stan/wiki/Contributing-New-Functions-to-Stan
We need to prioritize getting that single getting-started page for new contributors.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
The closest thing we have is the top-level wiki on stan-dev/stan, which has a lot of links:
/~https://github.com/stan-dev/stan/wiki
|
Don't worry! Things are a little complicated and we're still apparently working on our intro material, haha. We've tried to keep I think your code could go in PS Do you have experience using forward declarations to reduce compile times? It's something I've been thinking about lately but haven't done before. Compile time is a big concern of ours. |
You have a using fvar in the complex code, then var includes the complex code and hence fvar.
|
Right---the reason it's at the include level is to prevent code that only needs reverse-mode (like everything in Stan at the moment) from having to import and parse all the forward-mode code. It also avoids circular includes, which makes the include logic easier to understand. It also makes taming all the include-order dependencies for the metaprograms simpler.
… On Mar 7, 2018, at 6:28 PM, ChrisChiasson ***@***.***> wrote:
Yea, I had thought I was being clever by putting the file way up high, out of the rev and fwd directories, but I now see the policy isn't just a file/directory level-thing, but an include thing. Sorry about that.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.
|
Our directories are organized as:
That follows the data types in Stan of |
Thansk for the clarification---you're absolutely right. Just a simple forward declaration isn't going to cause a bunch of code to be brought in as I was suggesting---it's not an include. We still don't want to bring in the symbol because nothing will be able to bring in the declaration or definition. |
Scalar. There's no dependency on `std::vector` or `Eigen::Matrix`.
On Wed, Mar 7, 2018 at 8:18 PM, ChrisChiasson <notifications@github.com>
wrote:
… I guess I had trouble deciding because complex numbers are in one sense a
scalar of the domain of complex numbers, and in another sense are a vector
or array on the domain of real numbers. Where do you think it should go?
On Wed, Mar 7, 2018, 7:14 PM Bob Carpenter ***@***.***>
wrote:
> Our directories are organized as:
>
> - scal: int, double, var, fvar<T>
> - arr: std::vector, where Tis any Stan type
> - mat: Eigen::Matrix<T, R, C> where T is a scalar type and where R and
> C are the row and column int specifies determining if we have a vector
> (-1, 1), row vector (1, -1), or matrix (-1, -1).
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <#789 (comment)>, or
mute
> the thread
> </~https://github.com/notifications/unsubscribe-auth/ALTv-
71T0xsfoAqh0jR6rYIFWLge_G2wks5tcIXygaJpZM4ShF_6>
> .
>
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#789 (comment)>, or mute
the thread
</~https://github.com/notifications/unsubscribe-auth/AAZ_F2xWn4_E1vqt7w3V_HdC_VhVakoUks5tcIb3gaJpZM4ShF_6>
.
|
The way we have it, any templated code that can accept either primitives, I'll need to dig a little to figure out where it should live within scal. |
I'm not sure. (I've also been sick with a headache, so not completely on... I'll take a look again tomorrow.) @bob-carpenter, thoughts? I'd trust his judgement if he gets to it before I do. |
I just looked back at the code a little more carefully. Take all I've said with a grain of salt. I may not have gotten all the nuance there. (I'm still trying to get around the fact that So... I'm not sure exactly where it belongs. If we never need to template specialize for |
Yup. Makes sense. |
Allow me to comment on that — one of the reasons that we haven’t
tackled complex numbers is exactly this reason. In order to implement
autodiff with complex numbers correctly we’d have to specialize the
_entire algebra of complex numbers_ to our autodiff types. This kind
of cherry picking of some functionality will always leave holes that
compromise the UX. Ultimately we really want to bite the bullet and
specialize all of the operations or back off and just implement the
real outputs of common complex operations (for example moduli
or the power/phase output of FFTs).
… On Mar 7, 2018, at 9:31 PM, ChrisChiasson ***@***.***> wrote:
The reason I avoided directly specializing std::complex on var or fbar is
that the full class is large, and the specialization would need to
reimplement all of it. :-(
On Wed, Mar 7, 2018, 8:26 PM Daniel Lee ***@***.***> wrote:
> I just looked back at the code a little more carefully. Take all I've said
> with a grain of salt. I may not have gotten all the nuance there. (I'm
> still trying to get around the fact that stan::math::internal::complex<T>
> is a subclass of std::complex<T>, but then we template specialize
> std::complex<stan::math::var> as a subclass of
> stan::math::internal::complex.)
>
> So... I'm not sure exactly where it belongs. If we never need to template
> specialize for double, I'm almost tempted to suggest just specializing
> std::complex<var> and std::complex<fvar<T>> in their respective folders
> and not have anything live in prim. That would duplicate code -- based on
> the way you've handled the operators -- but I think it may be clearer? I'm
> not sure yet.
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <#789 (comment)>, or mute
> the thread
> </~https://github.com/notifications/unsubscribe-auth/ALTv-6ZIHP_5xapx8AyAhJHdgwyWrcOOks5tcJa6gaJpZM4ShF_6>
> .
>
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub <#789 (comment)>, or mute the thread </~https://github.com/notifications/unsubscribe-auth/ABdNlpglYzvoXBZoBCW39uhgmzCmTRY3ks5tcJgFgaJpZM4ShF_6>.
|
What do you mean by derivative examples? Specific operations
over complex numbers?
… On Mar 7, 2018, at 9:57 PM, ChrisChiasson ***@***.***> wrote:
Can you give 1 or 2 derivative examples you would like to cover so I can
start wrapping my mind around it?
On Wed, Mar 7, 2018, 8:54 PM Michael Betancourt ***@***.***>
wrote:
> Allow me to comment on that — one of the reasons that we haven’t
> tackled complex numbers is exactly this reason. In order to implement
> autodiff with complex numbers correctly we’d have to specialize the
> _entire algebra of complex numbers_ to our autodiff types. This kind
> of cherry picking of some functionality will always leave holes that
> compromise the UX. Ultimately we really want to bite the bullet and
> specialize all of the operations or back off and just implement the
> real outputs of common complex operations (for example moduli
> or the power/phase output of FFTs).
>
> > On Mar 7, 2018, at 9:31 PM, ChrisChiasson ***@***.***>
> wrote:
> >
> > The reason I avoided directly specializing std::complex on var or fbar is
> > that the full class is large, and the specialization would need to
> > reimplement all of it. :-(
> >
> > On Wed, Mar 7, 2018, 8:26 PM Daniel Lee ***@***.***>
> wrote:
> >
> > > I just looked back at the code a little more carefully. Take all I've
> said
> > > with a grain of salt. I may not have gotten all the nuance there. (I'm
> > > still trying to get around the fact that
> stan::math::internal::complex<T>
> > > is a subclass of std::complex<T>, but then we template specialize
> > > std::complex<stan::math::var> as a subclass of
> > > stan::math::internal::complex.)
> > >
> > > So... I'm not sure exactly where it belongs. If we never need to
> template
> > > specialize for double, I'm almost tempted to suggest just specializing
> > > std::complex<var> and std::complex<fvar<T>> in their respective folders
> > > and not have anything live in prim. That would duplicate code -- based
> on
> > > the way you've handled the operators -- but I think it may be clearer?
> I'm
> > > not sure yet.
> > >
> > > —
> > > You are receiving this because you authored the thread.
> > > Reply to this email directly, view it on GitHub
> > > <#789 (comment)>,
> or mute
> > > the thread
> > > <
> /~https://github.com/notifications/unsubscribe-auth/ALTv-6ZIHP_5xapx8AyAhJHdgwyWrcOOks5tcJa6gaJpZM4ShF_6
> >
> > > .
> > >
> > —
> > You are receiving this because you are subscribed to this thread.
> > Reply to this email directly, view it on GitHub <
> #789 (comment)>, or
> mute the thread <
> /~https://github.com/notifications/unsubscribe-auth/ABdNlpglYzvoXBZoBCW39uhgmzCmTRY3ks5tcJgFgaJpZM4ShF_6
> >.
> >
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <#789 (comment)>, or mute
> the thread
> </~https://github.com/notifications/unsubscribe-auth/ALTv-0QS6JXvtDVGqwfDFkVRJjofO6X1ks5tcJ1VgaJpZM4ShF_6>
> .
>
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub <#789 (comment)>, or mute the thread </~https://github.com/notifications/unsubscribe-auth/ABdNlnDqgZA-cSsxxNzpiL042RUv2NKpks5tcJ4ggaJpZM4ShF_6>.
|
Which examples are relevant depends deeply on the specific
application being considered. We haven’t had one application
be requested enough to warrant its inclusion, just a lot of
particular applications that are all related to complex numbers.
And that’s the challenge. Implementing a complete complex
algebra would enable most of those applications, but no single
application has enough demand that a specialized implementation
would yield significant use.
Might be worth a Discourse thread requesting input from users.
My main point is that an incomplete implementation of a complex
type, without the full algebra, will likely cause problems as it will
be hard to communicate what is implemented and what is not.
Unless the partial implementation is wrapped in specific functions,
as opposed to enable_if’ing the hell out of the complex class, but
then that brings us back to the beginning.
… On Mar 7, 2018, at 10:42 PM, ChrisChiasson ***@***.***> wrote:
Just one or two short ones involving derivative propagation so I can wrap
my head around it tomorrow. In the back of my mind I am envisioning some
kind scheme to disable specific Stan functions that are only valid on
reals, or alternatively only enable functions valid on complexes with
everything else failing to compile by default.
On Wed, Mar 7, 2018, 9:10 PM Michael Betancourt ***@***.***>
wrote:
> What do you mean by derivative examples? Specific operations
> over complex numbers?
>
> > On Mar 7, 2018, at 9:57 PM, ChrisChiasson ***@***.***>
> wrote:
> >
> > Can you give 1 or 2 derivative examples you would like to cover so I can
> > start wrapping my mind around it?
> >
> > On Wed, Mar 7, 2018, 8:54 PM Michael Betancourt <
> ***@***.***>
> > wrote:
> >
> > > Allow me to comment on that — one of the reasons that we haven’t
> > > tackled complex numbers is exactly this reason. In order to implement
> > > autodiff with complex numbers correctly we’d have to specialize the
> > > _entire algebra of complex numbers_ to our autodiff types. This kind
> > > of cherry picking of some functionality will always leave holes that
> > > compromise the UX. Ultimately we really want to bite the bullet and
> > > specialize all of the operations or back off and just implement the
> > > real outputs of common complex operations (for example moduli
> > > or the power/phase output of FFTs).
> > >
> > > > On Mar 7, 2018, at 9:31 PM, ChrisChiasson ***@***.***>
> > > wrote:
> > > >
> > > > The reason I avoided directly specializing std::complex on var or
> fbar is
> > > > that the full class is large, and the specialization would need to
> > > > reimplement all of it. :-(
> > > >
> > > > On Wed, Mar 7, 2018, 8:26 PM Daniel Lee ***@***.***>
> > > wrote:
> > > >
> > > > > I just looked back at the code a little more carefully. Take all
> I've
> > > said
> > > > > with a grain of salt. I may not have gotten all the nuance there.
> (I'm
> > > > > still trying to get around the fact that
> > > stan::math::internal::complex<T>
> > > > > is a subclass of std::complex<T>, but then we template specialize
> > > > > std::complex<stan::math::var> as a subclass of
> > > > > stan::math::internal::complex.)
> > > > >
> > > > > So... I'm not sure exactly where it belongs. If we never need to
> > > template
> > > > > specialize for double, I'm almost tempted to suggest just
> specializing
> > > > > std::complex<var> and std::complex<fvar<T>> in their respective
> folders
> > > > > and not have anything live in prim. That would duplicate code --
> based
> > > on
> > > > > the way you've handled the operators -- but I think it may be
> clearer?
> > > I'm
> > > > > not sure yet.
> > > > >
> > > > > —
> > > > > You are receiving this because you authored the thread.
> > > > > Reply to this email directly, view it on GitHub
> > > > > <#789 (comment)
> >,
> > > or mute
> > > > > the thread
> > > > > <
> > >
> /~https://github.com/notifications/unsubscribe-auth/ALTv-6ZIHP_5xapx8AyAhJHdgwyWrcOOks5tcJa6gaJpZM4ShF_6
> > > >
> > > > > .
> > > > >
> > > > —
> > > > You are receiving this because you are subscribed to this thread.
> > > > Reply to this email directly, view it on GitHub <
> > > #789 (comment)>, or
> > > mute the thread <
> > >
> /~https://github.com/notifications/unsubscribe-auth/ABdNlpglYzvoXBZoBCW39uhgmzCmTRY3ks5tcJgFgaJpZM4ShF_6
> > > >.
> > > >
> > >
> > > —
> > > You are receiving this because you authored the thread.
> > > Reply to this email directly, view it on GitHub
> > > <#789 (comment)>,
> or mute
> > > the thread
> > > <
> /~https://github.com/notifications/unsubscribe-auth/ALTv-0QS6JXvtDVGqwfDFkVRJjofO6X1ks5tcJ1VgaJpZM4ShF_6
> >
> > > .
> > >
> > —
> > You are receiving this because you commented.
> > Reply to this email directly, view it on GitHub <
> #789 (comment)>, or
> mute the thread <
> /~https://github.com/notifications/unsubscribe-auth/ABdNlnDqgZA-cSsxxNzpiL042RUv2NKpks5tcJ4ggaJpZM4ShF_6
> >.
> >
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <#789 (comment)>, or mute
> the thread
> </~https://github.com/notifications/unsubscribe-auth/ALTv-zxsAn5uqD14YO7W2eCciHqfHo_sks5tcKEJgaJpZM4ShF_6>
> .
>
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub <#789 (comment)>, or mute the thread </~https://github.com/notifications/unsubscribe-auth/ABdNltZT2imDDu6dPc8QXBjPh42nnxBPks5tcKjDgaJpZM4ShF_6>.
|
Since we need also need a spec before we can really evaluate a PR (as Bob mentioned), I went ahead and made a discourse thread asking for user input on applications. We can also use it for spec discussion (or we could make a new github issue for that, that could be better because we can summarize the comments at the top). Here's the link to the discourse thread: http://discourse.mc-stan.org/t/complex-number-support-in-math-library-autodiff/3511 |
Feel free to keep pushing. We may close the pull request if it seems like
it's far from being ready (closed doesn't mean won't accept; any open pull
request will test on every push and resources can get scarce at times).
What are ship RAOs?
…On Thu, Mar 8, 2018 at 9:16 AM, ChrisChiasson ***@***.***> wrote:
The travis build passed, but the jenkins status says it can't be built. I
noticed I don't seem to be able to load the details for jenkins, so I can't
tell what is wrong. I intend to keep working to add fvar support so I can
use complex numbers in an optimization problem involving ship RAOs. Let me
know if that isn't ok, because the pushes to my remote repo branch are
going to push notifications into this thread, though I will keep it to a
minimum.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#789 (comment)>, or mute
the thread
</~https://github.com/notifications/unsubscribe-auth/AAZ_F5SlpDTWlkUkSta2yKq-bYFZcspLks5tcT00gaJpZM4ShF_6>
.
|
Just to reiterate - Bob wants a spec first, which likely requires some
description of the use case. Code without some kind of spec or goal is
difficult to evaluate.
…On Thu, Mar 8, 2018 at 09:26 Daniel Lee ***@***.***> wrote:
Feel free to keep pushing. We may close the pull request if it seems like
it's far from being ready (closed doesn't mean won't accept; any open pull
request will test on every push and resources can get scarce at times).
What are ship RAOs?
On Thu, Mar 8, 2018 at 9:16 AM, ChrisChiasson ***@***.***>
wrote:
> The travis build passed, but the jenkins status says it can't be built. I
> noticed I don't seem to be able to load the details for jenkins, so I
can't
> tell what is wrong. I intend to keep working to add fvar support so I can
> use complex numbers in an optimization problem involving ship RAOs. Let
me
> know if that isn't ok, because the pushes to my remote repo branch are
> going to push notifications into this thread, though I will keep it to a
> minimum.
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <#789 (comment)>, or
mute
> the thread
> <
/~https://github.com/notifications/unsubscribe-auth/AAZ_F5SlpDTWlkUkSta2yKq-bYFZcspLks5tcT00gaJpZM4ShF_6
>
> .
>
—
You are receiving this because your review was requested.
Reply to this email directly, view it on GitHub
<#789 (comment)>, or mute
the thread
</~https://github.com/notifications/unsubscribe-auth/AAxJ7KKcuORvX6QVDKRHljckhqrpui15ks5tcT-tgaJpZM4ShF_6>
.
|
+1. Definitely design and spec first. Thanks for keeping us on track, Sean.
(When I said “pushing” I meant git push, not pushing forward without a design. Sorry for the confusion.)
… On Mar 8, 2018, at 10:06 AM, seantalts ***@***.***> wrote:
Just to reiterate - Bob wants a spec first, which likely requires some
description of the use case. Code without some kind of spec or goal is
difficult to evaluate.
On Thu, Mar 8, 2018 at 09:26 Daniel Lee ***@***.***> wrote:
> Feel free to keep pushing. We may close the pull request if it seems like
> it's far from being ready (closed doesn't mean won't accept; any open pull
> request will test on every push and resources can get scarce at times).
>
> What are ship RAOs?
>
> On Thu, Mar 8, 2018 at 9:16 AM, ChrisChiasson ***@***.***>
> wrote:
>
> > The travis build passed, but the jenkins status says it can't be built. I
> > noticed I don't seem to be able to load the details for jenkins, so I
> can't
> > tell what is wrong. I intend to keep working to add fvar support so I can
> > use complex numbers in an optimization problem involving ship RAOs. Let
> me
> > know if that isn't ok, because the pushes to my remote repo branch are
> > going to push notifications into this thread, though I will keep it to a
> > minimum.
> >
> > —
> > You are receiving this because you were mentioned.
> > Reply to this email directly, view it on GitHub
> > <#789 (comment)>, or
> mute
> > the thread
> > <
> /~https://github.com/notifications/unsubscribe-auth/AAZ_F5SlpDTWlkUkSta2yKq-bYFZcspLks5tcT00gaJpZM4ShF_6
> >
> > .
> >
>
> —
> You are receiving this because your review was requested.
> Reply to this email directly, view it on GitHub
> <#789 (comment)>, or mute
> the thread
> </~https://github.com/notifications/unsubscribe-auth/AAxJ7KKcuORvX6QVDKRHljckhqrpui15ks5tcT-tgaJpZM4ShF_6>
> .
>
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
I'm still not sure what this PR does and would very much like to see a matching issue with a description of the functionality. Daniel---can you write one out if you understand it? I barely understand complex numbers and don't at all understand the intent of this PR.
On a technical note, subclasses will inherit implementations, whereas template specializations won't. We have to be careful with what's virtual to make sure we don't overload non-virtual methods that would get sliced by references to the base class.
… On Mar 7, 2018, at 9:31 PM, ChrisChiasson ***@***.***> wrote:
The reason I avoided directly specializing std::complex on var or fbar is
that the full class is large, and the specialization would need to
reimplement all of it. :-(
On Wed, Mar 7, 2018, 8:26 PM Daniel Lee ***@***.***> wrote:
> I just looked back at the code a little more carefully. Take all I've said
> with a grain of salt. I may not have gotten all the nuance there. (I'm
> still trying to get around the fact that stan::math::internal::complex<T>
> is a subclass of std::complex<T>, but then we template specialize
> std::complex<stan::math::var> as a subclass of
> stan::math::internal::complex.)
>
> So... I'm not sure exactly where it belongs. If we never need to template
> specialize for double, I'm almost tempted to suggest just specializing
> std::complex<var> and std::complex<fvar<T>> in their respective folders
> and not have anything live in prim. That would duplicate code -- based on
> the way you've handled the operators -- but I think it may be clearer? I'm
> not sure yet.
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <#789 (comment)>, or mute
> the thread
> </~https://github.com/notifications/unsubscribe-auth/ALTv-6ZIHP_5xapx8AyAhJHdgwyWrcOOks5tcJa6gaJpZM4ShF_6>
> .
>
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
I think we're asking you to document what you're aiming to do before we merge your PR, haha. |
We don't have ay specific format, just something that lets us know what operations you want to work, what's not supported, that kind of thing. If you're dead set on coding before getting feedback on a spec, your tests might function as a sort of very detailed and functional spec, which I think would be great. |
That's correct.
The ode solvers can't handle forward mode autodiff now.
… On Mar 27, 2018, at 4:50 PM, ChrisChiasson ***@***.***> wrote:
I feel pretty stupid. It's beginning to look like the integrate_ode_bdf / rk45 functions aren't intended to be able to transmit fvar information from their inputs such as y0 or theta to their output. @wds15 ?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
For Jenkins, you are getting cpplint errors - check out the For Travis, I'm not sure where you're seeing what you're seeing, but the errors I see immediately at the Travis job link are that you're using C++17 stuff?
|
I misunderstood your question! Sorry about that. I have had bunches of trouble with Ubuntu's C compiler packages when trying to use C++11. I have no idea why - seems fairly basic, but I am no Ubuntu wizard. If you're trying to duplicate the travis environment, (which is Ubuntu 14.04, you can start with 14.04 and see how the So I think if you want clang, you want these additional PPLs: /~https://github.com/stan-dev/math/blob/develop/.travis.yml#L22 And then to apt-get install these packages: /~https://github.com/stan-dev/math/blob/develop/.travis.yml#L23 |
Also just want to confirm that you should indeed be using |
A few comments:
|
Some relevant information:
|
@ChrisChiasson, as far as I can tell, this isn't ready for review. I still don't know what you're trying to do! Can you write up a spec for what you're trying to accomplish and put it in the associated issue? If you have the ability, updating the first comment would be great. Then, can you write some notes to guide the reviewer through this implementation against that spec that you describe? It'd help to know some of the major design decisions and whether you've implemented the whole spec or part of it and there's more remaining. |
I'll just start with the first post: I don't understand well enough to
understand the usage.
I think you think the quoted paragraph explains it. Can you rewrite it so
that it has more context and more details? There still isn't enough there
to determine whether we want to accept this into Math. If you asked me to
evaluate this now, I'd have to reject because it adds maintenance burden
and the use isn't clear. I'm not suggesting that happen, I'm suggesting
strongly that the top level comment have enough context and detail to
understand what's being done. If you need help with this, please ask. I
think the best person to help would be @bgoodri. Once it's in, the code is
a community resource that's maintained, so it is a big deal that we
understand why this is happening.
Hope that makes sense.
I haven't looked at the code, but things that are decisions are things like
how you came to the conclusion the traits needed to be implemented and
included in the order you've included it. If you've changed constructors,
why that happened. I know... it's vague, but what I'm asking for is for
you, as the contributor, to leave breadcrumbs for the reviewer to follow.
This PR has 142 files changed! Where should the reviewer start? I just
peeked... why is there a new folder at the {scal, arr, mat} level? These
are things you should help a reviewer with.
…On Fri, Jul 27, 2018 at 8:05 AM ChrisChiasson ***@***.***> wrote:
@syclik </~https://github.com/syclik> the issue was that complex var
numbers couldn't be used because it would automatically dereference a null
ptr of thw imaginaty part. All this does is fix it so that complex numbers
can be used. "Used" is defined at the top of this PR. It has also gone
beyond that to implement the C++14 list of functions that work on complex
numbers, thanks to @bgoodri </~https://github.com/bgoodri> adding many
tests. For now I am considering the top post of this PR to be the location
where the spec is listed, because that is where a previous reviewer asked
me to put it ***@***.*** </~https://github.com/bob-carpenter> ).I will
be happy to add the C++14 note to it if you like. Van you classify "major
design decision"?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#789 (comment)>, or mute
the thread
</~https://github.com/notifications/unsubscribe-auth/AAZ_F2WjG-y5BNHiiBiJ-GrFOKvmn39Oks5uKwHwgaJpZM4ShF_6>
.
|
The use of the PR should be clear. If Stan Math <= 2.18 is an autodiff library for real numbers, then with this PR, Stan Math becomes an autodiff library for complex numbers conceptualized as a pair of There are several situations in which you would want to autodiff functions involving complex numbers, but none of them are actually implemented in this PR, which is fine because this PR is just the framework for them. Future PRs could implement FFTs, various Eigen functions that utilize complex numbers internally, PDFs for complex random variables, etc. We should not wait on this PR for things like that. @syclik your questions are largely about the implementation decisions. I don't fully understand why myself, but I do know that everything before this PR that pertained to complex numbers either would not compile or would segfault as soon as a complex The second principle is that functions in Stan Math under But there are not many functions whose signature is a |
Awesome. Thanks!
Thanks! That's the clearest I've seen it written out. Just to be clear, we never want to take a derivative of a Thanks both for clarifying the issue. That explains what we want. Time to get to the implementation and whether this is a decent implementation that gets us there. I'll start reviewing the code. |
Mind merging develop back in? It looks like some of the diff isn't related to the issue at hand and it's a little distracting.
We're not using the same terminology. If
Instead, what you're returning is just one term (when
I just don't read that to mean the "derivative of both components is taken"; hope that clears up a lot of the confusion in this thread and on discourse. I now understand that what you mean and how that plays out, so it's a lot clearer. I'll try to review this, but I may have a lot of questions for you. |
@@ -20,6 +20,12 @@ inline int is_inf(const fvar<T>& x) { | |||
return is_inf(x.val()); | |||
} | |||
|
|||
// forwarding for ADL | |||
template <class T> | |||
inline auto isinf(const fvar<T>& a) { |
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.
A bunch of questions:
- why is this function here? (this is
isinf
and notis_inf
) - why is it declared and defined multiple times? (in other files too)
- why is
isinf
in thestan::math
namespace? I'm guessing you need it in thestd
namespace?
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 see how we've handled it elsewhere. Is there a reason we can't do the same here? By that, I mean specialize isnan
and isinf
for stan::math::fvar<T>
and include it in its own header file called stan/math/fwd/core/std_isnan.hpp
and std_isinf
?
See:
stan/math/fwd/core/std_numeric_limits.hpp
stan/math/rev/core/std_isnan.hpp
stan/math/rev/core/std_numeric_limits.hpp
stan/math/rev/core/std_isinf.hpp
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.
Can you clarify? What other packages? I didn't see anywhere in this pull request that this is meant to work with other packages.
(I just found a stackoverflow post on isnan outside of any namespace; is this something you've run into or is this hypothetical?)
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 think we're way past that; std::complex
for our types are unspecified. We should do what we can verify is correct, is maintainable, and makes sense.
@ChrisChiasson, did you go through all the implementation notes here: https://en.cppreference.com/w/cpp/numeric/complex? (that's a question... I haven't verified that you did or didn't) There's no discussion in this pull request regarding what parts of it you have or haven't implemented. |
@ChrisChiasson, maybe this would explain it?
|
Ok. Can you revert the changes you've made to the makefiles? |
Sure. All of it? Did you satisfy all the requirements? How did you validate that There's a lot there... I don't know how much you walked through it or didn't. |
re: make. ok. I have no idea what GitHub is doing. |
@ChrisChiasson, yes, I read that. Questions that would help everyone else understand what you're doing:
In a pragmatic sense, things that are undefined are ok as long as we know that the compiler does the right thing (it looks like they start allowing it for C++20). If we have tests in place, at least we can validate that we're ok even if we're in undefined behavior land. |
re: contiguous. Awesome. I didn't realize that was going to be implemented by the standard library. It'd just help line up these things. re: limitation of grad. Hopefully that clears it up for you why I was asking for what you were attempting to do. That's not a limitation in our design: it's a limitation of reverse-mode automatic differentiation when it can't be retaped. Also, I don't understand what it means to compute |
@@ -20,6 +20,12 @@ inline int is_inf(const fvar<T>& x) { | |||
return is_inf(x.val()); | |||
} | |||
|
|||
// forwarding for ADL | |||
template <class T> | |||
inline auto isinf(const fvar<T>& a) { |
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 see how we've handled it elsewhere. Is there a reason we can't do the same here? By that, I mean specialize isnan
and isinf
for stan::math::fvar<T>
and include it in its own header file called stan/math/fwd/core/std_isnan.hpp
and std_isinf
?
See:
stan/math/fwd/core/std_numeric_limits.hpp
stan/math/rev/core/std_isnan.hpp
stan/math/rev/core/std_numeric_limits.hpp
stan/math/rev/core/std_isinf.hpp
@@ -0,0 +1,28 @@ | |||
#ifndef STAN_MATH_FWD_SCAL_FUN_PROJ_HPP |
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.
just following our (not very good) convention, can you rename this file std_proj.hpp
?
namespace math { | ||
|
||
/** | ||
* Complex class that forwards the interface of std::complex, brining |
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.
what is meant here? I still don't understand what "forwards" means in the way it's used here.
* division operations that the base std::complex doesn't have | ||
* defined usably for var, and, since stan::math::zeroing<var> zero | ||
* initializes itself, will also correctly work with the remaining | ||
* algorithms in std::complex<T> that require the expression T() to |
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.
Clarification? The algorithms expect T()
to initialize a variable to 0?
* T. This is the removal version of the trait. | ||
*/ | ||
template <class T> | ||
struct rm_zeroing<math::zeroing<T>> { |
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.
remove math::
in front of zeroing
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.
at that line in the file, the math
sub-namespace is not open, just the outer stan
, so if I did that, it would cause a compile error
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.
Thanks. I didn't catch that on the first read. Forgot that our meta is in the Stan namespace.
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.
Thanks. I didn't catch that on the first read. Forgot that our meta is in the Stan namespace.
* be 0. | ||
*/ | ||
template <class T> | ||
struct complex : std::complex<zeroing<T>> { |
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.
What's the motivation for having stan::math::complex<T>
? Shouldn't we just be using std::complex<T>
?
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.
If we did that, we would create an inheritance loop. The way we force things to work is by making a template specialization for std::complex<var>
inherit from stan::math::complex<var>
, which in turn inherits from std::complex<zeroing<var>>
. We wouldn't be able to do this if the starting and ending classes were the same.
@ChrisChiasson, I've been staring at the code. I just made some minor-ish comments (been sitting there as I tried to make heads / tails of the code). Some bigger questions that don't fit into a line-by-line commentary:
Sorry it's taken a while. Here's what would help me (or anyone else) review it:
I haven't walked through the tests yet. It'd help to know what you were trying to test. If not, it'll take a while to walk through and understand what you're trying to test. |
@ChrisChiasson, I probably should have asked this earlier on. It just dawned on me. In your experimentation, did you ever write a template specialization for any of these?
Would it be possible to write an explicit template specialization for just the constructor? Here's a short example along the lines of what I'm thinking (but I haven't done it for complex):
If we could just write a constructor for each, that would eliminate the need for |
Can you be more specific? I have no idea what you mean by "some of the
algorithms." If you have any more information than that, that'd be
enlightening. I just thought you were having to go through this effort
because of the constructor to std::complex.
On Mon, Aug 6, 2018 at 9:12 PM ChrisChiasson <notifications@github.com>
wrote:
… The problem occurrs inside some of the algorithms. The class type is
already T. The algorithms call T(). If T is var, go directly to jail, do
not collect $200. It is unfortunate, but T isn't `std::complex<var>`. BTW,
your solution would change `fvar<var>` ... not just for the complex class.
I did at one time post an outline of how to fix var itself, by modifying
the struct that contains chainable so that it maintained a vector stack of
zeros whose addresses would be usedwith default constructed vars. However I
was asked not to pursue it.
On Mon, Aug 6, 2018, 7:57 PM Daniel Lee ***@***.***> wrote:
> @ChrisChiasson </~https://github.com/ChrisChiasson>, I probably should
have
> asked this earlier on. It just dawned on me.
>
> In your experimentation, did you ever write a template specialization for
> any of these?
>
> - std::complex<stan::math::var>
> - std::complex<stan::math::fvar<double>>
> - std::complex<stan::math::fvar<stan::math::var>>
> - std::complex<stan::math::fvar<stan::math::fvar<double>>>
> - std::complex<stan::math::fvar<stan::math::fvar<stan::math::var>>>
>
> Would it be possible to write an explicit template specialization for
just
> the constructor? Here's a short example along the lines of what I'm
> thinking (but I haven't done it for complex):
>
> #include <stan/math.hpp>
> #include <iostream>
>
> template <typename T = double>
> class foo {
> public:
> foo(T x = T(), T y = T())
> : x_(x), y_(y) {
> }
> std::string print() {
> std::stringstream m;
> m << "(" << x_ << ", " << y_ << ")" << std::endl;
> return m.str();
> }
> T x_, y_;
> };
>
> template<> foo<stan::math::var>::foo(stan::math::var x, stan::math::var
y) {
> if (is_uninitialized(x))
> x_ = 0.0;
> if (is_uninitialized(y))
> y_ = 0.0;
> }
>
> int main() {
> foo<double> d;
> foo<stan::math::var> v;
> std::cout << "d = " << d.print() << std::endl;
> std::cout << "v = " << v.print() << std::endl;
> return 0;
> }
>
> If we could just write a constructor for each, that would eliminate the
> need for zeroing, the template metaprograms (e.g. rm_zeroing), and
> simplify a bunch of it? I'm not sure if you've already explored this and
> found that it wasn't possible.
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <#789 (comment)>, or
mute
> the thread
> <
/~https://github.com/notifications/unsubscribe-auth/ALTv-6LaaumX7IrcpGJNiae_LdNUfRvaks5uOOYHgaJpZM4ShF_6
>
> .
>
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#789 (comment)>, or mute
the thread
</~https://github.com/notifications/unsubscribe-auth/AAZ_F5CzogMjpXy1OZF7P-H3Sn7EVGqAks5uOOldgaJpZM4ShF_6>
.
|
Just to take inventory:
There are another half dozen places where it pops up. I don't see a problem with them, do you? |
@ChrisChiasson, I searched through your tests. What I didn't find were basic tests for This would be a requirement for accepting this sort of code. What I mean by tests:
Why here and not in something like I have a feeling that once we create these tests, we can replace the implementation with something a lot simpler: getting rid of |
Thanks for understanding. Am I ok to assume the code that was written is
considered BSD (with the copyright owners appropriately attributed)?
Hopefully someone will want to finish this PR out by writing the basic
tests required for it to get into the Math library.
Sorry about the length of time it took to get to this point. Would you mind
jumping on a video call with me to talk a little bit about the process? I’d
want to know how we could have provided better guidelines earlier or
communicated better to set expectations appropriately.
Thanks for putting in all this work. You’ve figured out a ton of
implementation details I wouldn’t have known how to figure out. I’ll try to
write out as much detail I can remember in the issue, but if there’s
anything I missed, would you mind helping update it? Thanks again.
…On Wed, Aug 8, 2018 at 3:12 PM ChrisChiasson ***@***.***> wrote:
I respectfully decline.Thank you for your time. Take care, all.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#789 (comment)>, or mute
the thread
</~https://github.com/notifications/unsubscribe-auth/AAZ_F1VgahkgZOgOTru5HYCS3W-osCt7ks5uOzf7gaJpZM4ShF_6>
.
|
Discourse use cases and spec discussion: http://discourse.mc-stan.org/t/complex-number-support-in-math-library-autodiff/3511
Submission Checklist
./runTests.py test/unit
make cpplint
Summary:
Initial attempt at adding complex number support to var, as referenced in issue #123, but extended further to do what I have laid out in the "Intended Effect" immediately following this.
Intended Effect:
Complex numbers work. For me, this means that it satisfies what I needed to do with complex numbers, which I described (after being prompted below) as:
It also means that the PR passes the tests I have added for forward, reverse, and the special mixed mode test that uses newton's method and involves checking (the definition of) eigendecomposition of a rotation matrix while converging to the point where the merit function is minimized because the real and imaginary parts of the first returned eigenvalue are equal.
Further clarification for reviewers Friday 2018-07-27:
The paragraphs above mean that
complex<var>
andcomplex<fvar<T>>
can be instantiated, added, subtracted, multiplied, divided, automatically differentiated, and integrated. As a side effect of getting the above working, the implementation was necessarily already very general and it was apparent that other functions would work. @bgoodri decided to take it further. He wrote additional tests (and I helped fix the resulting errors for) the list of C++ functions of complex numbers.With respect to traits: without the additional definition for Eigen's scalar binary op trait, it would not be possible to have matrix operations on complex AD types, so that is how I came to the conclusion that it was necessary.
With respect to the fvar ctor that previously took a dummy parameter for SFINAE purposes: I ended up changing this to eliminate the dummy parameter due to compilation errors I was getting on a development machine, as previously discussed.
With respect to the previously existing var ctors that construct a var from the real part of a
complex<double>
and throw an error if the suppliedcomplex<double>
's imaginary part is non-zero: I removed these because their original stated purpose was to check that Eigen didn't instantiate vars from complex numbers of this type. However, Eigen does not actually ever use those ctors, so this PR removes that dead code.With respect to the large number of files touched: some of this is due to Jenkins overzealous autoformat.
How to Verify:
Run unit test
Side Effects:
One I can think of is that the interface of the complex class in stan math has a more flexible interface than the normal std::complex. This is because the binary operators use templates and ADL to do things like multiple a std::complex by a number without first casting the number to a var.
Documentation:
I added some inline documentation using doxygen syntax.
Copyright and Licensing
Please list the copyright holder for the work you are submitting (this will be you or your assignee, such as a university or company): Oil States
By submitting this pull request, the copyright holder is agreeing to license the submitted work under the following licenses: