Skip to content

Commit 5f4500d

Browse files
committed
clarify join/meet and lattice structure
1 parent 2a98e55 commit 5f4500d

File tree

1 file changed

+98
-56
lines changed
  • src/bloqade/analysis/validation/nocloning

1 file changed

+98
-56
lines changed

src/bloqade/analysis/validation/nocloning/lattice.py

Lines changed: 98 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2,122 +2,164 @@
22
from typing import FrozenSet, final
33
from dataclasses import field, dataclass
44

5-
from kirin.lattice import (
6-
SingletonMeta,
7-
BoundedLattice,
8-
SimpleJoinMixin,
9-
SimpleMeetMixin,
10-
)
5+
from kirin.lattice import SingletonMeta, BoundedLattice
116

127

138
@dataclass
14-
class QubitValidation(
15-
SimpleJoinMixin["QubitValidation"],
16-
SimpleMeetMixin["QubitValidation"],
17-
BoundedLattice["QubitValidation"],
18-
):
19-
"""Base class for qubit cloning validation lattice.
20-
21-
Lattice ordering:
22-
Bottom ⊑ May{...} ⊑ Must{...} ⊑ Top
9+
class QubitValidation(BoundedLattice["QubitValidation"]):
10+
r"""Base class for qubit-cloning validation lattice.
11+
12+
Linear ordering (more precise --> less precise):
13+
Bottom ⊑ Must ⊑ May ⊑ Top
14+
15+
Semantics:
16+
- Bottom: proven safe / never occurs
17+
- Must: definitely occurs (strong)
18+
- May: possibly occurs (weak)
19+
- Top: unknown / no information
2320
"""
2421

2522
@classmethod
2623
def bottom(cls) -> "QubitValidation":
27-
"""No violations detected"""
2824
return Bottom()
2925

3026
@classmethod
3127
def top(cls) -> "QubitValidation":
32-
"""Unknown state"""
3328
return Top()
3429

3530
@abstractmethod
36-
def is_subseteq(self, other: "QubitValidation") -> bool:
37-
"""Check if this state is a subset of another."""
38-
...
31+
def is_subseteq(self, other: "QubitValidation") -> bool: ...
32+
33+
@abstractmethod
34+
def join(self, other: "QubitValidation") -> "QubitValidation": ...
35+
36+
@abstractmethod
37+
def meet(self, other: "QubitValidation") -> "QubitValidation": ...
3938

4039

4140
@final
4241
class Bottom(QubitValidation, metaclass=SingletonMeta):
43-
"""Bottom element: no violations detected (safe)."""
44-
4542
def is_subseteq(self, other: QubitValidation) -> bool:
46-
"""Bottom is subset of everything."""
4743
return True
4844

45+
def join(self, other: QubitValidation) -> QubitValidation:
46+
return other
47+
48+
def meet(self, other: QubitValidation) -> QubitValidation:
49+
return self
50+
4951
def __repr__(self) -> str:
5052
return "⊥ (No Errors)"
5153

5254

5355
@final
5456
class Top(QubitValidation, metaclass=SingletonMeta):
55-
"""Top element: unknown state (worst case - assume violations possible)."""
56-
5757
def is_subseteq(self, other: QubitValidation) -> bool:
58-
"""Top is only subset of Top."""
5958
return isinstance(other, Top)
6059

60+
def join(self, other: QubitValidation) -> QubitValidation:
61+
return self
62+
63+
def meet(self, other: QubitValidation) -> QubitValidation:
64+
return other
65+
6166
def __repr__(self) -> str:
6267
return "⊤ (Unknown)"
6368

6469

6570
@final
6671
@dataclass
67-
class May(QubitValidation):
68-
"""Potential violations that may occur depending on runtime values.
69-
70-
Used when we have unknown addresses (UnknownQubit, UnknownReg, Unknown).
71-
"""
72+
class Must(QubitValidation):
73+
"""Definite violations."""
7274

7375
violations: FrozenSet[str] = field(default_factory=frozenset)
7476

7577
def is_subseteq(self, other: QubitValidation) -> bool:
76-
"""May ⊑ May' if violations ⊆ violations'
77-
May ⊑ Must (any may is less precise than must)
78-
May ⊑ Top
79-
"""
8078
match other:
8179
case Bottom():
8280
return False
83-
case May(violations=other_violations):
84-
return self.violations.issubset(other_violations)
85-
case Must():
86-
return True # May is less precise than Must
81+
case Must(violations=ov):
82+
return self.violations.issubset(ov)
83+
case May(violations=_):
84+
return True
8785
case Top():
8886
return True
8987
return False
9088

89+
def join(self, other: QubitValidation) -> QubitValidation:
90+
match other:
91+
case Bottom():
92+
return self
93+
case Must(violations=ov):
94+
return Must(violations=self.violations | ov)
95+
case May(violations=ov):
96+
return May(violations=self.violations | ov)
97+
case Top():
98+
return Top()
99+
return Top()
100+
101+
def meet(self, other: QubitValidation) -> QubitValidation:
102+
match other:
103+
case Bottom():
104+
return Bottom()
105+
case Must(violations=ov):
106+
inter = self.violations & ov
107+
return Must(violations=inter) if inter else Bottom()
108+
case May(violations=ov):
109+
inter = self.violations & ov if ov else self.violations
110+
return Must(violations=inter) if inter else Bottom()
111+
case Top():
112+
return self
113+
return Bottom()
114+
91115
def __repr__(self) -> str:
92-
if not self.violations:
93-
return "MayError(∅)"
94-
return f"MayError({self.violations})"
116+
return f"Must({self.violations or '∅'})"
95117

96118

97119
@final
98120
@dataclass
99-
class Must(QubitValidation):
100-
"""Definite violations with concrete qubit addresses.
101-
102-
These are violations we can prove will definitely occur.
103-
"""
121+
class May(QubitValidation):
122+
"""Potential violations."""
104123

105124
violations: FrozenSet[str] = field(default_factory=frozenset)
106125

107126
def is_subseteq(self, other: QubitValidation) -> bool:
108-
"""Must ⊑ Must' if violations ⊆ violations'
109-
Must ⊑ Top
110-
"""
111127
match other:
112-
case Bottom() | May():
128+
case Bottom():
129+
return False
130+
case Must():
113131
return False
114-
case Must(violations=other_violations):
115-
return self.violations.issubset(other_violations)
132+
case May(violations=ov):
133+
return self.violations.issubset(ov)
116134
case Top():
117135
return True
118136
return False
119137

138+
def join(self, other: QubitValidation) -> QubitValidation:
139+
match other:
140+
case Bottom():
141+
return self
142+
case Must(violations=ov):
143+
return May(violations=self.violations | ov)
144+
case May(violations=ov):
145+
return May(violations=self.violations | ov)
146+
case Top():
147+
return Top()
148+
return Top()
149+
150+
def meet(self, other: QubitValidation) -> QubitValidation:
151+
match other:
152+
case Bottom():
153+
return Bottom()
154+
case Must(violations=ov):
155+
inter = self.violations & ov if ov else ov or self.violations
156+
return Must(violations=inter) if inter else Bottom()
157+
case May(violations=ov):
158+
inter = self.violations & ov
159+
return May(violations=inter) if inter else Bottom()
160+
case Top():
161+
return self
162+
return Bottom()
163+
120164
def __repr__(self) -> str:
121-
if not self.violations:
122-
return "MustError(∅)"
123-
return f"MustError({self.violations})"
165+
return f"May({self.violations or '∅'})"

0 commit comments

Comments
 (0)