@@ -50,7 +50,7 @@ impl<N: HugrNode> ModifierResolver<N> {
5050 let control = self . control_num ( ) ;
5151 let dagger = self . modifiers . dagger ;
5252
53- // No modification is needed
53+ // No modification is needed.
5454 if control == 0 && !dagger {
5555 let new = new_fn. add_child_node ( tket_op) ;
5656 let incoming = 0 ..new_fn. hugr ( ) . num_inputs ( new) ;
@@ -59,10 +59,12 @@ impl<N: HugrNode> ModifierResolver<N> {
5959 }
6060 match tket_op {
6161 X | CX | Toffoli | Y | CY | Z | CZ | S | Sdg | T | Tdg | V | Vdg | H
62- if ( control == 0 )
63- || ( control < 3 && tket_op == X )
62+ if ( control == 0 && dagger)
63+ || ( control == 1 && tket_op == X )
64+ || ( control == 2 && tket_op == X )
6465 || ( control == 1 && matches ! ( tket_op, CX | Y | Z ) ) =>
6566 {
67+ // The controlled or daggered G is itself a TketOp: emit it directly.
6668 let gate = self
6769 . modifiers
6870 . modified ( tket_op)
@@ -81,7 +83,8 @@ impl<N: HugrNode> ModifierResolver<N> {
8183 let if_rev = control..( control + qubits) ;
8284 Ok ( self . port_vector_dagger ( new, incoming, outgoing, if_rev) )
8385 }
84- Rz | CRz | Rx | Ry if control == 0 || ( control == 1 && tket_op == Rz ) => {
86+ Rz | CRz | Rx | Ry if ( control == 0 && dagger) || ( control == 1 && tket_op == Rz ) => {
87+ // The modified rotation is itself a TketOp; for G†(θ), negate θ.
8588 let qubits = if CRz == tket_op { 2 } else { 1 } ;
8689
8790 let new_op = self
@@ -137,7 +140,7 @@ impl<N: HugrNode> ModifierResolver<N> {
137140 }
138141 }
139142 H => {
140- // H = X * Ry(pi /2).
143+ // CnH(cs,t) = CnRy(cs,t,π /2); CnX(cs,t). For H†, reverse and dagger .
141144 let ( mut pv_ry, pv_x) = if !dagger {
142145 (
143146 self . modify_tket_op ( op_node, Ry , new_fn, ancilla) ?,
@@ -165,6 +168,7 @@ impl<N: HugrNode> ModifierResolver<N> {
165168 } )
166169 }
167170 Rx => {
171+ // CnRx(cs,t,θ) = H(t); CnRz(cs,t,θ); H(t).
168172 let h1 = new_fn. add_child_node ( H ) ;
169173 let h2 = new_fn. add_child_node ( H ) ;
170174 let mut pv = self . modify_tket_op ( op_node, Rz , new_fn, ancilla) ?;
@@ -173,6 +177,8 @@ impl<N: HugrNode> ModifierResolver<N> {
173177 Ok ( pv)
174178 }
175179 Ry | CY => {
180+ // CnRy(cs,t,θ) = Sdg(t); CnRx(cs,t,θ); S(t).
181+ // CnCY(cs,c,t) = Sdg(t); CnCX(cs,c,t); S(t).
176182 let ( gate, targ) = match tket_op {
177183 Ry => ( Rx , 0 ) ,
178184 CY => ( CX , 1 ) ,
@@ -191,7 +197,7 @@ impl<N: HugrNode> ModifierResolver<N> {
191197 Ok ( pv)
192198 }
193199 T | Tdg | S | Sdg | V | Vdg => {
194- // op( t) = Phase(θ) * U(t, 2θ)
200+ // CnOp(cs, t) = CnU(cs,t,2θ); CnPhase(cs,θ).
195201 let Some ( ( gate, angle) ) = self . modifiers . rot_angle ( tket_op) else {
196202 unreachable ! ( )
197203 } ;
@@ -314,6 +320,7 @@ impl<N: HugrNode> ModifierResolver<N> {
314320 Ok ( PortVector { incoming, outgoing } )
315321 }
316322 CX | X if !ancilla. is_empty ( ) => {
323+ // Reinterpret modifier controls as native controls, reducing CnX or Cn+1X to Cn-2+2X or Cn-1+2X.
317324 let c_num = if tket_op == X { 2 } else { 1 } ;
318325 let mut ctrls = vec ! [ ] ;
319326 for _ in 0 ..c_num {
@@ -443,7 +450,7 @@ impl<N: HugrNode> ModifierResolver<N> {
443450 Ok ( PortVector { incoming, outgoing } )
444451 }
445452 Rz | Y | Z => {
446- // reduce Rz, Y, Z to CRz, CY, CZ
453+ // CnG(cs,c,t) = Cn-1(CG)(cs,c,t), for G = Rz, Y, or Z.
447454 let c_op = if tket_op == Rz {
448455 CRz
449456 } else if tket_op == Y {
@@ -476,11 +483,12 @@ impl<N: HugrNode> ModifierResolver<N> {
476483 Ok ( pv)
477484 }
478485 CZ => {
479- // reduce CZ to CRz(pi)
480- let mut pv = self . modify_tket_op ( op_node, CRz , new_fn, ancilla) ?;
481- let halfturn = new_fn. add_load_value ( ConstRotation :: new ( 1.0 ) . unwrap ( ) ) ;
482- let dw = pv. incoming . remove ( 2 ) ;
483- connect ( new_fn, & dw, & halfturn. into ( ) ) ?;
486+ // Cn+1Z(cs,c,t) = H(t); Cn+1X(cs,c,t); H(t).
487+ let h1 = new_fn. add_child_node ( H ) ;
488+ let h2 = new_fn. add_child_node ( H ) ;
489+ let mut pv = self . modify_tket_op ( op_node, CX , new_fn, ancilla) ?;
490+ pv. incoming [ 1 ] = connect_by_num ( new_fn, & pv. incoming [ 1 ] , h1, 0 ) ;
491+ pv. outgoing [ 1 ] = connect_by_num ( new_fn, & pv. outgoing [ 1 ] , h2, 0 ) ;
484492 Ok ( pv)
485493 }
486494 X | CX | Toffoli => {
@@ -595,55 +603,35 @@ impl<N: HugrNode> ModifierResolver<N> {
595603impl CombinedModifier {
596604 /// If the modified operation can be represented as a TketOp,
597605 /// returns the modified operation, otherwise returns `None`.
606+ ///
607+ /// Not all the cases are handled here, since we assume that
608+ /// unmodified operations are handled directly in `modify_tket_op`.
598609 fn modified ( & self , op : TketOp ) -> Option < TketOp > {
599- match op {
600- X if self . control == 0 => Some ( X ) ,
601- X if self . control == 1 => Some ( CX ) ,
602- X if self . control == 2 => Some ( Toffoli ) ,
603- Y if self . control == 0 => Some ( Y ) ,
604- Y if self . control == 1 => Some ( CY ) ,
605- Z if self . control == 0 => Some ( Z ) ,
606- Z if self . control == 1 => Some ( CZ ) ,
607- CX if self . control == 0 => Some ( CX ) ,
608- CX if self . control == 1 => Some ( Toffoli ) ,
609- CY if self . control == 0 => Some ( CY ) ,
610- CZ if self . control == 0 => Some ( CZ ) ,
611- Toffoli if self . control == 0 => Some ( Toffoli ) ,
612- H if self . control == 0 => Some ( H ) ,
613- Rz if self . control == 0 => Some ( Rz ) ,
614- Rz if self . control == 1 => Some ( CRz ) ,
615- CRz if self . control == 0 => Some ( CRz ) ,
616- Rx if self . control == 0 => Some ( Rx ) ,
617- Ry if self . control == 0 => Some ( Ry ) ,
618- T if self . control == 0 => match self . dagger {
619- false => Some ( T ) ,
620- true => Some ( Tdg ) ,
621- } ,
622- Tdg if self . control == 0 => match self . dagger {
623- false => Some ( Tdg ) ,
624- true => Some ( T ) ,
625- } ,
626- S if self . control == 0 => match self . dagger {
627- false => Some ( S ) ,
628- true => Some ( Sdg ) ,
629- } ,
630- Sdg if self . control == 0 => match self . dagger {
631- false => Some ( Sdg ) ,
632- true => Some ( S ) ,
633- } ,
634- V if self . control == 0 => match self . dagger {
635- false => Some ( V ) ,
636- true => Some ( Vdg ) ,
637- } ,
638- Vdg if self . control == 0 => match self . dagger {
639- false => Some ( Vdg ) ,
640- true => Some ( V ) ,
641- } ,
642- Measure | MeasureFree | QAlloc | TryQAlloc | QFree | Reset
643- if self . control == 0 && !self . dagger =>
644- {
645- Some ( op)
646- }
610+ match ( op, self . control , self . dagger ) {
611+ ( X , 0 , _) => Some ( X ) ,
612+ ( X , 1 , _) => Some ( CX ) ,
613+ ( X , 2 , _) => Some ( Toffoli ) ,
614+ ( Y , 0 , _) => Some ( Y ) ,
615+ ( Y , 1 , _) => Some ( CY ) ,
616+ ( Z , 0 , _) => Some ( Z ) ,
617+ ( Z , 1 , _) => Some ( CZ ) ,
618+ ( CX , 0 , _) => Some ( CX ) ,
619+ ( CX , 1 , _) => Some ( Toffoli ) ,
620+ ( CY , 0 , _) => Some ( CY ) ,
621+ ( CZ , 0 , _) => Some ( CZ ) ,
622+ ( Toffoli , 0 , _) => Some ( Toffoli ) ,
623+ ( H , 0 , _) => Some ( H ) ,
624+ ( Rz , 0 , _) => Some ( Rz ) ,
625+ ( Rz , 1 , _) => Some ( CRz ) ,
626+ ( CRz , 0 , _) => Some ( CRz ) ,
627+ ( Rx , 0 , _) => Some ( Rx ) ,
628+ ( Ry , 0 , _) => Some ( Ry ) ,
629+ ( T , 0 , true ) => Some ( Tdg ) ,
630+ ( Tdg , 0 , true ) => Some ( T ) ,
631+ ( S , 0 , true ) => Some ( Sdg ) ,
632+ ( Sdg , 0 , true ) => Some ( S ) ,
633+ ( V , 0 , true ) => Some ( Vdg ) ,
634+ ( Vdg , 0 , true ) => Some ( V ) ,
647635 _ => None ,
648636 }
649637 }
0 commit comments