Пример #1
0
def numgradsigma_gaus(self,
                      iqubit,
                      igaus,
                      ini_state,
                      pobj,
                      hobj,
                      tlist,
                      nstep,
                      delx=0.0005):

    from ctrlq.lib.solve import pulsec

    pobj.sigma[iqubit][igaus] += delx
    amp__ = [[] for i in range(pobj.nqubit)]
    for i in range(pobj.nqubit):
        for j in tlist:
            tmpamp__ = 0.0
            for k in range(pobj.ngaus):
                tmpamp__ += pobj.amp[i][k] * exp(-pobj.sigma[i][k]**2 *
                                                 (j - pobj.mean[i][k])**2)
            amp__[i].append(tmpamp__)
    sfreq = numpy.array(pobj.freq) / pobj.fscale
    pobjc = pulsec(amp__, [[0.0]], sfreq, pobj.duration, pobj.nqubit, 0)
    f1 = self.efunc(ini_state,
                    pobjc,
                    hobj,
                    'trotter',
                    nstep,
                    False,
                    twindow=False,
                    cobj=True)

    pobj.sigma[iqubit][igaus] -= 2 * delx
    amp__ = [[] for i in range(pobj.nqubit)]
    for i in range(pobj.nqubit):
        for j in tlist:
            tmpamp__ = 0.0
            for k in range(pobj.ngaus):
                tmpamp__ += pobj.amp[i][k] * exp(-pobj.sigma[i][k]**2 *
                                                 (j - pobj.mean[i][k])**2)
            amp__[i].append(tmpamp__)
    sfreq = numpy.array(pobj.freq) / pobj.fscale
    pobjc = pulsec(amp__, [[0.0]], sfreq, pobj.duration, pobj.nqubit, 0)
    f2 = self.efunc(ini_state,
                    pobjc,
                    hobj,
                    'trotter',
                    nstep,
                    False,
                    twindow=False,
                    cobj=True)

    g_ = (f1 - f2) / (2 * delx)
    pobj.mean[iqubit][igaus] += delx
    return g_
Пример #2
0
def gradfunc(self, list1, pobj, hobj, nstep, test=False):
    import functools, operator, math
    from ctrlq.lib.solve import pulsec
    from ctrlq.lib.agradc import grad_trotter

    ini_state = hobj.initial_state
    tlist = numpy.linspace(0, pobj.duration, nstep)
    dsham = numpy.diagonal(-1j * hobj.dsham.toarray())

    cout = 0
    for i in range(pobj.nqubit):
        for j in range(pobj.nwindow):
            pobj.amp[i][j] = list1[cout]
            cout += 1

    for i in range(pobj.nqubit):
        pobj.freq[i] = list1[cout]
        cout += 1

    sfreq = numpy.array(pobj.freq) / pobj.fscale
    pobjc = pulsec(pobj.amp, pobj.tseq, sfreq, pobj.duration, pobj.nqubit,
                   pobj.nwindow)

    aobj = grad_trotter(tlist, ini_state, pobjc, numpy.array(hobj.hdrive),
                        dsham, hobj.states, hobj.mham)

    if test:
        cout_ = 0
        for i in range(pobj.nqubit):
            for j in range(pobj.nwindow):
                numag_ = self.numgradamp_5_(i,
                                            j,
                                            ini_state,
                                            pobj,
                                            hobj,
                                            nstep,
                                            delx=1e-8)
                if not math.isclose(numag_, aobj.gradient[i][j], abs_tol=1e-6):
                    cout_ += 1
        print('There are ' + str(cout_) +
              ' gradients with absolute difference of more than 1e-6')

    agradient = functools.reduce(operator.iconcat, aobj.gradient, [])

    for i in range(pobj.nqubit):
        ng1 = self.numgradfreq_2_(i, aobj.energy, ini_state, pobj, hobj, nstep)
        agradient.append(ng1)

    self.energy_ = aobj.energy
    self.leak = 1.0 - aobj.norm

    return (aobj.energy, agradient)
Пример #3
0
def gaussquare(ini_state, pobj, hobj, solver, nstep, normalize,
               twindow=False, leak=False):
    from ctrlq.lib.solve import pulsec
    from ctrlq.cvqe.evolve import evolve
    import matplotlib.pyplot as plt

    # Gaussian square (flattop) pulse, expt.
    # convert pobj to amp at every time step
    
    mean = pobj.duration/2.0
    amp = []
    for i in range(pobj.nqubit):
        tmp_a = []
        tlist = numpy.linspace(0., pobj.duration, nstep)
        for j in tlist:
            tmp_a.append(pobj.amp[i][0] * flattop(j-mean, mean, 8.0, 2.0))
        
        tmp_b = 1000.* (1/(numpy.pi * 2.0)) * numpy.array(tmp_a)
        plt.plot(tlist, tmp_b)
        plt.show()
        amp.append(tmp_a)
            
    stseq = numpy.array(pobj.tseq) / pobj.tscale
    sfreq = numpy.array(pobj.freq) / pobj.fscale
    pobjc = pulsec(amp, stseq, sfreq, pobj.duration,
                   pobj.nqubit, pobj.nwindow)

    out = evolve(ini_state, pobjc, hobj, solver=solver, nstep=nstep,
                 twindow=twindow)

    state_ = []
    for i in hobj.states:
        state_.append(out[i])
    state_ = numpy.array(state_)

    nrm = numpy.linalg.norm(state_)
    leak_ = 1. - nrm
    
    if normalize:
        nrm = numpy.linalg.norm(state_)
        staten = state_ /nrm
    else:
        staten = state_

    energy = functools.reduce(numpy.dot,
                              (staten.conj().T, hobj.mham, staten))
    
    energy = energy.real[0][0]
    if leak:
        return (energy, leak_)
    
    return energy
Пример #4
0
def anagaus(self, list1, pobj, hobj, nstep, normalize):

    from ctrlq.lib.solve import pulsec
    from ctrlq.lib.agradc import grad_trotter
    from ctrlq.lib.pulse_helper import gaus_getnamp

    # Analytic gradient for gaussian pulse
    # list1 [[[amp, mean, sigma] for ngaus] for nqubit]

    ini_state = hobj.initial_state
    tlist = numpy.linspace(0, pobj.duration, nstep)
    dsham = numpy.diagonal(-1j * hobj.dsham.toarray())

    cout = 0
    for i in range(pobj.nqubit):
        for j in range(pobj.ngaus):
            pobj.amp[i][j] = list1[cout]
            cout += 1
            pobj.mean[i][j] = list1[cout]
            cout += 1
            pobj.sigma[i][j] = list1[cout]
            cout += 1

    sfreq = numpy.array(pobj.freq) / pobj.fscale
    ggrad = gaus_getnamp(pobj.nqubit, pobj.ngaus, pobj.duration, pobj.amp,
                         pobj.sigma, pobj.mean, sfreq, tlist, ini_state,
                         numpy.array(hobj.hdrive), dsham, hobj.states,
                         hobj.mham)

    pobj.gausamp_ = ggrad.amp

    pobjc = pulsec(ggrad.amp, [[0.0]], sfreq, pobj.duration, pobj.nqubit, 0)

    gradient = ggrad.gradient
    for i in range(pobj.nqubit):
        # pobjc.amp - list of amp for every trotter step
        ng1 = self.numgradfreq_2_(i,
                                  ggrad.energy,
                                  ini_state,
                                  pobjc,
                                  hobj,
                                  nstep,
                                  cobj=True)
        gradient.append(ng1)

    self.energy_ = ggrad.energy
    self.leak = 1.0 - ggrad.norm
    self.gradient_ = gradient

    return (ggrad.energy, gradient)
Пример #5
0
    def efunc(self,
              ini_state,
              pobj,
              hobj,
              solver,
              nstep,
              normalize,
              supdate=False):
        from ctrlq.lib.solve import pulsec

        stseq = numpy.array(pobj.tseq) / pobj.tscale
        sfreq = numpy.array(pobj.freq) / pobj.fscale

        pobjc = pulsec(pobj.amp, stseq, sfreq, pobj.duration, pobj.nqubit,
                       pobj.nwindow)
        out = evolve(ini_state, pobjc, hobj, solver=solver, nstep=nstep)

        state_ = []
        for i in hobj.states:
            state_.append(out[i])
        state_ = numpy.array(state_)

        if normalize:
            nrm = numpy.linalg.norm(state_)
            if supdate:
                self.leak = 1.0 - nrm

            staten = state_ / nrm

        else:

            if supdate:
                nrm = numpy.linalg.norm(state_)
                self.leak = 1.0 - nrm

            staten = state_

        energy = functools.reduce(numpy.dot,
                                  (staten.conj().T, hobj.mham, staten))

        energy = energy.real[0][0]
        if supdate:
            self.energy_ = energy

        return energy
Пример #6
0
    def efunc(self,
              ini_state,
              pobj,
              hobj,
              solver,
              nstep,
              normalize,
              supdate=False,
              twindow=True,
              cobj=False,
              tmp=0,
              exactV=[]):

        from ctrlq.lib.solve import pulsec

        if not cobj:
            stseq = numpy.array(pobj.tseq) / pobj.tscale
            sfreq = numpy.array(pobj.freq) / pobj.fscale

            pobjc = pulsec(pobj.amp, stseq, sfreq, pobj.duration, pobj.nqubit,
                           pobj.nwindow)
            out = evolve(ini_state,
                         pobjc,
                         hobj,
                         solver=solver,
                         nstep=nstep,
                         twindow=twindow)
        else:
            out = evolve(ini_state,
                         pobj,
                         hobj,
                         solver=solver,
                         nstep=nstep,
                         twindow=twindow)

        state_ = []
        for i in hobj.states:
            state_.append(out[i])
        state_ = numpy.array(state_)

        if exactV:
            ovlp = numpy.dot(state_.conj().T, exactV)
            print(' Overlap           : {:>8.4f}     %'.format(ovlp * 100.))

        if normalize:
            nrm = numpy.linalg.norm(state_)
            if supdate:
                self.leak = 1.0 - nrm

            staten = state_ / nrm
        else:
            if supdate:
                nrm = numpy.linalg.norm(state_)
                self.leak = 1.0 - nrm

            staten = state_

        energy = functools.reduce(numpy.dot,
                                  (staten.conj().T, hobj.mham, staten))
        energy = energy.real[0][0]

        if supdate:
            self.energy_ = energy

        return energy
Пример #7
0
def anagaus_py(self, list1, pobj, hobj, nstep):

    from ctrlq.lib.solve import pulsec
    from ctrlq.lib.agradc import grad_trotter
    from ctrlq.lib.pulse_helper import gaus_getnamp  #,gaus_gettamp

    # Analytic gradient for gaussian pulse
    # list1 [[[amp, mean, sigma] for ngaus] for nqubit]

    ini_state = hobj.initial_state
    tlist = numpy.linspace(0, pobj.duration, nstep)
    dsham = numpy.diagonal(-1j * hobj.dsham.toarray())

    cout = 0
    for i in range(pobj.nqubit):
        for j in range(pobj.ngaus):
            pobj.amp[i][j] = list1[cout]
            cout += 1
            pobj.mean[i][j] = list1[cout]
            cout += 1
            pobj.sigma[i][j] = list1[cout]
            cout += 1

    sfreq = numpy.array(pobj.freq) / pobj.fscale

    amp__ = [[] for i in range(pobj.nqubit)]
    for i in range(pobj.nqubit):
        for j in tlist:

            tmpamp_ = 0.0
            for k in range(pobj.ngaus):
                tmpamp_ += pobj.amp[i][k] * exp(-pobj.sigma[i][k]**2 *
                                                (j - pobj.mean[i][k])**2)

            amp__[i].append(tmpamp_)

    pobj.gausamp_ = amp__
    pobjc_ = pulsec(amp__, [[0.0]], sfreq, pobj.duration, pobj.nqubit, 0)
    aobj = grad_trotter(tlist, ini_state, pobjc_, numpy.array(hobj.hdrive),
                        dsham, hobj.states, hobj.mham)

    agradient__ = []
    for i in range(pobj.nqubit):
        for j in range(pobj.ngaus):
            gamp_ = 0.0
            gsig_ = 0.0
            gmean = 0.0
            for k in range(nstep):

                esigmean_ = aobj.gradient[i][k] * exp(
                    -pobj.sigma[i][j]**2 * (tlist[k] - pobj.mean[i][j])**2)

                gamp_ += esigmean_
                gsig_ += esigmean_ * pobj.amp[i][j] * -2.0 * pobj.sigma[i][j] *\
                         (tlist[k] - pobj.mean[i][j])**2
                gmean += esigmean_ * pobj.amp[i][j] * 2.0 * pobj.sigma[i][j]**2 *\
                         (tlist[k] - pobj.mean[i][j])

            agradient__.extend([gamp_, gsig_, gmean])

    # freq
    for i in range(pobj.nqubit):
        # pobjc.amp - list of amp for every trotter step
        ng1 = self.numgradfreq_2_(i,
                                  ggrad.energy,
                                  ini_state,
                                  pobjc,
                                  hobj,
                                  nstep,
                                  cobj=True)
        agradient__.append(ng1)

    self.energy_ = aobj.energy
    self.leak = 1.0 - aobj.norm

    return (aobj.energy, agradient__)
Пример #8
0
def energy(self,
           normalize=True,
           twindow=True,
           flattop=False,
           exactV=[],
           shape='square'):
    """

    Parameters
    ----------
    normalize : bool
            Whether to normalize the expectation value. Defaults to True.        
    twindow : bool
            Turn on/off piecewise function. Deaults to True.
    shape : str
         Shape of control pulse. 'square' and 'gaussian' forms are supported. Defaults to 'square'                
    exactV : list
            Supply the exact state to print out overlap (optional).
    """
    from ._flattop import gaussquare
    from ctrlq.lib.solve import pulsec

    if flattop:
        e1, l1 = gaussquare(self.ham.initial_state,
                            self.pulse,
                            self.ham,
                            self.solver,
                            self.nstep,
                            normalize,
                            leak=True)
        return (e1, self.leak)

    if shape == 'gaussian':

        amp__ = [[] for i in range(self.pulse.nqubit)]
        tlist__ = numpy.linspace(0, self.pulse.duration, self.nstep)
        for i in range(self.pulse.nqubit):
            for j in tlist__:
                tmpamp__ = 0.0
                for k in range(self.pulse.ngaus):
                    tmpamp__ += self.pulse.amp[i][k] * exp(
                        -self.pulse.sigma[i][k]**2 *
                        (j - self.pulse.mean[i][k])**2)
                amp__[i].append(tmpamp__)
        sfreq__ = numpy.array(self.pulse.freq) / self.pulse.fscale
        pobjc__ = pulsec(amp__, [[0.0]], sfreq__, self.pulse.duration,
                         self.pulse.nqubit, 0)
        e1 = self.efunc(self.ham.initial_state,
                        pobjc__,
                        self.ham,
                        self.solver,
                        self.nstep,
                        normalize,
                        supdate=True,
                        twindow=False,
                        cobj=True)
    elif shape == 'square':

        e1 = self.efunc(self.ham.initial_state,
                        self.pulse,
                        self.ham,
                        self.solver,
                        self.nstep,
                        normalize,
                        supdate=True,
                        twindow=twindow,
                        exactV=exactV)
    else:
        sys.exit('Pulse shape not supported. Try square, gaussian or flattop')

    if self.iprint:
        print()
        print(' Energy (ctrl-vqe) : {:>18.12f} H'.format(e1))
        print(' Leakage           : {:>18.12f}     %'.format(self.leak * 100.))
    return (e1, self.leak)
Пример #9
0
def objfunc_wpulse(self, list1, pobj, hobj, nstep, normalize, interact,
                   freqopt):

    from ctrlq.lib.solve import pulsec
    from ctrlq.lib.agradc import grad_trotter
    from ctrlq.lib.agradc import grad_trotter_normalized

    pi2 = 2 * numpy.pi

    device_ = device4()  #
    ini_state = hobj.initial_state
    tlist = numpy.linspace(0, pobj.duration, nstep)

    ampcout = [[] for i in range(pobj.nqubit)]
    for i in range(pobj.nqubit):
        if pobj.nwindow == 1:
            ampcout[i].append(twinamp(0.0, pobj.duration, tlist))
            continue
        for j in range(pobj.nwindow - 1):

            if j == 0:
                ampcout[i].append(twinamp(0.0, pobj.tseq[i][j], tlist))
            else:
                ampcout[i].append(
                    twinamp(pobj.tseq[i][j - 1], pobj.tseq[i][j], tlist))
        ampcout[i].append(twinamp(pobj.tseq[i][j], pobj.duration, tlist))

    amp = [[] for j in range(pobj.nqubit)]
    samp = [[] for j in range(pobj.nqubit)]
    cout = 0
    for i in range(pobj.nqubit):
        for j in range(pobj.nwindow):

            if j == 0:
                amp[i].append(0.0)  #amp=0.0 at t=0.0
            for k in range(ampcout[i][j]):
                amp[i].append(list1[cout])
            samp[i].append(list1[cout])
            cout += 1

    self.square_amp = samp
    pobj.amp = amp

    if freqopt:
        for i in range(pobj.nqubit):
            pobj.freq[i] = list1[cout]
            cout += 1

    for i in range(pobj.nqubit):
        device_.w[i] = pi2 * list1[cout]
        cout += 1

    sfreq = numpy.array(pobj.freq) / pobj.fscale
    pobjc = pulsec(amp, pobj.tseq, sfreq, pobj.duration, pobj.nqubit,
                   pobj.nwindow)

    hstatic_ = transmon4_static(param=device_, interact=interact)
    hobj_ = transmon(mham=hobj.mham, nqubit=hobj.nqubit, Hstatic=hstatic_)
    dsham = numpy.diagonal(-1j * hobj_.dsham.toarray())

    if normalize:
        aobj = grad_trotter_normalized(tlist, ini_state, pobjc,
                                       numpy.array(hobj_.hdrive), dsham,
                                       hobj_.states, hobj_.mham)
    else:
        aobj = grad_trotter(tlist, ini_state, pobjc, numpy.array(hobj_.hdrive),
                            dsham, hobj_.states, hobj_.mham)

    self.square_gamp = aobj.gradient

    agradient = []
    for i in range(pobj.nqubit):
        cout_ = 0
        for j in range(pobj.nwindow):
            agrad__ = 0.0
            if j == 0:
                #agrad__ += aobj.gradient[i][0]
                cout_ += 1
            for k in range(ampcout[i][j]):
                agrad__ += aobj.gradient[i][cout_]
                cout_ += 1
            agradient.append(agrad__)

    if freqopt:
        for i in range(pobj.nqubit):
            ng1 = self.numgradfreq_2_(i,
                                      aobj.energy,
                                      ini_state,
                                      pobj,
                                      hobj_,
                                      nstep,
                                      normalize=normalize)
            agradient.append(ng1)

    for i in range(pobj.nqubit):
        ng1 = self.numgradw_2_(i,
                               aobj.energy,
                               ini_state,
                               pobj,
                               hobj_,
                               nstep,
                               device_,
                               interact,
                               normalize=normalize)
        agradient.append(ng1)

    self.energy_ = aobj.energy
    self.leak = 1.0 - aobj.norm
    self.gradient_ = agradient

    return (aobj.energy, agradient)
Пример #10
0
def optimize(self,
             method='l-bfgs-b',
             maxiter=100,
             maxls=20,
             gtol=1.0e-09,
             ftol=1.0e-09,
             exactE=0.0,
             normalize=False,
             gradient='numerical',
             shape='square',
             optiter=True,
             pulse_return=False):
    """Variational pulse optimization:
    Perform ctrl-VQE pulse optimization using the expectation 
    value of the molecular hamiltonian supplied in ham class.

    Parameters
    ----------
    method : str
         Numerical optimization method. Only supports 'l-bfgs-b'.
    normalize : bool
         Whether to normalize the expectation value. Defaults to False.
    maxiter : int
         Maximum number of iteration for optimization. Defaults to 100.
    maxls : int
         Set the maximum number of line searches in each optimization step (l-bfgs-b line search). Defaults to 20.
    gradient : str
         Method for computing the gradients in the optimization. 'numerical' for numerical gradients for all pulse parameters. 'analytical' for an analytical gradients for the amplitudes and numerical gradients for the frequencies. Defaults to 'numerical'.
    optiter : bool
         If set False, energy and gradients for the initial step can be returned. Defaults to True.
    gtol : float
         Exposes gtol of l-bfgs-b's in scipy. Defaults to 1e-9.
    ftol : float
         Exposes ftol of l-bfgs-b's in scipy. Defaults to 1e-9.
    shape : str
         Shape of control pulse. 'square' and 'gaussian' forms are supported. Defaults to 'square'
    pulse_return: bool
         Returns the pulse object if set True. Defaults to False. 
    """
    from ctrlq.lib.solve import pulsec

    # initial parameters
    ilist = []
    if method == 'l-bfgs-b':

        if shape == 'gaussian':
            for i in range(self.pulse.nqubit):
                for j in range(self.pulse.ngaus):
                    ilist.extend([
                        self.pulse.amp[i][j], self.pulse.mean[i][j],
                        self.pulse.sigma[i][j]
                    ])
        elif shape == 'square':
            for i in range(self.pulse.nqubit):
                for j in range(self.pulse.nwindow):
                    ilist.append(self.pulse.amp[i][j])
        elif shape == 'flattop':  # exp.
            for i in range(self.pulse.nqubit):
                ilist.append(self.pulse.amp[i][0])
        else:
            sys.exit(
                'Pulse shape not supported. Try square, gaussian or flattop')

        for i in self.pulse.freq:
            ilist.append(i)

        if self.iprint > 1:
            print('  -----* Entering pulse optimizations *-----', flush=True)
            print(
                '  Pulse parameters: Amplitude, time window (if any), frequency',
                flush=True)

        if gradient == 'numerical':
            if shape == 'square':
                E_ = self.efunc(self.ham.initial_state,
                                self.pulse,
                                self.ham,
                                self.solver,
                                self.nstep,
                                normalize,
                                supdate=True,
                                twindow=True)
            elif shape == 'flattop':
                E_ = self.gaussquare_obj(ilist,
                                         self.pulse,
                                         self.ham,
                                         self.solver,
                                         self.nstep,
                                         normalize,
                                         grad=False)
        else:
            if shape == 'square':
                self.anatwin(ilist, self.pulse, self.ham, self.nstep,
                             normalize)
            elif shape == 'flattop':
                E_ = self.gaussquare_obj(ilist,
                                         self.pulse,
                                         self.ham,
                                         self.solver,
                                         self.nstep,
                                         normalize,
                                         grad=False)

        if shape == 'gaussian':

            amp__ = [[] for i in range(self.pulse.nqubit)]
            tlist__ = numpy.linspace(0, self.pulse.duration, self.nstep)
            for i in range(self.pulse.nqubit):
                for j in tlist__:
                    tmpamp__ = 0.0
                    for k in range(self.pulse.ngaus):
                        tmpamp__ += self.pulse.amp[i][k] * exp(
                            -self.pulse.sigma[i][k]**2 *
                            (j - self.pulse.mean[i][k])**2)
                    amp__[i].append(tmpamp__)
            sfreq__ = numpy.array(self.pulse.freq) / self.pulse.fscale
            pobjc__ = pulsec(amp__, [[0.0]], sfreq__, self.pulse.duration,
                             self.pulse.nqubit, 0)
            E_ = self.efunc(self.ham.initial_state,
                            pobjc__,
                            self.ham,
                            self.solver,
                            self.nstep,
                            normalize,
                            supdate=True,
                            twindow=False,
                            cobj=True)

        self.print_step(ilist)

        if gradient == 'numerical':

            if shape == 'square':
                res1 = scipy.optimize.minimize(self.objfunc,
                                               ilist,
                                               args=(self.pulse, self.ham,
                                                     self.solver, self.nstep,
                                                     normalize, False),
                                               method=method,
                                               jac=True,
                                               bounds=self.pulse.constraint,
                                               callback=self.print_step,
                                               options={
                                                   'maxiter': maxiter,
                                                   'gtol': gtol,
                                                   'ftol': ftol,
                                                   'maxls': maxls
                                               })  #, 'iprint':1,'disp':1})

            elif shape == 'flattop':
                res1 = scipy.optimize.minimize(self.gaussquare_obj,
                                               ilist,
                                               args=(self.pulse, self.ham,
                                                     self.solver, self.nstep,
                                                     normalize),
                                               method=method,
                                               jac=True,
                                               bounds=self.pulse.constraint,
                                               callback=self.print_step,
                                               options={
                                                   'maxiter': maxiter,
                                                   'gtol': gtol,
                                                   'ftol': ftol,
                                                   'maxls': maxls
                                               })  #, 'iprint':1,'disp':1})

        elif gradient == 'analytical':

            if shape == 'square' or shape == 'gaussian':

                if shape == 'square':
                    objf__ = self.anatwin
                elif shape == 'gaussian':
                    objf__ = self.anagaus

                if optiter:
                    res1 = scipy.optimize.minimize(
                        objf__,
                        ilist,
                        args=(self.pulse, self.ham, self.nstep, normalize),
                        method=method,
                        jac=True,
                        bounds=self.pulse.constraint,
                        callback=self.print_step,
                        options={
                            'maxiter': maxiter,
                            'gtol': gtol,
                            'ftol': ftol,
                            'maxls': maxls
                        })  #, 'iprint':1000,'disp':1000})
                else:
                    objf__(ilist, self.pulse, self.ham, self.nstep, normalize)

            else:
                res1 = scipy.optimize.minimize(self.gradfunc,
                                               ilist,
                                               args=(self.pulse, self.ham,
                                                     self.nstep),
                                               method=method,
                                               jac=True,
                                               bounds=self.pulse.constraint,
                                               callback=self.print_step,
                                               options={
                                                   'maxiter': maxiter,
                                                   'gtol': gtol,
                                                   'ftol': ftol,
                                                   'maxls': maxls
                                               })  #, 'iprint':1,'disp':1})

        else:
            sys.exit(
                'Gradient method not implemented. Supports \'numerical\' and \'analytical\' only.'
            )

        if self.iprint > 0:
            print(flush=True)
            print('  Pulse optimization ends', flush=True)
            if optiter:
                print(' ', res1.message)
            print('  ------------------------------------------', flush=True)
            print(flush=True)
            print('  Printing progress', flush=True)
            print('  --------------------------------------------------------',
                  flush=True)
            print('  --------------------------------------------------------',
                  flush=True)
            print('  Iter       Energy(H)      Leak(%)  Ediff(H)    Gnorm',
                  flush=True)
            for i in range(len(self.elist_)):
                if i == 0:
                    idx__ = 0
                else:
                    idx__ = i - 1
                print(
                    '  {:>3d}  {:>18.12f}  {:>7.4f}  {:>.4e}  {:>.4e}'.format(
                        i, self.elist_[i], self.llist_[i] * 100.,
                        abs(self.elist_[i] - self.elist_[idx__]),
                        numpy.linalg.norm(self.glist_[i])))
            print('  --------------------------------------------------------',
                  flush=True)
            print('  --------------------------------------------------------',
                  flush=True)
            print(flush=True)
            self.elist_ = []
            self.llist_ = []
            self.glist_ = []

        if optiter:
            if self.iprint > 0:
                cout = 0
                print(flush=True)
                print('  -----* Optimal pulse parameters *-----', flush=True)

                if shape == 'square':
                    print('  | Amplitudes', flush=True)
                    for i in range(self.pulse.nqubit):
                        print('  Qubit ', i + 1, ' : ', end='', flush=True)

                        cout_ = 0
                        for j in range(self.pulse.nwindow):
                            if cout_ == 4:
                                print(flush=True)
                                print('              ', end='', flush=True)
                                cout_ = 0
                            print(' {:>20.16f}  '.format(res1.x[cout]),
                                  end='',
                                  flush=True)
                            cout_ += 1
                            cout += 1
                        print(flush=True)
                    print(flush=True)
                    if not self.nstep == len(self.pulse.tseq[0]) + 1:
                        qu = 1
                        print('  | Time Windows', flush=True)
                        for i in self.pulse.tseq:
                            print('  Qubit ', qu, ' : ', end='', flush=True)
                            qu += 1
                            cout_ = 0
                            for j in i:
                                if cout_ == 4:
                                    print(flush=True)
                                    print('              ', end='', flush=True)
                                    cout_ = 0

                                print(' {:>20.16f} '.format(j),
                                      end='',
                                      flush=True)
                                cout_ += 1
                            print(flush=True)
                        print(flush=True)

                elif shape == 'gaussian':

                    amp__ = [[] for i in range(self.pulse.nqubit)]
                    mean__ = [[] for i in range(self.pulse.nqubit)]
                    sigma__ = [[] for i in range(self.pulse.nqubit)]

                    for i in range(self.pulse.nqubit):
                        for j in range(self.pulse.ngaus):
                            amp__[i].append(res1.x[cout])
                            cout += 1
                            mean__[i].append(res1.x[cout])
                            cout += 1
                            sigma__[i].append(res1.x[cout])
                            cout += 1

                    print('  | Amplitudes', flush=True)
                    for i in range(self.pulse.nqubit):
                        print('  Qubit ', i + 1, ' : ', end='', flush=True)

                        cout_ = 0
                        for j in range(self.pulse.ngaus):
                            if cout_ == 4:
                                print(flush=True)
                                print('              ', end='', flush=True)
                                cout_ = 0
                            print(' {:>20.16f}  '.format(amp__[i][j]),
                                  end='',
                                  flush=True)
                            cout_ += 1
                        print(flush=True)
                    print(flush=True)

                    print('  | Mean', flush=True)
                    for i in range(self.pulse.nqubit):
                        print('  Qubit ', i + 1, ' : ', end='', flush=True)

                        cout_ = 0
                        for j in range(self.pulse.ngaus):
                            if cout_ == 4:
                                print(flush=True)
                                print('              ', end='', flush=True)
                                cout_ = 0
                            print(' {:>20.16f}  '.format(mean__[i][j]),
                                  end='',
                                  flush=True)
                            cout_ += 1
                        print(flush=True)
                    print(flush=True)

                    print('  | Variance', flush=True)
                    for i in range(self.pulse.nqubit):
                        print('  Qubit ', i + 1, ' : ', end='', flush=True)

                        cout_ = 0
                        for j in range(self.pulse.ngaus):
                            if cout_ == 4:
                                print(flush=True)
                                print('              ', end='', flush=True)
                                cout_ = 0
                            print(' {:>20.16f}  '.format(sigma__[i][j]),
                                  end='',
                                  flush=True)
                            cout_ += 1
                        print(flush=True)
                    print(flush=True)

                qu = 1
                print('  | Frequencies', flush=True)
                for i in self.pulse.freq:
                    print('  Qubit ', qu, ' : ', end='', flush=True)
                    qu += 1
                    print(' {:>20.16f}  '.format(res1.x[cout]), flush=True)
                    cout += 1
                print(flush=True)
                print('  Printing ends ', flush=True)
                print('  --------------------------------------', flush=True)
                print(flush=True)

        if pulse_return:
            return (self.pulse, self.energy_, self.leak)
        return (self.energy_, self.leak)
Пример #11
0
def anatwin(self, list1, pobj, hobj, nstep, normalize):

    from ctrlq.lib.solve import pulsec
    from ctrlq.lib.agradc import grad_trotter
    from ctrlq.lib.agradc import grad_trotter_normalized

    ini_state = hobj.initial_state
    tlist = numpy.linspace(0, pobj.duration, nstep)
    dsham = numpy.diagonal(-1j * hobj.dsham.toarray())

    ampcout = [[] for i in range(pobj.nqubit)]
    for i in range(pobj.nqubit):
        if pobj.nwindow == 1:
            ampcout[i].append(twinamp(0.0, pobj.duration, tlist))
            continue
        for j in range(pobj.nwindow - 1):

            if j == 0:
                ampcout[i].append(twinamp(0.0, pobj.tseq[i][j], tlist))
            else:
                ampcout[i].append(
                    twinamp(pobj.tseq[i][j - 1], pobj.tseq[i][j], tlist))
        ampcout[i].append(twinamp(pobj.tseq[i][j], pobj.duration, tlist))

    amp = [[] for j in range(pobj.nqubit)]
    samp = [[] for j in range(pobj.nqubit)]
    cout = 0
    for i in range(pobj.nqubit):
        for j in range(pobj.nwindow):

            if j == 0:
                amp[i].append(0.0)  #amp=0.0 at t=0.0
            for k in range(ampcout[i][j]):
                amp[i].append(list1[cout])
            samp[i].append(list1[cout])
            cout += 1

    self.square_amp = samp
    pobj.amp = amp

    for i in range(pobj.nqubit):
        pobj.freq[i] = list1[cout]
        cout += 1
    sfreq = numpy.array(pobj.freq) / pobj.fscale
    pobjc = pulsec(amp, pobj.tseq, sfreq, pobj.duration, pobj.nqubit,
                   pobj.nwindow)

    if normalize:
        aobj = grad_trotter_normalized(tlist, ini_state, pobjc,
                                       numpy.array(hobj.hdrive), dsham,
                                       hobj.states, hobj.mham)
    else:
        aobj = grad_trotter(tlist, ini_state, pobjc, numpy.array(hobj.hdrive),
                            dsham, hobj.states, hobj.mham)

    self.square_gamp = aobj.gradient

    agradient = []
    for i in range(pobj.nqubit):
        cout_ = 0
        for j in range(pobj.nwindow):
            agrad__ = 0.0
            if j == 0:
                #agrad__ += aobj.gradient[i][0]
                cout_ += 1
            for k in range(ampcout[i][j]):
                agrad__ += aobj.gradient[i][cout_]
                cout_ += 1
            agradient.append(agrad__)

    for i in range(pobj.nqubit):
        ng1 = self.numgradfreq_2_(i,
                                  aobj.energy,
                                  ini_state,
                                  pobj,
                                  hobj,
                                  nstep,
                                  normalize=normalize)
        agradient.append(ng1)
    self.energy_ = aobj.energy
    self.leak = 1.0 - aobj.norm
    self.gradient_ = agradient

    return (aobj.energy, agradient)