.import:: boolean, None+
..from: kindnames

.import:: EquivalenceRelation, UniSet, UniSet+, EquivalenceRelation+, EquivalenceRelationByDictOwner,
Kind, SetOfKind, Kind+

..from: heapykinds

.and: EquivalenceRelation
..self: x
..subkind of: UniSet
...d: The operations of UniSet are supported by EquivalenceRelation as well,
but some have a redefined behaviour which are described here.

..rop: in
...d:
Inclusion test. True if y is a member of x, False otherwise.

....p: The members of an equivalence relation in this implementation
are defined to be the subsets of its equivalence classes. The
inclusion test can be used to see if all elements of a set classify
equal according to the classifier of an equivalence relation.

...dwh: Example
....pre
>>> from guppy import hpy; hp=hpy()
>>> hp.iso([],[]) in hp.Size # Equal sizes
True
>>> hp.iso([],range(100)) in hp.Size # Different sizes
False
>>> hp.iso([],range(100)) in hp.Type # Equal types
True
>>> hp.iso([],xrange(100)) in hp.Type # Different types
False
>>>
>>> hp.Size(56) in hp.Size # An equivalence class of hp.Size
True
>>> hp.Type.Int in hp.Size # Not an equivalence class of hp.Size
False
....c: end pre

...dwh: Note

....small: Mathematically equivalence relations are often modelled as
set of pairs of equal elements, I considered to mimic this in the
implementation of the inclusion test but found some problems and I
think another model is more useful here.
....c:
 -- I just added this function
while writing this doc because the inclusion test was undefined before
so EquivalenceRelation didn't really derive from UniSet in a strict
sense - so the inclusion test is not tested much and likely to have
some bugs.
.....pre
>>> (hp.Size(56) & hp.Type.Int) in (hp.Size & hp.Type.Int)
False # I think this should be True but I don't care for now.
>>>
.....c: end pre

...arg: y: UniSet+
...returns: boolean

..op: &
...d:
Intersection: the set of objects that are in both x and y.

...d
....t: When y is an equivalence relation, the result will be one of
the arguments if that one was mathematically a subset of the other, or
otherwise, which is the normally usable case, it will be a new
equivalence relation that is a symbolic intersection of the two
arguments.  This can be used to partition a set based on a combination
of classification criteria.

...dwh: Example
....pre:
>>> from guppy import hpy; hp=hpy()
>>> hp.iso(1, 10, [], [2], [3,4]).by(hp.Type & hp.Size)
Partition of a set of 5 objects. Total size = 172 bytes.
 Index  Count   %     Size   % Cumulative  % Type & Individual Size
     0      2  40      120  70       120  70 list & 60
     1      1  20       28  16       148  86 list & 28
     2      2  40       24  14       172 100 int & 12
>>>
....c: end pre

...dwh: Note
When y is not an equivalence relation, the result will be a
symbolic intersected UniSet, that is it can not be used for
partitioning but may still be used for inclusion tests.

...arg: y: EquivalenceRelation+
...returns: EquivalenceRelation

..op: <
...d:
Subset, also called subrelation, strict:
             all elements in x are also in y,
             and x and y are not equal.

....p: An EquivalenceRelation can only be a subrelation of another
EquivalenceRelation. This is an explicitly defined relationship among
the equivalence relations. In most cases the equivalence relations are
disjoint, i.e. none is a subrelation of the other.  But it is useful
to know which ones are actually subrelations.  The following table
shows for each pair of predefined relations, whether the one at the
top of the column is a strict subrelation of the one at the end of the
row.  ( I have included Size & Type as an example of an intersected
equivalence relation. )

....table
.....tr
......th: Clodo
......th: Id
......th: Module
......th: Rcs
......th: Size
......th: Type
......th: Unity
......th: Size&Type
.....tr
......td:
......td:
......td:
......td:
......td:
......td:
......td:
......td: <
......th: Size
.....tr
......td: <
......td:
......td:
......td:
......td:
......td:
......td:
......td: <
......th: Type
.....tr
......td: <
......td: <
......td: <
......td: <
......td: <
......td: <
......td:
......td: <
......th: Unity

....small: Generated by printrel.py at Nov 21 2005.
...dwh: Example (outdated)

....t: Class is a subrelation of Type, since all objects with the same
class also have the same type. On the other hand, Type is not a
subrelation of Class, since objects with the same type (InstanceType)
may be of different class.

....pre:
>>> hp.Class < hp.Type
True
>>> hp.Type < hp.Class
False
>>>
....c: end pre

...dwh: Note
....t: The other relational operators are derived from this one.
...dwh: Note
....small:
Id is currently not defined to be a subrelation
of anything else except Unity, due to some subtle considerations.


...arg: y: EquivalenceRelation+
...returns: boolean

..attr:: dictof
...kind of: EquivalenceRelationByDictOwner

...d: This attribute, when accessed, will contain a derived
equivalence relation. This equivalence relation classifies objects
either as not being a dict, or as being a dict owned by a particular
kind. The owner, if any, is classified by x.

...dwh: Example
....pre:
>>> from guppy import hpy; hp=hpy()
>>> h=hp.heap()&dict
>>> h.by(hp.Size.dictof)
Partition of a set of 1512 objects. Total size = 715008 bytes.
 Index  Count   %     Size   % Cumulative  % Dict of Individual Size
     0    140   9   225056  31    225056  31 dict of        24
     1    336  22   172800  24    397856  56 dict of        44
     2    582  38   152112  21    549968  77 dict (no owner)
     3    347  23    92120  13    642088  90 dict of        32
....c: end pre

....t: This shows that there are 140 dicts that are owned by
some objects of size 24, 336 dicts that are owned by some objects
of size 44, 582 dicts without owner and so on.

..attr:: refdby
...kind of: EquivalenceRelation
...d: This attribute, when accessed, creates a derived
equivalence relation. It will classify objects according to
the set of their referrer classification. The referrers
are classified by x.
....p: The
.....ref: .mykind.Use.Rcs
.....t: equivalence relation is a special case of this
construction, where the underlying equivalence relation is
.....ref: .mykind.Use.Clodo.
.....t::

.....pre:
>>> hp.Clodo.refdby == hp.Rcs
True
.....c: end pre

...dwh: See also
....ref: .mykind.Use.Rcs

..method:: sokind
...c: no auto test

...d: Create a set of kinds; a set of equivalence classes of x. The
arguments are the same as when calling x itself.  One call to x.sokind
returns a set of one equivalence class.  This set is again callable,
with the same kind of arguments. Each call will return a new set with
one new equivalence class added to the previous set.

...c
....dwh: Note
.....small: The reason for this mystical way of creating set of kinds
is somewhat subtle, but there is (or was) a reason that I can try to
defend some time if required.

...returns: SetOfKind
....d: an object that may be used to get at the corresponding referred-by
equivalence class via its .refdby attribute.

...dwh: Example
Show the objects in the heap that are referred from only the dict of __main__.
....pre
>>> from guppy import hpy; hp=hpy()
>>> hp.heap() & hp.Module.dictof.sokind(hp.Module('__main__')).refdby
Partition of a set of 1 object. Total size = 32 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0      1 100       32 100        32 100 str
>>>
...c: end pre



.and: EquivalenceRelationByDictOwner
..self: x
..subkind of: EquivalenceRelation

..d: This equivalence relation classifies objects either as not being
a dict, or as being a dict owned by a particular kind of objects. The
owner, if any, is classified by the equivalence relation used to
create
...strong: x
...t:, usually via
...ref: .myfile.EquivalenceRelation.dictof
...t:.

..mapping
...d: Calling this equivalence relation creates a Kind object
representing an equivalence class. The argument specifies if the kind
should be about dicts at all, and in that case, the kind of dict
owner.

...self: x
...c: no auto test

...alt
....arg: k: None+
.....d: With a None argument, the returned equivalence class will
be "all objects except dicts", i.e.
......code: ~hp.Type.Dict
......t:.
....arg: k: Kind+

.....d: If not None, the argument must be a Kind object.
The returned kind will be the kind representing dicts that are owned
by objects of the kind specified in arg. If the argument is
......ref: .myfile.Use.Nothing
......t: , the returned kind represents dicts with no owner.
...returns: Kind
....d: an equivalence class.

...dwh: Note
....small: To make the argument an equivalence class of x, the
argument must be an equivalence class of the equivalence relation
associated with the owner classification of x, though this is not
currently checked.
