-
Notifications
You must be signed in to change notification settings - Fork 3
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
Improve logfuncdensity behavior and add isdensity #9
Conversation
Codecov Report
@@ Coverage Diff @@
## master #9 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 2 2
Lines 37 59 +22
=========================================
+ Hits 37 59 +22
Continue to review full report at Codecov.
|
CC @devmotion , @cscherrer , @mschauer, @phipsgabler |
Closes #5 (well, eventually ...) |
Great! Just a note, we'll need a similar PR for MeasureTheory in addition to the one for MeasureBase, to be sure this can extend naturally and all tests can pass. I'll try this out with Soss as well, that can help us check for a wider range of use cases. |
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 now find the semantics of hasdensity
and ismeasure
a bit complicated for the casual user. And especially it ties things to measures by name; not that I'm against that for the special case, but it precludes other names a priori.
I know you have discussed the return type of hasdensity
already, but what about something like IteratorEltype
to cover three cases?
abstract type DensityType end
struct NoDensity <: DensityType end
struct HasDensity <: DensityType end
struct IsDensity <: DensityType end
struct IsMeasure <: DensityType end # can perhaps even be left out
DensityType(x) = DensityType(typeof(x))
DensityType(::Type) = NoDensity()
DensityType(::Union{FuncDensity, LogFuncDensity}) = IsDensity()
DensityType(::Union{Distribution, PPLModel}) = HasDensity()
DensityType(::AbstractMeasure) = IsMeasure() # can perhaps even be left out
# some name to cover both "has" and "is"...
isdensitylike(x) = !(DensityType(x) isa NoDensity)
In my opinion this is clearer than conditionals like hasdensity(object) && !ismeasure(object)
, and users outside measure theory never need to even see the term.
I like this since it would keep the API simpler and cleaner. |
I don't like that specific version so much, because that way Using types would make this extensible by other packages. We should think a bit about possible implications first, though. |
I don't think this is really a counterexample. mass density is a local ratio of mass to volume, both of which are measures. The physical object isn't a measure, but it has these measures associated with it, and this "density" is a proper density in the measure-theoretic sense. |
Yes, that's what I mean - we'd say the object has a proper density, so |
With a
be done with it. One can wonder if one of those makes a sensible fallback. It would be useful to give density function wrappers which do this for you: say |
I would call it |
There is a second thing I would like to add (sorry for upsetting the apple cart), but I think a signature |
I don't think that would be upsetting at all. :-) In fact, it may be quite natural, from a software design point of view: We say that Maybe this could also help with the ProductOver / IIDDensity construct, semantically? If the base density can depend on the argument, the PDF of |
Co-authored-by: Philipp Gabler <[email protected]>
I have a question: Are primitive measures like I have a feeling that this is an important design decision: I imagine that it would be useful in many cases, practically, to be able to predict things like array sizes bases on a base measure, and so on. On the other hand, do we always have dimensionality information available when we want/need to create a measure, esp. a primitive one? If we go with @mschauer's suggestion of having I would tend towards |
I'm sorry to crash the party here but I have serious doubts about integrating The measure-theoretical parts, however, seem to me like a reduced and more limited version of MeasureBase. I think it would be cleaner and the interface and the amount of measures would be less limited if packages that want to define and work with explicit base measures just implement the MeasureBase interface. Why adding a reduced version of something to DensityInterface that already exists in another interface package? I would view MeasureBase basically as the measuretheoretical extension of DensityInterface with explicit base measures. I tried to explain my concerns also in this thread. |
|
Isn't this just a matter of abbreviated language? The object may also have a charge or heat density. At some point, don't you end up saying "mass per unit volume"? Ok, I have a proposal:
Then
An advantage of this is that we can easily make sure Distributions has |
What about:
Alternatively, if MeasureBase is not lightweight enough one could extract a more lightweight MeasuresInterface package. But I assume it might not be worth it since, as far as I understand, MeasureBase is already a reduced base package and hence I fear breaking it up might lead to a somewhat incomplete package. The main principle would be similar to ChainRules: |
Sounds good to me. Should we maybe prototype that stuff here in this PR first, though, so we have all the lightweight stuff in context, and then split up? I expect the line where to split will be obvious when the design is done.
I would actually favour having that in Distributions. As long as it's not a lot of code, Distributions can take it, it's not exactly a small package. And having it in Distributions will encourage third-party dist developers to define their base measure. Also, when new dists are added to Distributions, we won't always need to do a separate PR to DistributionMeasures if it was integrated. |
The problem that I see with @cscherrer's proposal is the amount of type piracy in e.g. DistributionsMeasures it would create and the overall dependency structure. I would prefer if one just has to depend on MeasureBase (or a more lightweight interface package). |
I agree, it's more flexible that way. I'll add it to this PR, then we can take a look at it in practice. |
I agree - I guess that more lightweight package (MeasureBase is too heavy I think) would be @cscherrer's proposed MeasureInterface (I like the name). Distributions would depend on it and dist-specific measures (like for Dirichlet) would live in Distributions, right next to "their" distribution. |
I like the general ideaof @phipsgabler 's suggestion a lot, we just need some time to think through how this will interface with MT, especially in terms of
So Distributions would depend on MeasureBase?
Our [compat]
ConcreteStructs = "0.2"
ConstructionBase = "1.3"
FillArrays = "0.12"
KeywordCalls = "0.2"
LogExpFunctions = "0.3"
MLStyle = "0.4"
MappedArrays = "0.4"
PrettyPrinting = "0.3"
Tricks = "0.1"
julia = "1.3" We could probably pare this down some more:
Right, that was the original intent of MeasureBase.
Great catch, thanks
I'm a little confused now. If Distributions will depend on MeasureInterface, how is that different than just adding |
I agree with @devmotion - in the end a lightweight measure-oriented package, extending DensityInterface will be more flexible than adding too much measure theory to DensityInterface itself. I like @cscherrer 's proposed name For convenience though (so we don't have to hop between too many different PRs) and to see how everything with mesh, it might be easiest to prototype this lightweight measures interface within this PR initially (and mark parts of it with a comment) to see how it all fits together. |
Co-authored-by: David Widmann <[email protected]>
Great. I still like |
I agree, "type" could be misleading here, I think. |
I don't mind 🤷♂️ If there's an abstract supertype |
|
Ok, we have We should squash when we merge, this PR's commit history is very ugly. |
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.
It seems you forgot to actually define them as subtypes 🙂
👍 Generally, I prefer if PRs are squashed and not all commits end up in the default branch - maybe we could make it the default (and possibly disable other options)? |
Co-authored-by: David Widmann <[email protected]>
Co-authored-by: David Widmann <[email protected]>
Co-authored-by: David Widmann <[email protected]>
I think in some cases a merge commit can make sense, though (but not in this one!). |
Thanks for the fixes @devmotion! Good the way it is now? |
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.
Looks good, just some minor comment regarding ==
and ===
.
""" | ||
IsOrHasDensity = Union{IsDensity, HasDensity} | ||
|
||
As a return value of [`DensityKind(object)`](@ref), indicates that `object` |
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.
Should this ever be a return value of DensityKind
?
Co-authored-by: David Widmann <[email protected]>
Co-authored-by: David Widmann <[email protected]>
Co-authored-by: David Widmann <[email protected]>
Co-authored-by: David Widmann <[email protected]>
Co-authored-by: David Widmann <[email protected]>
Thanks for the equality fixes (don't wonder about the multiple commits, for some reason GitHub didn't let me batch them). |
Increased version number to v0.4.0, since this is breaking (I volunteer to take care of the PR to update Distributions). |
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.
Looks good to me, thanks!
Thanks everyone! |
Here's the update for Distributions: JuliaStats/Distributions.jl#1427 |
Updated
Replaces hasdensity by DensityKind (#9)
Also changes behavior of
logfuncdensity
to always return a density and addsfuncdensity
.