|
2 | 2 | from typing import FrozenSet, final |
3 | 3 | from dataclasses import field, dataclass |
4 | 4 |
|
5 | | -from kirin.lattice import ( |
6 | | - SingletonMeta, |
7 | | - BoundedLattice, |
8 | | - SimpleJoinMixin, |
9 | | - SimpleMeetMixin, |
10 | | -) |
| 5 | +from kirin.lattice import SingletonMeta, BoundedLattice |
11 | 6 |
|
12 | 7 |
|
13 | 8 | @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 |
23 | 20 | """ |
24 | 21 |
|
25 | 22 | @classmethod |
26 | 23 | def bottom(cls) -> "QubitValidation": |
27 | | - """No violations detected""" |
28 | 24 | return Bottom() |
29 | 25 |
|
30 | 26 | @classmethod |
31 | 27 | def top(cls) -> "QubitValidation": |
32 | | - """Unknown state""" |
33 | 28 | return Top() |
34 | 29 |
|
35 | 30 | @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": ... |
39 | 38 |
|
40 | 39 |
|
41 | 40 | @final |
42 | 41 | class Bottom(QubitValidation, metaclass=SingletonMeta): |
43 | | - """Bottom element: no violations detected (safe).""" |
44 | | - |
45 | 42 | def is_subseteq(self, other: QubitValidation) -> bool: |
46 | | - """Bottom is subset of everything.""" |
47 | 43 | return True |
48 | 44 |
|
| 45 | + def join(self, other: QubitValidation) -> QubitValidation: |
| 46 | + return other |
| 47 | + |
| 48 | + def meet(self, other: QubitValidation) -> QubitValidation: |
| 49 | + return self |
| 50 | + |
49 | 51 | def __repr__(self) -> str: |
50 | 52 | return "⊥ (No Errors)" |
51 | 53 |
|
52 | 54 |
|
53 | 55 | @final |
54 | 56 | class Top(QubitValidation, metaclass=SingletonMeta): |
55 | | - """Top element: unknown state (worst case - assume violations possible).""" |
56 | | - |
57 | 57 | def is_subseteq(self, other: QubitValidation) -> bool: |
58 | | - """Top is only subset of Top.""" |
59 | 58 | return isinstance(other, Top) |
60 | 59 |
|
| 60 | + def join(self, other: QubitValidation) -> QubitValidation: |
| 61 | + return self |
| 62 | + |
| 63 | + def meet(self, other: QubitValidation) -> QubitValidation: |
| 64 | + return other |
| 65 | + |
61 | 66 | def __repr__(self) -> str: |
62 | 67 | return "⊤ (Unknown)" |
63 | 68 |
|
64 | 69 |
|
65 | 70 | @final |
66 | 71 | @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.""" |
72 | 74 |
|
73 | 75 | violations: FrozenSet[str] = field(default_factory=frozenset) |
74 | 76 |
|
75 | 77 | 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 | | - """ |
80 | 78 | match other: |
81 | 79 | case Bottom(): |
82 | 80 | 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 |
87 | 85 | case Top(): |
88 | 86 | return True |
89 | 87 | return False |
90 | 88 |
|
| 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 | + |
91 | 115 | 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 '∅'})" |
95 | 117 |
|
96 | 118 |
|
97 | 119 | @final |
98 | 120 | @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.""" |
104 | 123 |
|
105 | 124 | violations: FrozenSet[str] = field(default_factory=frozenset) |
106 | 125 |
|
107 | 126 | def is_subseteq(self, other: QubitValidation) -> bool: |
108 | | - """Must ⊑ Must' if violations ⊆ violations' |
109 | | - Must ⊑ Top |
110 | | - """ |
111 | 127 | match other: |
112 | | - case Bottom() | May(): |
| 128 | + case Bottom(): |
| 129 | + return False |
| 130 | + case Must(): |
113 | 131 | 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) |
116 | 134 | case Top(): |
117 | 135 | return True |
118 | 136 | return False |
119 | 137 |
|
| 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 | + |
120 | 164 | 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