|
14 | 14 | from bloqade.analysis.address import AddressAnalysis |
15 | 15 | from bloqade.qasm2.passes.qasm2py import _QASM2Py as QASM2ToPyRule |
16 | 16 | from bloqade.analysis.address.lattice import AddressReg |
| 17 | +from bloqade.squin.passes.qasm2_to_squin import QASM2ToSquin |
17 | 18 | from bloqade.squin.passes.qasm2_gate_func_to_squin import QASM2GateFuncToSquinPass |
18 | 19 |
|
19 | 20 |
|
@@ -342,3 +343,116 @@ def main_kernel(): |
342 | 343 | actual_stmts = [type(stmt) for stmt in main_kernel.callable_region.walk()] |
343 | 344 | assert actual_stmts.count(squin.gate.stmts.CX) == 1 |
344 | 345 | assert actual_stmts.count(squin.gate.stmts.X) == 1 |
| 346 | + |
| 347 | + |
| 348 | +def test_ccx_to_2_and_1q_gates(): |
| 349 | + |
| 350 | + # use Nielsen and Chuang decomposition of CCX/Toffoli |
| 351 | + # into 2 and 1 qubit gates. This is intentionally |
| 352 | + # more complex than necessary just to test things out. |
| 353 | + |
| 354 | + @qasm2.main |
| 355 | + def layer_1(ctrl1, ctrl2, target): |
| 356 | + qasm2.h(target) |
| 357 | + qasm2.cx(ctrl2, target) |
| 358 | + qasm2.tdg(target) |
| 359 | + qasm2.cx(ctrl1, target) |
| 360 | + return |
| 361 | + |
| 362 | + @qasm2.main |
| 363 | + def layer_2(ctrl1, ctrl2, target): |
| 364 | + qasm2.t(ctrl1) |
| 365 | + qasm2.cx(ctrl2, target) |
| 366 | + qasm2.tdg(target) |
| 367 | + qasm2.cx(ctrl1, target) |
| 368 | + |
| 369 | + @qasm2.main |
| 370 | + def layer_3(ctrl1, ctrl2, target): |
| 371 | + qasm2.t(ctrl2) |
| 372 | + qasm2.t(target) |
| 373 | + qasm2.cx(ctrl1, ctrl2) |
| 374 | + qasm2.h(target) |
| 375 | + qasm2.t(ctrl1) |
| 376 | + qasm2.tdg(ctrl2) |
| 377 | + qasm2.cx(ctrl1, ctrl2) |
| 378 | + return |
| 379 | + |
| 380 | + @qasm2.extended |
| 381 | + def lossy_toffoli_gate(ctrl1, ctrl2, target): |
| 382 | + |
| 383 | + layer_1(ctrl1, ctrl2, target) |
| 384 | + noise.atom_loss_channel(qargs=[ctrl1, ctrl2, target], prob=0.01) |
| 385 | + layer_2(ctrl1, ctrl2, target) |
| 386 | + noise.atom_loss_channel(qargs=[ctrl1, ctrl2, target], prob=0.01) |
| 387 | + layer_3(ctrl1, ctrl2, target) |
| 388 | + noise.atom_loss_channel(qargs=[ctrl1, ctrl2, target], prob=0.01) |
| 389 | + return |
| 390 | + |
| 391 | + @qasm2.extended |
| 392 | + def rotation_layer(qs): |
| 393 | + |
| 394 | + glob.u(qs, math.pi, math.pi / 2, math.pi / 16) |
| 395 | + parallel.rz(qs, math.pi / 4) |
| 396 | + parallel.u(qs, math.pi / 2, math.pi / 2, math.pi / 8) |
| 397 | + return |
| 398 | + |
| 399 | + @qasm2.main |
| 400 | + def main(): |
| 401 | + qs = qasm2.qreg(3) |
| 402 | + # set up the control qubits |
| 403 | + qasm2.x(qs[0]) |
| 404 | + qasm2.x(qs[1]) |
| 405 | + lossy_toffoli_gate(qs[0], qs[1], qs[2]) |
| 406 | + rotation_layer(qs) |
| 407 | + |
| 408 | + QASM2ToSquin(dialects=main.dialects)(main) |
| 409 | + AggressiveUnroll(dialects=main.dialects).fixpoint(main) |
| 410 | + |
| 411 | + actual_stmts = [ |
| 412 | + type(stmt) |
| 413 | + for stmt in main.callable_region.walk() |
| 414 | + if isinstance(stmt, squin.gate.stmts.Gate) |
| 415 | + or isinstance(stmt, squin.noise.stmts.NoiseChannel) |
| 416 | + ] |
| 417 | + expected_stmts = [ |
| 418 | + squin.gate.stmts.X, |
| 419 | + squin.gate.stmts.X, |
| 420 | + # go into the toffoli |
| 421 | + ## layer 1 |
| 422 | + squin.gate.stmts.H, |
| 423 | + squin.gate.stmts.CX, |
| 424 | + squin.gate.stmts.T, # adjoint=True |
| 425 | + squin.gate.stmts.CX, |
| 426 | + ### atom loss |
| 427 | + squin.noise.stmts.QubitLoss, |
| 428 | + ## layer 2 |
| 429 | + squin.gate.stmts.T, |
| 430 | + squin.gate.stmts.CX, |
| 431 | + squin.gate.stmts.T, # adjoint=True |
| 432 | + squin.gate.stmts.CX, |
| 433 | + ### atom loss |
| 434 | + squin.noise.stmts.QubitLoss, |
| 435 | + ## layer 3 |
| 436 | + squin.gate.stmts.T, |
| 437 | + squin.gate.stmts.T, |
| 438 | + squin.gate.stmts.CX, |
| 439 | + squin.gate.stmts.H, |
| 440 | + squin.gate.stmts.T, |
| 441 | + squin.gate.stmts.T, # adjoint=True |
| 442 | + squin.gate.stmts.CX, |
| 443 | + ### atom loss |
| 444 | + squin.noise.stmts.QubitLoss, |
| 445 | + # random rotation layer |
| 446 | + squin.gate.stmts.U3, |
| 447 | + squin.gate.stmts.Rz, |
| 448 | + squin.gate.stmts.U3, |
| 449 | + ] |
| 450 | + |
| 451 | + assert actual_stmts == expected_stmts |
| 452 | + |
| 453 | + num_T_adj = 0 |
| 454 | + for stmt in main.callable_region.walk(): |
| 455 | + if isinstance(stmt, squin.gate.stmts.T) and stmt.adjoint: |
| 456 | + num_T_adj += 1 |
| 457 | + |
| 458 | + assert num_T_adj == 3 |
0 commit comments