Advanced node and edge attributes¶
ReGraph implements a collection of data structures for representation of potentially infinite sets of attribute values, together with all the default set operations on them (such as union, intersection, inclusion test etc.):
FiniteSet, a wrapper for Python finite sets.
RegexSet, a class for possibly infinite sets of strings given by regular expressions.
IntegerSet, a class for possibly infinite sets of integers defined by a set of disjoint intervals.
Import module containing attribute sets data structures:
from math import inf
import regraph.attribute_sets as atsets
Define an infinite integer set:
>>> ints = atsets.IntegerSet({(0, 8), (11, inf)})
Test if an interger value is in the set:
>>> ints.contains(5)
True
>>> ints.contains(9)
False
Test if another integer set is a subset:
>>> a = atsets.IntegerSet({(0, 3), (20, 30)})
>>> a.issubset(ints)
True
>>> b = atsets.IntegerSet({(0, 10)})
>>> b.issubset(ints)
False
Find the intersection of two IntegerSet objects:
>>> a_and_ints = a.intersection(ints)
>>> a_and_ints
[0, 3], [20, 30]
>>> b_and_ints = b.intersection(ints)
[0, 8]
Find the union of two IntegerSet objects:
>>> a_or_ints = a.union(ints)
>>> a_or_ints
[0, 8], [11, inf]
>>> b_or_ints = b.union(ints)
>>> b_or_ints
[0, inf]
We can also find unions and intersections of integer sets with ordinary Python sets, as long as these sets contain integer values:
>>> a.union({13, 14})
>>> a
[0, 3] [13, 14] [20, 30]
The following line of code with cause the AttributeSetError exception:
>>> a.union({13, 14, "a"})
AttributeSetError: Set '{'a', 13, 14}' contains non-integer elements!
Now, define objects of RegexSet:
>>> words = atsets.RegexSet("[A-Za-z]+")
>>> integers = atsets.RegexSet("\d+")
>>> alphanums = atsets.RegexSet("[A-Za-z\d]+")
Test if strings are matched by regex’s defining our RegexSet objects:
>>> words.match("42")
False
>>> integers.match("42")
True
>>> words.match("hello")
True
>>> integers.match("hello")
False
Test if one regex set is a subset of another:
>>> integers.issubset(words)
False
>>> integers.issubset(alphanums)
True
Find the intersection of two regex sets:
>>> integers.intersection(words)
[]
>>> integers.intersection(alphanums)
\d+
Find the union of two regex sets:
>>> integers.union(words)
\d+|[A-Za-z]+
Subtract a finite set of strings from a regex set:
>>> words.difference({"hi", "bye"})
([A-Zac-gi-z]|b([A-Za-xz]|y([A-Za-df-z]|e[A-Za-z]))|h([A-Za-hj-z]|i[A-Za-z]))[A-Za-z]*|by?|h
The result may be not extremely readable, but we can test it in the following way:
>>> no_hi_bye = words.difference({"hi", "bye"})
>>> no_hi_bye.match("hi")
False
>>> no_hi_bye.match("bye")
False
>>> no_hi_bye.match("afternoon")
True
Now, we can also wrap Python set objects into FiniteSet class provided in ReGraph.
>>> a = atsets.FiniteSet({1, 2, 3})
It allows us to apply to them any set operations from the common interface of ReGraph’s attribute sets. For example:
>>> from math import inf
>>> int_regex = atsets.RegexSet("\d+")
>>> positive_integers = atsets.IntegerSet([(0, inf)])
>>> a.issubset(int_regex)
True
>>> a.issubset(positive_integers)
True
ReGraph provides two special classes of attribute sets: UniversalSet and EmptySet, which in their essence are static classes. These classes contain all standard set theoretic operations and follow the common interface defined in the base class AttributeSet (as all previously presented attribute set classes). Consider a couple of examples illustrating the behaviour of UniversalSet and EmptySet:
>>> univ = atsets.UniversalSet()
>>> empty = atsets.EmptySet()
>>> univ.union(empty)
UniversalSet
>>> univ.intersection(empty)
EmptySet
>>> a = atsets.FiniteSet({1, 2, 3})
>>> a.issubset(univ)
True
>>> a.issubset(empty)
False
>>> univ.intersection(a)
{1, 2, 3}
>>> univ.union(a)
UniversalSet
Module reference: Attribute Sets