Repository navigation
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.
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 <phipsgabler@users.noreply.github.com>
|
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. |
|
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. |
devmotion
left a comment
There was a problem hiding this comment.
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 <devmotion@users.noreply.github.com>
Co-authored-by: David Widmann <devmotion@users.noreply.github.com>
Co-authored-by: David Widmann <devmotion@users.noreply.github.com>
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? |
devmotion
left a comment
There was a problem hiding this comment.
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.
Should this ever be a return value of DensityKind?
Co-authored-by: David Widmann <devmotion@users.noreply.github.com>
Co-authored-by: David Widmann <devmotion@users.noreply.github.com>
Co-authored-by: David Widmann <devmotion@users.noreply.github.com>
Co-authored-by: David Widmann <devmotion@users.noreply.github.com>
Co-authored-by: David Widmann <devmotion@users.noreply.github.com>
|
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). |
|
Thanks everyone! |
|
Here's the update for Distributions: JuliaStats/Distributions.jl#1427 |
Updated
Replaces hasdensity by DensityKind (#9)
Also changes behavior of
logfuncdensityto always return a density and addsfuncdensity.