libqasm 0.6.7__cp39-cp39-macosx_11_0_arm64.whl → 0.6.8__cp39-cp39-macosx_11_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cqasm/v3x/semantic.py CHANGED
@@ -638,10 +638,14 @@ class Annotated(Node):
638
638
  typ = cbor.get('@t', None)
639
639
  if typ is None:
640
640
  raise ValueError('type (@t) field is missing from node serialization')
641
+ if typ == 'Gate':
642
+ return Gate._deserialize(cbor, seq_to_ob, links)
641
643
  if typ == 'Variable':
642
644
  return Variable._deserialize(cbor, seq_to_ob, links)
643
- if typ == 'Instruction':
644
- return Instruction._deserialize(cbor, seq_to_ob, links)
645
+ if typ == 'GateInstruction':
646
+ return GateInstruction._deserialize(cbor, seq_to_ob, links)
647
+ if typ == 'NonGateInstruction':
648
+ return NonGateInstruction._deserialize(cbor, seq_to_ob, links)
645
649
  raise ValueError('unknown or unexpected type (@t) found in node serialization')
646
650
 
647
651
  def _serialize(self, id_map):
@@ -1162,6 +1166,342 @@ class MultiBlock(_Multiple):
1162
1166
 
1163
1167
  _typemap['Block'] = Block
1164
1168
 
1169
+ class Gate(Annotated):
1170
+ """A gate can be a named gate or a composition of gate modifiers acting on a
1171
+ gate. pow is the only gate modifier that has an operand."""
1172
+
1173
+ __slots__ = [
1174
+ '_attr_name',
1175
+ '_attr_gate',
1176
+ '_attr_parameter',
1177
+ ]
1178
+
1179
+ def __init__(
1180
+ self,
1181
+ name=None,
1182
+ gate=None,
1183
+ parameter=None,
1184
+ annotations=None,
1185
+ ):
1186
+ super().__init__(annotations=annotations)
1187
+ self.name = name
1188
+ self.gate = gate
1189
+ self.parameter = parameter
1190
+
1191
+ @property
1192
+ def name(self):
1193
+ return self._attr_name
1194
+
1195
+ @name.setter
1196
+ def name(self, val):
1197
+ if val is None:
1198
+ del self.name
1199
+ return
1200
+ if not isinstance(val, cqasm.v3x.primitives.Str):
1201
+ # Try to "typecast" if this isn't an obvious mistake.
1202
+ if isinstance(val, Node):
1203
+ raise TypeError('name must be of type cqasm.v3x.primitives.Str')
1204
+ val = cqasm.v3x.primitives.Str(val)
1205
+ self._attr_name = val
1206
+
1207
+ @name.deleter
1208
+ def name(self):
1209
+ self._attr_name = cqasm.v3x.primitives.Str()
1210
+
1211
+ @property
1212
+ def gate(self):
1213
+ return self._attr_gate
1214
+
1215
+ @gate.setter
1216
+ def gate(self, val):
1217
+ if val is None:
1218
+ del self.gate
1219
+ return
1220
+ if not isinstance(val, Gate):
1221
+ # Try to "typecast" if this isn't an obvious mistake.
1222
+ if isinstance(val, Node):
1223
+ raise TypeError('gate must be of type Gate')
1224
+ val = Gate(val)
1225
+ self._attr_gate = val
1226
+
1227
+ @gate.deleter
1228
+ def gate(self):
1229
+ self._attr_gate = None
1230
+
1231
+ @property
1232
+ def parameter(self):
1233
+ return self._attr_parameter
1234
+
1235
+ @parameter.setter
1236
+ def parameter(self, val):
1237
+ if val is None:
1238
+ del self.parameter
1239
+ return
1240
+ if not isinstance(val, cqasm.v3x.values.ValueBase):
1241
+ # Try to "typecast" if this isn't an obvious mistake.
1242
+ if isinstance(val, Node):
1243
+ raise TypeError('parameter must be of type cqasm.v3x.values.ValueBase')
1244
+ val = cqasm.v3x.values.ValueBase(val)
1245
+ self._attr_parameter = val
1246
+
1247
+ @parameter.deleter
1248
+ def parameter(self):
1249
+ self._attr_parameter = None
1250
+
1251
+ def __eq__(self, other):
1252
+ """Equality operator. Ignores annotations!"""
1253
+ if not isinstance(other, Gate):
1254
+ return False
1255
+ if self.name != other.name:
1256
+ return False
1257
+ if self.gate != other.gate:
1258
+ return False
1259
+ if self.parameter != other.parameter:
1260
+ return False
1261
+ if self.annotations != other.annotations:
1262
+ return False
1263
+ return True
1264
+
1265
+ def dump(self, indent=0, annotations=None, links=1):
1266
+ """Returns a debug representation of this tree as a multiline string.
1267
+ indent is the number of double spaces prefixed before every line.
1268
+ annotations, if specified, must be a set-like object containing the key
1269
+ strings of the annotations that are to be printed. links specifies the
1270
+ maximum link recursion depth."""
1271
+ s = [' '*indent]
1272
+ s.append('Gate(')
1273
+ if annotations is None:
1274
+ annotations = []
1275
+ for key in annotations:
1276
+ if key in self:
1277
+ s.append(' # {}: {}'.format(key, self[key]))
1278
+ s.append('\n')
1279
+ indent += 1
1280
+ s.append(' '*indent)
1281
+ s.append('name: ')
1282
+ s.append(str(self.name) + '\n')
1283
+ s.append(' '*indent)
1284
+ s.append('gate: ')
1285
+ if self.gate is None:
1286
+ s.append('-\n')
1287
+ else:
1288
+ s.append('<\n')
1289
+ s.append(self.gate.dump(indent + 1, annotations, links) + '\n')
1290
+ s.append(' '*indent + '>\n')
1291
+ s.append(' '*indent)
1292
+ s.append('parameter: ')
1293
+ if self.parameter is None:
1294
+ s.append('-\n')
1295
+ else:
1296
+ s.append('<\n')
1297
+ s.append(self.parameter.dump(indent + 1, annotations, links) + '\n')
1298
+ s.append(' '*indent + '>\n')
1299
+ s.append(' '*indent)
1300
+ s.append('annotations: ')
1301
+ if not self.annotations:
1302
+ s.append('-\n')
1303
+ else:
1304
+ s.append('[\n')
1305
+ for child in self.annotations:
1306
+ s.append(child.dump(indent + 1, annotations, links) + '\n')
1307
+ s.append(' '*indent + ']\n')
1308
+ indent -= 1
1309
+ s.append(' '*indent)
1310
+ s.append(')')
1311
+ return ''.join(s)
1312
+
1313
+ __str__ = dump
1314
+ __repr__ = dump
1315
+
1316
+ def find_reachable(self, id_map=None):
1317
+ """Returns a dictionary mapping Python id() values to stable sequence
1318
+ numbers for all nodes in the tree rooted at this node. If id_map is
1319
+ specified, found nodes are appended to it."""
1320
+ if id_map is None:
1321
+ id_map = {}
1322
+ if id(self) in id_map:
1323
+ raise NotWellFormed('node {!r} with id {} occurs more than once'.format(self, id(self)))
1324
+ id_map[id(self)] = len(id_map)
1325
+ if self._attr_gate is not None:
1326
+ self._attr_gate.find_reachable(id_map)
1327
+ if self._attr_parameter is not None:
1328
+ self._attr_parameter.find_reachable(id_map)
1329
+ for el in self._attr_annotations:
1330
+ el.find_reachable(id_map)
1331
+ return id_map
1332
+
1333
+ def check_complete(self, id_map=None):
1334
+ """Raises NotWellFormed if the tree rooted at this node is not
1335
+ well-formed. If id_map is specified, this tree is only a subtree in the
1336
+ context of a larger tree, and id_map must be a dict mapping from Python
1337
+ id() codes to tree indices for all reachable nodes."""
1338
+ if id_map is None:
1339
+ id_map = self.find_reachable()
1340
+ if self._attr_gate is not None:
1341
+ self._attr_gate.check_complete(id_map)
1342
+ if self._attr_parameter is not None:
1343
+ self._attr_parameter.check_complete(id_map)
1344
+ for child in self._attr_annotations:
1345
+ child.check_complete(id_map)
1346
+
1347
+ def copy(self):
1348
+ """Returns a shallow copy of this node."""
1349
+ return Gate(
1350
+ name=self._attr_name,
1351
+ gate=self._attr_gate,
1352
+ parameter=self._attr_parameter,
1353
+ annotations=self._attr_annotations.copy()
1354
+ )
1355
+
1356
+ def clone(self):
1357
+ """Returns a deep copy of this node. This mimics the C++ interface,
1358
+ deficiencies with links included; that is, links always point to the
1359
+ original tree. If you're not cloning a subtree in a context where this
1360
+ is the desired behavior, you may want to use the copy.deepcopy() from
1361
+ the stdlib instead, which should copy links correctly."""
1362
+ return Gate(
1363
+ name=_cloned(self._attr_name),
1364
+ gate=_cloned(self._attr_gate),
1365
+ parameter=_cloned(self._attr_parameter),
1366
+ annotations=_cloned(self._attr_annotations)
1367
+ )
1368
+
1369
+ @staticmethod
1370
+ def _deserialize(cbor, seq_to_ob, links):
1371
+ """Attempts to deserialize the given cbor object (in Python primitive
1372
+ representation) into a node of this type. All (sub)nodes are added to
1373
+ the seq_to_ob dict, indexed by their cbor sequence number. All links are
1374
+ registered in the links list by means of a two-tuple of the setter
1375
+ function for the link field and the sequence number of the target node.
1376
+ """
1377
+ if not isinstance(cbor, dict):
1378
+ raise TypeError('node description object must be a dict')
1379
+ typ = cbor.get('@t', None)
1380
+ if typ is None:
1381
+ raise ValueError('type (@t) field is missing from node serialization')
1382
+ if typ != 'Gate':
1383
+ raise ValueError('found node serialization for ' + typ + ', but expected Gate')
1384
+
1385
+ # Deserialize the name field.
1386
+ field = cbor.get('name', None)
1387
+ if not isinstance(field, dict):
1388
+ raise ValueError('missing or invalid serialization of field name')
1389
+ if hasattr(cqasm.v3x.primitives.Str, 'deserialize_cbor'):
1390
+ f_name = cqasm.v3x.primitives.Str.deserialize_cbor(field)
1391
+ else:
1392
+ f_name = cqasm.v3x.primitives.deserialize(cqasm.v3x.primitives.Str, field)
1393
+
1394
+ # Deserialize the gate field.
1395
+ field = cbor.get('gate', None)
1396
+ if not isinstance(field, dict):
1397
+ raise ValueError('missing or invalid serialization of field gate')
1398
+ if field.get('@T') != '?':
1399
+ raise ValueError('unexpected edge type for field gate')
1400
+ if field.get('@t', None) is None:
1401
+ f_gate = None
1402
+ else:
1403
+ f_gate = Gate._deserialize(field, seq_to_ob, links)
1404
+
1405
+ # Deserialize the parameter field.
1406
+ field = cbor.get('parameter', None)
1407
+ if not isinstance(field, dict):
1408
+ raise ValueError('missing or invalid serialization of field parameter')
1409
+ if field.get('@T') != '?':
1410
+ raise ValueError('unexpected edge type for field parameter')
1411
+ if field.get('@t', None) is None:
1412
+ f_parameter = None
1413
+ else:
1414
+ f_parameter = cqasm.v3x.values.ValueBase._deserialize(field, seq_to_ob, links)
1415
+
1416
+ # Deserialize the annotations field.
1417
+ field = cbor.get('annotations', None)
1418
+ if not isinstance(field, dict):
1419
+ raise ValueError('missing or invalid serialization of field annotations')
1420
+ if field.get('@T') != '*':
1421
+ raise ValueError('unexpected edge type for field annotations')
1422
+ data = field.get('@d', None)
1423
+ if not isinstance(data, list):
1424
+ raise ValueError('missing serialization of Any/Many contents')
1425
+ f_annotations = MultiAnnotationData()
1426
+ for element in data:
1427
+ if element.get('@T') != '1':
1428
+ raise ValueError('unexpected edge type for Any/Many element')
1429
+ f_annotations.append(AnnotationData._deserialize(element, seq_to_ob, links))
1430
+
1431
+ # Construct the Gate node.
1432
+ node = Gate(f_name, f_gate, f_parameter, f_annotations)
1433
+
1434
+ # Deserialize annotations.
1435
+ for key, val in cbor.items():
1436
+ if not (key.startswith('{') and key.endswith('}')):
1437
+ continue
1438
+ key = key[1:-1]
1439
+ node[key] = cqasm.v3x.primitives.deserialize(key, val)
1440
+
1441
+ # Register node in sequence number lookup.
1442
+ seq = cbor.get('@i', None)
1443
+ if not isinstance(seq, int):
1444
+ raise ValueError('sequence number field (@i) is not an integer or missing from node serialization')
1445
+ if seq in seq_to_ob:
1446
+ raise ValueError('duplicate sequence number %d' % seq)
1447
+ seq_to_ob[seq] = node
1448
+
1449
+ return node
1450
+
1451
+ def _serialize(self, id_map):
1452
+ """Serializes this node to the Python primitive representation of its
1453
+ CBOR serialization. The tree that the node belongs to must be
1454
+ well-formed. id_map must match Python id() calls for all nodes to unique
1455
+ integers, to use for the sequence number representation of links."""
1456
+ cbor = {'@i': id_map[id(self)], '@t': 'Gate'}
1457
+
1458
+ # Serialize the name field.
1459
+ if hasattr(self._attr_name, 'serialize_cbor'):
1460
+ cbor['name'] = self._attr_name.serialize_cbor()
1461
+ else:
1462
+ cbor['name'] = cqasm.v3x.primitives.serialize(cqasm.v3x.primitives.Str, self._attr_name)
1463
+
1464
+ # Serialize the gate field.
1465
+ field = {'@T': '?'}
1466
+ if self._attr_gate is None:
1467
+ field['@t'] = None
1468
+ else:
1469
+ field.update(self._attr_gate._serialize(id_map))
1470
+ cbor['gate'] = field
1471
+
1472
+ # Serialize the parameter field.
1473
+ field = {'@T': '?'}
1474
+ if self._attr_parameter is None:
1475
+ field['@t'] = None
1476
+ else:
1477
+ field.update(self._attr_parameter._serialize(id_map))
1478
+ cbor['parameter'] = field
1479
+
1480
+ # Serialize the annotations field.
1481
+ field = {'@T': '*'}
1482
+ lst = []
1483
+ for el in self._attr_annotations:
1484
+ el = el._serialize(id_map)
1485
+ el['@T'] = '1'
1486
+ lst.append(el)
1487
+ field['@d'] = lst
1488
+ cbor['annotations'] = field
1489
+
1490
+ # Serialize annotations.
1491
+ for key, val in self._annot.items():
1492
+ cbor['{%s}' % key] = _py_to_cbor(cqasm.v3x.primitives.serialize(key, val))
1493
+
1494
+ return cbor
1495
+
1496
+
1497
+ class MultiGate(_Multiple):
1498
+ """Wrapper for an edge with multiple Gate objects."""
1499
+
1500
+ _T = Gate
1501
+
1502
+
1503
+ _typemap['Gate'] = Gate
1504
+
1165
1505
  class Statement(Annotated):
1166
1506
  __slots__ = []
1167
1507
 
@@ -1184,16 +1524,422 @@ class Statement(Annotated):
1184
1524
  typ = cbor.get('@t', None)
1185
1525
  if typ is None:
1186
1526
  raise ValueError('type (@t) field is missing from node serialization')
1187
- if typ == 'Instruction':
1188
- return Instruction._deserialize(cbor, seq_to_ob, links)
1189
- raise ValueError('unknown or unexpected type (@t) found in node serialization')
1527
+ if typ == 'GateInstruction':
1528
+ return GateInstruction._deserialize(cbor, seq_to_ob, links)
1529
+ if typ == 'NonGateInstruction':
1530
+ return NonGateInstruction._deserialize(cbor, seq_to_ob, links)
1531
+ raise ValueError('unknown or unexpected type (@t) found in node serialization')
1532
+
1533
+ def _serialize(self, id_map):
1534
+ """Serializes this node to the Python primitive representation of its
1535
+ CBOR serialization. The tree that the node belongs to must be
1536
+ well-formed. id_map must match Python id() calls for all nodes to unique
1537
+ integers, to use for the sequence number representation of links."""
1538
+ cbor = {'@i': id_map[id(self)], '@t': 'Statement'}
1539
+
1540
+ # Serialize the annotations field.
1541
+ field = {'@T': '*'}
1542
+ lst = []
1543
+ for el in self._attr_annotations:
1544
+ el = el._serialize(id_map)
1545
+ el['@T'] = '1'
1546
+ lst.append(el)
1547
+ field['@d'] = lst
1548
+ cbor['annotations'] = field
1549
+
1550
+ # Serialize annotations.
1551
+ for key, val in self._annot.items():
1552
+ cbor['{%s}' % key] = _py_to_cbor(cqasm.v3x.primitives.serialize(key, val))
1553
+
1554
+ return cbor
1555
+
1556
+
1557
+ class MultiStatement(_Multiple):
1558
+ """Wrapper for an edge with multiple Statement objects."""
1559
+
1560
+ _T = Statement
1561
+
1562
+
1563
+ _typemap['Statement'] = Statement
1564
+
1565
+ class Instruction(Statement):
1566
+ __slots__ = []
1567
+
1568
+ def __init__(
1569
+ self,
1570
+ annotations=None,
1571
+ ):
1572
+ super().__init__(annotations=annotations)
1573
+
1574
+ @staticmethod
1575
+ def _deserialize(cbor, seq_to_ob, links):
1576
+ """Attempts to deserialize the given cbor object (in Python primitive
1577
+ representation) into a node of this type. All (sub)nodes are added to
1578
+ the seq_to_ob dict, indexed by their cbor sequence number. All links are
1579
+ registered in the links list by means of a two-tuple of the setter
1580
+ function for the link field and the sequence number of the target node.
1581
+ """
1582
+ if not isinstance(cbor, dict):
1583
+ raise TypeError('node description object must be a dict')
1584
+ typ = cbor.get('@t', None)
1585
+ if typ is None:
1586
+ raise ValueError('type (@t) field is missing from node serialization')
1587
+ if typ == 'GateInstruction':
1588
+ return GateInstruction._deserialize(cbor, seq_to_ob, links)
1589
+ if typ == 'NonGateInstruction':
1590
+ return NonGateInstruction._deserialize(cbor, seq_to_ob, links)
1591
+ raise ValueError('unknown or unexpected type (@t) found in node serialization')
1592
+
1593
+ def _serialize(self, id_map):
1594
+ """Serializes this node to the Python primitive representation of its
1595
+ CBOR serialization. The tree that the node belongs to must be
1596
+ well-formed. id_map must match Python id() calls for all nodes to unique
1597
+ integers, to use for the sequence number representation of links."""
1598
+ cbor = {'@i': id_map[id(self)], '@t': 'Instruction'}
1599
+
1600
+ # Serialize the annotations field.
1601
+ field = {'@T': '*'}
1602
+ lst = []
1603
+ for el in self._attr_annotations:
1604
+ el = el._serialize(id_map)
1605
+ el['@T'] = '1'
1606
+ lst.append(el)
1607
+ field['@d'] = lst
1608
+ cbor['annotations'] = field
1609
+
1610
+ # Serialize annotations.
1611
+ for key, val in self._annot.items():
1612
+ cbor['{%s}' % key] = _py_to_cbor(cqasm.v3x.primitives.serialize(key, val))
1613
+
1614
+ return cbor
1615
+
1616
+
1617
+ class MultiInstruction(_Multiple):
1618
+ """Wrapper for an edge with multiple Instruction objects."""
1619
+
1620
+ _T = Instruction
1621
+
1622
+
1623
+ _typemap['Instruction'] = Instruction
1624
+
1625
+ class GateInstruction(Instruction):
1626
+ """A gate, or a composition of gate modifiers and a gate"""
1627
+
1628
+ __slots__ = [
1629
+ '_attr_instruction_ref',
1630
+ '_attr_gate',
1631
+ '_attr_operands',
1632
+ ]
1633
+
1634
+ def __init__(
1635
+ self,
1636
+ instruction_ref=None,
1637
+ gate=None,
1638
+ operands=None,
1639
+ annotations=None,
1640
+ ):
1641
+ super().__init__(annotations=annotations)
1642
+ self.instruction_ref = instruction_ref
1643
+ self.gate = gate
1644
+ self.operands = operands
1645
+
1646
+ @property
1647
+ def instruction_ref(self):
1648
+ return self._attr_instruction_ref
1649
+
1650
+ @instruction_ref.setter
1651
+ def instruction_ref(self, val):
1652
+ if val is None:
1653
+ del self.instruction_ref
1654
+ return
1655
+ if not isinstance(val, cqasm.v3x.instruction.InstructionRef):
1656
+ # Try to "typecast" if this isn't an obvious mistake.
1657
+ if isinstance(val, Node):
1658
+ raise TypeError('instruction_ref must be of type cqasm.v3x.instruction.InstructionRef')
1659
+ val = cqasm.v3x.instruction.InstructionRef(val)
1660
+ self._attr_instruction_ref = val
1661
+
1662
+ @instruction_ref.deleter
1663
+ def instruction_ref(self):
1664
+ self._attr_instruction_ref = cqasm.v3x.instruction.InstructionRef()
1665
+
1666
+ @property
1667
+ def gate(self):
1668
+ return self._attr_gate
1669
+
1670
+ @gate.setter
1671
+ def gate(self, val):
1672
+ if val is None:
1673
+ del self.gate
1674
+ return
1675
+ if not isinstance(val, Gate):
1676
+ # Try to "typecast" if this isn't an obvious mistake.
1677
+ if isinstance(val, Node):
1678
+ raise TypeError('gate must be of type Gate')
1679
+ val = Gate(val)
1680
+ self._attr_gate = val
1681
+
1682
+ @gate.deleter
1683
+ def gate(self):
1684
+ self._attr_gate = None
1685
+
1686
+ @property
1687
+ def operands(self):
1688
+ return self._attr_operands
1689
+
1690
+ @operands.setter
1691
+ def operands(self, val):
1692
+ if val is None:
1693
+ del self.operands
1694
+ return
1695
+ if not isinstance(val, cqasm.v3x.values.MultiValueBase):
1696
+ # Try to "typecast" if this isn't an obvious mistake.
1697
+ if isinstance(val, Node):
1698
+ raise TypeError('operands must be of type cqasm.v3x.values.MultiValueBase')
1699
+ val = cqasm.v3x.values.MultiValueBase(val)
1700
+ self._attr_operands = val
1701
+
1702
+ @operands.deleter
1703
+ def operands(self):
1704
+ self._attr_operands = cqasm.v3x.values.MultiValueBase()
1705
+
1706
+ def __eq__(self, other):
1707
+ """Equality operator. Ignores annotations!"""
1708
+ if not isinstance(other, GateInstruction):
1709
+ return False
1710
+ if self.instruction_ref != other.instruction_ref:
1711
+ return False
1712
+ if self.gate != other.gate:
1713
+ return False
1714
+ if self.operands != other.operands:
1715
+ return False
1716
+ if self.annotations != other.annotations:
1717
+ return False
1718
+ return True
1719
+
1720
+ def dump(self, indent=0, annotations=None, links=1):
1721
+ """Returns a debug representation of this tree as a multiline string.
1722
+ indent is the number of double spaces prefixed before every line.
1723
+ annotations, if specified, must be a set-like object containing the key
1724
+ strings of the annotations that are to be printed. links specifies the
1725
+ maximum link recursion depth."""
1726
+ s = [' '*indent]
1727
+ s.append('GateInstruction(')
1728
+ if annotations is None:
1729
+ annotations = []
1730
+ for key in annotations:
1731
+ if key in self:
1732
+ s.append(' # {}: {}'.format(key, self[key]))
1733
+ s.append('\n')
1734
+ indent += 1
1735
+ s.append(' '*indent)
1736
+ s.append('instruction_ref: ')
1737
+ s.append(str(self.instruction_ref) + '\n')
1738
+ s.append(' '*indent)
1739
+ s.append('gate: ')
1740
+ if self.gate is None:
1741
+ s.append('!MISSING\n')
1742
+ else:
1743
+ s.append('<\n')
1744
+ s.append(self.gate.dump(indent + 1, annotations, links) + '\n')
1745
+ s.append(' '*indent + '>\n')
1746
+ s.append(' '*indent)
1747
+ s.append('operands: ')
1748
+ if not self.operands:
1749
+ s.append('-\n')
1750
+ else:
1751
+ s.append('[\n')
1752
+ for child in self.operands:
1753
+ s.append(child.dump(indent + 1, annotations, links) + '\n')
1754
+ s.append(' '*indent + ']\n')
1755
+ s.append(' '*indent)
1756
+ s.append('annotations: ')
1757
+ if not self.annotations:
1758
+ s.append('-\n')
1759
+ else:
1760
+ s.append('[\n')
1761
+ for child in self.annotations:
1762
+ s.append(child.dump(indent + 1, annotations, links) + '\n')
1763
+ s.append(' '*indent + ']\n')
1764
+ indent -= 1
1765
+ s.append(' '*indent)
1766
+ s.append(')')
1767
+ return ''.join(s)
1768
+
1769
+ __str__ = dump
1770
+ __repr__ = dump
1771
+
1772
+ def find_reachable(self, id_map=None):
1773
+ """Returns a dictionary mapping Python id() values to stable sequence
1774
+ numbers for all nodes in the tree rooted at this node. If id_map is
1775
+ specified, found nodes are appended to it."""
1776
+ if id_map is None:
1777
+ id_map = {}
1778
+ if id(self) in id_map:
1779
+ raise NotWellFormed('node {!r} with id {} occurs more than once'.format(self, id(self)))
1780
+ id_map[id(self)] = len(id_map)
1781
+ if self._attr_gate is not None:
1782
+ self._attr_gate.find_reachable(id_map)
1783
+ for el in self._attr_operands:
1784
+ el.find_reachable(id_map)
1785
+ for el in self._attr_annotations:
1786
+ el.find_reachable(id_map)
1787
+ return id_map
1788
+
1789
+ def check_complete(self, id_map=None):
1790
+ """Raises NotWellFormed if the tree rooted at this node is not
1791
+ well-formed. If id_map is specified, this tree is only a subtree in the
1792
+ context of a larger tree, and id_map must be a dict mapping from Python
1793
+ id() codes to tree indices for all reachable nodes."""
1794
+ if id_map is None:
1795
+ id_map = self.find_reachable()
1796
+ if self._attr_gate is None:
1797
+ raise NotWellFormed('gate is required but not set')
1798
+ if self._attr_gate is not None:
1799
+ self._attr_gate.check_complete(id_map)
1800
+ for child in self._attr_operands:
1801
+ child.check_complete(id_map)
1802
+ for child in self._attr_annotations:
1803
+ child.check_complete(id_map)
1804
+
1805
+ def copy(self):
1806
+ """Returns a shallow copy of this node."""
1807
+ return GateInstruction(
1808
+ instruction_ref=self._attr_instruction_ref,
1809
+ gate=self._attr_gate,
1810
+ operands=self._attr_operands.copy(),
1811
+ annotations=self._attr_annotations.copy()
1812
+ )
1813
+
1814
+ def clone(self):
1815
+ """Returns a deep copy of this node. This mimics the C++ interface,
1816
+ deficiencies with links included; that is, links always point to the
1817
+ original tree. If you're not cloning a subtree in a context where this
1818
+ is the desired behavior, you may want to use the copy.deepcopy() from
1819
+ the stdlib instead, which should copy links correctly."""
1820
+ return GateInstruction(
1821
+ instruction_ref=_cloned(self._attr_instruction_ref),
1822
+ gate=_cloned(self._attr_gate),
1823
+ operands=_cloned(self._attr_operands),
1824
+ annotations=_cloned(self._attr_annotations)
1825
+ )
1826
+
1827
+ @staticmethod
1828
+ def _deserialize(cbor, seq_to_ob, links):
1829
+ """Attempts to deserialize the given cbor object (in Python primitive
1830
+ representation) into a node of this type. All (sub)nodes are added to
1831
+ the seq_to_ob dict, indexed by their cbor sequence number. All links are
1832
+ registered in the links list by means of a two-tuple of the setter
1833
+ function for the link field and the sequence number of the target node.
1834
+ """
1835
+ if not isinstance(cbor, dict):
1836
+ raise TypeError('node description object must be a dict')
1837
+ typ = cbor.get('@t', None)
1838
+ if typ is None:
1839
+ raise ValueError('type (@t) field is missing from node serialization')
1840
+ if typ != 'GateInstruction':
1841
+ raise ValueError('found node serialization for ' + typ + ', but expected GateInstruction')
1842
+
1843
+ # Deserialize the instruction_ref field.
1844
+ field = cbor.get('instruction_ref', None)
1845
+ if not isinstance(field, dict):
1846
+ raise ValueError('missing or invalid serialization of field instruction_ref')
1847
+ if hasattr(cqasm.v3x.instruction.InstructionRef, 'deserialize_cbor'):
1848
+ f_instruction_ref = cqasm.v3x.instruction.InstructionRef.deserialize_cbor(field)
1849
+ else:
1850
+ f_instruction_ref = cqasm.v3x.primitives.deserialize(cqasm.v3x.instruction.InstructionRef, field)
1851
+
1852
+ # Deserialize the gate field.
1853
+ field = cbor.get('gate', None)
1854
+ if not isinstance(field, dict):
1855
+ raise ValueError('missing or invalid serialization of field gate')
1856
+ if field.get('@T') != '1':
1857
+ raise ValueError('unexpected edge type for field gate')
1858
+ if field.get('@t', None) is None:
1859
+ f_gate = None
1860
+ else:
1861
+ f_gate = Gate._deserialize(field, seq_to_ob, links)
1862
+
1863
+ # Deserialize the operands field.
1864
+ field = cbor.get('operands', None)
1865
+ if not isinstance(field, dict):
1866
+ raise ValueError('missing or invalid serialization of field operands')
1867
+ if field.get('@T') != '*':
1868
+ raise ValueError('unexpected edge type for field operands')
1869
+ data = field.get('@d', None)
1870
+ if not isinstance(data, list):
1871
+ raise ValueError('missing serialization of Any/Many contents')
1872
+ f_operands = cqasm.v3x.values.MultiValueBase()
1873
+ for element in data:
1874
+ if element.get('@T') != '1':
1875
+ raise ValueError('unexpected edge type for Any/Many element')
1876
+ f_operands.append(cqasm.v3x.values.ValueBase._deserialize(element, seq_to_ob, links))
1877
+
1878
+ # Deserialize the annotations field.
1879
+ field = cbor.get('annotations', None)
1880
+ if not isinstance(field, dict):
1881
+ raise ValueError('missing or invalid serialization of field annotations')
1882
+ if field.get('@T') != '*':
1883
+ raise ValueError('unexpected edge type for field annotations')
1884
+ data = field.get('@d', None)
1885
+ if not isinstance(data, list):
1886
+ raise ValueError('missing serialization of Any/Many contents')
1887
+ f_annotations = MultiAnnotationData()
1888
+ for element in data:
1889
+ if element.get('@T') != '1':
1890
+ raise ValueError('unexpected edge type for Any/Many element')
1891
+ f_annotations.append(AnnotationData._deserialize(element, seq_to_ob, links))
1892
+
1893
+ # Construct the GateInstruction node.
1894
+ node = GateInstruction(f_instruction_ref, f_gate, f_operands, f_annotations)
1895
+
1896
+ # Deserialize annotations.
1897
+ for key, val in cbor.items():
1898
+ if not (key.startswith('{') and key.endswith('}')):
1899
+ continue
1900
+ key = key[1:-1]
1901
+ node[key] = cqasm.v3x.primitives.deserialize(key, val)
1902
+
1903
+ # Register node in sequence number lookup.
1904
+ seq = cbor.get('@i', None)
1905
+ if not isinstance(seq, int):
1906
+ raise ValueError('sequence number field (@i) is not an integer or missing from node serialization')
1907
+ if seq in seq_to_ob:
1908
+ raise ValueError('duplicate sequence number %d' % seq)
1909
+ seq_to_ob[seq] = node
1910
+
1911
+ return node
1190
1912
 
1191
1913
  def _serialize(self, id_map):
1192
1914
  """Serializes this node to the Python primitive representation of its
1193
1915
  CBOR serialization. The tree that the node belongs to must be
1194
1916
  well-formed. id_map must match Python id() calls for all nodes to unique
1195
1917
  integers, to use for the sequence number representation of links."""
1196
- cbor = {'@i': id_map[id(self)], '@t': 'Statement'}
1918
+ cbor = {'@i': id_map[id(self)], '@t': 'GateInstruction'}
1919
+
1920
+ # Serialize the instruction_ref field.
1921
+ if hasattr(self._attr_instruction_ref, 'serialize_cbor'):
1922
+ cbor['instruction_ref'] = self._attr_instruction_ref.serialize_cbor()
1923
+ else:
1924
+ cbor['instruction_ref'] = cqasm.v3x.primitives.serialize(cqasm.v3x.instruction.InstructionRef, self._attr_instruction_ref)
1925
+
1926
+ # Serialize the gate field.
1927
+ field = {'@T': '1'}
1928
+ if self._attr_gate is None:
1929
+ field['@t'] = None
1930
+ else:
1931
+ field.update(self._attr_gate._serialize(id_map))
1932
+ cbor['gate'] = field
1933
+
1934
+ # Serialize the operands field.
1935
+ field = {'@T': '*'}
1936
+ lst = []
1937
+ for el in self._attr_operands:
1938
+ el = el._serialize(id_map)
1939
+ el['@T'] = '1'
1940
+ lst.append(el)
1941
+ field['@d'] = lst
1942
+ cbor['operands'] = field
1197
1943
 
1198
1944
  # Serialize the annotations field.
1199
1945
  field = {'@T': '*'}
@@ -1212,16 +1958,16 @@ class Statement(Annotated):
1212
1958
  return cbor
1213
1959
 
1214
1960
 
1215
- class MultiStatement(_Multiple):
1216
- """Wrapper for an edge with multiple Statement objects."""
1961
+ class MultiGateInstruction(_Multiple):
1962
+ """Wrapper for an edge with multiple GateInstruction objects."""
1217
1963
 
1218
- _T = Statement
1964
+ _T = GateInstruction
1219
1965
 
1220
1966
 
1221
- _typemap['Statement'] = Statement
1967
+ _typemap['GateInstruction'] = GateInstruction
1222
1968
 
1223
- class Instruction(Statement):
1224
- """Regular instruction (a gate, or a measure instruction)."""
1969
+ class NonGateInstruction(Instruction):
1970
+ """A measure instruction or a reset instruction"""
1225
1971
 
1226
1972
  __slots__ = [
1227
1973
  '_attr_instruction_ref',
@@ -1303,7 +2049,7 @@ class Instruction(Statement):
1303
2049
 
1304
2050
  def __eq__(self, other):
1305
2051
  """Equality operator. Ignores annotations!"""
1306
- if not isinstance(other, Instruction):
2052
+ if not isinstance(other, NonGateInstruction):
1307
2053
  return False
1308
2054
  if self.instruction_ref != other.instruction_ref:
1309
2055
  return False
@@ -1322,7 +2068,7 @@ class Instruction(Statement):
1322
2068
  strings of the annotations that are to be printed. links specifies the
1323
2069
  maximum link recursion depth."""
1324
2070
  s = [' '*indent]
1325
- s.append('Instruction(')
2071
+ s.append('NonGateInstruction(')
1326
2072
  if annotations is None:
1327
2073
  annotations = []
1328
2074
  for key in annotations:
@@ -1391,7 +2137,7 @@ class Instruction(Statement):
1391
2137
 
1392
2138
  def copy(self):
1393
2139
  """Returns a shallow copy of this node."""
1394
- return Instruction(
2140
+ return NonGateInstruction(
1395
2141
  instruction_ref=self._attr_instruction_ref,
1396
2142
  name=self._attr_name,
1397
2143
  operands=self._attr_operands.copy(),
@@ -1404,7 +2150,7 @@ class Instruction(Statement):
1404
2150
  original tree. If you're not cloning a subtree in a context where this
1405
2151
  is the desired behavior, you may want to use the copy.deepcopy() from
1406
2152
  the stdlib instead, which should copy links correctly."""
1407
- return Instruction(
2153
+ return NonGateInstruction(
1408
2154
  instruction_ref=_cloned(self._attr_instruction_ref),
1409
2155
  name=_cloned(self._attr_name),
1410
2156
  operands=_cloned(self._attr_operands),
@@ -1424,8 +2170,8 @@ class Instruction(Statement):
1424
2170
  typ = cbor.get('@t', None)
1425
2171
  if typ is None:
1426
2172
  raise ValueError('type (@t) field is missing from node serialization')
1427
- if typ != 'Instruction':
1428
- raise ValueError('found node serialization for ' + typ + ', but expected Instruction')
2173
+ if typ != 'NonGateInstruction':
2174
+ raise ValueError('found node serialization for ' + typ + ', but expected NonGateInstruction')
1429
2175
 
1430
2176
  # Deserialize the instruction_ref field.
1431
2177
  field = cbor.get('instruction_ref', None)
@@ -1475,8 +2221,8 @@ class Instruction(Statement):
1475
2221
  raise ValueError('unexpected edge type for Any/Many element')
1476
2222
  f_annotations.append(AnnotationData._deserialize(element, seq_to_ob, links))
1477
2223
 
1478
- # Construct the Instruction node.
1479
- node = Instruction(f_instruction_ref, f_name, f_operands, f_annotations)
2224
+ # Construct the NonGateInstruction node.
2225
+ node = NonGateInstruction(f_instruction_ref, f_name, f_operands, f_annotations)
1480
2226
 
1481
2227
  # Deserialize annotations.
1482
2228
  for key, val in cbor.items():
@@ -1500,7 +2246,7 @@ class Instruction(Statement):
1500
2246
  CBOR serialization. The tree that the node belongs to must be
1501
2247
  well-formed. id_map must match Python id() calls for all nodes to unique
1502
2248
  integers, to use for the sequence number representation of links."""
1503
- cbor = {'@i': id_map[id(self)], '@t': 'Instruction'}
2249
+ cbor = {'@i': id_map[id(self)], '@t': 'NonGateInstruction'}
1504
2250
 
1505
2251
  # Serialize the instruction_ref field.
1506
2252
  if hasattr(self._attr_instruction_ref, 'serialize_cbor'):
@@ -1541,13 +2287,13 @@ class Instruction(Statement):
1541
2287
  return cbor
1542
2288
 
1543
2289
 
1544
- class MultiInstruction(_Multiple):
1545
- """Wrapper for an edge with multiple Instruction objects."""
2290
+ class MultiNonGateInstruction(_Multiple):
2291
+ """Wrapper for an edge with multiple NonGateInstruction objects."""
1546
2292
 
1547
- _T = Instruction
2293
+ _T = NonGateInstruction
1548
2294
 
1549
2295
 
1550
- _typemap['Instruction'] = Instruction
2296
+ _typemap['NonGateInstruction'] = NonGateInstruction
1551
2297
 
1552
2298
  class Program(Node):
1553
2299
  __slots__ = [