|
22 | 22 | SOFTWARE.
|
23 | 23 | """
|
24 | 24 |
|
| 25 | +import torch |
25 | 26 | import torch.nn as nn
|
26 | 27 | import torchquantum as tq
|
27 | 28 | import torchquantum.functional as tqf
|
|
49 | 50 | "CXCXCXLayer",
|
50 | 51 | "SWAPSWAPLayer",
|
51 | 52 | "RXYZCXLayer0",
|
| 53 | + "QFTLayer", |
52 | 54 | ]
|
53 | 55 |
|
54 | 56 |
|
@@ -1467,6 +1469,113 @@ def build_layers(self):
|
1467 | 1469 | return layers_all
|
1468 | 1470 |
|
1469 | 1471 |
|
| 1472 | +class QFTLayer(tq.QuantumModule): |
| 1473 | + def __init__( |
| 1474 | + self, |
| 1475 | + n_wires: int = None, |
| 1476 | + wires: Iterable = None, |
| 1477 | + do_swaps: bool = True, |
| 1478 | + inverse: bool = False, |
| 1479 | + ): |
| 1480 | + """ |
| 1481 | + Constructs a Quantum Fourier Transform (QFT) layer |
| 1482 | +
|
| 1483 | + Args: |
| 1484 | + n_wires (int): Number of wires for the QFT as an integer |
| 1485 | + wires (Iterable): Wires to perform the QFT as an Iterable |
| 1486 | + do_swaps (bool): Whether or not to add the final swaps in a boolean format |
| 1487 | + inverse (bool): Whether to create an inverse QFT layer in a boolean format |
| 1488 | + """ |
| 1489 | + super().__init__() |
| 1490 | + |
| 1491 | + assert n_wires is not None or wires is not None |
| 1492 | + |
| 1493 | + if n_wires is None: |
| 1494 | + self.n_wires = len(wires) |
| 1495 | + |
| 1496 | + if wires is None: |
| 1497 | + wires = range(n_wires) |
| 1498 | + |
| 1499 | + self.n_wires = n_wires |
| 1500 | + self.wires = wires |
| 1501 | + self.do_swaps = do_swaps |
| 1502 | + |
| 1503 | + if inverse: |
| 1504 | + self.gates_all = self.build_inverse_circuit() |
| 1505 | + else: |
| 1506 | + self.gates_all = self.build_circuit() |
| 1507 | + |
| 1508 | + def build_circuit(self): |
| 1509 | + """Construct a QFT circuit.""" |
| 1510 | + |
| 1511 | + operation_list = [] |
| 1512 | + |
| 1513 | + # add the H and CU1 gates |
| 1514 | + for top_wire in range(self.n_wires): |
| 1515 | + operation_list.append({"name": "hadamard", "wires": self.wires[top_wire]}) |
| 1516 | + for wire in range(top_wire + 1, self.n_wires): |
| 1517 | + lam = torch.pi / (2 ** (wire - top_wire)) |
| 1518 | + operation_list.append( |
| 1519 | + { |
| 1520 | + "name": "cu1", |
| 1521 | + "params": lam, |
| 1522 | + "wires": [self.wires[wire], self.wires[top_wire]], |
| 1523 | + } |
| 1524 | + ) |
| 1525 | + |
| 1526 | + # add swaps if specified |
| 1527 | + if self.do_swaps: |
| 1528 | + for wire in range(self.n_wires // 2): |
| 1529 | + operation_list.append( |
| 1530 | + { |
| 1531 | + "name": "swap", |
| 1532 | + "wires": [ |
| 1533 | + self.wires[wire], |
| 1534 | + self.wires[self.n_wires - wire - 1], |
| 1535 | + ], |
| 1536 | + } |
| 1537 | + ) |
| 1538 | + |
| 1539 | + return tq.QuantumModule.from_op_history(operation_list) |
| 1540 | + |
| 1541 | + def build_inverse_circuit(self): |
| 1542 | + """Construct the inverse of a QFT circuit.""" |
| 1543 | + |
| 1544 | + operation_list = [] |
| 1545 | + |
| 1546 | + # add swaps if specified |
| 1547 | + if self.do_swaps: |
| 1548 | + for wire in range(self.n_wires // 2): |
| 1549 | + operation_list.append( |
| 1550 | + { |
| 1551 | + "name": "swap", |
| 1552 | + "wires": [ |
| 1553 | + self.wires[wire], |
| 1554 | + self.wires[self.n_wires - wire - 1], |
| 1555 | + ], |
| 1556 | + } |
| 1557 | + ) |
| 1558 | + |
| 1559 | + # add the CU1 and H gates |
| 1560 | + for top_wire in range(self.n_wires)[::-1]: |
| 1561 | + for wire in range(top_wire + 1, self.n_wires)[::-1]: |
| 1562 | + lam = -torch.pi / (2 ** (wire - top_wire)) |
| 1563 | + operation_list.append( |
| 1564 | + { |
| 1565 | + "name": "cu1", |
| 1566 | + "params": lam, |
| 1567 | + "wires": [self.wires[wire], self.wires[top_wire]], |
| 1568 | + } |
| 1569 | + ) |
| 1570 | + operation_list.append({"name": "hadamard", "wires": self.wires[top_wire]}) |
| 1571 | + |
| 1572 | + return tq.QuantumModule.from_op_history(operation_list) |
| 1573 | + |
| 1574 | + @tq.static_support |
| 1575 | + def forward(self, q_device: tq.QuantumDevice): |
| 1576 | + self.gates_all(q_device) |
| 1577 | + |
| 1578 | + |
1470 | 1579 | layer_name_dict = {
|
1471 | 1580 | "u3cu3_0": U3CU3Layer0,
|
1472 | 1581 | "cu3_0": CU3Layer0,
|
|
0 commit comments