libqasm 0.5.2__cp310-cp310-win_amd64.whl → 0.6.1__cp310-cp310-win_amd64.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/v1x/values.py DELETED
@@ -1,3200 +0,0 @@
1
- import functools
2
- import struct
3
- import cqasm.v1x.primitives
4
- import cqasm.v1x.types
5
- import cqasm.v1x.semantic
6
-
7
-
8
- _typemap = {}
9
-
10
-
11
- def _cbor_read_intlike(cbor, offset, info):
12
- """Parses the additional information and reads any additional bytes it
13
- specifies the existence of, and returns the encoded integer. offset
14
- should point to the byte immediately following the initial byte. Returns
15
- the encoded integer and the offset immediately following the object."""
16
-
17
- # Info less than 24 is a shorthand for the integer itself.
18
- if info < 24:
19
- return info, offset
20
-
21
- # 24 is 8-bit following the info byte.
22
- if info == 24:
23
- return cbor[offset], offset + 1
24
-
25
- # 25 is 16-bit following the info byte.
26
- if info == 25:
27
- val, = struct.unpack('>H', cbor[offset:offset+2])
28
- return val, offset + 2
29
-
30
- # 26 is 32-bit following the info byte.
31
- if info == 26:
32
- val, = struct.unpack('>I', cbor[offset:offset+4])
33
- return val, offset + 4
34
-
35
- # 27 is 64-bit following the info byte.
36
- if info == 27:
37
- val, = struct.unpack('>Q', cbor[offset:offset+8])
38
- return val, offset + 8
39
-
40
- # Info greater than or equal to 28 is illegal. Note that 31 is used for
41
- # indefinite lengths, so this must be checked prior to calling this
42
- # method.
43
- raise ValueError("invalid CBOR: illegal additional info for integer or object length")
44
-
45
-
46
- def _sub_cbor_to_py(cbor, offset):
47
- """Converts the CBOR object starting at cbor[offset] to its Python
48
- representation for as far as tree-gen supports CBOR. Returns this Python
49
- representation and the offset immediately following the CBOR representation
50
- thereof. Supported types:
51
-
52
- - 0: unsigned integer (int)
53
- - 1: negative integer (int)
54
- - 2: byte string (bytes)
55
- - 3: UTF-8 string (str)
56
- - 4: array (list)
57
- - 5: map (dict)
58
- - 6: semantic tag (ignored)
59
- - 7.20: false (bool)
60
- - 7.21: true (bool)
61
- - 7.22: null (NoneType)
62
- - 7.27: double-precision float (float)
63
-
64
- Both definite-length and indefinite-length notation is supported for sized
65
- objects (strings, arrays, maps). A ValueError is thrown if the CBOR is
66
- invalid or contains unsupported structures."""
67
-
68
- # Read the initial byte.
69
- initial = cbor[offset]
70
- typ = initial >> 5
71
- info = initial & 0x1F
72
- offset += 1
73
-
74
- # Handle unsigned integer (0) and negative integer (1).
75
- if typ <= 1:
76
- value, offset = _cbor_read_intlike(cbor, offset, info)
77
- if typ == 1:
78
- value = -1 - value
79
- return value, offset
80
-
81
- # Handle byte string (2) and UTF-8 string (3).
82
- if typ <= 3:
83
-
84
- # Gather components of the string in here.
85
- if info == 31:
86
-
87
- # Handle indefinite length strings. These consist of a
88
- # break-terminated (0xFF) list of definite-length strings of the
89
- # same type.
90
- value = []
91
- while True:
92
- sub_initial = cbor[offset]; offset += 1
93
- if sub_initial == 0xFF:
94
- break
95
- sub_typ = sub_initial >> 5
96
- sub_info = sub_initial & 0x1F
97
- if sub_typ != typ:
98
- raise ValueError('invalid CBOR: illegal indefinite-length string component')
99
-
100
- # Seek past definite-length string component. The size in
101
- # bytes is encoded as an integer.
102
- size, offset = _cbor_read_intlike(cbor, offset, sub_info)
103
- value.append(cbor[offset:offset + size])
104
- offset += size
105
- value = b''.join(value)
106
-
107
- else:
108
-
109
- # Handle definite-length strings. The size in bytes is encoded as
110
- # an integer.
111
- size, offset = _cbor_read_intlike(cbor, offset, info)
112
- value = cbor[offset:offset + size]
113
- offset += size
114
-
115
- if typ == 3:
116
- value = value.decode('UTF-8')
117
- return value, offset
118
-
119
- # Handle array (4) and map (5).
120
- if typ <= 5:
121
-
122
- # Create result container.
123
- container = [] if typ == 4 else {}
124
-
125
- # Handle indefinite length arrays and maps.
126
- if info == 31:
127
-
128
- # Read objects/object pairs until we encounter a break.
129
- while cbor[offset] != 0xFF:
130
- if typ == 4:
131
- value, offset = _sub_cbor_to_py(cbor, offset)
132
- container.append(value)
133
- else:
134
- key, offset = _sub_cbor_to_py(cbor, offset)
135
- if not isinstance(key, str):
136
- raise ValueError('invalid CBOR: map key is not a UTF-8 string')
137
- value, offset = _sub_cbor_to_py(cbor, offset)
138
- container[key] = value
139
-
140
- # Seek past the break.
141
- offset += 1
142
-
143
- else:
144
-
145
- # Handle definite-length arrays and maps. The amount of
146
- # objects/object pairs is encoded as an integer.
147
- size, offset = _cbor_read_intlike(cbor, offset, info)
148
- for _ in range(size):
149
- if typ == 4:
150
- value, offset = _sub_cbor_to_py(cbor, offset)
151
- container.append(value)
152
- else:
153
- key, offset = _sub_cbor_to_py(cbor, offset)
154
- if not isinstance(key, str):
155
- raise ValueError('invalid CBOR: map key is not a UTF-8 string')
156
- value, offset = _sub_cbor_to_py(cbor, offset)
157
- container[key] = value
158
-
159
- return container, offset
160
-
161
- # Handle semantic tags.
162
- if typ == 6:
163
-
164
- # We don't use semantic tags for anything, but ignoring them is
165
- # legal and reading past them is easy enough.
166
- _, offset = _cbor_read_intlike(cbor, offset, info)
167
- return _sub_cbor_to_py(cbor, offset)
168
-
169
- # Handle major type 7. Here, the type is defined by the additional info.
170
- # Additional info 24 is reserved for having the type specified by the
171
- # next byte, but all such values are unassigned.
172
- if info == 20:
173
- # false
174
- return False, offset
175
-
176
- if info == 21:
177
- # true
178
- return True, offset
179
-
180
- if info == 22:
181
- # null
182
- return None, offset
183
-
184
- if info == 23:
185
- # Undefined value.
186
- raise ValueError('invalid CBOR: undefined value is not supported')
187
-
188
- if info == 25:
189
- # Half-precision float.
190
- raise ValueError('invalid CBOR: half-precision float is not supported')
191
-
192
- if info == 26:
193
- # Single-precision float.
194
- raise ValueError('invalid CBOR: single-precision float is not supported')
195
-
196
- if info == 27:
197
- # Double-precision float.
198
- value, = struct.unpack('>d', cbor[offset:offset+8])
199
- return value, offset + 8
200
-
201
- if info == 31:
202
- # Break value used for indefinite-length objects.
203
- raise ValueError('invalid CBOR: unexpected break')
204
-
205
- raise ValueError('invalid CBOR: unknown type code')
206
-
207
-
208
- def _cbor_to_py(cbor):
209
- """Converts the given CBOR object (bytes) to its Python representation for
210
- as far as tree-gen supports CBOR. Supported types:
211
-
212
- - 0: unsigned integer (int)
213
- - 1: negative integer (int)
214
- - 2: byte string (bytes)
215
- - 3: UTF-8 string (str)
216
- - 4: array (list)
217
- - 5: map (dict)
218
- - 6: semantic tag (ignored)
219
- - 7.20: false (bool)
220
- - 7.21: true (bool)
221
- - 7.22: null (NoneType)
222
- - 7.27: double-precision float (float)
223
-
224
- Both definite-length and indefinite-length notation is supported for sized
225
- objects (strings, arrays, maps). A ValueError is thrown if the CBOR is
226
- invalid or contains unsupported structures."""
227
-
228
- value, length = _sub_cbor_to_py(cbor, 0)
229
- if length < len(cbor):
230
- raise ValueError('invalid CBOR: garbage at the end')
231
- return value
232
-
233
-
234
- class _Cbor(bytes):
235
- """Marker class indicating that this bytes object represents CBOR."""
236
- pass
237
-
238
-
239
- def _cbor_write_intlike(value, major=0):
240
- """Converts the given integer to its minimal representation in CBOR. The
241
- major code can be overridden to write lengths for strings, arrays, and
242
- maps."""
243
-
244
- # Negative integers use major code 1.
245
- if value < 0:
246
- major = 1
247
- value = -1 - value
248
- initial = major << 5
249
-
250
- # Use the minimal representation.
251
- if value < 24:
252
- return struct.pack('>B', initial | value)
253
- if value < 0x100:
254
- return struct.pack('>BB', initial | 24, value)
255
- if value < 0x10000:
256
- return struct.pack('>BH', initial | 25, value)
257
- if value < 0x100000000:
258
- return struct.pack('>BI', initial | 26, value)
259
- if value < 0x10000000000000000:
260
- return struct.pack('>BQ', initial | 27, value)
261
-
262
- raise ValueError('integer too large for CBOR (bigint not supported)')
263
-
264
-
265
- def _py_to_cbor(value, type_converter=None):
266
- """Inverse of _cbor_to_py(). type_converter optionally specifies a function
267
- that takes a value and either converts it to a primitive for serialization,
268
- converts it to a _Cbor object manually, or raises a TypeError if no
269
- conversion is known. If no type_converter is specified, a TypeError is
270
- raised in all cases the type_converter would otherwise be called. The cbor
271
- serialization is returned using a _Cbor object, which is just a marker class
272
- behaving just like bytes."""
273
- if isinstance(value, _Cbor):
274
- return value
275
-
276
- if isinstance(value, int):
277
- return _Cbor(_cbor_write_intlike(value))
278
-
279
- if isinstance(value, float):
280
- return _Cbor(struct.pack('>Bd', 0xFB, value))
281
-
282
- if isinstance(value, str):
283
- value = value.encode('UTF-8')
284
- return _Cbor(_cbor_write_intlike(len(value), 3) + value)
285
-
286
- if isinstance(value, bytes):
287
- return _Cbor(_cbor_write_intlike(len(value), 2) + value)
288
-
289
- if value is False:
290
- return _Cbor(b'\xF4')
291
-
292
- if value is True:
293
- return _Cbor(b'\xF5')
294
-
295
- if value is None:
296
- return _Cbor(b'\xF6')
297
-
298
- if isinstance(value, (list, tuple)):
299
- cbor = [_cbor_write_intlike(len(value), 4)]
300
- for val in value:
301
- cbor.append(_py_to_cbor(val, type_converter))
302
- return _Cbor(b''.join(cbor))
303
-
304
- if isinstance(value, dict):
305
- cbor = [_cbor_write_intlike(len(value), 5)]
306
- for key, val in sorted(value.items()):
307
- if not isinstance(key, str):
308
- raise TypeError('dict keys must be strings')
309
- cbor.append(_py_to_cbor(key, type_converter))
310
- cbor.append(_py_to_cbor(val, type_converter))
311
- return _Cbor(b''.join(cbor))
312
-
313
- if type_converter is not None:
314
- return _py_to_cbor(type_converter(value))
315
-
316
- raise TypeError('unsupported type for conversion to cbor: %r' % (value,))
317
-
318
-
319
- class NotWellFormed(ValueError):
320
- """Exception class for well-formedness checks."""
321
-
322
- def __init__(self, msg):
323
- super().__init__('not well-formed: ' + str(msg))
324
-
325
-
326
- class Node(object):
327
- """Base class for nodes."""
328
-
329
- __slots__ = ['_annot']
330
-
331
- def __init__(self):
332
- super().__init__()
333
- self._annot = {}
334
-
335
- def __getitem__(self, key):
336
- """Returns the annotation object with the specified key, or raises
337
- KeyError if not found."""
338
- if not isinstance(key, str):
339
- raise TypeError('indexing a node with something other than an '
340
- 'annotation key string')
341
- return self._annot[key]
342
-
343
- def __setitem__(self, key, val):
344
- """Assigns the annotation object with the specified key."""
345
- if not isinstance(key, str):
346
- raise TypeError('indexing a node with something other than an '
347
- 'annotation key string')
348
- self._annot[key] = val
349
-
350
- def __delitem__(self, key):
351
- """Deletes the annotation object with the specified key."""
352
- if not isinstance(key, str):
353
- raise TypeError('indexing a node with something other than an '
354
- 'annotation key string')
355
- del self._annot[key]
356
-
357
- def __contains__(self, key):
358
- """Returns whether an annotation exists for the specified key."""
359
- return key in self._annot
360
-
361
- @staticmethod
362
- def find_reachable(self, id_map=None):
363
- """Returns a dictionary mapping Python id() values to stable sequence
364
- numbers for all nodes in the tree rooted at this node. If id_map is
365
- specified, found nodes are appended to it. Note that this is overridden
366
- by the actual node class implementations; this base function does very
367
- little."""
368
- if id_map is None:
369
- id_map = {}
370
- return id_map
371
-
372
- def check_complete(self, id_map=None):
373
- """Raises NotWellFormed if the tree rooted at this node is not
374
- well-formed. If id_map is specified, this tree is only a subtree in the
375
- context of a larger tree, and id_map must be a dict mapping from Python
376
- id() codes to tree indices for all reachable nodes. Note that this is
377
- overridden by the actual node class implementations; this base function
378
- always raises an exception."""
379
- raise NotWellFormed('found node of abstract type ' + type(self).__name__)
380
-
381
- def check_well_formed(self):
382
- """Checks whether the tree starting at this node is well-formed. That
383
- is:
384
-
385
- - all One, Link, and Many edges have (at least) one entry;
386
- - all the One entries internally stored by Any/Many have an entry;
387
- - all Link and filled OptLink nodes link to a node that's reachable
388
- from this node;
389
- - the nodes referred to be One/Maybe only appear once in the tree
390
- (except through links).
391
-
392
- If it isn't well-formed, a NotWellFormed is thrown."""
393
- self.check_complete()
394
-
395
- def is_well_formed(self):
396
- """Returns whether the tree starting at this node is well-formed. That
397
- is:
398
-
399
- - all One, Link, and Many edges have (at least) one entry;
400
- - all the One entries internally stored by Any/Many have an entry;
401
- - all Link and filled OptLink nodes link to a node that's reachable
402
- from this node;
403
- - the nodes referred to be One/Maybe only appear once in the tree
404
- (except through links)."""
405
- try:
406
- self.check_well_formed()
407
- return True
408
- except NotWellFormed:
409
- return False
410
-
411
- def copy(self):
412
- """Returns a shallow copy of this node. Note that this is overridden by
413
- the actual node class implementations; this base function always raises
414
- an exception."""
415
- raise TypeError('can\'t copy node of abstract type ' + type(self).__name__)
416
-
417
- def clone(self):
418
- """Returns a deep copy of this node. Note that this is overridden by
419
- the actual node class implementations; this base function always raises
420
- an exception."""
421
- raise TypeError('can\'t clone node of abstract type ' + type(self).__name__)
422
-
423
- @classmethod
424
- def deserialize(cls, cbor):
425
- """Attempts to deserialize the given cbor object (either as bytes or as
426
- its Python primitive representation) into a node of this type."""
427
- if isinstance(cbor, bytes):
428
- cbor = _cbor_to_py(cbor)
429
- seq_to_ob = {}
430
- links = []
431
- root = cls._deserialize(cbor, seq_to_ob, links)
432
- for link_setter, seq in links:
433
- ob = seq_to_ob.get(seq, None)
434
- if ob is None:
435
- raise ValueError('found link to nonexistent object')
436
- link_setter(ob)
437
- return root
438
-
439
- def serialize(self):
440
- """Serializes this node into its cbor representation in the form of a
441
- bytes object."""
442
- id_map = self.find_reachable()
443
- self.check_complete(id_map)
444
- return _py_to_cbor(self._serialize(id_map))
445
-
446
- @staticmethod
447
- def _deserialize(cbor, seq_to_ob, links):
448
- if not isinstance(cbor, dict):
449
- raise TypeError('node description object must be a dict')
450
- typ = cbor.get('@t', None)
451
- if typ is None:
452
- raise ValueError('type (@t) field is missing from node serialization')
453
- node_type = _typemap.get(cbor.get('@t'), None)
454
- if node_type is None:
455
- raise ValueError('unknown node type (@t): ' + str(cbor.get('@t')))
456
- return node_type._deserialize(cbor, seq_to_ob, links)
457
-
458
-
459
- @functools.total_ordering
460
- class _Multiple(object):
461
- """Base class for the Any* and Many* edge helper classes. Inheriting
462
- classes must set the class constant _T to the node type they are made
463
- for."""
464
-
465
- __slots__ = ['_l']
466
-
467
- def __init__(self, *args, **kwargs):
468
- super().__init__()
469
- self._l = list(*args, **kwargs)
470
- for idx, val in enumerate(self._l):
471
- if not isinstance(val, self._T):
472
- raise TypeError(
473
- 'object {!r} at index {:d} is not an instance of {!r}'
474
- .format(val, idx, self._T))
475
-
476
- def __repr__(self):
477
- return '{}({!r})'.format(type(self).__name__, self._l)
478
-
479
- def clone(self):
480
- return self.__class__(map(lambda node: node.clone(), self._l))
481
-
482
- def __len__(self):
483
- return len(self._l)
484
-
485
- def __getitem__(self, idx):
486
- return self._l[idx]
487
-
488
- def __setitem__(self, idx, val):
489
- if not isinstance(val, self._T):
490
- raise TypeError(
491
- 'object {!r} is not an instance of {!r}'
492
- .format(val, idx, self._T))
493
- self._l[idx] = val
494
-
495
- def __delitem__(self, idx):
496
- del self._l[idx]
497
-
498
- def __iter__(self):
499
- return iter(self._l)
500
-
501
- def __reversed__(self):
502
- return reversed(self._l)
503
-
504
- def __contains__(self, val):
505
- return val in self._l
506
-
507
- def append(self, val):
508
- if not isinstance(val, self._T):
509
- raise TypeError(
510
- 'object {!r} is not an instance of {!r}'
511
- .format(val, self._T))
512
- self._l.append(val)
513
-
514
- def extend(self, iterable):
515
- for val in iterable:
516
- self.append(val)
517
-
518
- def insert(self, idx, val):
519
- if not isinstance(val, self._T):
520
- raise TypeError(
521
- 'object {!r} is not an instance of {!r}'
522
- .format(val, self._T))
523
- self._l.insert(idx, val)
524
-
525
- def remote(self, val):
526
- self._l.remove(val)
527
-
528
- def pop(self, idx=-1):
529
- return self._l.pop(idx)
530
-
531
- def clear(self):
532
- self._l.clear()
533
-
534
- def idx(self, val, start=0, end=-1):
535
- return self._l.idx(val, start, end)
536
-
537
- def count(self, val):
538
- return self._l.count(val)
539
-
540
- def sort(self, key=None, reverse=False):
541
- self._l.sort(key=key, reverse=reverse)
542
-
543
- def reverse(self):
544
- self._l.reverse()
545
-
546
- def copy(self):
547
- return self.__class__(self)
548
-
549
- def __eq__(self, other):
550
- if not isinstance(other, _Multiple):
551
- return False
552
- return self._l == other._l
553
-
554
- def __lt__(self, other):
555
- return self._l < other._l
556
-
557
- def __iadd__(self, other):
558
- self.extend(other)
559
-
560
- def __add__(self, other):
561
- copy = self.copy()
562
- copy += other
563
- return copy
564
-
565
- def __imul__(self, other):
566
- self._l *= other
567
-
568
- def __mul__(self, other):
569
- copy = self.copy()
570
- copy *= other
571
- return copy
572
-
573
- def __rmul__(self, other):
574
- copy = self.copy()
575
- copy *= other
576
- return copy
577
-
578
-
579
- class MultiNode(_Multiple):
580
- """Wrapper for an edge with multiple Node objects."""
581
-
582
- _T = Node
583
-
584
-
585
- def _cloned(obj):
586
- """Attempts to clone the given object by calling its clone() method, if it
587
- has one."""
588
- if hasattr(obj, 'clone'):
589
- return obj.clone()
590
- return obj
591
-
592
-
593
- class Reference(Node):
594
- """Represents a reference to some storage location."""
595
-
596
- __slots__ = []
597
-
598
- def __init__(self):
599
- super().__init__()
600
-
601
- @staticmethod
602
- def _deserialize(cbor, seq_to_ob, links):
603
- """Attempts to deserialize the given cbor object (in Python primitive
604
- representation) into a node of this type. All (sub)nodes are added to
605
- the seq_to_ob dict, indexed by their cbor sequence number. All links are
606
- registered in the links list by means of a two-tuple of the setter
607
- function for the link field and the sequence number of the target node.
608
- """
609
- if not isinstance(cbor, dict):
610
- raise TypeError('node description object must be a dict')
611
- typ = cbor.get('@t', None)
612
- if typ is None:
613
- raise ValueError('type (@t) field is missing from node serialization')
614
- if typ == 'QubitRefs':
615
- return QubitRefs._deserialize(cbor, seq_to_ob, links)
616
- if typ == 'BitRefs':
617
- return BitRefs._deserialize(cbor, seq_to_ob, links)
618
- if typ == 'VariableRef':
619
- return VariableRef._deserialize(cbor, seq_to_ob, links)
620
- raise ValueError('unknown or unexpected type (@t) found in node serialization')
621
-
622
- def _serialize(self, id_map):
623
- """Serializes this node to the Python primitive representation of its
624
- CBOR serialization. The tree that the node belongs to must be
625
- well-formed. id_map must match Python id() calls for all nodes to unique
626
- integers, to use for the sequence number representation of links."""
627
- cbor = {'@i': id_map[id(self)], '@t': 'Reference'}
628
-
629
- # Serialize annotations.
630
- for key, val in self._annot.items():
631
- cbor['{%s}' % key] = _py_to_cbor(cqasm.v1x.primitives.serialize(key, val))
632
-
633
- return cbor
634
-
635
-
636
- class MultiReference(_Multiple):
637
- """Wrapper for an edge with multiple Reference objects."""
638
-
639
- _T = Reference
640
-
641
-
642
- _typemap['Reference'] = Reference
643
-
644
- class BitRefs(Reference):
645
- """Represents a measurement bit, or a number of measurement bits for
646
- conditional gates with multiple conditions. When there are multiple, the
647
- conditions are all and'ed together."""
648
-
649
- __slots__ = [
650
- '_attr_index',
651
- ]
652
-
653
- def __init__(
654
- self,
655
- index=None,
656
- ):
657
- super().__init__()
658
- self.index = index
659
-
660
- @property
661
- def index(self):
662
- """Set of qubit indices for which these are measurement bits, starting
663
- at 0."""
664
- return self._attr_index
665
-
666
- @index.setter
667
- def index(self, val):
668
- if val is None:
669
- del self.index
670
- return
671
- if not isinstance(val, MultiConstInt):
672
- # Try to "typecast" if this isn't an obvious mistake.
673
- if isinstance(val, Node):
674
- raise TypeError('index must be of type MultiConstInt')
675
- val = MultiConstInt(val)
676
- self._attr_index = val
677
-
678
- @index.deleter
679
- def index(self):
680
- self._attr_index = MultiConstInt()
681
-
682
- def __eq__(self, other):
683
- """Equality operator. Ignores annotations!"""
684
- if not isinstance(other, BitRefs):
685
- return False
686
- if self.index != other.index:
687
- return False
688
- return True
689
-
690
- def dump(self, indent=0, annotations=None, links=1):
691
- """Returns a debug representation of this tree as a multiline string.
692
- indent is the number of double spaces prefixed before every line.
693
- annotations, if specified, must be a set-like object containing the key
694
- strings of the annotations that are to be printed. links specifies the
695
- maximum link recursion depth."""
696
- s = [' '*indent]
697
- s.append('BitRefs(')
698
- if annotations is None:
699
- annotations = []
700
- for key in annotations:
701
- if key in self:
702
- s.append(' # {}: {}'.format(key, self[key]))
703
- s.append('\n')
704
- indent += 1
705
- s.append(' '*indent)
706
- s.append('index: ')
707
- if not self.index:
708
- s.append('!MISSING\n')
709
- else:
710
- s.append('[\n')
711
- for child in self.index:
712
- s.append(child.dump(indent + 1, annotations, links) + '\n')
713
- s.append(' '*indent + ']\n')
714
- indent -= 1
715
- s.append(' '*indent)
716
- s.append(')')
717
- return ''.join(s)
718
-
719
- __str__ = dump
720
- __repr__ = dump
721
-
722
- def find_reachable(self, id_map=None):
723
- """Returns a dictionary mapping Python id() values to stable sequence
724
- numbers for all nodes in the tree rooted at this node. If id_map is
725
- specified, found nodes are appended to it."""
726
- if id_map is None:
727
- id_map = {}
728
- if id(self) in id_map:
729
- raise NotWellFormed('node {!r} with id {} occurs more than once'.format(self, id(self)))
730
- id_map[id(self)] = len(id_map)
731
- for el in self._attr_index:
732
- el.find_reachable(id_map)
733
- return id_map
734
-
735
- def check_complete(self, id_map=None):
736
- """Raises NotWellFormed if the tree rooted at this node is not
737
- well-formed. If id_map is specified, this tree is only a subtree in the
738
- context of a larger tree, and id_map must be a dict mapping from Python
739
- id() codes to tree indices for all reachable nodes."""
740
- if id_map is None:
741
- id_map = self.find_reachable()
742
- if not self._attr_index:
743
- raise NotWellFormed('index needs at least one node but has zero')
744
- for child in self._attr_index:
745
- child.check_complete(id_map)
746
-
747
- def copy(self):
748
- """Returns a shallow copy of this node."""
749
- return BitRefs(
750
- index=self._attr_index.copy()
751
- )
752
-
753
- def clone(self):
754
- """Returns a deep copy of this node. This mimics the C++ interface,
755
- deficiencies with links included; that is, links always point to the
756
- original tree. If you're not cloning a subtree in a context where this
757
- is the desired behavior, you may want to use the copy.deepcopy() from
758
- the stdlib instead, which should copy links correctly."""
759
- return BitRefs(
760
- index=_cloned(self._attr_index)
761
- )
762
-
763
- @staticmethod
764
- def _deserialize(cbor, seq_to_ob, links):
765
- """Attempts to deserialize the given cbor object (in Python primitive
766
- representation) into a node of this type. All (sub)nodes are added to
767
- the seq_to_ob dict, indexed by their cbor sequence number. All links are
768
- registered in the links list by means of a two-tuple of the setter
769
- function for the link field and the sequence number of the target node.
770
- """
771
- if not isinstance(cbor, dict):
772
- raise TypeError('node description object must be a dict')
773
- typ = cbor.get('@t', None)
774
- if typ is None:
775
- raise ValueError('type (@t) field is missing from node serialization')
776
- if typ != 'BitRefs':
777
- raise ValueError('found node serialization for ' + typ + ', but expected BitRefs')
778
-
779
- # Deserialize the index field.
780
- field = cbor.get('index', None)
781
- if not isinstance(field, dict):
782
- raise ValueError('missing or invalid serialization of field index')
783
- if field.get('@T') != '+':
784
- raise ValueError('unexpected edge type for field index')
785
- data = field.get('@d', None)
786
- if not isinstance(data, list):
787
- raise ValueError('missing serialization of Any/Many contents')
788
- f_index = MultiConstInt()
789
- for element in data:
790
- if element.get('@T') != '1':
791
- raise ValueError('unexpected edge type for Any/Many element')
792
- f_index.append(ConstInt._deserialize(element, seq_to_ob, links))
793
-
794
- # Construct the BitRefs node.
795
- node = BitRefs(f_index)
796
-
797
- # Deserialize annotations.
798
- for key, val in cbor.items():
799
- if not (key.startswith('{') and key.endswith('}')):
800
- continue
801
- key = key[1:-1]
802
- node[key] = cqasm.v1x.primitives.deserialize(key, val)
803
-
804
- # Register node in sequence number lookup.
805
- seq = cbor.get('@i', None)
806
- if not isinstance(seq, int):
807
- raise ValueError('sequence number field (@i) is not an integer or missing from node serialization')
808
- if seq in seq_to_ob:
809
- raise ValueError('duplicate sequence number %d' % seq)
810
- seq_to_ob[seq] = node
811
-
812
- return node
813
-
814
- def _serialize(self, id_map):
815
- """Serializes this node to the Python primitive representation of its
816
- CBOR serialization. The tree that the node belongs to must be
817
- well-formed. id_map must match Python id() calls for all nodes to unique
818
- integers, to use for the sequence number representation of links."""
819
- cbor = {'@i': id_map[id(self)], '@t': 'BitRefs'}
820
-
821
- # Serialize the index field.
822
- field = {'@T': '+'}
823
- lst = []
824
- for el in self._attr_index:
825
- el = el._serialize(id_map)
826
- el['@T'] = '1'
827
- lst.append(el)
828
- field['@d'] = lst
829
- cbor['index'] = field
830
-
831
- # Serialize annotations.
832
- for key, val in self._annot.items():
833
- cbor['{%s}' % key] = _py_to_cbor(cqasm.v1x.primitives.serialize(key, val))
834
-
835
- return cbor
836
-
837
-
838
- class MultiBitRefs(_Multiple):
839
- """Wrapper for an edge with multiple BitRefs objects."""
840
-
841
- _T = BitRefs
842
-
843
-
844
- _typemap['BitRefs'] = BitRefs
845
-
846
- class Constant(Node):
847
- """Represents a constant value."""
848
-
849
- __slots__ = []
850
-
851
- def __init__(self):
852
- super().__init__()
853
-
854
- @staticmethod
855
- def _deserialize(cbor, seq_to_ob, links):
856
- """Attempts to deserialize the given cbor object (in Python primitive
857
- representation) into a node of this type. All (sub)nodes are added to
858
- the seq_to_ob dict, indexed by their cbor sequence number. All links are
859
- registered in the links list by means of a two-tuple of the setter
860
- function for the link field and the sequence number of the target node.
861
- """
862
- if not isinstance(cbor, dict):
863
- raise TypeError('node description object must be a dict')
864
- typ = cbor.get('@t', None)
865
- if typ is None:
866
- raise ValueError('type (@t) field is missing from node serialization')
867
- if typ == 'ConstBool':
868
- return ConstBool._deserialize(cbor, seq_to_ob, links)
869
- if typ == 'ConstAxis':
870
- return ConstAxis._deserialize(cbor, seq_to_ob, links)
871
- if typ == 'ConstInt':
872
- return ConstInt._deserialize(cbor, seq_to_ob, links)
873
- if typ == 'ConstReal':
874
- return ConstReal._deserialize(cbor, seq_to_ob, links)
875
- if typ == 'ConstComplex':
876
- return ConstComplex._deserialize(cbor, seq_to_ob, links)
877
- if typ == 'ConstRealMatrix':
878
- return ConstRealMatrix._deserialize(cbor, seq_to_ob, links)
879
- if typ == 'ConstComplexMatrix':
880
- return ConstComplexMatrix._deserialize(cbor, seq_to_ob, links)
881
- if typ == 'ConstString':
882
- return ConstString._deserialize(cbor, seq_to_ob, links)
883
- if typ == 'ConstJson':
884
- return ConstJson._deserialize(cbor, seq_to_ob, links)
885
- raise ValueError('unknown or unexpected type (@t) found in node serialization')
886
-
887
- def _serialize(self, id_map):
888
- """Serializes this node to the Python primitive representation of its
889
- CBOR serialization. The tree that the node belongs to must be
890
- well-formed. id_map must match Python id() calls for all nodes to unique
891
- integers, to use for the sequence number representation of links."""
892
- cbor = {'@i': id_map[id(self)], '@t': 'Constant'}
893
-
894
- # Serialize annotations.
895
- for key, val in self._annot.items():
896
- cbor['{%s}' % key] = _py_to_cbor(cqasm.v1x.primitives.serialize(key, val))
897
-
898
- return cbor
899
-
900
-
901
- class MultiConstant(_Multiple):
902
- """Wrapper for an edge with multiple Constant objects."""
903
-
904
- _T = Constant
905
-
906
-
907
- _typemap['Constant'] = Constant
908
-
909
- class ConstAxis(Constant):
910
- """Represents an axis value (x, y, or z)."""
911
-
912
- __slots__ = [
913
- '_attr_value',
914
- ]
915
-
916
- def __init__(
917
- self,
918
- value=None,
919
- ):
920
- super().__init__()
921
- self.value = value
922
-
923
- @property
924
- def value(self):
925
- """The contained value."""
926
- return self._attr_value
927
-
928
- @value.setter
929
- def value(self, val):
930
- if val is None:
931
- del self.value
932
- return
933
- if not isinstance(val, cqasm.v1x.primitives.Axis):
934
- # Try to "typecast" if this isn't an obvious mistake.
935
- if isinstance(val, Node):
936
- raise TypeError('value must be of type cqasm.v1x.primitives.Axis')
937
- val = cqasm.v1x.primitives.Axis(val)
938
- self._attr_value = val
939
-
940
- @value.deleter
941
- def value(self):
942
- self._attr_value = cqasm.v1x.primitives.Axis()
943
-
944
- def __eq__(self, other):
945
- """Equality operator. Ignores annotations!"""
946
- if not isinstance(other, ConstAxis):
947
- return False
948
- if self.value != other.value:
949
- return False
950
- return True
951
-
952
- def dump(self, indent=0, annotations=None, links=1):
953
- """Returns a debug representation of this tree as a multiline string.
954
- indent is the number of double spaces prefixed before every line.
955
- annotations, if specified, must be a set-like object containing the key
956
- strings of the annotations that are to be printed. links specifies the
957
- maximum link recursion depth."""
958
- s = [' '*indent]
959
- s.append('ConstAxis(')
960
- if annotations is None:
961
- annotations = []
962
- for key in annotations:
963
- if key in self:
964
- s.append(' # {}: {}'.format(key, self[key]))
965
- s.append('\n')
966
- indent += 1
967
- s.append(' '*indent)
968
- s.append('value: ')
969
- s.append(str(self.value) + '\n')
970
- indent -= 1
971
- s.append(' '*indent)
972
- s.append(')')
973
- return ''.join(s)
974
-
975
- __str__ = dump
976
- __repr__ = dump
977
-
978
- def find_reachable(self, id_map=None):
979
- """Returns a dictionary mapping Python id() values to stable sequence
980
- numbers for all nodes in the tree rooted at this node. If id_map is
981
- specified, found nodes are appended to it."""
982
- if id_map is None:
983
- id_map = {}
984
- if id(self) in id_map:
985
- raise NotWellFormed('node {!r} with id {} occurs more than once'.format(self, id(self)))
986
- id_map[id(self)] = len(id_map)
987
- return id_map
988
-
989
- def check_complete(self, id_map=None):
990
- """Raises NotWellFormed if the tree rooted at this node is not
991
- well-formed. If id_map is specified, this tree is only a subtree in the
992
- context of a larger tree, and id_map must be a dict mapping from Python
993
- id() codes to tree indices for all reachable nodes."""
994
- if id_map is None:
995
- id_map = self.find_reachable()
996
-
997
- def copy(self):
998
- """Returns a shallow copy of this node."""
999
- return ConstAxis(
1000
- value=self._attr_value
1001
- )
1002
-
1003
- def clone(self):
1004
- """Returns a deep copy of this node. This mimics the C++ interface,
1005
- deficiencies with links included; that is, links always point to the
1006
- original tree. If you're not cloning a subtree in a context where this
1007
- is the desired behavior, you may want to use the copy.deepcopy() from
1008
- the stdlib instead, which should copy links correctly."""
1009
- return ConstAxis(
1010
- value=_cloned(self._attr_value)
1011
- )
1012
-
1013
- @staticmethod
1014
- def _deserialize(cbor, seq_to_ob, links):
1015
- """Attempts to deserialize the given cbor object (in Python primitive
1016
- representation) into a node of this type. All (sub)nodes are added to
1017
- the seq_to_ob dict, indexed by their cbor sequence number. All links are
1018
- registered in the links list by means of a two-tuple of the setter
1019
- function for the link field and the sequence number of the target node.
1020
- """
1021
- if not isinstance(cbor, dict):
1022
- raise TypeError('node description object must be a dict')
1023
- typ = cbor.get('@t', None)
1024
- if typ is None:
1025
- raise ValueError('type (@t) field is missing from node serialization')
1026
- if typ != 'ConstAxis':
1027
- raise ValueError('found node serialization for ' + typ + ', but expected ConstAxis')
1028
-
1029
- # Deserialize the value field.
1030
- field = cbor.get('value', None)
1031
- if not isinstance(field, dict):
1032
- raise ValueError('missing or invalid serialization of field value')
1033
- if hasattr(cqasm.v1x.primitives.Axis, 'deserialize_cbor'):
1034
- f_value = cqasm.v1x.primitives.Axis.deserialize_cbor(field)
1035
- else:
1036
- f_value = cqasm.v1x.primitives.deserialize(cqasm.v1x.primitives.Axis, field)
1037
-
1038
- # Construct the ConstAxis node.
1039
- node = ConstAxis(f_value)
1040
-
1041
- # Deserialize annotations.
1042
- for key, val in cbor.items():
1043
- if not (key.startswith('{') and key.endswith('}')):
1044
- continue
1045
- key = key[1:-1]
1046
- node[key] = cqasm.v1x.primitives.deserialize(key, val)
1047
-
1048
- # Register node in sequence number lookup.
1049
- seq = cbor.get('@i', None)
1050
- if not isinstance(seq, int):
1051
- raise ValueError('sequence number field (@i) is not an integer or missing from node serialization')
1052
- if seq in seq_to_ob:
1053
- raise ValueError('duplicate sequence number %d' % seq)
1054
- seq_to_ob[seq] = node
1055
-
1056
- return node
1057
-
1058
- def _serialize(self, id_map):
1059
- """Serializes this node to the Python primitive representation of its
1060
- CBOR serialization. The tree that the node belongs to must be
1061
- well-formed. id_map must match Python id() calls for all nodes to unique
1062
- integers, to use for the sequence number representation of links."""
1063
- cbor = {'@i': id_map[id(self)], '@t': 'ConstAxis'}
1064
-
1065
- # Serialize the value field.
1066
- if hasattr(self._attr_value, 'serialize_cbor'):
1067
- cbor['value'] = self._attr_value.serialize_cbor()
1068
- else:
1069
- cbor['value'] = cqasm.v1x.primitives.serialize(cqasm.v1x.primitives.Axis, self._attr_value)
1070
-
1071
- # Serialize annotations.
1072
- for key, val in self._annot.items():
1073
- cbor['{%s}' % key] = _py_to_cbor(cqasm.v1x.primitives.serialize(key, val))
1074
-
1075
- return cbor
1076
-
1077
-
1078
- class MultiConstAxis(_Multiple):
1079
- """Wrapper for an edge with multiple ConstAxis objects."""
1080
-
1081
- _T = ConstAxis
1082
-
1083
-
1084
- _typemap['ConstAxis'] = ConstAxis
1085
-
1086
- class ConstBool(Constant):
1087
- """Represents a value of type bool."""
1088
-
1089
- __slots__ = [
1090
- '_attr_value',
1091
- ]
1092
-
1093
- def __init__(
1094
- self,
1095
- value=None,
1096
- ):
1097
- super().__init__()
1098
- self.value = value
1099
-
1100
- @property
1101
- def value(self):
1102
- """The contained value."""
1103
- return self._attr_value
1104
-
1105
- @value.setter
1106
- def value(self, val):
1107
- if val is None:
1108
- del self.value
1109
- return
1110
- if not isinstance(val, cqasm.v1x.primitives.Bool):
1111
- # Try to "typecast" if this isn't an obvious mistake.
1112
- if isinstance(val, Node):
1113
- raise TypeError('value must be of type cqasm.v1x.primitives.Bool')
1114
- val = cqasm.v1x.primitives.Bool(val)
1115
- self._attr_value = val
1116
-
1117
- @value.deleter
1118
- def value(self):
1119
- self._attr_value = cqasm.v1x.primitives.Bool()
1120
-
1121
- def __eq__(self, other):
1122
- """Equality operator. Ignores annotations!"""
1123
- if not isinstance(other, ConstBool):
1124
- return False
1125
- if self.value != other.value:
1126
- return False
1127
- return True
1128
-
1129
- def dump(self, indent=0, annotations=None, links=1):
1130
- """Returns a debug representation of this tree as a multiline string.
1131
- indent is the number of double spaces prefixed before every line.
1132
- annotations, if specified, must be a set-like object containing the key
1133
- strings of the annotations that are to be printed. links specifies the
1134
- maximum link recursion depth."""
1135
- s = [' '*indent]
1136
- s.append('ConstBool(')
1137
- if annotations is None:
1138
- annotations = []
1139
- for key in annotations:
1140
- if key in self:
1141
- s.append(' # {}: {}'.format(key, self[key]))
1142
- s.append('\n')
1143
- indent += 1
1144
- s.append(' '*indent)
1145
- s.append('value: ')
1146
- s.append(str(self.value) + '\n')
1147
- indent -= 1
1148
- s.append(' '*indent)
1149
- s.append(')')
1150
- return ''.join(s)
1151
-
1152
- __str__ = dump
1153
- __repr__ = dump
1154
-
1155
- def find_reachable(self, id_map=None):
1156
- """Returns a dictionary mapping Python id() values to stable sequence
1157
- numbers for all nodes in the tree rooted at this node. If id_map is
1158
- specified, found nodes are appended to it."""
1159
- if id_map is None:
1160
- id_map = {}
1161
- if id(self) in id_map:
1162
- raise NotWellFormed('node {!r} with id {} occurs more than once'.format(self, id(self)))
1163
- id_map[id(self)] = len(id_map)
1164
- return id_map
1165
-
1166
- def check_complete(self, id_map=None):
1167
- """Raises NotWellFormed if the tree rooted at this node is not
1168
- well-formed. If id_map is specified, this tree is only a subtree in the
1169
- context of a larger tree, and id_map must be a dict mapping from Python
1170
- id() codes to tree indices for all reachable nodes."""
1171
- if id_map is None:
1172
- id_map = self.find_reachable()
1173
-
1174
- def copy(self):
1175
- """Returns a shallow copy of this node."""
1176
- return ConstBool(
1177
- value=self._attr_value
1178
- )
1179
-
1180
- def clone(self):
1181
- """Returns a deep copy of this node. This mimics the C++ interface,
1182
- deficiencies with links included; that is, links always point to the
1183
- original tree. If you're not cloning a subtree in a context where this
1184
- is the desired behavior, you may want to use the copy.deepcopy() from
1185
- the stdlib instead, which should copy links correctly."""
1186
- return ConstBool(
1187
- value=_cloned(self._attr_value)
1188
- )
1189
-
1190
- @staticmethod
1191
- def _deserialize(cbor, seq_to_ob, links):
1192
- """Attempts to deserialize the given cbor object (in Python primitive
1193
- representation) into a node of this type. All (sub)nodes are added to
1194
- the seq_to_ob dict, indexed by their cbor sequence number. All links are
1195
- registered in the links list by means of a two-tuple of the setter
1196
- function for the link field and the sequence number of the target node.
1197
- """
1198
- if not isinstance(cbor, dict):
1199
- raise TypeError('node description object must be a dict')
1200
- typ = cbor.get('@t', None)
1201
- if typ is None:
1202
- raise ValueError('type (@t) field is missing from node serialization')
1203
- if typ != 'ConstBool':
1204
- raise ValueError('found node serialization for ' + typ + ', but expected ConstBool')
1205
-
1206
- # Deserialize the value field.
1207
- field = cbor.get('value', None)
1208
- if not isinstance(field, dict):
1209
- raise ValueError('missing or invalid serialization of field value')
1210
- if hasattr(cqasm.v1x.primitives.Bool, 'deserialize_cbor'):
1211
- f_value = cqasm.v1x.primitives.Bool.deserialize_cbor(field)
1212
- else:
1213
- f_value = cqasm.v1x.primitives.deserialize(cqasm.v1x.primitives.Bool, field)
1214
-
1215
- # Construct the ConstBool node.
1216
- node = ConstBool(f_value)
1217
-
1218
- # Deserialize annotations.
1219
- for key, val in cbor.items():
1220
- if not (key.startswith('{') and key.endswith('}')):
1221
- continue
1222
- key = key[1:-1]
1223
- node[key] = cqasm.v1x.primitives.deserialize(key, val)
1224
-
1225
- # Register node in sequence number lookup.
1226
- seq = cbor.get('@i', None)
1227
- if not isinstance(seq, int):
1228
- raise ValueError('sequence number field (@i) is not an integer or missing from node serialization')
1229
- if seq in seq_to_ob:
1230
- raise ValueError('duplicate sequence number %d' % seq)
1231
- seq_to_ob[seq] = node
1232
-
1233
- return node
1234
-
1235
- def _serialize(self, id_map):
1236
- """Serializes this node to the Python primitive representation of its
1237
- CBOR serialization. The tree that the node belongs to must be
1238
- well-formed. id_map must match Python id() calls for all nodes to unique
1239
- integers, to use for the sequence number representation of links."""
1240
- cbor = {'@i': id_map[id(self)], '@t': 'ConstBool'}
1241
-
1242
- # Serialize the value field.
1243
- if hasattr(self._attr_value, 'serialize_cbor'):
1244
- cbor['value'] = self._attr_value.serialize_cbor()
1245
- else:
1246
- cbor['value'] = cqasm.v1x.primitives.serialize(cqasm.v1x.primitives.Bool, self._attr_value)
1247
-
1248
- # Serialize annotations.
1249
- for key, val in self._annot.items():
1250
- cbor['{%s}' % key] = _py_to_cbor(cqasm.v1x.primitives.serialize(key, val))
1251
-
1252
- return cbor
1253
-
1254
-
1255
- class MultiConstBool(_Multiple):
1256
- """Wrapper for an edge with multiple ConstBool objects."""
1257
-
1258
- _T = ConstBool
1259
-
1260
-
1261
- _typemap['ConstBool'] = ConstBool
1262
-
1263
- class ConstComplex(Constant):
1264
- """Represents a value of type complex."""
1265
-
1266
- __slots__ = [
1267
- '_attr_value',
1268
- ]
1269
-
1270
- def __init__(
1271
- self,
1272
- value=None,
1273
- ):
1274
- super().__init__()
1275
- self.value = value
1276
-
1277
- @property
1278
- def value(self):
1279
- """The contained value."""
1280
- return self._attr_value
1281
-
1282
- @value.setter
1283
- def value(self, val):
1284
- if val is None:
1285
- del self.value
1286
- return
1287
- if not isinstance(val, cqasm.v1x.primitives.Complex):
1288
- # Try to "typecast" if this isn't an obvious mistake.
1289
- if isinstance(val, Node):
1290
- raise TypeError('value must be of type cqasm.v1x.primitives.Complex')
1291
- val = cqasm.v1x.primitives.Complex(val)
1292
- self._attr_value = val
1293
-
1294
- @value.deleter
1295
- def value(self):
1296
- self._attr_value = cqasm.v1x.primitives.Complex()
1297
-
1298
- def __eq__(self, other):
1299
- """Equality operator. Ignores annotations!"""
1300
- if not isinstance(other, ConstComplex):
1301
- return False
1302
- if self.value != other.value:
1303
- return False
1304
- return True
1305
-
1306
- def dump(self, indent=0, annotations=None, links=1):
1307
- """Returns a debug representation of this tree as a multiline string.
1308
- indent is the number of double spaces prefixed before every line.
1309
- annotations, if specified, must be a set-like object containing the key
1310
- strings of the annotations that are to be printed. links specifies the
1311
- maximum link recursion depth."""
1312
- s = [' '*indent]
1313
- s.append('ConstComplex(')
1314
- if annotations is None:
1315
- annotations = []
1316
- for key in annotations:
1317
- if key in self:
1318
- s.append(' # {}: {}'.format(key, self[key]))
1319
- s.append('\n')
1320
- indent += 1
1321
- s.append(' '*indent)
1322
- s.append('value: ')
1323
- s.append(str(self.value) + '\n')
1324
- indent -= 1
1325
- s.append(' '*indent)
1326
- s.append(')')
1327
- return ''.join(s)
1328
-
1329
- __str__ = dump
1330
- __repr__ = dump
1331
-
1332
- def find_reachable(self, id_map=None):
1333
- """Returns a dictionary mapping Python id() values to stable sequence
1334
- numbers for all nodes in the tree rooted at this node. If id_map is
1335
- specified, found nodes are appended to it."""
1336
- if id_map is None:
1337
- id_map = {}
1338
- if id(self) in id_map:
1339
- raise NotWellFormed('node {!r} with id {} occurs more than once'.format(self, id(self)))
1340
- id_map[id(self)] = len(id_map)
1341
- return id_map
1342
-
1343
- def check_complete(self, id_map=None):
1344
- """Raises NotWellFormed if the tree rooted at this node is not
1345
- well-formed. If id_map is specified, this tree is only a subtree in the
1346
- context of a larger tree, and id_map must be a dict mapping from Python
1347
- id() codes to tree indices for all reachable nodes."""
1348
- if id_map is None:
1349
- id_map = self.find_reachable()
1350
-
1351
- def copy(self):
1352
- """Returns a shallow copy of this node."""
1353
- return ConstComplex(
1354
- value=self._attr_value
1355
- )
1356
-
1357
- def clone(self):
1358
- """Returns a deep copy of this node. This mimics the C++ interface,
1359
- deficiencies with links included; that is, links always point to the
1360
- original tree. If you're not cloning a subtree in a context where this
1361
- is the desired behavior, you may want to use the copy.deepcopy() from
1362
- the stdlib instead, which should copy links correctly."""
1363
- return ConstComplex(
1364
- value=_cloned(self._attr_value)
1365
- )
1366
-
1367
- @staticmethod
1368
- def _deserialize(cbor, seq_to_ob, links):
1369
- """Attempts to deserialize the given cbor object (in Python primitive
1370
- representation) into a node of this type. All (sub)nodes are added to
1371
- the seq_to_ob dict, indexed by their cbor sequence number. All links are
1372
- registered in the links list by means of a two-tuple of the setter
1373
- function for the link field and the sequence number of the target node.
1374
- """
1375
- if not isinstance(cbor, dict):
1376
- raise TypeError('node description object must be a dict')
1377
- typ = cbor.get('@t', None)
1378
- if typ is None:
1379
- raise ValueError('type (@t) field is missing from node serialization')
1380
- if typ != 'ConstComplex':
1381
- raise ValueError('found node serialization for ' + typ + ', but expected ConstComplex')
1382
-
1383
- # Deserialize the value field.
1384
- field = cbor.get('value', None)
1385
- if not isinstance(field, dict):
1386
- raise ValueError('missing or invalid serialization of field value')
1387
- if hasattr(cqasm.v1x.primitives.Complex, 'deserialize_cbor'):
1388
- f_value = cqasm.v1x.primitives.Complex.deserialize_cbor(field)
1389
- else:
1390
- f_value = cqasm.v1x.primitives.deserialize(cqasm.v1x.primitives.Complex, field)
1391
-
1392
- # Construct the ConstComplex node.
1393
- node = ConstComplex(f_value)
1394
-
1395
- # Deserialize annotations.
1396
- for key, val in cbor.items():
1397
- if not (key.startswith('{') and key.endswith('}')):
1398
- continue
1399
- key = key[1:-1]
1400
- node[key] = cqasm.v1x.primitives.deserialize(key, val)
1401
-
1402
- # Register node in sequence number lookup.
1403
- seq = cbor.get('@i', None)
1404
- if not isinstance(seq, int):
1405
- raise ValueError('sequence number field (@i) is not an integer or missing from node serialization')
1406
- if seq in seq_to_ob:
1407
- raise ValueError('duplicate sequence number %d' % seq)
1408
- seq_to_ob[seq] = node
1409
-
1410
- return node
1411
-
1412
- def _serialize(self, id_map):
1413
- """Serializes this node to the Python primitive representation of its
1414
- CBOR serialization. The tree that the node belongs to must be
1415
- well-formed. id_map must match Python id() calls for all nodes to unique
1416
- integers, to use for the sequence number representation of links."""
1417
- cbor = {'@i': id_map[id(self)], '@t': 'ConstComplex'}
1418
-
1419
- # Serialize the value field.
1420
- if hasattr(self._attr_value, 'serialize_cbor'):
1421
- cbor['value'] = self._attr_value.serialize_cbor()
1422
- else:
1423
- cbor['value'] = cqasm.v1x.primitives.serialize(cqasm.v1x.primitives.Complex, self._attr_value)
1424
-
1425
- # Serialize annotations.
1426
- for key, val in self._annot.items():
1427
- cbor['{%s}' % key] = _py_to_cbor(cqasm.v1x.primitives.serialize(key, val))
1428
-
1429
- return cbor
1430
-
1431
-
1432
- class MultiConstComplex(_Multiple):
1433
- """Wrapper for an edge with multiple ConstComplex objects."""
1434
-
1435
- _T = ConstComplex
1436
-
1437
-
1438
- _typemap['ConstComplex'] = ConstComplex
1439
-
1440
- class ConstComplexMatrix(Constant):
1441
- """Represents a value of type complex_matrix."""
1442
-
1443
- __slots__ = [
1444
- '_attr_value',
1445
- ]
1446
-
1447
- def __init__(
1448
- self,
1449
- value=None,
1450
- ):
1451
- super().__init__()
1452
- self.value = value
1453
-
1454
- @property
1455
- def value(self):
1456
- """The contained value."""
1457
- return self._attr_value
1458
-
1459
- @value.setter
1460
- def value(self, val):
1461
- if val is None:
1462
- del self.value
1463
- return
1464
- if not isinstance(val, cqasm.v1x.primitives.CMatrix):
1465
- # Try to "typecast" if this isn't an obvious mistake.
1466
- if isinstance(val, Node):
1467
- raise TypeError('value must be of type cqasm.v1x.primitives.CMatrix')
1468
- val = cqasm.v1x.primitives.CMatrix(val)
1469
- self._attr_value = val
1470
-
1471
- @value.deleter
1472
- def value(self):
1473
- self._attr_value = cqasm.v1x.primitives.CMatrix()
1474
-
1475
- def __eq__(self, other):
1476
- """Equality operator. Ignores annotations!"""
1477
- if not isinstance(other, ConstComplexMatrix):
1478
- return False
1479
- if self.value != other.value:
1480
- return False
1481
- return True
1482
-
1483
- def dump(self, indent=0, annotations=None, links=1):
1484
- """Returns a debug representation of this tree as a multiline string.
1485
- indent is the number of double spaces prefixed before every line.
1486
- annotations, if specified, must be a set-like object containing the key
1487
- strings of the annotations that are to be printed. links specifies the
1488
- maximum link recursion depth."""
1489
- s = [' '*indent]
1490
- s.append('ConstComplexMatrix(')
1491
- if annotations is None:
1492
- annotations = []
1493
- for key in annotations:
1494
- if key in self:
1495
- s.append(' # {}: {}'.format(key, self[key]))
1496
- s.append('\n')
1497
- indent += 1
1498
- s.append(' '*indent)
1499
- s.append('value: ')
1500
- s.append(str(self.value) + '\n')
1501
- indent -= 1
1502
- s.append(' '*indent)
1503
- s.append(')')
1504
- return ''.join(s)
1505
-
1506
- __str__ = dump
1507
- __repr__ = dump
1508
-
1509
- def find_reachable(self, id_map=None):
1510
- """Returns a dictionary mapping Python id() values to stable sequence
1511
- numbers for all nodes in the tree rooted at this node. If id_map is
1512
- specified, found nodes are appended to it."""
1513
- if id_map is None:
1514
- id_map = {}
1515
- if id(self) in id_map:
1516
- raise NotWellFormed('node {!r} with id {} occurs more than once'.format(self, id(self)))
1517
- id_map[id(self)] = len(id_map)
1518
- return id_map
1519
-
1520
- def check_complete(self, id_map=None):
1521
- """Raises NotWellFormed if the tree rooted at this node is not
1522
- well-formed. If id_map is specified, this tree is only a subtree in the
1523
- context of a larger tree, and id_map must be a dict mapping from Python
1524
- id() codes to tree indices for all reachable nodes."""
1525
- if id_map is None:
1526
- id_map = self.find_reachable()
1527
-
1528
- def copy(self):
1529
- """Returns a shallow copy of this node."""
1530
- return ConstComplexMatrix(
1531
- value=self._attr_value
1532
- )
1533
-
1534
- def clone(self):
1535
- """Returns a deep copy of this node. This mimics the C++ interface,
1536
- deficiencies with links included; that is, links always point to the
1537
- original tree. If you're not cloning a subtree in a context where this
1538
- is the desired behavior, you may want to use the copy.deepcopy() from
1539
- the stdlib instead, which should copy links correctly."""
1540
- return ConstComplexMatrix(
1541
- value=_cloned(self._attr_value)
1542
- )
1543
-
1544
- @staticmethod
1545
- def _deserialize(cbor, seq_to_ob, links):
1546
- """Attempts to deserialize the given cbor object (in Python primitive
1547
- representation) into a node of this type. All (sub)nodes are added to
1548
- the seq_to_ob dict, indexed by their cbor sequence number. All links are
1549
- registered in the links list by means of a two-tuple of the setter
1550
- function for the link field and the sequence number of the target node.
1551
- """
1552
- if not isinstance(cbor, dict):
1553
- raise TypeError('node description object must be a dict')
1554
- typ = cbor.get('@t', None)
1555
- if typ is None:
1556
- raise ValueError('type (@t) field is missing from node serialization')
1557
- if typ != 'ConstComplexMatrix':
1558
- raise ValueError('found node serialization for ' + typ + ', but expected ConstComplexMatrix')
1559
-
1560
- # Deserialize the value field.
1561
- field = cbor.get('value', None)
1562
- if not isinstance(field, dict):
1563
- raise ValueError('missing or invalid serialization of field value')
1564
- if hasattr(cqasm.v1x.primitives.CMatrix, 'deserialize_cbor'):
1565
- f_value = cqasm.v1x.primitives.CMatrix.deserialize_cbor(field)
1566
- else:
1567
- f_value = cqasm.v1x.primitives.deserialize(cqasm.v1x.primitives.CMatrix, field)
1568
-
1569
- # Construct the ConstComplexMatrix node.
1570
- node = ConstComplexMatrix(f_value)
1571
-
1572
- # Deserialize annotations.
1573
- for key, val in cbor.items():
1574
- if not (key.startswith('{') and key.endswith('}')):
1575
- continue
1576
- key = key[1:-1]
1577
- node[key] = cqasm.v1x.primitives.deserialize(key, val)
1578
-
1579
- # Register node in sequence number lookup.
1580
- seq = cbor.get('@i', None)
1581
- if not isinstance(seq, int):
1582
- raise ValueError('sequence number field (@i) is not an integer or missing from node serialization')
1583
- if seq in seq_to_ob:
1584
- raise ValueError('duplicate sequence number %d' % seq)
1585
- seq_to_ob[seq] = node
1586
-
1587
- return node
1588
-
1589
- def _serialize(self, id_map):
1590
- """Serializes this node to the Python primitive representation of its
1591
- CBOR serialization. The tree that the node belongs to must be
1592
- well-formed. id_map must match Python id() calls for all nodes to unique
1593
- integers, to use for the sequence number representation of links."""
1594
- cbor = {'@i': id_map[id(self)], '@t': 'ConstComplexMatrix'}
1595
-
1596
- # Serialize the value field.
1597
- if hasattr(self._attr_value, 'serialize_cbor'):
1598
- cbor['value'] = self._attr_value.serialize_cbor()
1599
- else:
1600
- cbor['value'] = cqasm.v1x.primitives.serialize(cqasm.v1x.primitives.CMatrix, self._attr_value)
1601
-
1602
- # Serialize annotations.
1603
- for key, val in self._annot.items():
1604
- cbor['{%s}' % key] = _py_to_cbor(cqasm.v1x.primitives.serialize(key, val))
1605
-
1606
- return cbor
1607
-
1608
-
1609
- class MultiConstComplexMatrix(_Multiple):
1610
- """Wrapper for an edge with multiple ConstComplexMatrix objects."""
1611
-
1612
- _T = ConstComplexMatrix
1613
-
1614
-
1615
- _typemap['ConstComplexMatrix'] = ConstComplexMatrix
1616
-
1617
- class ConstInt(Constant):
1618
- """Represents a value of type int."""
1619
-
1620
- __slots__ = [
1621
- '_attr_value',
1622
- ]
1623
-
1624
- def __init__(
1625
- self,
1626
- value=None,
1627
- ):
1628
- super().__init__()
1629
- self.value = value
1630
-
1631
- @property
1632
- def value(self):
1633
- """The contained value."""
1634
- return self._attr_value
1635
-
1636
- @value.setter
1637
- def value(self, val):
1638
- if val is None:
1639
- del self.value
1640
- return
1641
- if not isinstance(val, cqasm.v1x.primitives.Int):
1642
- # Try to "typecast" if this isn't an obvious mistake.
1643
- if isinstance(val, Node):
1644
- raise TypeError('value must be of type cqasm.v1x.primitives.Int')
1645
- val = cqasm.v1x.primitives.Int(val)
1646
- self._attr_value = val
1647
-
1648
- @value.deleter
1649
- def value(self):
1650
- self._attr_value = cqasm.v1x.primitives.Int()
1651
-
1652
- def __eq__(self, other):
1653
- """Equality operator. Ignores annotations!"""
1654
- if not isinstance(other, ConstInt):
1655
- return False
1656
- if self.value != other.value:
1657
- return False
1658
- return True
1659
-
1660
- def dump(self, indent=0, annotations=None, links=1):
1661
- """Returns a debug representation of this tree as a multiline string.
1662
- indent is the number of double spaces prefixed before every line.
1663
- annotations, if specified, must be a set-like object containing the key
1664
- strings of the annotations that are to be printed. links specifies the
1665
- maximum link recursion depth."""
1666
- s = [' '*indent]
1667
- s.append('ConstInt(')
1668
- if annotations is None:
1669
- annotations = []
1670
- for key in annotations:
1671
- if key in self:
1672
- s.append(' # {}: {}'.format(key, self[key]))
1673
- s.append('\n')
1674
- indent += 1
1675
- s.append(' '*indent)
1676
- s.append('value: ')
1677
- s.append(str(self.value) + '\n')
1678
- indent -= 1
1679
- s.append(' '*indent)
1680
- s.append(')')
1681
- return ''.join(s)
1682
-
1683
- __str__ = dump
1684
- __repr__ = dump
1685
-
1686
- def find_reachable(self, id_map=None):
1687
- """Returns a dictionary mapping Python id() values to stable sequence
1688
- numbers for all nodes in the tree rooted at this node. If id_map is
1689
- specified, found nodes are appended to it."""
1690
- if id_map is None:
1691
- id_map = {}
1692
- if id(self) in id_map:
1693
- raise NotWellFormed('node {!r} with id {} occurs more than once'.format(self, id(self)))
1694
- id_map[id(self)] = len(id_map)
1695
- return id_map
1696
-
1697
- def check_complete(self, id_map=None):
1698
- """Raises NotWellFormed if the tree rooted at this node is not
1699
- well-formed. If id_map is specified, this tree is only a subtree in the
1700
- context of a larger tree, and id_map must be a dict mapping from Python
1701
- id() codes to tree indices for all reachable nodes."""
1702
- if id_map is None:
1703
- id_map = self.find_reachable()
1704
-
1705
- def copy(self):
1706
- """Returns a shallow copy of this node."""
1707
- return ConstInt(
1708
- value=self._attr_value
1709
- )
1710
-
1711
- def clone(self):
1712
- """Returns a deep copy of this node. This mimics the C++ interface,
1713
- deficiencies with links included; that is, links always point to the
1714
- original tree. If you're not cloning a subtree in a context where this
1715
- is the desired behavior, you may want to use the copy.deepcopy() from
1716
- the stdlib instead, which should copy links correctly."""
1717
- return ConstInt(
1718
- value=_cloned(self._attr_value)
1719
- )
1720
-
1721
- @staticmethod
1722
- def _deserialize(cbor, seq_to_ob, links):
1723
- """Attempts to deserialize the given cbor object (in Python primitive
1724
- representation) into a node of this type. All (sub)nodes are added to
1725
- the seq_to_ob dict, indexed by their cbor sequence number. All links are
1726
- registered in the links list by means of a two-tuple of the setter
1727
- function for the link field and the sequence number of the target node.
1728
- """
1729
- if not isinstance(cbor, dict):
1730
- raise TypeError('node description object must be a dict')
1731
- typ = cbor.get('@t', None)
1732
- if typ is None:
1733
- raise ValueError('type (@t) field is missing from node serialization')
1734
- if typ != 'ConstInt':
1735
- raise ValueError('found node serialization for ' + typ + ', but expected ConstInt')
1736
-
1737
- # Deserialize the value field.
1738
- field = cbor.get('value', None)
1739
- if not isinstance(field, dict):
1740
- raise ValueError('missing or invalid serialization of field value')
1741
- if hasattr(cqasm.v1x.primitives.Int, 'deserialize_cbor'):
1742
- f_value = cqasm.v1x.primitives.Int.deserialize_cbor(field)
1743
- else:
1744
- f_value = cqasm.v1x.primitives.deserialize(cqasm.v1x.primitives.Int, field)
1745
-
1746
- # Construct the ConstInt node.
1747
- node = ConstInt(f_value)
1748
-
1749
- # Deserialize annotations.
1750
- for key, val in cbor.items():
1751
- if not (key.startswith('{') and key.endswith('}')):
1752
- continue
1753
- key = key[1:-1]
1754
- node[key] = cqasm.v1x.primitives.deserialize(key, val)
1755
-
1756
- # Register node in sequence number lookup.
1757
- seq = cbor.get('@i', None)
1758
- if not isinstance(seq, int):
1759
- raise ValueError('sequence number field (@i) is not an integer or missing from node serialization')
1760
- if seq in seq_to_ob:
1761
- raise ValueError('duplicate sequence number %d' % seq)
1762
- seq_to_ob[seq] = node
1763
-
1764
- return node
1765
-
1766
- def _serialize(self, id_map):
1767
- """Serializes this node to the Python primitive representation of its
1768
- CBOR serialization. The tree that the node belongs to must be
1769
- well-formed. id_map must match Python id() calls for all nodes to unique
1770
- integers, to use for the sequence number representation of links."""
1771
- cbor = {'@i': id_map[id(self)], '@t': 'ConstInt'}
1772
-
1773
- # Serialize the value field.
1774
- if hasattr(self._attr_value, 'serialize_cbor'):
1775
- cbor['value'] = self._attr_value.serialize_cbor()
1776
- else:
1777
- cbor['value'] = cqasm.v1x.primitives.serialize(cqasm.v1x.primitives.Int, self._attr_value)
1778
-
1779
- # Serialize annotations.
1780
- for key, val in self._annot.items():
1781
- cbor['{%s}' % key] = _py_to_cbor(cqasm.v1x.primitives.serialize(key, val))
1782
-
1783
- return cbor
1784
-
1785
-
1786
- class MultiConstInt(_Multiple):
1787
- """Wrapper for an edge with multiple ConstInt objects."""
1788
-
1789
- _T = ConstInt
1790
-
1791
-
1792
- _typemap['ConstInt'] = ConstInt
1793
-
1794
- class ConstJson(Constant):
1795
- """Represents a value of type json."""
1796
-
1797
- __slots__ = [
1798
- '_attr_value',
1799
- ]
1800
-
1801
- def __init__(
1802
- self,
1803
- value=None,
1804
- ):
1805
- super().__init__()
1806
- self.value = value
1807
-
1808
- @property
1809
- def value(self):
1810
- """The contained value."""
1811
- return self._attr_value
1812
-
1813
- @value.setter
1814
- def value(self, val):
1815
- if val is None:
1816
- del self.value
1817
- return
1818
- if not isinstance(val, cqasm.v1x.primitives.Str):
1819
- # Try to "typecast" if this isn't an obvious mistake.
1820
- if isinstance(val, Node):
1821
- raise TypeError('value must be of type cqasm.v1x.primitives.Str')
1822
- val = cqasm.v1x.primitives.Str(val)
1823
- self._attr_value = val
1824
-
1825
- @value.deleter
1826
- def value(self):
1827
- self._attr_value = cqasm.v1x.primitives.Str()
1828
-
1829
- def __eq__(self, other):
1830
- """Equality operator. Ignores annotations!"""
1831
- if not isinstance(other, ConstJson):
1832
- return False
1833
- if self.value != other.value:
1834
- return False
1835
- return True
1836
-
1837
- def dump(self, indent=0, annotations=None, links=1):
1838
- """Returns a debug representation of this tree as a multiline string.
1839
- indent is the number of double spaces prefixed before every line.
1840
- annotations, if specified, must be a set-like object containing the key
1841
- strings of the annotations that are to be printed. links specifies the
1842
- maximum link recursion depth."""
1843
- s = [' '*indent]
1844
- s.append('ConstJson(')
1845
- if annotations is None:
1846
- annotations = []
1847
- for key in annotations:
1848
- if key in self:
1849
- s.append(' # {}: {}'.format(key, self[key]))
1850
- s.append('\n')
1851
- indent += 1
1852
- s.append(' '*indent)
1853
- s.append('value: ')
1854
- s.append(str(self.value) + '\n')
1855
- indent -= 1
1856
- s.append(' '*indent)
1857
- s.append(')')
1858
- return ''.join(s)
1859
-
1860
- __str__ = dump
1861
- __repr__ = dump
1862
-
1863
- def find_reachable(self, id_map=None):
1864
- """Returns a dictionary mapping Python id() values to stable sequence
1865
- numbers for all nodes in the tree rooted at this node. If id_map is
1866
- specified, found nodes are appended to it."""
1867
- if id_map is None:
1868
- id_map = {}
1869
- if id(self) in id_map:
1870
- raise NotWellFormed('node {!r} with id {} occurs more than once'.format(self, id(self)))
1871
- id_map[id(self)] = len(id_map)
1872
- return id_map
1873
-
1874
- def check_complete(self, id_map=None):
1875
- """Raises NotWellFormed if the tree rooted at this node is not
1876
- well-formed. If id_map is specified, this tree is only a subtree in the
1877
- context of a larger tree, and id_map must be a dict mapping from Python
1878
- id() codes to tree indices for all reachable nodes."""
1879
- if id_map is None:
1880
- id_map = self.find_reachable()
1881
-
1882
- def copy(self):
1883
- """Returns a shallow copy of this node."""
1884
- return ConstJson(
1885
- value=self._attr_value
1886
- )
1887
-
1888
- def clone(self):
1889
- """Returns a deep copy of this node. This mimics the C++ interface,
1890
- deficiencies with links included; that is, links always point to the
1891
- original tree. If you're not cloning a subtree in a context where this
1892
- is the desired behavior, you may want to use the copy.deepcopy() from
1893
- the stdlib instead, which should copy links correctly."""
1894
- return ConstJson(
1895
- value=_cloned(self._attr_value)
1896
- )
1897
-
1898
- @staticmethod
1899
- def _deserialize(cbor, seq_to_ob, links):
1900
- """Attempts to deserialize the given cbor object (in Python primitive
1901
- representation) into a node of this type. All (sub)nodes are added to
1902
- the seq_to_ob dict, indexed by their cbor sequence number. All links are
1903
- registered in the links list by means of a two-tuple of the setter
1904
- function for the link field and the sequence number of the target node.
1905
- """
1906
- if not isinstance(cbor, dict):
1907
- raise TypeError('node description object must be a dict')
1908
- typ = cbor.get('@t', None)
1909
- if typ is None:
1910
- raise ValueError('type (@t) field is missing from node serialization')
1911
- if typ != 'ConstJson':
1912
- raise ValueError('found node serialization for ' + typ + ', but expected ConstJson')
1913
-
1914
- # Deserialize the value field.
1915
- field = cbor.get('value', None)
1916
- if not isinstance(field, dict):
1917
- raise ValueError('missing or invalid serialization of field value')
1918
- if hasattr(cqasm.v1x.primitives.Str, 'deserialize_cbor'):
1919
- f_value = cqasm.v1x.primitives.Str.deserialize_cbor(field)
1920
- else:
1921
- f_value = cqasm.v1x.primitives.deserialize(cqasm.v1x.primitives.Str, field)
1922
-
1923
- # Construct the ConstJson node.
1924
- node = ConstJson(f_value)
1925
-
1926
- # Deserialize annotations.
1927
- for key, val in cbor.items():
1928
- if not (key.startswith('{') and key.endswith('}')):
1929
- continue
1930
- key = key[1:-1]
1931
- node[key] = cqasm.v1x.primitives.deserialize(key, val)
1932
-
1933
- # Register node in sequence number lookup.
1934
- seq = cbor.get('@i', None)
1935
- if not isinstance(seq, int):
1936
- raise ValueError('sequence number field (@i) is not an integer or missing from node serialization')
1937
- if seq in seq_to_ob:
1938
- raise ValueError('duplicate sequence number %d' % seq)
1939
- seq_to_ob[seq] = node
1940
-
1941
- return node
1942
-
1943
- def _serialize(self, id_map):
1944
- """Serializes this node to the Python primitive representation of its
1945
- CBOR serialization. The tree that the node belongs to must be
1946
- well-formed. id_map must match Python id() calls for all nodes to unique
1947
- integers, to use for the sequence number representation of links."""
1948
- cbor = {'@i': id_map[id(self)], '@t': 'ConstJson'}
1949
-
1950
- # Serialize the value field.
1951
- if hasattr(self._attr_value, 'serialize_cbor'):
1952
- cbor['value'] = self._attr_value.serialize_cbor()
1953
- else:
1954
- cbor['value'] = cqasm.v1x.primitives.serialize(cqasm.v1x.primitives.Str, self._attr_value)
1955
-
1956
- # Serialize annotations.
1957
- for key, val in self._annot.items():
1958
- cbor['{%s}' % key] = _py_to_cbor(cqasm.v1x.primitives.serialize(key, val))
1959
-
1960
- return cbor
1961
-
1962
-
1963
- class MultiConstJson(_Multiple):
1964
- """Wrapper for an edge with multiple ConstJson objects."""
1965
-
1966
- _T = ConstJson
1967
-
1968
-
1969
- _typemap['ConstJson'] = ConstJson
1970
-
1971
- class ConstReal(Constant):
1972
- """Represents a value of type real."""
1973
-
1974
- __slots__ = [
1975
- '_attr_value',
1976
- ]
1977
-
1978
- def __init__(
1979
- self,
1980
- value=None,
1981
- ):
1982
- super().__init__()
1983
- self.value = value
1984
-
1985
- @property
1986
- def value(self):
1987
- """The contained value."""
1988
- return self._attr_value
1989
-
1990
- @value.setter
1991
- def value(self, val):
1992
- if val is None:
1993
- del self.value
1994
- return
1995
- if not isinstance(val, cqasm.v1x.primitives.Real):
1996
- # Try to "typecast" if this isn't an obvious mistake.
1997
- if isinstance(val, Node):
1998
- raise TypeError('value must be of type cqasm.v1x.primitives.Real')
1999
- val = cqasm.v1x.primitives.Real(val)
2000
- self._attr_value = val
2001
-
2002
- @value.deleter
2003
- def value(self):
2004
- self._attr_value = cqasm.v1x.primitives.Real()
2005
-
2006
- def __eq__(self, other):
2007
- """Equality operator. Ignores annotations!"""
2008
- if not isinstance(other, ConstReal):
2009
- return False
2010
- if self.value != other.value:
2011
- return False
2012
- return True
2013
-
2014
- def dump(self, indent=0, annotations=None, links=1):
2015
- """Returns a debug representation of this tree as a multiline string.
2016
- indent is the number of double spaces prefixed before every line.
2017
- annotations, if specified, must be a set-like object containing the key
2018
- strings of the annotations that are to be printed. links specifies the
2019
- maximum link recursion depth."""
2020
- s = [' '*indent]
2021
- s.append('ConstReal(')
2022
- if annotations is None:
2023
- annotations = []
2024
- for key in annotations:
2025
- if key in self:
2026
- s.append(' # {}: {}'.format(key, self[key]))
2027
- s.append('\n')
2028
- indent += 1
2029
- s.append(' '*indent)
2030
- s.append('value: ')
2031
- s.append(str(self.value) + '\n')
2032
- indent -= 1
2033
- s.append(' '*indent)
2034
- s.append(')')
2035
- return ''.join(s)
2036
-
2037
- __str__ = dump
2038
- __repr__ = dump
2039
-
2040
- def find_reachable(self, id_map=None):
2041
- """Returns a dictionary mapping Python id() values to stable sequence
2042
- numbers for all nodes in the tree rooted at this node. If id_map is
2043
- specified, found nodes are appended to it."""
2044
- if id_map is None:
2045
- id_map = {}
2046
- if id(self) in id_map:
2047
- raise NotWellFormed('node {!r} with id {} occurs more than once'.format(self, id(self)))
2048
- id_map[id(self)] = len(id_map)
2049
- return id_map
2050
-
2051
- def check_complete(self, id_map=None):
2052
- """Raises NotWellFormed if the tree rooted at this node is not
2053
- well-formed. If id_map is specified, this tree is only a subtree in the
2054
- context of a larger tree, and id_map must be a dict mapping from Python
2055
- id() codes to tree indices for all reachable nodes."""
2056
- if id_map is None:
2057
- id_map = self.find_reachable()
2058
-
2059
- def copy(self):
2060
- """Returns a shallow copy of this node."""
2061
- return ConstReal(
2062
- value=self._attr_value
2063
- )
2064
-
2065
- def clone(self):
2066
- """Returns a deep copy of this node. This mimics the C++ interface,
2067
- deficiencies with links included; that is, links always point to the
2068
- original tree. If you're not cloning a subtree in a context where this
2069
- is the desired behavior, you may want to use the copy.deepcopy() from
2070
- the stdlib instead, which should copy links correctly."""
2071
- return ConstReal(
2072
- value=_cloned(self._attr_value)
2073
- )
2074
-
2075
- @staticmethod
2076
- def _deserialize(cbor, seq_to_ob, links):
2077
- """Attempts to deserialize the given cbor object (in Python primitive
2078
- representation) into a node of this type. All (sub)nodes are added to
2079
- the seq_to_ob dict, indexed by their cbor sequence number. All links are
2080
- registered in the links list by means of a two-tuple of the setter
2081
- function for the link field and the sequence number of the target node.
2082
- """
2083
- if not isinstance(cbor, dict):
2084
- raise TypeError('node description object must be a dict')
2085
- typ = cbor.get('@t', None)
2086
- if typ is None:
2087
- raise ValueError('type (@t) field is missing from node serialization')
2088
- if typ != 'ConstReal':
2089
- raise ValueError('found node serialization for ' + typ + ', but expected ConstReal')
2090
-
2091
- # Deserialize the value field.
2092
- field = cbor.get('value', None)
2093
- if not isinstance(field, dict):
2094
- raise ValueError('missing or invalid serialization of field value')
2095
- if hasattr(cqasm.v1x.primitives.Real, 'deserialize_cbor'):
2096
- f_value = cqasm.v1x.primitives.Real.deserialize_cbor(field)
2097
- else:
2098
- f_value = cqasm.v1x.primitives.deserialize(cqasm.v1x.primitives.Real, field)
2099
-
2100
- # Construct the ConstReal node.
2101
- node = ConstReal(f_value)
2102
-
2103
- # Deserialize annotations.
2104
- for key, val in cbor.items():
2105
- if not (key.startswith('{') and key.endswith('}')):
2106
- continue
2107
- key = key[1:-1]
2108
- node[key] = cqasm.v1x.primitives.deserialize(key, val)
2109
-
2110
- # Register node in sequence number lookup.
2111
- seq = cbor.get('@i', None)
2112
- if not isinstance(seq, int):
2113
- raise ValueError('sequence number field (@i) is not an integer or missing from node serialization')
2114
- if seq in seq_to_ob:
2115
- raise ValueError('duplicate sequence number %d' % seq)
2116
- seq_to_ob[seq] = node
2117
-
2118
- return node
2119
-
2120
- def _serialize(self, id_map):
2121
- """Serializes this node to the Python primitive representation of its
2122
- CBOR serialization. The tree that the node belongs to must be
2123
- well-formed. id_map must match Python id() calls for all nodes to unique
2124
- integers, to use for the sequence number representation of links."""
2125
- cbor = {'@i': id_map[id(self)], '@t': 'ConstReal'}
2126
-
2127
- # Serialize the value field.
2128
- if hasattr(self._attr_value, 'serialize_cbor'):
2129
- cbor['value'] = self._attr_value.serialize_cbor()
2130
- else:
2131
- cbor['value'] = cqasm.v1x.primitives.serialize(cqasm.v1x.primitives.Real, self._attr_value)
2132
-
2133
- # Serialize annotations.
2134
- for key, val in self._annot.items():
2135
- cbor['{%s}' % key] = _py_to_cbor(cqasm.v1x.primitives.serialize(key, val))
2136
-
2137
- return cbor
2138
-
2139
-
2140
- class MultiConstReal(_Multiple):
2141
- """Wrapper for an edge with multiple ConstReal objects."""
2142
-
2143
- _T = ConstReal
2144
-
2145
-
2146
- _typemap['ConstReal'] = ConstReal
2147
-
2148
- class ConstRealMatrix(Constant):
2149
- """Represents a value of type real_matrix."""
2150
-
2151
- __slots__ = [
2152
- '_attr_value',
2153
- ]
2154
-
2155
- def __init__(
2156
- self,
2157
- value=None,
2158
- ):
2159
- super().__init__()
2160
- self.value = value
2161
-
2162
- @property
2163
- def value(self):
2164
- """The contained value."""
2165
- return self._attr_value
2166
-
2167
- @value.setter
2168
- def value(self, val):
2169
- if val is None:
2170
- del self.value
2171
- return
2172
- if not isinstance(val, cqasm.v1x.primitives.RMatrix):
2173
- # Try to "typecast" if this isn't an obvious mistake.
2174
- if isinstance(val, Node):
2175
- raise TypeError('value must be of type cqasm.v1x.primitives.RMatrix')
2176
- val = cqasm.v1x.primitives.RMatrix(val)
2177
- self._attr_value = val
2178
-
2179
- @value.deleter
2180
- def value(self):
2181
- self._attr_value = cqasm.v1x.primitives.RMatrix()
2182
-
2183
- def __eq__(self, other):
2184
- """Equality operator. Ignores annotations!"""
2185
- if not isinstance(other, ConstRealMatrix):
2186
- return False
2187
- if self.value != other.value:
2188
- return False
2189
- return True
2190
-
2191
- def dump(self, indent=0, annotations=None, links=1):
2192
- """Returns a debug representation of this tree as a multiline string.
2193
- indent is the number of double spaces prefixed before every line.
2194
- annotations, if specified, must be a set-like object containing the key
2195
- strings of the annotations that are to be printed. links specifies the
2196
- maximum link recursion depth."""
2197
- s = [' '*indent]
2198
- s.append('ConstRealMatrix(')
2199
- if annotations is None:
2200
- annotations = []
2201
- for key in annotations:
2202
- if key in self:
2203
- s.append(' # {}: {}'.format(key, self[key]))
2204
- s.append('\n')
2205
- indent += 1
2206
- s.append(' '*indent)
2207
- s.append('value: ')
2208
- s.append(str(self.value) + '\n')
2209
- indent -= 1
2210
- s.append(' '*indent)
2211
- s.append(')')
2212
- return ''.join(s)
2213
-
2214
- __str__ = dump
2215
- __repr__ = dump
2216
-
2217
- def find_reachable(self, id_map=None):
2218
- """Returns a dictionary mapping Python id() values to stable sequence
2219
- numbers for all nodes in the tree rooted at this node. If id_map is
2220
- specified, found nodes are appended to it."""
2221
- if id_map is None:
2222
- id_map = {}
2223
- if id(self) in id_map:
2224
- raise NotWellFormed('node {!r} with id {} occurs more than once'.format(self, id(self)))
2225
- id_map[id(self)] = len(id_map)
2226
- return id_map
2227
-
2228
- def check_complete(self, id_map=None):
2229
- """Raises NotWellFormed if the tree rooted at this node is not
2230
- well-formed. If id_map is specified, this tree is only a subtree in the
2231
- context of a larger tree, and id_map must be a dict mapping from Python
2232
- id() codes to tree indices for all reachable nodes."""
2233
- if id_map is None:
2234
- id_map = self.find_reachable()
2235
-
2236
- def copy(self):
2237
- """Returns a shallow copy of this node."""
2238
- return ConstRealMatrix(
2239
- value=self._attr_value
2240
- )
2241
-
2242
- def clone(self):
2243
- """Returns a deep copy of this node. This mimics the C++ interface,
2244
- deficiencies with links included; that is, links always point to the
2245
- original tree. If you're not cloning a subtree in a context where this
2246
- is the desired behavior, you may want to use the copy.deepcopy() from
2247
- the stdlib instead, which should copy links correctly."""
2248
- return ConstRealMatrix(
2249
- value=_cloned(self._attr_value)
2250
- )
2251
-
2252
- @staticmethod
2253
- def _deserialize(cbor, seq_to_ob, links):
2254
- """Attempts to deserialize the given cbor object (in Python primitive
2255
- representation) into a node of this type. All (sub)nodes are added to
2256
- the seq_to_ob dict, indexed by their cbor sequence number. All links are
2257
- registered in the links list by means of a two-tuple of the setter
2258
- function for the link field and the sequence number of the target node.
2259
- """
2260
- if not isinstance(cbor, dict):
2261
- raise TypeError('node description object must be a dict')
2262
- typ = cbor.get('@t', None)
2263
- if typ is None:
2264
- raise ValueError('type (@t) field is missing from node serialization')
2265
- if typ != 'ConstRealMatrix':
2266
- raise ValueError('found node serialization for ' + typ + ', but expected ConstRealMatrix')
2267
-
2268
- # Deserialize the value field.
2269
- field = cbor.get('value', None)
2270
- if not isinstance(field, dict):
2271
- raise ValueError('missing or invalid serialization of field value')
2272
- if hasattr(cqasm.v1x.primitives.RMatrix, 'deserialize_cbor'):
2273
- f_value = cqasm.v1x.primitives.RMatrix.deserialize_cbor(field)
2274
- else:
2275
- f_value = cqasm.v1x.primitives.deserialize(cqasm.v1x.primitives.RMatrix, field)
2276
-
2277
- # Construct the ConstRealMatrix node.
2278
- node = ConstRealMatrix(f_value)
2279
-
2280
- # Deserialize annotations.
2281
- for key, val in cbor.items():
2282
- if not (key.startswith('{') and key.endswith('}')):
2283
- continue
2284
- key = key[1:-1]
2285
- node[key] = cqasm.v1x.primitives.deserialize(key, val)
2286
-
2287
- # Register node in sequence number lookup.
2288
- seq = cbor.get('@i', None)
2289
- if not isinstance(seq, int):
2290
- raise ValueError('sequence number field (@i) is not an integer or missing from node serialization')
2291
- if seq in seq_to_ob:
2292
- raise ValueError('duplicate sequence number %d' % seq)
2293
- seq_to_ob[seq] = node
2294
-
2295
- return node
2296
-
2297
- def _serialize(self, id_map):
2298
- """Serializes this node to the Python primitive representation of its
2299
- CBOR serialization. The tree that the node belongs to must be
2300
- well-formed. id_map must match Python id() calls for all nodes to unique
2301
- integers, to use for the sequence number representation of links."""
2302
- cbor = {'@i': id_map[id(self)], '@t': 'ConstRealMatrix'}
2303
-
2304
- # Serialize the value field.
2305
- if hasattr(self._attr_value, 'serialize_cbor'):
2306
- cbor['value'] = self._attr_value.serialize_cbor()
2307
- else:
2308
- cbor['value'] = cqasm.v1x.primitives.serialize(cqasm.v1x.primitives.RMatrix, self._attr_value)
2309
-
2310
- # Serialize annotations.
2311
- for key, val in self._annot.items():
2312
- cbor['{%s}' % key] = _py_to_cbor(cqasm.v1x.primitives.serialize(key, val))
2313
-
2314
- return cbor
2315
-
2316
-
2317
- class MultiConstRealMatrix(_Multiple):
2318
- """Wrapper for an edge with multiple ConstRealMatrix objects."""
2319
-
2320
- _T = ConstRealMatrix
2321
-
2322
-
2323
- _typemap['ConstRealMatrix'] = ConstRealMatrix
2324
-
2325
- class ConstString(Constant):
2326
- """Represents a value of type string."""
2327
-
2328
- __slots__ = [
2329
- '_attr_value',
2330
- ]
2331
-
2332
- def __init__(
2333
- self,
2334
- value=None,
2335
- ):
2336
- super().__init__()
2337
- self.value = value
2338
-
2339
- @property
2340
- def value(self):
2341
- """The contained value."""
2342
- return self._attr_value
2343
-
2344
- @value.setter
2345
- def value(self, val):
2346
- if val is None:
2347
- del self.value
2348
- return
2349
- if not isinstance(val, cqasm.v1x.primitives.Str):
2350
- # Try to "typecast" if this isn't an obvious mistake.
2351
- if isinstance(val, Node):
2352
- raise TypeError('value must be of type cqasm.v1x.primitives.Str')
2353
- val = cqasm.v1x.primitives.Str(val)
2354
- self._attr_value = val
2355
-
2356
- @value.deleter
2357
- def value(self):
2358
- self._attr_value = cqasm.v1x.primitives.Str()
2359
-
2360
- def __eq__(self, other):
2361
- """Equality operator. Ignores annotations!"""
2362
- if not isinstance(other, ConstString):
2363
- return False
2364
- if self.value != other.value:
2365
- return False
2366
- return True
2367
-
2368
- def dump(self, indent=0, annotations=None, links=1):
2369
- """Returns a debug representation of this tree as a multiline string.
2370
- indent is the number of double spaces prefixed before every line.
2371
- annotations, if specified, must be a set-like object containing the key
2372
- strings of the annotations that are to be printed. links specifies the
2373
- maximum link recursion depth."""
2374
- s = [' '*indent]
2375
- s.append('ConstString(')
2376
- if annotations is None:
2377
- annotations = []
2378
- for key in annotations:
2379
- if key in self:
2380
- s.append(' # {}: {}'.format(key, self[key]))
2381
- s.append('\n')
2382
- indent += 1
2383
- s.append(' '*indent)
2384
- s.append('value: ')
2385
- s.append(str(self.value) + '\n')
2386
- indent -= 1
2387
- s.append(' '*indent)
2388
- s.append(')')
2389
- return ''.join(s)
2390
-
2391
- __str__ = dump
2392
- __repr__ = dump
2393
-
2394
- def find_reachable(self, id_map=None):
2395
- """Returns a dictionary mapping Python id() values to stable sequence
2396
- numbers for all nodes in the tree rooted at this node. If id_map is
2397
- specified, found nodes are appended to it."""
2398
- if id_map is None:
2399
- id_map = {}
2400
- if id(self) in id_map:
2401
- raise NotWellFormed('node {!r} with id {} occurs more than once'.format(self, id(self)))
2402
- id_map[id(self)] = len(id_map)
2403
- return id_map
2404
-
2405
- def check_complete(self, id_map=None):
2406
- """Raises NotWellFormed if the tree rooted at this node is not
2407
- well-formed. If id_map is specified, this tree is only a subtree in the
2408
- context of a larger tree, and id_map must be a dict mapping from Python
2409
- id() codes to tree indices for all reachable nodes."""
2410
- if id_map is None:
2411
- id_map = self.find_reachable()
2412
-
2413
- def copy(self):
2414
- """Returns a shallow copy of this node."""
2415
- return ConstString(
2416
- value=self._attr_value
2417
- )
2418
-
2419
- def clone(self):
2420
- """Returns a deep copy of this node. This mimics the C++ interface,
2421
- deficiencies with links included; that is, links always point to the
2422
- original tree. If you're not cloning a subtree in a context where this
2423
- is the desired behavior, you may want to use the copy.deepcopy() from
2424
- the stdlib instead, which should copy links correctly."""
2425
- return ConstString(
2426
- value=_cloned(self._attr_value)
2427
- )
2428
-
2429
- @staticmethod
2430
- def _deserialize(cbor, seq_to_ob, links):
2431
- """Attempts to deserialize the given cbor object (in Python primitive
2432
- representation) into a node of this type. All (sub)nodes are added to
2433
- the seq_to_ob dict, indexed by their cbor sequence number. All links are
2434
- registered in the links list by means of a two-tuple of the setter
2435
- function for the link field and the sequence number of the target node.
2436
- """
2437
- if not isinstance(cbor, dict):
2438
- raise TypeError('node description object must be a dict')
2439
- typ = cbor.get('@t', None)
2440
- if typ is None:
2441
- raise ValueError('type (@t) field is missing from node serialization')
2442
- if typ != 'ConstString':
2443
- raise ValueError('found node serialization for ' + typ + ', but expected ConstString')
2444
-
2445
- # Deserialize the value field.
2446
- field = cbor.get('value', None)
2447
- if not isinstance(field, dict):
2448
- raise ValueError('missing or invalid serialization of field value')
2449
- if hasattr(cqasm.v1x.primitives.Str, 'deserialize_cbor'):
2450
- f_value = cqasm.v1x.primitives.Str.deserialize_cbor(field)
2451
- else:
2452
- f_value = cqasm.v1x.primitives.deserialize(cqasm.v1x.primitives.Str, field)
2453
-
2454
- # Construct the ConstString node.
2455
- node = ConstString(f_value)
2456
-
2457
- # Deserialize annotations.
2458
- for key, val in cbor.items():
2459
- if not (key.startswith('{') and key.endswith('}')):
2460
- continue
2461
- key = key[1:-1]
2462
- node[key] = cqasm.v1x.primitives.deserialize(key, val)
2463
-
2464
- # Register node in sequence number lookup.
2465
- seq = cbor.get('@i', None)
2466
- if not isinstance(seq, int):
2467
- raise ValueError('sequence number field (@i) is not an integer or missing from node serialization')
2468
- if seq in seq_to_ob:
2469
- raise ValueError('duplicate sequence number %d' % seq)
2470
- seq_to_ob[seq] = node
2471
-
2472
- return node
2473
-
2474
- def _serialize(self, id_map):
2475
- """Serializes this node to the Python primitive representation of its
2476
- CBOR serialization. The tree that the node belongs to must be
2477
- well-formed. id_map must match Python id() calls for all nodes to unique
2478
- integers, to use for the sequence number representation of links."""
2479
- cbor = {'@i': id_map[id(self)], '@t': 'ConstString'}
2480
-
2481
- # Serialize the value field.
2482
- if hasattr(self._attr_value, 'serialize_cbor'):
2483
- cbor['value'] = self._attr_value.serialize_cbor()
2484
- else:
2485
- cbor['value'] = cqasm.v1x.primitives.serialize(cqasm.v1x.primitives.Str, self._attr_value)
2486
-
2487
- # Serialize annotations.
2488
- for key, val in self._annot.items():
2489
- cbor['{%s}' % key] = _py_to_cbor(cqasm.v1x.primitives.serialize(key, val))
2490
-
2491
- return cbor
2492
-
2493
-
2494
- class MultiConstString(_Multiple):
2495
- """Wrapper for an edge with multiple ConstString objects."""
2496
-
2497
- _T = ConstString
2498
-
2499
-
2500
- _typemap['ConstString'] = ConstString
2501
-
2502
- class Function(Node):
2503
- """This can be returned by user-defined functions as a placeholder value for
2504
- something that needs to be evaluated at runtime rather than during constant
2505
- propagation. Annotations should be used to attach semantic information."""
2506
-
2507
- __slots__ = [
2508
- '_attr_name',
2509
- '_attr_operands',
2510
- '_attr_return_type',
2511
- ]
2512
-
2513
- def __init__(
2514
- self,
2515
- name=None,
2516
- operands=None,
2517
- return_type=None,
2518
- ):
2519
- super().__init__()
2520
- self.name = name
2521
- self.operands = operands
2522
- self.return_type = return_type
2523
-
2524
- @property
2525
- def name(self):
2526
- """Name of the function as it appears or should appear in the cQASM
2527
- file."""
2528
- return self._attr_name
2529
-
2530
- @name.setter
2531
- def name(self, val):
2532
- if val is None:
2533
- del self.name
2534
- return
2535
- if not isinstance(val, cqasm.v1x.primitives.Str):
2536
- # Try to "typecast" if this isn't an obvious mistake.
2537
- if isinstance(val, Node):
2538
- raise TypeError('name must be of type cqasm.v1x.primitives.Str')
2539
- val = cqasm.v1x.primitives.Str(val)
2540
- self._attr_name = val
2541
-
2542
- @name.deleter
2543
- def name(self):
2544
- self._attr_name = cqasm.v1x.primitives.Str()
2545
-
2546
- @property
2547
- def operands(self):
2548
- """Operands for the function."""
2549
- return self._attr_operands
2550
-
2551
- @operands.setter
2552
- def operands(self, val):
2553
- if val is None:
2554
- del self.operands
2555
- return
2556
- if not isinstance(val, cqasm.v1x.values.MultiNode):
2557
- # Try to "typecast" if this isn't an obvious mistake.
2558
- if isinstance(val, Node):
2559
- raise TypeError('operands must be of type cqasm.v1x.values.MultiNode')
2560
- val = cqasm.v1x.values.MultiNode(val)
2561
- self._attr_operands = val
2562
-
2563
- @operands.deleter
2564
- def operands(self):
2565
- self._attr_operands = cqasm.v1x.values.MultiNode()
2566
-
2567
- @property
2568
- def return_type(self):
2569
- """Operands for the function."""
2570
- return self._attr_return_type
2571
-
2572
- @return_type.setter
2573
- def return_type(self, val):
2574
- if val is None:
2575
- del self.return_type
2576
- return
2577
- if not isinstance(val, cqasm.v1x.types.Node):
2578
- # Try to "typecast" if this isn't an obvious mistake.
2579
- if isinstance(val, Node):
2580
- raise TypeError('return_type must be of type cqasm.v1x.types.Node')
2581
- val = cqasm.v1x.types.Node(val)
2582
- self._attr_return_type = val
2583
-
2584
- @return_type.deleter
2585
- def return_type(self):
2586
- self._attr_return_type = None
2587
-
2588
- def __eq__(self, other):
2589
- """Equality operator. Ignores annotations!"""
2590
- if not isinstance(other, Function):
2591
- return False
2592
- if self.name != other.name:
2593
- return False
2594
- if self.operands != other.operands:
2595
- return False
2596
- if self.return_type != other.return_type:
2597
- return False
2598
- return True
2599
-
2600
- def dump(self, indent=0, annotations=None, links=1):
2601
- """Returns a debug representation of this tree as a multiline string.
2602
- indent is the number of double spaces prefixed before every line.
2603
- annotations, if specified, must be a set-like object containing the key
2604
- strings of the annotations that are to be printed. links specifies the
2605
- maximum link recursion depth."""
2606
- s = [' '*indent]
2607
- s.append('Function(')
2608
- if annotations is None:
2609
- annotations = []
2610
- for key in annotations:
2611
- if key in self:
2612
- s.append(' # {}: {}'.format(key, self[key]))
2613
- s.append('\n')
2614
- indent += 1
2615
- s.append(' '*indent)
2616
- s.append('name: ')
2617
- s.append(str(self.name) + '\n')
2618
- s.append(' '*indent)
2619
- s.append('operands: ')
2620
- if not self.operands:
2621
- s.append('-\n')
2622
- else:
2623
- s.append('[\n')
2624
- for child in self.operands:
2625
- s.append(child.dump(indent + 1, annotations, links) + '\n')
2626
- s.append(' '*indent + ']\n')
2627
- s.append(' '*indent)
2628
- s.append('return_type: ')
2629
- if self.return_type is None:
2630
- s.append('!MISSING\n')
2631
- else:
2632
- s.append('<\n')
2633
- s.append(self.return_type.dump(indent + 1, annotations, links) + '\n')
2634
- s.append(' '*indent + '>\n')
2635
- indent -= 1
2636
- s.append(' '*indent)
2637
- s.append(')')
2638
- return ''.join(s)
2639
-
2640
- __str__ = dump
2641
- __repr__ = dump
2642
-
2643
- def find_reachable(self, id_map=None):
2644
- """Returns a dictionary mapping Python id() values to stable sequence
2645
- numbers for all nodes in the tree rooted at this node. If id_map is
2646
- specified, found nodes are appended to it."""
2647
- if id_map is None:
2648
- id_map = {}
2649
- if id(self) in id_map:
2650
- raise NotWellFormed('node {!r} with id {} occurs more than once'.format(self, id(self)))
2651
- id_map[id(self)] = len(id_map)
2652
- for el in self._attr_operands:
2653
- el.find_reachable(id_map)
2654
- if self._attr_return_type is not None:
2655
- self._attr_return_type.find_reachable(id_map)
2656
- return id_map
2657
-
2658
- def check_complete(self, id_map=None):
2659
- """Raises NotWellFormed if the tree rooted at this node is not
2660
- well-formed. If id_map is specified, this tree is only a subtree in the
2661
- context of a larger tree, and id_map must be a dict mapping from Python
2662
- id() codes to tree indices for all reachable nodes."""
2663
- if id_map is None:
2664
- id_map = self.find_reachable()
2665
- for child in self._attr_operands:
2666
- child.check_complete(id_map)
2667
- if self._attr_return_type is None:
2668
- raise NotWellFormed('return_type is required but not set')
2669
- if self._attr_return_type is not None:
2670
- self._attr_return_type.check_complete(id_map)
2671
-
2672
- def copy(self):
2673
- """Returns a shallow copy of this node."""
2674
- return Function(
2675
- name=self._attr_name,
2676
- operands=self._attr_operands.copy(),
2677
- return_type=self._attr_return_type
2678
- )
2679
-
2680
- def clone(self):
2681
- """Returns a deep copy of this node. This mimics the C++ interface,
2682
- deficiencies with links included; that is, links always point to the
2683
- original tree. If you're not cloning a subtree in a context where this
2684
- is the desired behavior, you may want to use the copy.deepcopy() from
2685
- the stdlib instead, which should copy links correctly."""
2686
- return Function(
2687
- name=_cloned(self._attr_name),
2688
- operands=_cloned(self._attr_operands),
2689
- return_type=_cloned(self._attr_return_type)
2690
- )
2691
-
2692
- @staticmethod
2693
- def _deserialize(cbor, seq_to_ob, links):
2694
- """Attempts to deserialize the given cbor object (in Python primitive
2695
- representation) into a node of this type. All (sub)nodes are added to
2696
- the seq_to_ob dict, indexed by their cbor sequence number. All links are
2697
- registered in the links list by means of a two-tuple of the setter
2698
- function for the link field and the sequence number of the target node.
2699
- """
2700
- if not isinstance(cbor, dict):
2701
- raise TypeError('node description object must be a dict')
2702
- typ = cbor.get('@t', None)
2703
- if typ is None:
2704
- raise ValueError('type (@t) field is missing from node serialization')
2705
- if typ != 'Function':
2706
- raise ValueError('found node serialization for ' + typ + ', but expected Function')
2707
-
2708
- # Deserialize the name field.
2709
- field = cbor.get('name', None)
2710
- if not isinstance(field, dict):
2711
- raise ValueError('missing or invalid serialization of field name')
2712
- if hasattr(cqasm.v1x.primitives.Str, 'deserialize_cbor'):
2713
- f_name = cqasm.v1x.primitives.Str.deserialize_cbor(field)
2714
- else:
2715
- f_name = cqasm.v1x.primitives.deserialize(cqasm.v1x.primitives.Str, field)
2716
-
2717
- # Deserialize the operands field.
2718
- field = cbor.get('operands', None)
2719
- if not isinstance(field, dict):
2720
- raise ValueError('missing or invalid serialization of field operands')
2721
- if field.get('@T') != '*':
2722
- raise ValueError('unexpected edge type for field operands')
2723
- data = field.get('@d', None)
2724
- if not isinstance(data, list):
2725
- raise ValueError('missing serialization of Any/Many contents')
2726
- f_operands = cqasm.v1x.values.MultiNode()
2727
- for element in data:
2728
- if element.get('@T') != '1':
2729
- raise ValueError('unexpected edge type for Any/Many element')
2730
- f_operands.append(cqasm.v1x.values.Node._deserialize(element, seq_to_ob, links))
2731
-
2732
- # Deserialize the return_type field.
2733
- field = cbor.get('return_type', None)
2734
- if not isinstance(field, dict):
2735
- raise ValueError('missing or invalid serialization of field return_type')
2736
- if field.get('@T') != '1':
2737
- raise ValueError('unexpected edge type for field return_type')
2738
- if field.get('@t', None) is None:
2739
- f_return_type = None
2740
- else:
2741
- f_return_type = cqasm.v1x.types.Node._deserialize(field, seq_to_ob, links)
2742
-
2743
- # Construct the Function node.
2744
- node = Function(f_name, f_operands, f_return_type)
2745
-
2746
- # Deserialize annotations.
2747
- for key, val in cbor.items():
2748
- if not (key.startswith('{') and key.endswith('}')):
2749
- continue
2750
- key = key[1:-1]
2751
- node[key] = cqasm.v1x.primitives.deserialize(key, val)
2752
-
2753
- # Register node in sequence number lookup.
2754
- seq = cbor.get('@i', None)
2755
- if not isinstance(seq, int):
2756
- raise ValueError('sequence number field (@i) is not an integer or missing from node serialization')
2757
- if seq in seq_to_ob:
2758
- raise ValueError('duplicate sequence number %d' % seq)
2759
- seq_to_ob[seq] = node
2760
-
2761
- return node
2762
-
2763
- def _serialize(self, id_map):
2764
- """Serializes this node to the Python primitive representation of its
2765
- CBOR serialization. The tree that the node belongs to must be
2766
- well-formed. id_map must match Python id() calls for all nodes to unique
2767
- integers, to use for the sequence number representation of links."""
2768
- cbor = {'@i': id_map[id(self)], '@t': 'Function'}
2769
-
2770
- # Serialize the name field.
2771
- if hasattr(self._attr_name, 'serialize_cbor'):
2772
- cbor['name'] = self._attr_name.serialize_cbor()
2773
- else:
2774
- cbor['name'] = cqasm.v1x.primitives.serialize(cqasm.v1x.primitives.Str, self._attr_name)
2775
-
2776
- # Serialize the operands field.
2777
- field = {'@T': '*'}
2778
- lst = []
2779
- for el in self._attr_operands:
2780
- el = el._serialize(id_map)
2781
- el['@T'] = '1'
2782
- lst.append(el)
2783
- field['@d'] = lst
2784
- cbor['operands'] = field
2785
-
2786
- # Serialize the return_type field.
2787
- field = {'@T': '1'}
2788
- if self._attr_return_type is None:
2789
- field['@t'] = None
2790
- else:
2791
- field.update(self._attr_return_type._serialize(id_map))
2792
- cbor['return_type'] = field
2793
-
2794
- # Serialize annotations.
2795
- for key, val in self._annot.items():
2796
- cbor['{%s}' % key] = _py_to_cbor(cqasm.v1x.primitives.serialize(key, val))
2797
-
2798
- return cbor
2799
-
2800
-
2801
- class MultiFunction(_Multiple):
2802
- """Wrapper for an edge with multiple Function objects."""
2803
-
2804
- _T = Function
2805
-
2806
-
2807
- _typemap['Function'] = Function
2808
-
2809
- class QubitRefs(Reference):
2810
- """Represents a qubit, or a set of qubits for single-gate-multiple-qubit
2811
- notation. The indices must not repeat."""
2812
-
2813
- __slots__ = [
2814
- '_attr_index',
2815
- ]
2816
-
2817
- def __init__(
2818
- self,
2819
- index=None,
2820
- ):
2821
- super().__init__()
2822
- self.index = index
2823
-
2824
- @property
2825
- def index(self):
2826
- """Set of qubit indices referred to, starting at 0."""
2827
- return self._attr_index
2828
-
2829
- @index.setter
2830
- def index(self, val):
2831
- if val is None:
2832
- del self.index
2833
- return
2834
- if not isinstance(val, MultiConstInt):
2835
- # Try to "typecast" if this isn't an obvious mistake.
2836
- if isinstance(val, Node):
2837
- raise TypeError('index must be of type MultiConstInt')
2838
- val = MultiConstInt(val)
2839
- self._attr_index = val
2840
-
2841
- @index.deleter
2842
- def index(self):
2843
- self._attr_index = MultiConstInt()
2844
-
2845
- def __eq__(self, other):
2846
- """Equality operator. Ignores annotations!"""
2847
- if not isinstance(other, QubitRefs):
2848
- return False
2849
- if self.index != other.index:
2850
- return False
2851
- return True
2852
-
2853
- def dump(self, indent=0, annotations=None, links=1):
2854
- """Returns a debug representation of this tree as a multiline string.
2855
- indent is the number of double spaces prefixed before every line.
2856
- annotations, if specified, must be a set-like object containing the key
2857
- strings of the annotations that are to be printed. links specifies the
2858
- maximum link recursion depth."""
2859
- s = [' '*indent]
2860
- s.append('QubitRefs(')
2861
- if annotations is None:
2862
- annotations = []
2863
- for key in annotations:
2864
- if key in self:
2865
- s.append(' # {}: {}'.format(key, self[key]))
2866
- s.append('\n')
2867
- indent += 1
2868
- s.append(' '*indent)
2869
- s.append('index: ')
2870
- if not self.index:
2871
- s.append('!MISSING\n')
2872
- else:
2873
- s.append('[\n')
2874
- for child in self.index:
2875
- s.append(child.dump(indent + 1, annotations, links) + '\n')
2876
- s.append(' '*indent + ']\n')
2877
- indent -= 1
2878
- s.append(' '*indent)
2879
- s.append(')')
2880
- return ''.join(s)
2881
-
2882
- __str__ = dump
2883
- __repr__ = dump
2884
-
2885
- def find_reachable(self, id_map=None):
2886
- """Returns a dictionary mapping Python id() values to stable sequence
2887
- numbers for all nodes in the tree rooted at this node. If id_map is
2888
- specified, found nodes are appended to it."""
2889
- if id_map is None:
2890
- id_map = {}
2891
- if id(self) in id_map:
2892
- raise NotWellFormed('node {!r} with id {} occurs more than once'.format(self, id(self)))
2893
- id_map[id(self)] = len(id_map)
2894
- for el in self._attr_index:
2895
- el.find_reachable(id_map)
2896
- return id_map
2897
-
2898
- def check_complete(self, id_map=None):
2899
- """Raises NotWellFormed if the tree rooted at this node is not
2900
- well-formed. If id_map is specified, this tree is only a subtree in the
2901
- context of a larger tree, and id_map must be a dict mapping from Python
2902
- id() codes to tree indices for all reachable nodes."""
2903
- if id_map is None:
2904
- id_map = self.find_reachable()
2905
- if not self._attr_index:
2906
- raise NotWellFormed('index needs at least one node but has zero')
2907
- for child in self._attr_index:
2908
- child.check_complete(id_map)
2909
-
2910
- def copy(self):
2911
- """Returns a shallow copy of this node."""
2912
- return QubitRefs(
2913
- index=self._attr_index.copy()
2914
- )
2915
-
2916
- def clone(self):
2917
- """Returns a deep copy of this node. This mimics the C++ interface,
2918
- deficiencies with links included; that is, links always point to the
2919
- original tree. If you're not cloning a subtree in a context where this
2920
- is the desired behavior, you may want to use the copy.deepcopy() from
2921
- the stdlib instead, which should copy links correctly."""
2922
- return QubitRefs(
2923
- index=_cloned(self._attr_index)
2924
- )
2925
-
2926
- @staticmethod
2927
- def _deserialize(cbor, seq_to_ob, links):
2928
- """Attempts to deserialize the given cbor object (in Python primitive
2929
- representation) into a node of this type. All (sub)nodes are added to
2930
- the seq_to_ob dict, indexed by their cbor sequence number. All links are
2931
- registered in the links list by means of a two-tuple of the setter
2932
- function for the link field and the sequence number of the target node.
2933
- """
2934
- if not isinstance(cbor, dict):
2935
- raise TypeError('node description object must be a dict')
2936
- typ = cbor.get('@t', None)
2937
- if typ is None:
2938
- raise ValueError('type (@t) field is missing from node serialization')
2939
- if typ != 'QubitRefs':
2940
- raise ValueError('found node serialization for ' + typ + ', but expected QubitRefs')
2941
-
2942
- # Deserialize the index field.
2943
- field = cbor.get('index', None)
2944
- if not isinstance(field, dict):
2945
- raise ValueError('missing or invalid serialization of field index')
2946
- if field.get('@T') != '+':
2947
- raise ValueError('unexpected edge type for field index')
2948
- data = field.get('@d', None)
2949
- if not isinstance(data, list):
2950
- raise ValueError('missing serialization of Any/Many contents')
2951
- f_index = MultiConstInt()
2952
- for element in data:
2953
- if element.get('@T') != '1':
2954
- raise ValueError('unexpected edge type for Any/Many element')
2955
- f_index.append(ConstInt._deserialize(element, seq_to_ob, links))
2956
-
2957
- # Construct the QubitRefs node.
2958
- node = QubitRefs(f_index)
2959
-
2960
- # Deserialize annotations.
2961
- for key, val in cbor.items():
2962
- if not (key.startswith('{') and key.endswith('}')):
2963
- continue
2964
- key = key[1:-1]
2965
- node[key] = cqasm.v1x.primitives.deserialize(key, val)
2966
-
2967
- # Register node in sequence number lookup.
2968
- seq = cbor.get('@i', None)
2969
- if not isinstance(seq, int):
2970
- raise ValueError('sequence number field (@i) is not an integer or missing from node serialization')
2971
- if seq in seq_to_ob:
2972
- raise ValueError('duplicate sequence number %d' % seq)
2973
- seq_to_ob[seq] = node
2974
-
2975
- return node
2976
-
2977
- def _serialize(self, id_map):
2978
- """Serializes this node to the Python primitive representation of its
2979
- CBOR serialization. The tree that the node belongs to must be
2980
- well-formed. id_map must match Python id() calls for all nodes to unique
2981
- integers, to use for the sequence number representation of links."""
2982
- cbor = {'@i': id_map[id(self)], '@t': 'QubitRefs'}
2983
-
2984
- # Serialize the index field.
2985
- field = {'@T': '+'}
2986
- lst = []
2987
- for el in self._attr_index:
2988
- el = el._serialize(id_map)
2989
- el['@T'] = '1'
2990
- lst.append(el)
2991
- field['@d'] = lst
2992
- cbor['index'] = field
2993
-
2994
- # Serialize annotations.
2995
- for key, val in self._annot.items():
2996
- cbor['{%s}' % key] = _py_to_cbor(cqasm.v1x.primitives.serialize(key, val))
2997
-
2998
- return cbor
2999
-
3000
-
3001
- class MultiQubitRefs(_Multiple):
3002
- """Wrapper for an edge with multiple QubitRefs objects."""
3003
-
3004
- _T = QubitRefs
3005
-
3006
-
3007
- _typemap['QubitRefs'] = QubitRefs
3008
-
3009
- class VariableRef(Reference):
3010
- """Represents a variable reference."""
3011
-
3012
- __slots__ = [
3013
- '_attr_variable',
3014
- ]
3015
-
3016
- def __init__(
3017
- self,
3018
- variable=None,
3019
- ):
3020
- super().__init__()
3021
- self.variable = variable
3022
-
3023
- @property
3024
- def variable(self):
3025
- """The referenced variable."""
3026
- return self._attr_variable
3027
-
3028
- @variable.setter
3029
- def variable(self, val):
3030
- if val is None:
3031
- del self.variable
3032
- return
3033
- if not isinstance(val, cqasm.v1x.semantic.Variable):
3034
- raise TypeError('variable must be of type cqasm.v1x.semantic.Variable')
3035
- self._attr_variable = val
3036
-
3037
- @variable.deleter
3038
- def variable(self):
3039
- self._attr_variable = None
3040
-
3041
- def __eq__(self, other):
3042
- """Equality operator. Ignores annotations!"""
3043
- if not isinstance(other, VariableRef):
3044
- return False
3045
- if self.variable is not other.variable:
3046
- return False
3047
- return True
3048
-
3049
- def dump(self, indent=0, annotations=None, links=1):
3050
- """Returns a debug representation of this tree as a multiline string.
3051
- indent is the number of double spaces prefixed before every line.
3052
- annotations, if specified, must be a set-like object containing the key
3053
- strings of the annotations that are to be printed. links specifies the
3054
- maximum link recursion depth."""
3055
- s = [' '*indent]
3056
- s.append('VariableRef(')
3057
- if annotations is None:
3058
- annotations = []
3059
- for key in annotations:
3060
- if key in self:
3061
- s.append(' # {}: {}'.format(key, self[key]))
3062
- s.append('\n')
3063
- indent += 1
3064
- s.append(' '*indent)
3065
- s.append('variable --> ')
3066
- if self.variable is None:
3067
- s.append('!MISSING\n')
3068
- else:
3069
- s.append('<\n')
3070
- if links:
3071
- s.append(self.variable.dump(indent + 1, annotations, links - 1) + '\n')
3072
- else:
3073
- s.append(' '*(indent+1) + '...\n')
3074
- s.append(' '*indent + '>\n')
3075
- indent -= 1
3076
- s.append(' '*indent)
3077
- s.append(')')
3078
- return ''.join(s)
3079
-
3080
- __str__ = dump
3081
- __repr__ = dump
3082
-
3083
- def find_reachable(self, id_map=None):
3084
- """Returns a dictionary mapping Python id() values to stable sequence
3085
- numbers for all nodes in the tree rooted at this node. If id_map is
3086
- specified, found nodes are appended to it."""
3087
- if id_map is None:
3088
- id_map = {}
3089
- if id(self) in id_map:
3090
- raise NotWellFormed('node {!r} with id {} occurs more than once'.format(self, id(self)))
3091
- id_map[id(self)] = len(id_map)
3092
- return id_map
3093
-
3094
- def check_complete(self, id_map=None):
3095
- """Raises NotWellFormed if the tree rooted at this node is not
3096
- well-formed. If id_map is specified, this tree is only a subtree in the
3097
- context of a larger tree, and id_map must be a dict mapping from Python
3098
- id() codes to tree indices for all reachable nodes."""
3099
- if id_map is None:
3100
- id_map = self.find_reachable()
3101
- if self._attr_variable is None:
3102
- raise NotWellFormed('variable is required but not set')
3103
- if self._attr_variable is not None:
3104
- if id(self._attr_variable) not in id_map:
3105
- raise NotWellFormed('variable links to unreachable node')
3106
-
3107
- def copy(self):
3108
- """Returns a shallow copy of this node."""
3109
- return VariableRef(
3110
- variable=self._attr_variable
3111
- )
3112
-
3113
- def clone(self):
3114
- """Returns a deep copy of this node. This mimics the C++ interface,
3115
- deficiencies with links included; that is, links always point to the
3116
- original tree. If you're not cloning a subtree in a context where this
3117
- is the desired behavior, you may want to use the copy.deepcopy() from
3118
- the stdlib instead, which should copy links correctly."""
3119
- return VariableRef(
3120
- variable=self._attr_variable
3121
- )
3122
-
3123
- @staticmethod
3124
- def _deserialize(cbor, seq_to_ob, links):
3125
- """Attempts to deserialize the given cbor object (in Python primitive
3126
- representation) into a node of this type. All (sub)nodes are added to
3127
- the seq_to_ob dict, indexed by their cbor sequence number. All links are
3128
- registered in the links list by means of a two-tuple of the setter
3129
- function for the link field and the sequence number of the target node.
3130
- """
3131
- if not isinstance(cbor, dict):
3132
- raise TypeError('node description object must be a dict')
3133
- typ = cbor.get('@t', None)
3134
- if typ is None:
3135
- raise ValueError('type (@t) field is missing from node serialization')
3136
- if typ != 'VariableRef':
3137
- raise ValueError('found node serialization for ' + typ + ', but expected VariableRef')
3138
-
3139
- # Deserialize the variable field.
3140
- field = cbor.get('variable', None)
3141
- if not isinstance(field, dict):
3142
- raise ValueError('missing or invalid serialization of field variable')
3143
- if field.get('@T') != '$':
3144
- raise ValueError('unexpected edge type for field variable')
3145
- f_variable = None
3146
- l_variable = field.get('@l', None)
3147
-
3148
- # Construct the VariableRef node.
3149
- node = VariableRef(f_variable)
3150
-
3151
- # Register links to be made after tree construction.
3152
- links.append((lambda val: VariableRef.variable.fset(node, val), l_variable))
3153
-
3154
- # Deserialize annotations.
3155
- for key, val in cbor.items():
3156
- if not (key.startswith('{') and key.endswith('}')):
3157
- continue
3158
- key = key[1:-1]
3159
- node[key] = cqasm.v1x.primitives.deserialize(key, val)
3160
-
3161
- # Register node in sequence number lookup.
3162
- seq = cbor.get('@i', None)
3163
- if not isinstance(seq, int):
3164
- raise ValueError('sequence number field (@i) is not an integer or missing from node serialization')
3165
- if seq in seq_to_ob:
3166
- raise ValueError('duplicate sequence number %d' % seq)
3167
- seq_to_ob[seq] = node
3168
-
3169
- return node
3170
-
3171
- def _serialize(self, id_map):
3172
- """Serializes this node to the Python primitive representation of its
3173
- CBOR serialization. The tree that the node belongs to must be
3174
- well-formed. id_map must match Python id() calls for all nodes to unique
3175
- integers, to use for the sequence number representation of links."""
3176
- cbor = {'@i': id_map[id(self)], '@t': 'VariableRef'}
3177
-
3178
- # Serialize the variable field.
3179
- field = {'@T': '$'}
3180
- if self._attr_variable is None:
3181
- field['@l'] = None
3182
- else:
3183
- field['@l'] = id_map[id(self._attr_variable)]
3184
- cbor['variable'] = field
3185
-
3186
- # Serialize annotations.
3187
- for key, val in self._annot.items():
3188
- cbor['{%s}' % key] = _py_to_cbor(cqasm.v1x.primitives.serialize(key, val))
3189
-
3190
- return cbor
3191
-
3192
-
3193
- class MultiVariableRef(_Multiple):
3194
- """Wrapper for an edge with multiple VariableRef objects."""
3195
-
3196
- _T = VariableRef
3197
-
3198
-
3199
- _typemap['VariableRef'] = VariableRef
3200
-