@@ -373,6 +373,9 @@ def _parse_custom_operation(
373
373
) = custom_operations [gate_name ]
374
374
else :
375
375
type_str , num_qubits , num_clbits , definition = custom_operations [gate_name ]
376
+ # Strip the trailing "_{uuid}" from the gate name if the version >=11
377
+ if version >= 11 :
378
+ gate_name = "_" .join (gate_name .split ("_" )[:- 1 ])
376
379
type_key = type_keys .CircuitInstruction (type_str )
377
380
378
381
if type_key == type_keys .CircuitInstruction .INSTRUCTION :
@@ -572,7 +575,7 @@ def _dumps_instruction_parameter(param, index_map, use_symengine):
572
575
573
576
574
577
# pylint: disable=too-many-boolean-expressions
575
- def _write_instruction (file_obj , instruction , custom_operations , index_map , use_symengine ):
578
+ def _write_instruction (file_obj , instruction , custom_operations , index_map , use_symengine , version ):
576
579
if isinstance (instruction .operation , Instruction ):
577
580
gate_class_name = instruction .operation .base_class .__name__
578
581
else :
@@ -591,15 +594,17 @@ def _write_instruction(file_obj, instruction, custom_operations, index_map, use_
591
594
or isinstance (instruction .operation , library .BlueprintCircuit )
592
595
):
593
596
gate_class_name = instruction .operation .name
597
+ if version >= 11 :
598
+ # Assign a uuid to each instance of a custom operation
599
+ gate_class_name = f"{ gate_class_name } _{ uuid .uuid4 ().hex } "
594
600
# ucr*_dg gates can have different numbers of parameters,
595
601
# the uuid is appended to avoid storing a single definition
596
602
# in circuits with multiple ucr*_dg gates.
597
- if instruction .operation .name in [ "ucrx_dg" , "ucry_dg" , "ucrz_dg" ] :
598
- gate_class_name += "_" + str ( uuid .uuid4 ())
603
+ elif instruction .operation .name in { "ucrx_dg" , "ucry_dg" , "ucrz_dg" } :
604
+ gate_class_name = f" { gate_class_name } _ { uuid .uuid4 ()} "
599
605
600
- if gate_class_name not in custom_operations :
601
- custom_operations [gate_class_name ] = instruction .operation
602
- custom_operations_list .append (gate_class_name )
606
+ custom_operations [gate_class_name ] = instruction .operation
607
+ custom_operations_list .append (gate_class_name )
603
608
604
609
elif gate_class_name == "ControlledGate" :
605
610
# controlled gates can have the same name but different parameter
@@ -724,7 +729,7 @@ def _write_elem(buffer, op):
724
729
file_obj .write (synth_data )
725
730
726
731
727
- def _write_custom_operation (file_obj , name , operation , custom_operations , use_symengine ):
732
+ def _write_custom_operation (file_obj , name , operation , custom_operations , use_symengine , version ):
728
733
type_key = type_keys .CircuitInstruction .assign (operation )
729
734
has_definition = False
730
735
size = 0
@@ -768,6 +773,7 @@ def _write_custom_operation(file_obj, name, operation, custom_operations, use_sy
768
773
custom_operations ,
769
774
{},
770
775
use_symengine ,
776
+ version ,
771
777
)
772
778
base_gate_raw = base_gate_buffer .getvalue ()
773
779
name_raw = name .encode (common .ENCODE )
@@ -1002,7 +1008,9 @@ def _read_layout_v2(file_obj, circuit):
1002
1008
circuit ._layout ._output_qubit_list = circuit .qubits
1003
1009
1004
1010
1005
- def write_circuit (file_obj , circuit , metadata_serializer = None , use_symengine = False ):
1011
+ def write_circuit (
1012
+ file_obj , circuit , metadata_serializer = None , use_symengine = False , version = common .QPY_VERSION
1013
+ ):
1006
1014
"""Write a single QuantumCircuit object in the file like object.
1007
1015
1008
1016
Args:
@@ -1016,6 +1024,7 @@ def write_circuit(file_obj, circuit, metadata_serializer=None, use_symengine=Fal
1016
1024
native mechanism. This is a faster serialization alternative, but not supported in all
1017
1025
platforms. Please check that your target platform is supported by the symengine library
1018
1026
before setting this option, as it will be required by qpy to deserialize the payload.
1027
+ version (int): The QPY format version to use for serializing this circuit
1019
1028
"""
1020
1029
metadata_raw = json .dumps (
1021
1030
circuit .metadata , separators = ("," , ":" ), cls = metadata_serializer
@@ -1056,7 +1065,7 @@ def write_circuit(file_obj, circuit, metadata_serializer=None, use_symengine=Fal
1056
1065
index_map ["c" ] = {bit : index for index , bit in enumerate (circuit .clbits )}
1057
1066
for instruction in circuit .data :
1058
1067
_write_instruction (
1059
- instruction_buffer , instruction , custom_operations , index_map , use_symengine
1068
+ instruction_buffer , instruction , custom_operations , index_map , use_symengine , version
1060
1069
)
1061
1070
1062
1071
with io .BytesIO () as custom_operations_buffer :
@@ -1068,7 +1077,12 @@ def write_circuit(file_obj, circuit, metadata_serializer=None, use_symengine=Fal
1068
1077
operation = custom_operations [name ]
1069
1078
new_custom_operations .extend (
1070
1079
_write_custom_operation (
1071
- custom_operations_buffer , name , operation , custom_operations , use_symengine
1080
+ custom_operations_buffer ,
1081
+ name ,
1082
+ operation ,
1083
+ custom_operations ,
1084
+ use_symengine ,
1085
+ version ,
1072
1086
)
1073
1087
)
1074
1088
0 commit comments