libqasm 0.6.7__cp312-cp312-macosx_11_0_arm64.whl → 0.6.8__cp312-cp312-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/__init__.py +2 -2
- cqasm/v3x/ast.py +665 -675
- cqasm/v3x/semantic.py +771 -25
- libqasm/_libqasm.cpython-312-darwin.so +0 -0
- libqasm/libqasm.py +2 -2
- {libqasm-0.6.7.dist-info → libqasm-0.6.8.dist-info}/METADATA +6 -5
- libqasm-0.6.8.dist-info/RECORD +16 -0
- {libqasm-0.6.7.dist-info → libqasm-0.6.8.dist-info}/WHEEL +1 -1
- libqasm-0.6.7.dist-info/RECORD +0 -16
- {libqasm-0.6.7.dist-info → libqasm-0.6.8.dist-info}/LICENSE.md +0 -0
- {libqasm-0.6.7.dist-info → libqasm-0.6.8.dist-info}/top_level.txt +0 -0
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 == '
|
644
|
-
return
|
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 == '
|
1188
|
-
return
|
1189
|
-
|
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': '
|
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
|
1216
|
-
"""Wrapper for an edge with multiple
|
1961
|
+
class MultiGateInstruction(_Multiple):
|
1962
|
+
"""Wrapper for an edge with multiple GateInstruction objects."""
|
1217
1963
|
|
1218
|
-
_T =
|
1964
|
+
_T = GateInstruction
|
1219
1965
|
|
1220
1966
|
|
1221
|
-
_typemap['
|
1967
|
+
_typemap['GateInstruction'] = GateInstruction
|
1222
1968
|
|
1223
|
-
class Instruction
|
1224
|
-
"""
|
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,
|
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('
|
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
|
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
|
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 != '
|
1428
|
-
raise ValueError('found node serialization for ' + typ + ', but expected
|
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
|
1479
|
-
node =
|
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': '
|
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
|
1545
|
-
"""Wrapper for an edge with multiple
|
2290
|
+
class MultiNonGateInstruction(_Multiple):
|
2291
|
+
"""Wrapper for an edge with multiple NonGateInstruction objects."""
|
1546
2292
|
|
1547
|
-
_T =
|
2293
|
+
_T = NonGateInstruction
|
1548
2294
|
|
1549
2295
|
|
1550
|
-
_typemap['
|
2296
|
+
_typemap['NonGateInstruction'] = NonGateInstruction
|
1551
2297
|
|
1552
2298
|
class Program(Node):
|
1553
2299
|
__slots__ = [
|