|
141 | 141 | "show_counts_sigma(toffoli_sigma)" |
142 | 142 | ] |
143 | 143 | }, |
| 144 | + { |
| 145 | + "cell_type": "markdown", |
| 146 | + "id": "dc13c6f1-86b7-4a0b-9b4a-e7f3ed67e3a6", |
| 147 | + "metadata": {}, |
| 148 | + "source": [ |
| 149 | + "## Controlled\n", |
| 150 | + "\n", |
| 151 | + "We use `Toffoli` for specifically two control bits of the `XGate`. Requesting `Toffoli().controlled(ctrl_spec)` will give an instance of the generic `ControlledViaAnd(XGate(), ...)` bloq, which will control the `XGate` on an arbitrary boolean function supported by `CtrlSpec`. The set of control registers present on the resulting bloq will 1) the control registers needed for the provided `ctrl_spec` and 2) one additional `QBit()[2]` register for the original Toffoli control bits." |
| 152 | + ] |
| 153 | + }, |
| 154 | + { |
| 155 | + "cell_type": "code", |
| 156 | + "execution_count": null, |
| 157 | + "id": "d4e0647b-ce06-47eb-9e18-7d49e375a9ed", |
| 158 | + "metadata": {}, |
| 159 | + "outputs": [], |
| 160 | + "source": [ |
| 161 | + "from qualtran import CtrlSpec\n", |
| 162 | + "print(repr(Toffoli().controlled()))\n", |
| 163 | + "show_bloq(Toffoli().controlled(), 'musical_score')" |
| 164 | + ] |
| 165 | + }, |
| 166 | + { |
| 167 | + "cell_type": "code", |
| 168 | + "execution_count": null, |
| 169 | + "id": "7fffec98-d1fe-42d5-8878-4117ecc881bc", |
| 170 | + "metadata": {}, |
| 171 | + "outputs": [], |
| 172 | + "source": [ |
| 173 | + "print(repr(Toffoli().controlled(CtrlSpec(cvs=0))))\n", |
| 174 | + "show_bloq(Toffoli().controlled(CtrlSpec(cvs=0)), 'musical_score')" |
| 175 | + ] |
| 176 | + }, |
| 177 | + { |
| 178 | + "cell_type": "markdown", |
| 179 | + "id": "4a58a0e7-1219-4bc6-ae2b-8df71d7d85d5", |
| 180 | + "metadata": {}, |
| 181 | + "source": [ |
| 182 | + "### Complex control specs\n", |
| 183 | + "\n", |
| 184 | + "Per above, `Toffoli.controlled()` can support arbitrary control specs." |
| 185 | + ] |
| 186 | + }, |
144 | 187 | { |
145 | 188 | "cell_type": "code", |
146 | 189 | "execution_count": null, |
147 | | - "id": "ad6ba003", |
| 190 | + "id": "59d97e1f-b957-432f-b0de-edeee84e5b71", |
148 | 191 | "metadata": {}, |
149 | 192 | "outputs": [], |
150 | | - "source": [] |
| 193 | + "source": [ |
| 194 | + "active_six = CtrlSpec(qdtypes=QInt(8), cvs=6)\n", |
| 195 | + "six_and_toffoli = Toffoli().controlled(active_six)\n", |
| 196 | + "print(repr(six_and_toffoli))\n", |
| 197 | + "show_bloq(six_and_toffoli, 'musical_score')" |
| 198 | + ] |
| 199 | + }, |
| 200 | + { |
| 201 | + "cell_type": "markdown", |
| 202 | + "id": "afcbb7aa-c098-4c56-8961-e0cfc9661a5c", |
| 203 | + "metadata": {}, |
| 204 | + "source": [ |
| 205 | + "### Calling controlled gates automatically\n", |
| 206 | + "\n", |
| 207 | + "The `Toffoli().controlled()` method (and in general, the `.controlled()` method for any bloq object) returns a bloq that implements a controlled version of the original gate. The returned bloq can structure its signature however it chooses. You can see that `Toffoli.controlled()` returns a `ControlledViaAnd(XGate(), ...)` which names its control registers `ctrl{n}` with the final one corresponding to the original Toffoli control bits. \n", |
| 208 | + "\n", |
| 209 | + "When writing meta-bloqs that need to support adding arbitrarily-controlled versions of Toffoli to a decomposition, you should not rely on any particular signature. `Bloq.get_ctrl_system()` is the method for automatically `bb.add`-ing controlled versions of arbitrary bloqs. We demonstrate that below." |
| 210 | + ] |
| 211 | + }, |
| 212 | + { |
| 213 | + "cell_type": "code", |
| 214 | + "execution_count": null, |
| 215 | + "id": "afc14f80-44cd-4fc8-a626-427ef8fd4a99", |
| 216 | + "metadata": {}, |
| 217 | + "outputs": [], |
| 218 | + "source": [ |
| 219 | + "from qualtran.bloqs.basic_gates import IntState, IntEffect\n", |
| 220 | + "\n", |
| 221 | + "bb = BloqBuilder()\n", |
| 222 | + "# q0, q1, target will be original wires for calling Toffoli\n", |
| 223 | + "q0 = bb.add_register('q0', QBit())\n", |
| 224 | + "q1 = bb.add_register('q1', QBit())\n", |
| 225 | + "target = bb.add_register('target', QBit())\n", |
| 226 | + "\n", |
| 227 | + "# \"six\" is a new wire that we additionally want to control the Toffoli with\n", |
| 228 | + "six = bb.add(IntState(val=6, bitsize=8))\n", |
| 229 | + "ctrl_spec = CtrlSpec(qdtypes=QUInt(8), cvs=6)\n", |
| 230 | + "\n", |
| 231 | + "# Instead of using Toffoli().controlled() directly, we use the ctrl_system\n", |
| 232 | + "ctof, ctof_adder = Toffoli().get_ctrl_system(ctrl_spec)\n", |
| 233 | + "\n", |
| 234 | + "# The new control variables are passed in their own list and returned in their own list\n", |
| 235 | + "# The existing Toffoli inputs are provided in a dictionary and returned in their own list\n", |
| 236 | + "(six,), ((q0, q1), target) = ctof_adder(bb, ctrl_soqs=[six], in_soqs=dict(ctrl=[q0,q1], target=target))\n", |
| 237 | + "\n", |
| 238 | + "# # below is a brittle way to achieve the same effect for this particular ctrl_spec\n", |
| 239 | + "# # it assumes control registers named ctrl1 and ctrl2\n", |
| 240 | + "# six_and_toffoli = Toffoli().controlled(ctrl_spec)\n", |
| 241 | + "# six, (q0, q1), target = bb.add(six_and_toffoli, ctrl1=six, ctrl2=[q0, q1], q=target)\n", |
| 242 | + "\n", |
| 243 | + "bb.add(IntEffect(val=6, bitsize=8), val=six)\n", |
| 244 | + "program = bb.finalize(q0=q0, q1=q1, target=target)\n", |
| 245 | + "show_bloq(program, 'musical_score')" |
| 246 | + ] |
151 | 247 | } |
152 | 248 | ], |
153 | 249 | "metadata": { |
|
166 | 262 | "name": "python", |
167 | 263 | "nbconvert_exporter": "python", |
168 | 264 | "pygments_lexer": "ipython3", |
169 | | - "version": "3.10.9" |
| 265 | + "version": "3.13.9" |
170 | 266 | } |
171 | 267 | }, |
172 | 268 | "nbformat": 4, |
|
0 commit comments