class Approximant_real(Approximant):
    def __init__(self, layers, domain, ansatz, function):
        self.function = function
        super().__init__(layers, domain, ansatz)
        self.target = self.function(self.domain)
        self.target = 2 * (self.target - np.min(self.target)) / (
            np.max(self.target) - np.min(self.target)) - 1
        self.H = Hamiltonian(1, matrices._Z)
        self.classical = globals()[f"classical_real_{self.ansatz}"]

    def name_folder(self, quantum=True):
        folder = self.ansatz + '/' + self.function.name + '/%s_layers' % (
            self.layers)
        if quantum:
            folder = 'quantum/' + folder
        else:
            folder = 'classical/' + folder
        folder = 'results/' + folder
        import os
        try:
            l = os.listdir(folder)
            l = [int(_) for _ in l]
            l.sort()
            trial = int(l[-1]) + 1
        except:
            trial = 0
            os.makedirs(folder)
        fold_name = folder + '/%s' % (trial)
        os.makedirs(fold_name)
        return fold_name, trial

    def cf_one_point(self, x, f):
        state = self.get_state(x)
        o = self.H.expectation(state)
        cf = (o - f)**2
        return cf

    def derivative_cf_one_point(self, x, f):
        self.theta_with_x(x)
        derivatives = np.zeros_like(self.params)
        index = 0
        ch_index = 0
        for l in range(self.layers - 1):
            cir_params_ = self.cir_params.copy()
            delta = np.zeros_like(cir_params_)
            delta[ch_index] = np.pi / 2
            self.C.set_parameters(cir_params_ + delta)
            state = self.C()
            z1 = self.H.expectation(state)
            self.C.set_parameters(cir_params_ - delta)
            state = self.C()
            z2 = self.H.expectation(state)
            derivatives[index + 1] = 0.5 * ((z1**2 - z2**2) - 2 * f *
                                            (z1 - z2))
            derivatives[index] = x * derivatives[index + 1]
            index += 2
            ch_index += 1

            cir_params_ = self.cir_params.copy()
            delta = np.zeros_like(cir_params_)
            delta[ch_index] = np.pi / 2
            self.C.set_parameters(cir_params_ + delta)
            state = self.C()
            z1 = self.H.expectation(state)
            self.C.set_parameters(cir_params_ - delta)
            state = self.C()
            z2 = self.H.expectation(state)
            derivatives[index] = 0.5 * ((z1**2 - z2**2) - 2 * f * (z1 - z2))
            index += 1
            ch_index += 1

        cir_params_ = self.cir_params.copy()
        delta = np.zeros_like(cir_params_)
        delta[ch_index] = np.pi / 2
        self.C.set_parameters(cir_params_ + delta)
        state = self.C()
        z1 = self.H.expectation(state)
        self.C.set_parameters(cir_params_ - delta)
        state = self.C()
        z2 = self.H.expectation(state)
        derivatives[index + 1] = 0.5 * ((z1**2 - z2**2) - 2 * f * (z1 - z2))
        derivatives[index] = x * derivatives[index + 1]
        index += 2
        ch_index += 1

        return derivatives

    def derivative_cf(self, params):
        try:
            params = params.flatten()
        except:
            pass
        self.set_parameters(params)
        derivatives = np.zeros_like(params)
        for x, t in zip(self.domain, self.target):
            derivatives += self.derivative_cf_one_point(x, t)
        derivatives /= len(self.domain)

        return derivatives

    def paint_representation_1D(self, name):
        fig, axs = plt.subplots()

        axs.plot(self.domain,
                 self.target,
                 color='black',
                 label='Target Function')
        outcomes = np.zeros_like(self.domain)
        for j, x in enumerate(self.domain):
            state = self.get_state(x)
            outcomes[j] = self.H.expectation(state)

        axs.plot(self.domain,
                 outcomes,
                 color='C1',
                 label='Quantum ' + self.ansatz + ' model')

        axs.legend()

        fig.savefig(name)
        plt.close(fig)

    def paint_representation_1D_classical(self, prediction, name):
        fig, axs = plt.subplots()

        axs.plot(self.domain,
                 self.target,
                 color='black',
                 label='Target Function')
        axs.plot(self.domain,
                 prediction,
                 color='C0',
                 label='Classical ' + self.ansatz + ' model')
        axs.legend()

        fig.savefig(name)
        plt.close(fig)

    def paint_representation_2D(self):
        from mpl_toolkits.mplot3d import Axes3D
        fig = plt.figure()
        ax = fig.add_subplot(111, projection='3d')

        if self.num_functions == 1:
            ax = fig.gca(projection='3d')
            print('shape', self.target[0].shape)
            ax.plot_trisurf(self.domain[:, 0],
                            self.domain[:, 1],
                            self.target[:, 0],
                            label='Target Function',
                            linewidth=0.2,
                            antialiased=True)
            outcomes = np.zeros_like(self.domain)
            for j, x in enumerate(self.domain):
                C = self.circuit(x)
                state = C.execute()
                outcomes[j] = self.hamiltonian[0].expectation(state)

            ax.plot_trisurf(self.domain[:, 0],
                            self.domain[:, 1],
                            outcomes[:, 0] + 0.1,
                            label='Approximation',
                            linewidth=0.2,
                            antialiased=True)
            #ax.legend()
        else:
            for i in range(self.num_functions):
                ax = fig.add_subplot(1, 1, i + 1, projection='3d')
                ax.plot(self.domain,
                        self.functions[i](self.domain).flatten(),
                        color='black')
                outcomes = np.zeros_like(self.domain)
                for j, x in enumerate(self.domain):
                    C = self.circuit(x)
                    state = C.execute()
                    outcomes[j] = self.hamiltonian[i].expectation(state)

                ax.scatter(self.domain[:, 0],
                           self.domain[:, 1],
                           outcomes,
                           color='C0',
                           label=self.measurements[i])
                ax.legend()

        fig.savefig(name)
        plt.close(fig)

    def paint_historical(self, name):
        import matplotlib.pyplot as plt
        fig, axs = plt.subplots(nrows=2)
        axs[0].plot(np.arange(len(self.hist_chi)), self.hist_chi)
        axs[0].set(yscale='log', ylabel=r'$\chi^2$')
        hist_params = np.array(self.hist_params)
        for i in range(len(self.params)):
            axs[1].plot(np.arange(len(self.hist_chi)), hist_params[:, i],
                        'C%s' % i)

        axs[1].set(ylabel='Parameter', xlabel='Function evaluation')
        fig.suptitle('Historical behaviour', fontsize=16)
        fig.savefig(name)
class Approximant_real_2D(Approximant):
    def __init__(self, layers, domain, function, ansatz):
        self.function = function
        super().__init__(layers, domain, ansatz)
        self.target = np.array(list(self.function(self.domain)))
        self.target = 2 * (self.target - np.min(self.target)) / (
            np.max(self.target) - np.min(self.target)) - 1

        self.H = Hamiltonian(1, matrices._Z)
        self.classical = classical_real_Weighted_2D

    def name_folder(self, quantum=True):
        folder = self.ansatz + '/' + self.function.name + '/%s_layers' % (
            self.layers)
        if quantum:
            folder = 'quantum/' + folder
        else:
            folder = 'classical/' + folder
        folder = 'results/' + folder
        import os
        try:
            l = os.listdir(folder)
            l = [int(_) for _ in l]
            l.sort()
            trial = int(l[-1]) + 1
        except:
            trial = 0
            os.makedirs(folder)
        fold_name = folder + '/%s' % (trial)
        os.makedirs(fold_name)
        return fold_name, trial

    def cf_one_point(self, x, f):
        state = self.get_state(x)
        o = self.H.expectation(state)
        cf = (o - f)**2
        return cf

    def paint_representation_2D(self, name):
        fig = plt.figure()
        axs = fig.gca(projection='3d')

        axs.plot_trisurf(self.domain[:, 0],
                         self.domain[:, 1],
                         self.target,
                         color='black',
                         label='Target Function',
                         alpha=0.5)
        outcomes = np.zeros_like(self.target)
        for j, x in enumerate(self.domain):
            state = self.get_state(x)
            outcomes[j] = self.H.expectation(state)

        axs.scatter(self.domain[:, 0],
                    self.domain[:, 1],
                    outcomes,
                    color='C1',
                    label='Quantum ' + self.ansatz + ' model')

        fig.savefig(name)
        plt.close(fig)

    def paint_representation_2D_classical(self, prediction, name):
        fig = plt.figure()
        axs = fig.gca(projection='3d')

        prediction = np.array(list(prediction))

        axs.plot_trisurf(self.domain[:, 0],
                         self.domain[:, 1],
                         self.target,
                         color='black',
                         label='Target Function',
                         alpha=0.5)
        axs.scatter(self.domain[:, 0],
                    self.domain[:, 1],
                    prediction,
                    color='C0',
                    label='Classical ' + self.ansatz + ' model')

        fig.savefig(name)
        #plt.show()
        plt.close(fig)
Ejemplo n.º 3
0
 def expectation(self, state, normalize=False):
     return Hamiltonian.expectation(self, state, normalize)