13
13
use crate :: circuit_instruction:: CircuitInstruction ;
14
14
use crate :: intern_context:: { BitType , IndexType , InternContext } ;
15
15
use crate :: SliceOrInt ;
16
+ use smallvec:: SmallVec ;
17
+
18
+ use crate :: operations:: { OperationType , Param } ;
16
19
17
20
use hashbrown:: HashMap ;
18
21
use pyo3:: exceptions:: { PyIndexError , PyKeyError , PyRuntimeError , PyValueError } ;
@@ -25,11 +28,15 @@ use std::hash::{Hash, Hasher};
25
28
#[ derive( Clone , Debug ) ]
26
29
struct PackedInstruction {
27
30
/// The Python-side operation instance.
28
- op : PyObject ,
31
+ op : OperationType ,
29
32
/// The index under which the interner has stored `qubits`.
30
33
qubits_id : IndexType ,
31
34
/// The index under which the interner has stored `clbits`.
32
35
clbits_id : IndexType ,
36
+ params : Option < SmallVec < [ Param ; 3 ] > > ,
37
+ label : Option < String > ,
38
+ duration : Option < PyObject > ,
39
+ unit : Option < String > ,
33
40
}
34
41
35
42
/// Private wrapper for Python-side Bit instances that implements
@@ -324,7 +331,7 @@ impl CircuitData {
324
331
0 ,
325
332
) ?;
326
333
res. intern_context = self . intern_context . clone ( ) ;
327
- res. data = self . data . clone ( ) ;
334
+ res. data . clone_from ( & self . data ) ;
328
335
Ok ( res)
329
336
}
330
337
@@ -366,7 +373,15 @@ impl CircuitData {
366
373
#[ pyo3( signature = ( func) ) ]
367
374
pub fn foreach_op ( & self , py : Python < ' _ > , func : & Bound < PyAny > ) -> PyResult < ( ) > {
368
375
for inst in self . data . iter ( ) {
369
- func. call1 ( ( inst. op . bind ( py) , ) ) ?;
376
+ match & inst. op {
377
+ OperationType :: Standard ( op) => {
378
+ let op = op. into_py ( py) ;
379
+ func. call1 ( ( op, ) )
380
+ }
381
+ OperationType :: Instruction ( op) => func. call1 ( ( op. instruction . clone_ref ( py) , ) ) ,
382
+ OperationType :: Gate ( op) => func. call1 ( ( op. gate . clone_ref ( py) , ) ) ,
383
+ OperationType :: Operation ( op) => func. call1 ( ( op. operation . clone_ref ( py) , ) ) ,
384
+ } ?;
370
385
}
371
386
Ok ( ( ) )
372
387
}
@@ -380,7 +395,15 @@ impl CircuitData {
380
395
#[ pyo3( signature = ( func) ) ]
381
396
pub fn foreach_op_indexed ( & self , py : Python < ' _ > , func : & Bound < PyAny > ) -> PyResult < ( ) > {
382
397
for ( index, inst) in self . data . iter ( ) . enumerate ( ) {
383
- func. call1 ( ( index, inst. op . bind ( py) ) ) ?;
398
+ match & inst. op {
399
+ OperationType :: Standard ( op) => {
400
+ let op = op. into_py ( py) ;
401
+ func. call1 ( ( index, op) )
402
+ }
403
+ OperationType :: Instruction ( op) => func. call1 ( ( index, op. instruction . clone_ref ( py) ) ) ,
404
+ OperationType :: Gate ( op) => func. call1 ( ( index, op. gate . clone_ref ( py) ) ) ,
405
+ OperationType :: Operation ( op) => func. call1 ( ( index, op. operation . clone_ref ( py) ) ) ,
406
+ } ?;
384
407
}
385
408
Ok ( ( ) )
386
409
}
@@ -395,7 +418,16 @@ impl CircuitData {
395
418
#[ pyo3( signature = ( func) ) ]
396
419
pub fn map_ops ( & mut self , py : Python < ' _ > , func : & Bound < PyAny > ) -> PyResult < ( ) > {
397
420
for inst in self . data . iter_mut ( ) {
398
- inst. op = func. call1 ( ( inst. op . bind ( py) , ) ) ?. into_py ( py) ;
421
+ inst. op = match & inst. op {
422
+ OperationType :: Standard ( op) => {
423
+ let op = op. into_py ( py) ;
424
+ func. call1 ( ( op, ) )
425
+ }
426
+ OperationType :: Instruction ( op) => func. call1 ( ( op. instruction . clone_ref ( py) , ) ) ,
427
+ OperationType :: Gate ( op) => func. call1 ( ( op. gate . clone_ref ( py) , ) ) ,
428
+ OperationType :: Operation ( op) => func. call1 ( ( op. operation . clone_ref ( py) , ) ) ,
429
+ } ?
430
+ . extract ( ) ?;
399
431
}
400
432
Ok ( ( ) )
401
433
}
@@ -666,9 +698,13 @@ impl CircuitData {
666
698
. collect :: < PyResult < Vec < BitType > > > ( ) ?;
667
699
668
700
self . data . push ( PackedInstruction {
669
- op : inst. op . clone_ref ( py ) ,
701
+ op : inst. op . clone ( ) ,
670
702
qubits_id : self . intern_context . intern ( qubits) ?,
671
703
clbits_id : self . intern_context . intern ( clbits) ?,
704
+ params : inst. params . clone ( ) ,
705
+ label : inst. label . clone ( ) ,
706
+ duration : inst. duration . clone ( ) ,
707
+ unit : inst. unit . clone ( ) ,
672
708
} ) ;
673
709
}
674
710
return Ok ( ( ) ) ;
@@ -720,7 +756,7 @@ impl CircuitData {
720
756
721
757
fn __traverse__ ( & self , visit : PyVisit < ' _ > ) -> Result < ( ) , PyTraverseError > {
722
758
for packed in self . data . iter ( ) {
723
- visit. call ( & packed. op ) ?;
759
+ visit. call ( & packed. duration ) ?;
724
760
}
725
761
for bit in self . qubits_native . iter ( ) . chain ( self . clbits_native . iter ( ) ) {
726
762
visit. call ( bit) ?;
@@ -820,17 +856,21 @@ impl CircuitData {
820
856
self . intern_context . intern ( args)
821
857
} ;
822
858
Ok ( PackedInstruction {
823
- op : inst. operation . clone_ref ( py ) ,
859
+ op : inst. operation . clone ( ) ,
824
860
qubits_id : interned_bits ( & self . qubit_indices_native , inst. qubits . bind ( py) ) ?,
825
861
clbits_id : interned_bits ( & self . clbit_indices_native , inst. clbits . bind ( py) ) ?,
862
+ params : inst. params . clone ( ) ,
863
+ label : inst. label . clone ( ) ,
864
+ duration : inst. duration . clone ( ) ,
865
+ unit : inst. unit . clone ( ) ,
826
866
} )
827
867
}
828
868
829
869
fn unpack ( & self , py : Python < ' _ > , inst : & PackedInstruction ) -> PyResult < Py < CircuitInstruction > > {
830
870
Py :: new (
831
871
py,
832
872
CircuitInstruction {
833
- operation : inst. op . clone_ref ( py ) ,
873
+ operation : inst. op . clone ( ) ,
834
874
qubits : PyTuple :: new_bound (
835
875
py,
836
876
self . intern_context
@@ -849,6 +889,10 @@ impl CircuitData {
849
889
. collect :: < Vec < _ > > ( ) ,
850
890
)
851
891
. unbind ( ) ,
892
+ params : inst. params . clone ( ) ,
893
+ label : inst. label . clone ( ) ,
894
+ duration : inst. duration . clone ( ) ,
895
+ unit : inst. unit . clone ( ) ,
852
896
} ,
853
897
)
854
898
}
0 commit comments