Skip to content

scope

scope ¤

Scope ¤

Bases: Collection[int], Hashable

An immutable container for a set of int to represent the scope of a node in the region graph or a layer in the circuit. Currently, it is implemented on top of a Python frozenset of integers.

Source code in cirkit/utils/scope.py
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
class Scope(Collection[int], Hashable):
    """An immutable container for a set of int to represent the scope of a node in the region
    graph or a layer in the circuit. Currently, it is implemented on top of a Python frozenset of
    integers.
    """

    def __init__(self, scope: Iterable[int] | None = None) -> None:
        """Initializes a scope object.

        Args:
            scope: The scope as an iterable of variable non-negative integer IDs.
                It can be None as to construct an empty scope.
        """
        self._set: frozenset[int] = frozenset(scope) if scope is not None else frozenset()

    def __repr__(self) -> str:
        """Generate the repr string of the scope, for repr().

        Returns:
            str: The str representation of the scope.
        """
        return f"Scope({repr(set(self))})"  # Scope({0, 1, ...}).

    ################################################################################################
    # The following are the methods used by users.
    ################################################################################################

    def __contains__(self, var: object) -> bool:
        """Test whether a variable is in the scope, for `in` and `not in` operators.

        Args:
            var: The variable non-negative ID to test.

        Returns:
            bool: Whether the variable is in this scope.
        """
        if not isinstance(var, int):
            raise NotImplementedError
        return var in self._set

    def __iter__(self) -> Iterator[int]:
        """Iterate over the scope variables in the order of id, for conversion to other containers.

        Returns:
            Iterator[int]: The iterator over the scope, that is sorted.
        """
        return iter(self._set)

    def __len__(self) -> int:
        """Get the length, i.e., the number of variables) of the scope.

        Returns:
            int: The number of variables in the scope.
        """
        return len(self._set)

    def __hash__(self) -> int:
        """Get the hash value of the scope, for use as dict/set keys.

        The same scope (same set of variables) always has the same hash value.

        Returns:
            int: The hash value.
        """
        return hash(self._set)

    def __eq__(self, other: object) -> bool:
        """Test equality between scopes, for == and != operators.

        Two scopes are equal when they contain the same set of variables, with hash also the same.

        Args:
            other: The other scope to compare with.

        Returns:
            bool: Whether self == other.
        """
        if not isinstance(other, Scope):
            raise NotImplementedError
        return self._set == other._set

    def __lt__(self, other: "Scope") -> bool:
        """Test whether self is a subset (strictly) of other.

        Args:
            other: The other scope to test.

        Returns:
            bool: Whether self ⊆ other.
        """
        return self._set < other._set

    def __gt__(self, other: "Scope") -> bool:
        """Test whether self is a superset (strictly) of other.

        Args:
            other: The other scope to test.

        Returns:
            bool: Whether self ⊇ other.
        """
        return self._set > other._set

    def __le__(self, other: "Scope") -> bool:
        """Test whether self is a subset (or equal) of other.

        It is guaranteed that (a == b) <=> (a <= b and a >= b).

        Args:
            other: The other scope to test.

        Returns:
            bool: Whether self ⊆ other.
        """
        return self._set <= other._set

    def __ge__(self, other: "Scope") -> bool:
        """Test whether self is a superset (or equal) of other.

        Args:
            other: The other scope to test.

        Returns:
            bool: Whether self ⊇ other.
        """
        return self._set >= other._set

    def __and__(self, other: "Scope") -> "Scope":
        """Get the intersection of two scopes, for & operator.

        Args:
            other: The other scope to take intersection with.

        Returns:
            Scope: The intersection.
        """
        return Scope(self._set & other._set)

    def __or__(self, other: "Scope") -> "Scope":
        """Get the union of two scopes, for | operator.

        Args:
            other: The other scope to take union with.

        Returns:
            Scope: The union.
        """
        return Scope(self._set | other._set)

    # pylint: disable-next=no-self-argument
    def union(*scopes: "Scope") -> "Scope":
        """Take the union over multiple scopes, for use as reduction with n-ary | operator.

        Can be used as either self.union(...) or Scope.union(...).

        Args:
            *scopes: The other scope to take union with.

        Returns:
            Scope: The union.
        """
        sets = tuple(s._set for s in scopes)  # pylint: disable=protected-access
        # Populate the scope by taking the unions of the input scopes
        scope = Scope(frozenset().union(*sets))
        return scope

    def difference(self, other: "Scope") -> "Scope":
        """Take the difference w.r.t. another scope, i.e., the scope
        containing the variables that are not in the other scope.

        Args:
            other: The other scope to take the difference with.

        Returns:
            Scope: The difference between scopes.
        """
        return Scope(self._set.difference(other._set))  # pylint: disable=protected-access

    def __sub__(self, other: "Scope") -> "Scope":
        """Take the difference w.r.t. another scope, i.e., the scope
        containing the variables that are not in the other scope.

        Args:
            other: The other scope to take the difference with.

        Returns:
            Scope: The difference between scopes.
        """
        return self.difference(other)

__and__(other) ¤

Get the intersection of two scopes, for & operator.

Parameters:

Name Type Description Default
other Scope

The other scope to take intersection with.

required

Returns:

Name Type Description
Scope Scope

The intersection.

Source code in cirkit/utils/scope.py
131
132
133
134
135
136
137
138
139
140
def __and__(self, other: "Scope") -> "Scope":
    """Get the intersection of two scopes, for & operator.

    Args:
        other: The other scope to take intersection with.

    Returns:
        Scope: The intersection.
    """
    return Scope(self._set & other._set)

__contains__(var) ¤

Test whether a variable is in the scope, for in and not in operators.

Parameters:

Name Type Description Default
var object

The variable non-negative ID to test.

required

Returns:

Name Type Description
bool bool

Whether the variable is in this scope.

Source code in cirkit/utils/scope.py
31
32
33
34
35
36
37
38
39
40
41
42
def __contains__(self, var: object) -> bool:
    """Test whether a variable is in the scope, for `in` and `not in` operators.

    Args:
        var: The variable non-negative ID to test.

    Returns:
        bool: Whether the variable is in this scope.
    """
    if not isinstance(var, int):
        raise NotImplementedError
    return var in self._set

__eq__(other) ¤

Test equality between scopes, for == and != operators.

Two scopes are equal when they contain the same set of variables, with hash also the same.

Parameters:

Name Type Description Default
other object

The other scope to compare with.

required

Returns:

Name Type Description
bool bool

Whether self == other.

Source code in cirkit/utils/scope.py
70
71
72
73
74
75
76
77
78
79
80
81
82
83
def __eq__(self, other: object) -> bool:
    """Test equality between scopes, for == and != operators.

    Two scopes are equal when they contain the same set of variables, with hash also the same.

    Args:
        other: The other scope to compare with.

    Returns:
        bool: Whether self == other.
    """
    if not isinstance(other, Scope):
        raise NotImplementedError
    return self._set == other._set

__ge__(other) ¤

Test whether self is a superset (or equal) of other.

Parameters:

Name Type Description Default
other Scope

The other scope to test.

required

Returns:

Name Type Description
bool bool

Whether self ⊇ other.

Source code in cirkit/utils/scope.py
120
121
122
123
124
125
126
127
128
129
def __ge__(self, other: "Scope") -> bool:
    """Test whether self is a superset (or equal) of other.

    Args:
        other: The other scope to test.

    Returns:
        bool: Whether self ⊇ other.
    """
    return self._set >= other._set

__gt__(other) ¤

Test whether self is a superset (strictly) of other.

Parameters:

Name Type Description Default
other Scope

The other scope to test.

required

Returns:

Name Type Description
bool bool

Whether self ⊇ other.

Source code in cirkit/utils/scope.py
 96
 97
 98
 99
100
101
102
103
104
105
def __gt__(self, other: "Scope") -> bool:
    """Test whether self is a superset (strictly) of other.

    Args:
        other: The other scope to test.

    Returns:
        bool: Whether self ⊇ other.
    """
    return self._set > other._set

__hash__() ¤

Get the hash value of the scope, for use as dict/set keys.

The same scope (same set of variables) always has the same hash value.

Returns:

Name Type Description
int int

The hash value.

Source code in cirkit/utils/scope.py
60
61
62
63
64
65
66
67
68
def __hash__(self) -> int:
    """Get the hash value of the scope, for use as dict/set keys.

    The same scope (same set of variables) always has the same hash value.

    Returns:
        int: The hash value.
    """
    return hash(self._set)

__init__(scope=None) ¤

Initializes a scope object.

Parameters:

Name Type Description Default
scope Iterable[int] | None

The scope as an iterable of variable non-negative integer IDs. It can be None as to construct an empty scope.

None
Source code in cirkit/utils/scope.py
10
11
12
13
14
15
16
17
def __init__(self, scope: Iterable[int] | None = None) -> None:
    """Initializes a scope object.

    Args:
        scope: The scope as an iterable of variable non-negative integer IDs.
            It can be None as to construct an empty scope.
    """
    self._set: frozenset[int] = frozenset(scope) if scope is not None else frozenset()

__iter__() ¤

Iterate over the scope variables in the order of id, for conversion to other containers.

Returns:

Type Description
Iterator[int]

Iterator[int]: The iterator over the scope, that is sorted.

Source code in cirkit/utils/scope.py
44
45
46
47
48
49
50
def __iter__(self) -> Iterator[int]:
    """Iterate over the scope variables in the order of id, for conversion to other containers.

    Returns:
        Iterator[int]: The iterator over the scope, that is sorted.
    """
    return iter(self._set)

__le__(other) ¤

Test whether self is a subset (or equal) of other.

It is guaranteed that (a == b) <=> (a <= b and a >= b).

Parameters:

Name Type Description Default
other Scope

The other scope to test.

required

Returns:

Name Type Description
bool bool

Whether self ⊆ other.

Source code in cirkit/utils/scope.py
107
108
109
110
111
112
113
114
115
116
117
118
def __le__(self, other: "Scope") -> bool:
    """Test whether self is a subset (or equal) of other.

    It is guaranteed that (a == b) <=> (a <= b and a >= b).

    Args:
        other: The other scope to test.

    Returns:
        bool: Whether self ⊆ other.
    """
    return self._set <= other._set

__len__() ¤

Get the length, i.e., the number of variables) of the scope.

Returns:

Name Type Description
int int

The number of variables in the scope.

Source code in cirkit/utils/scope.py
52
53
54
55
56
57
58
def __len__(self) -> int:
    """Get the length, i.e., the number of variables) of the scope.

    Returns:
        int: The number of variables in the scope.
    """
    return len(self._set)

__lt__(other) ¤

Test whether self is a subset (strictly) of other.

Parameters:

Name Type Description Default
other Scope

The other scope to test.

required

Returns:

Name Type Description
bool bool

Whether self ⊆ other.

Source code in cirkit/utils/scope.py
85
86
87
88
89
90
91
92
93
94
def __lt__(self, other: "Scope") -> bool:
    """Test whether self is a subset (strictly) of other.

    Args:
        other: The other scope to test.

    Returns:
        bool: Whether self ⊆ other.
    """
    return self._set < other._set

__or__(other) ¤

Get the union of two scopes, for | operator.

Parameters:

Name Type Description Default
other Scope

The other scope to take union with.

required

Returns:

Name Type Description
Scope Scope

The union.

Source code in cirkit/utils/scope.py
142
143
144
145
146
147
148
149
150
151
def __or__(self, other: "Scope") -> "Scope":
    """Get the union of two scopes, for | operator.

    Args:
        other: The other scope to take union with.

    Returns:
        Scope: The union.
    """
    return Scope(self._set | other._set)

__repr__() ¤

Generate the repr string of the scope, for repr().

Returns:

Name Type Description
str str

The str representation of the scope.

Source code in cirkit/utils/scope.py
19
20
21
22
23
24
25
def __repr__(self) -> str:
    """Generate the repr string of the scope, for repr().

    Returns:
        str: The str representation of the scope.
    """
    return f"Scope({repr(set(self))})"  # Scope({0, 1, ...}).

__sub__(other) ¤

Take the difference w.r.t. another scope, i.e., the scope containing the variables that are not in the other scope.

Parameters:

Name Type Description Default
other Scope

The other scope to take the difference with.

required

Returns:

Name Type Description
Scope Scope

The difference between scopes.

Source code in cirkit/utils/scope.py
182
183
184
185
186
187
188
189
190
191
192
def __sub__(self, other: "Scope") -> "Scope":
    """Take the difference w.r.t. another scope, i.e., the scope
    containing the variables that are not in the other scope.

    Args:
        other: The other scope to take the difference with.

    Returns:
        Scope: The difference between scopes.
    """
    return self.difference(other)

difference(other) ¤

Take the difference w.r.t. another scope, i.e., the scope containing the variables that are not in the other scope.

Parameters:

Name Type Description Default
other Scope

The other scope to take the difference with.

required

Returns:

Name Type Description
Scope Scope

The difference between scopes.

Source code in cirkit/utils/scope.py
170
171
172
173
174
175
176
177
178
179
180
def difference(self, other: "Scope") -> "Scope":
    """Take the difference w.r.t. another scope, i.e., the scope
    containing the variables that are not in the other scope.

    Args:
        other: The other scope to take the difference with.

    Returns:
        Scope: The difference between scopes.
    """
    return Scope(self._set.difference(other._set))  # pylint: disable=protected-access

union(*scopes) ¤

Take the union over multiple scopes, for use as reduction with n-ary | operator.

Can be used as either self.union(...) or Scope.union(...).

Parameters:

Name Type Description Default
*scopes Scope

The other scope to take union with.

()

Returns:

Name Type Description
Scope Scope

The union.

Source code in cirkit/utils/scope.py
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
def union(*scopes: "Scope") -> "Scope":
    """Take the union over multiple scopes, for use as reduction with n-ary | operator.

    Can be used as either self.union(...) or Scope.union(...).

    Args:
        *scopes: The other scope to take union with.

    Returns:
        Scope: The union.
    """
    sets = tuple(s._set for s in scopes)  # pylint: disable=protected-access
    # Populate the scope by taking the unions of the input scopes
    scope = Scope(frozenset().union(*sets))
    return scope