Source code for prm.relationalschema
class ERClass():
[docs] '''
This abstract class serves as a container for the objects that contain
attributes. These objects are either :class:`.Entity` classes or :class:`.Relationship` classes;
each can contain :class:`.Attribute` classes which themselves have to know
which container object they belong to. The :class:`Entity`/:class:`Relationship` classes inherit
the :class:`ERClass` class. Therefore, an attribute can find the type of its container
object by calling `self.erClass.type()`
.. inheritance-diagram:: prm.relationalschema
'''
def __init__(self):
raise Exception("Abstract class ERClass can't be instantiated")
def isEntity(self):
[docs] '''
Returns `True` if the type is `Entity`
'''
return self.type() == 'Entity'
def isRelationship(self):
[docs] '''
Returns `True` if the type is `Relationship`
'''
return self.type() == 'Relationship'
def isUncertainRelationship(self):
[docs] '''
Returns `True` if the type is `UncertainRelationship`
'''
return self.type() == 'UncertainRelationship'
def type(self):
[docs] '''
The type of an ERClass, either `Entity` or `Relationship`
'''
return self.__class__.__name__
class Entity(ERClass):
[docs] '''
Represents an entity class in the relational schema.
'''
def __init__(self, name):
'''
Constructs an Entity class
'''
self.name=name
"""Unique name
"""
self.pk = []
"""
The primary key is a list of :class:`.Attribute` objects of the entity. The pk is created automatically as a
:class:`.NotProbabilisticAttribute` if not specified otherwise. It is stored as a list with just one item.
"""
self.pk_string = []
"""
String representation of primary key
"""
self.attributes = None
"""
List that contains the :class:`.Attributes` references of the entity class
"""
self.relationships = {}
"""
List that contains the :class:`.Relationship` references that are connected to
the entity.
"""
def __repr__(self):
'''
Returns a string representation of the instance
'''
return "Entity (%s), pk=%s"%(self.name,self.pk[0].name)
class Relationship(ERClass):
[docs] '''
An relationship class relates two entity classes ( implicitly using their primary
keys as identifiers). Note the source of confusion, `Relationship` refers to the Entity-Relationship model;
not to be confused with the probabilistic :class:`.Dependency` which is conceptually also a relationship
'''
def __init__(self, name):
'''
Constructs an Relationship instance
'''
self.name = name
"""Unique name
"""
self.pk = []
"""
The primary key of a relationship class is usually specified by the set of foreign keys of connected entities.
A relationship class has a primary key that consists of a list of :class:`ForeignAttribute` instances
whose `target`'s are attributes of the connecting entities (usually their primary key attributes).
"""
self.pk_string = []
"""List of string representation of `self.pk`
"""
self.foreign = {}
"""Dictionary represenation of `self.pk` where the key is an entity and the value a list of foreign
attributes that belong to that entity, e.g. {key= :class:`.Entity` : value=[ :class:`.ForeignAttribute` , .. ]}
"""
self.entities = []
"""List of :class:`Entities` connected to the relationship
"""
self.attributes = None
"""
A dictionary that contains the attributes references of the relationship class
{key : Attribute name, value: :class:`.Attribute`}
"""
def __repr__(self):
'''
Returns a string representation of the instance
'''
return "Relationship (%s , pk=[%s], type=%s)"%(self.name,",".join(['%s->%s'%(fa.fullname,fa.target.fullname) for fa in self.pk]), self.relationType)
class UncertainRelationship(Relationship):
[docs] '''
Reference uncertainty introduces uncertainty about the structure of the data itself, e.g. the entries of a relationship table of an ER diagram, and thus the state space of the Markov Chain increases considerably. We associate a binary `exist` variable with every possible entry in uncertain relationship tables. As the number of `exist' attributes grows exponentially with the size of the tables, inference becomes intractable. We avoid the explosion of the state space by introducing a `constraint` attribute that enforces certain structural properties, e.g. a *1:n* relationship. However, this results in complex probabilistic dependencies among the `exist` objects. A more involved Metropolis-Hastings algorithm is required that samples `exist` objects using an appropriate proposal distribution. A proposal is an assignment to all `exist` objects associated with one `constraint` object, which allows us to introduce probabilistic dependencies that would not be allowed in a traditional PRM.
'''
def __init__(self, name, nTok, k):
Relationship.__init__(self, name)
self.existAttribute = None
'''The exist attribute of type :class:`.ExistAttribute`.
'''
self.nTok = nTok
"""
Boolean. The type of an relationship is `n:k` (=True) or `k:n` (=False). If a type is specified it is assumed that it describes the relation between the first two primary keys in :attr:`.pk`.
"""
self.k = int(k)
"""
The value `uncertain` is the fixed-parameter `ntoK` in the `k` in the `n:k` relationship type. This parameter serves as a fixed-parameter tractability approach, for more information see the documentation.
"""
self.nEnitity = None
'''
Reference to the :class:`.Enitity` that is on the `n`-side of the relationship
'''
self.kEnitity = None
'''
Reference to the :class:`.Enitity` that is on the `k`-side of the relationship
'''
def __repr__(self):
'''
Returns a string representation of the instance
'''
return "UncertainRelationship (%s , pk=[%s], nTok=%s, k=%s)"%(self.name,",".join(['%s->%s'%(fa.fullname,fa.target.fullname) for fa in self.pk]), self.nTok,self.k)