Skip to content

Document equality/equivalence semantics #36

@ctrueden

Description

@ctrueden

Historically, it has been a requirement of ops that two ops with the same name accepting the same inputs should produce equivalent output, where "equivalent output" means equality of content. This has nice consequences, including facilitating reproducibility and caching. However, there are questions:

It is too draconian with respect to "create" ops that implement Source, since two ops of the same name may return different sorts of objects that are not comparable with one another, given the same inputs (that is to say: no inputs).

If you consider the output type as part of the "OpRef uniqueness signature" then there is no conflict, because the output types differ. We could have e.g. a LongType create() with names="create, create.integerType, create.longType" and DoubleType create() with names="create, create.floatingType, create.doubleType (at higher priority, so that a request for a "create" op of type Source<T extends RealType<T>> prefers the DoubleType creator).

However, "equality of content" is subtle and complex. Do a LongType and a DoubleType have equal content if their getRealDouble() methods return the same value? Do a CellImg and an ArrayImg have equal content if they are the same type with same values and same dimensionality? Intuitively that was the idea, although it is important to note that the will not compare as equal via equals—those classes do not override equals. This invites the possibility of additional new ops: equals or perhaps equalContent that tests two objects for this sort of content equality; and compatible or perhaps isContentComparable that discerns whether it even makes sense to consider this question across two types.

We already have copy computer ops that require you to specify the preallocated output object into which the content of the input will be copied. It would make sense to formally state that doing equalContent(in, out) after calling copy(in, out) should always return true; similarly, if isContentComparable(in, out) returns false then calling copy(in, out) should not find any ops to perform the work, since it makes no sense.

My feeling is that there are many subtleties and edge cases surrounding these behaviors, so: A) these design decisions are crucial, and we need to write them down as formally as possible; and B) where feasible, we need to programmatically validate them in unit tests etc.

Metadata

Metadata

Assignees

Labels

docsIssues relating to documentation of the Ops framework

Type

No type

Projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions