@@ -695,6 +695,9 @@ var QuantumCircuit = function(numQubits) {
695695 name : "phaseshift" ,
696696 params : [ "lambda" ]
697697 } ,
698+ qasm : {
699+ name : "p"
700+ } ,
698701 aqasm : {
699702 name : "PH"
700703 }
@@ -3617,6 +3620,227 @@ QuantumCircuit.prototype.appendCircuit = function(circuit, pack) {
36173620 }
36183621} ;
36193622
3623+
3624+
3625+ var generateGrayCode = function ( numBits ) {
3626+ if ( numBits <= 0 ) {
3627+ throw new Error ( "Cannot generate the gray code for less than 1 bit." ) ;
3628+ }
3629+
3630+ var result = [ 0 ] ;
3631+ for ( i = 0 ; i < numBits ; i ++ ) {
3632+ var reversed = [ ] . concat ( result ) . reverse ( ) ;
3633+ reversed . map ( function ( x ) {
3634+ result . push ( x + math . pow ( 2 , i ) ) ;
3635+ } ) ;
3636+ }
3637+
3638+ var gray = [ ] ;
3639+ result . map ( function ( dec ) {
3640+ gray . push ( binStr ( dec , numBits ) ) ;
3641+ } ) ;
3642+
3643+ return gray ;
3644+ } ;
3645+
3646+
3647+ QuantumCircuit . prototype . grayCodeChain = function ( numCtrlQubits , gateName , gateOptions ) {
3648+
3649+ function compareStrings ( s1 , s2 ) {
3650+ var comp = [ ] ;
3651+ for ( var i = 0 ; i < s1 . length ; i ++ ) {
3652+ comp . push ( s1 [ i ] != s2 [ i ] ) ;
3653+ }
3654+ return comp ;
3655+ }
3656+
3657+ function indicesOfChar ( s , ch ) {
3658+ var indices = [ ] ;
3659+ for ( var i = 0 ; i < s . length ; i ++ ) {
3660+ if ( s [ i ] == ch ) {
3661+ indices . push ( i ) ;
3662+ }
3663+ }
3664+ return indices ;
3665+ }
3666+
3667+ function countChar ( s , ch ) {
3668+ var count = 0 ;
3669+ for ( var i = 0 ; i < s . length ; i ++ ) {
3670+ if ( s [ i ] == ch ) {
3671+ count ++ ;
3672+ }
3673+ }
3674+ return count ;
3675+ }
3676+
3677+ var qControls = [ ] ;
3678+ for ( var i = 0 ; i < numCtrlQubits ; i ++ ) {
3679+ qControls . push ( i ) ;
3680+ }
3681+
3682+ var qTarget = numCtrlQubits ;
3683+ var grayCode = generateGrayCode ( numCtrlQubits ) ;
3684+ var lastPattern = null ;
3685+
3686+ var rules = [ ] ;
3687+ grayCode . map ( function ( pattern ) {
3688+ var lmPos = pattern . indexOf ( "1" ) ;
3689+ if ( lmPos >= 0 ) {
3690+ if ( ! lastPattern ) {
3691+ lastPattern = pattern ;
3692+ }
3693+
3694+ var comp = compareStrings ( pattern , lastPattern ) ;
3695+ var pos = comp . indexOf ( true ) ;
3696+ if ( pos >= 0 ) {
3697+ if ( pos != lmPos ) {
3698+ rules . push ( { gateName : "cx" , wires : [ qControls [ pos ] , qControls [ lmPos ] ] , options : null } ) ;
3699+ } else {
3700+ var indices = indicesOfChar ( pattern , "1" ) ;
3701+ for ( var idx = 1 ; idx < indices . length ; idx ++ ) {
3702+ rules . push ( { gateName : "cx" , wires : [ qControls [ indices [ idx ] ] , qControls [ lmPos ] ] , options : null } ) ;
3703+ }
3704+ }
3705+ }
3706+
3707+ if ( ! ( countChar ( pattern , "1" ) % 2 ) ) {
3708+ // inverse
3709+ // !!!
3710+ // Warning - this works only with gate which is own inverse
3711+ // TODO: implement proper inverse for all gates
3712+ // !!!
3713+ var inverseOptions = null ;
3714+ if ( gateOptions ) {
3715+ inverseOptions = JSON . parse ( JSON . stringify ( gateOptions ) ) ;
3716+ if ( inverseOptions . params ) {
3717+ for ( key in inverseOptions . params ) {
3718+ var val = inverseOptions . params [ key ] ;
3719+ if ( typeof val == "number" ) {
3720+ val = 0 - val ;
3721+ } else {
3722+ val = "-(" + val + ")" ;
3723+ }
3724+ inverseOptions . params [ key ] = val ;
3725+ }
3726+ }
3727+ }
3728+ rules . push ( { gateName : gateName , wires : [ qControls [ lmPos ] , qTarget ] , options : inverseOptions } ) ;
3729+ } else {
3730+ rules . push ( { gateName : gateName , wires : [ qControls [ lmPos ] , qTarget ] , options : gateOptions } ) ;
3731+ }
3732+ lastPattern = pattern ;
3733+ }
3734+ } ) ;
3735+
3736+ return rules ;
3737+ } ;
3738+
3739+ QuantumCircuit . prototype . MCU1Circuit = function ( ctrlQubits ) {
3740+ var numCtrlQubits = 0 ;
3741+ var invertControls = [ ] ;
3742+ if ( typeof ctrlQubits == "number" ) {
3743+ numCtrlQubits = ctrlQubits ;
3744+ } else {
3745+ numCtrlQubits = ctrlQubits . length ;
3746+ for ( var i = 0 ; i < numCtrlQubits ; i ++ ) {
3747+ if ( ! ctrlQubits [ i ] || ( typeof ctrlQubits [ i ] == "number" && ctrlQubits [ i ] < 0 ) ) {
3748+ invertControls . push ( i ) ;
3749+ }
3750+ }
3751+ }
3752+
3753+ if ( numCtrlQubits == 0 ) {
3754+ throw new Error ( "Cannot create multi-controlled gate with zero control qubits." ) ;
3755+ }
3756+
3757+ function addX ( circuit , wires ) {
3758+ wires . map ( function ( wire ) {
3759+ circuit . appendGate ( "x" , wire ) ;
3760+ } ) ;
3761+ }
3762+
3763+ var scaledLambda = "lambda / " + math . pow ( 2 , numCtrlQubits - 1 ) ;
3764+ var gateOptions = { params : { lambda : scaledLambda } } ;
3765+
3766+ var qc = new QuantumCircuit ( ) ;
3767+
3768+ if ( numCtrlQubits == 1 ) {
3769+ addX ( qc , invertControls ) ;
3770+ qc . appendGate ( "cu1" , [ 0 , 1 ] , gateOptions ) ;
3771+ addX ( qc , invertControls ) ;
3772+ return qc ;
3773+ }
3774+
3775+ addX ( qc , invertControls ) ;
3776+ var rules = this . grayCodeChain ( numCtrlQubits , "cu1" , gateOptions ) ;
3777+ rules . map ( function ( rule ) {
3778+ qc . appendGate ( rule . gateName , rule . wires , rule . options ) ;
3779+ } ) ;
3780+ addX ( qc , invertControls ) ;
3781+
3782+ return qc ;
3783+ } ;
3784+
3785+
3786+ QuantumCircuit . prototype . MCXCircuit = function ( ctrlQubits ) {
3787+ var numCtrlQubits = 0 ;
3788+ var invertControls = [ ] ;
3789+ if ( typeof ctrlQubits == "number" ) {
3790+ numCtrlQubits = ctrlQubits ;
3791+ } else {
3792+ numCtrlQubits = ctrlQubits . length ;
3793+ for ( var i = 0 ; i < numCtrlQubits ; i ++ ) {
3794+ if ( ! ctrlQubits [ i ] || ( typeof ctrlQubits [ i ] == "number" && ctrlQubits [ i ] < 0 ) ) {
3795+ invertControls . push ( i ) ;
3796+ }
3797+ }
3798+ }
3799+
3800+ var qc = new QuantumCircuit ( ) ;
3801+ if ( numCtrlQubits == 0 ) {
3802+ throw new Error ( "Cannot create multi-controlled gate with zero control qubits." ) ;
3803+ }
3804+
3805+ function addX ( circuit , wires ) {
3806+ wires . map ( function ( wire ) {
3807+ circuit . appendGate ( "x" , wire ) ;
3808+ } ) ;
3809+ }
3810+
3811+ if ( numCtrlQubits == 1 ) {
3812+ addX ( qc , invertControls ) ;
3813+ qc . appendGate ( "cx" , [ 0 , 1 ] ) ;
3814+ addX ( qc , invertControls ) ;
3815+ return qc ;
3816+ }
3817+
3818+ if ( numCtrlQubits == 2 ) {
3819+ addX ( qc , invertControls ) ;
3820+ qc . appendGate ( "ccx" , [ 0 , 1 , 2 ] ) ;
3821+ addX ( qc , invertControls ) ;
3822+ return qc ;
3823+ }
3824+
3825+ var mcu1 = qc . MCU1Circuit ( numCtrlQubits ) ;
3826+ var mcu1name = "mcu1_" + numCtrlQubits ;
3827+ var mcu1wires = [ ] ;
3828+ for ( var i = 0 ; i < numCtrlQubits + 1 ; i ++ ) {
3829+ mcu1wires . push ( i ) ;
3830+ }
3831+
3832+ qc . registerGate ( mcu1name , mcu1 ) ;
3833+ addX ( qc , invertControls ) ;
3834+ qc . appendGate ( "h" , numCtrlQubits ) ;
3835+ qc . appendGate ( mcu1name , mcu1wires , { params : { lambda : "pi" } } ) ;
3836+ addX ( qc , invertControls ) ;
3837+ qc . appendGate ( "h" , numCtrlQubits ) ;
3838+
3839+ return qc ;
3840+ } ;
3841+
3842+
3843+
36203844QuantumCircuit . prototype . removeTrailingColumns = function ( ) {
36213845 var numCols = this . numCols ( ) ;
36223846 for ( var column = numCols - 1 ; column >= 0 ; column -- ) {
0 commit comments