A set of attributes.
Closure
Suppose is an attribute set and is a set of functional dependencies.
Closure of under a set of functional dependencies , is the set of all attributes functionally determined by using the dependencies in . Denoted as ,
Algorithm
can be computed by:
- Start with .
- For each dependency in :
If , then add to . - Repeat until no new attributes can be added.
If includes all attributes of , then is a superkey of .
Can be used to test if a given functional dependency holds.
def attribute_closure(attributes, fds):
"""
Compute the closure of a set of attributes with respect to a set of functional dependencies.
:param attributes: set of attribute strings, e.g. {'A', 'B'}
:param fds: list of tuples (lhs, rhs), where lhs and rhs are sets of attributes
e.g. [({'A'}, {'B'}), ({'B'}, {'C'})]
:return: set of attributes in the closure
"""
closure = set(attributes)
changed = True
while changed:
changed = False
for lhs, rhs in fds:
if lhs.issubset(closure) and not rhs.issubset(closure):
closure.update(rhs)
changed = True
return closure
Extraneous Attributes
Unnecessary attributes in a functional dependency (FD) that can be removed without affecting the closure. Can either be in LHS or RHS.
Removing extraneous attributes:
- Simplifies functional dependency sets
- Helps compute minimal covers
- Avoids redundant checks during normalization
Testing
Consider a set of functional dependencies , and .
The attribute is extraneous in if contains .
The attribute is extraneous in if:
- Compute using only the dependencies in
- Check if contains . If it does, is extraneous in
Examples
Attribute in the LHS.
Given . Test in .
Solution Reveal Hide
- and
- using
- contains , so is extraneous
- reduces to
Attribute in the RHS.
Given . Test in .
Solution Reveal Hide
- and
- in , using then
- contains , so is extraneous
- reduces to