Пример #1
0
    def get_rho(self):
        # Runs the circuit specified by self.qc and determines the expectation values for 'ZI', 'IZ', 'ZZ', 'XI', 'IX', 'XX', 'ZX' and 'XZ' (and the ones with Ys too if needed).

        if self.y_boxes:
            corr = ['ZZ', 'ZX', 'XZ', 'XX', 'YY', 'YX', 'YZ', 'XY', 'ZY']
            ps = ['X', 'Y', 'Z']
        else:
            corr = ['ZZ', 'ZX', 'XZ', 'XX']
            ps = ['X', 'Z']

        self.rho = {}

        results = {}
        for basis in corr:
            temp_qc = copy.deepcopy(self.qc)
            for j in range(2):
                if basis[j] == 'X':
                    temp_qc.h(self.qr[j])
                elif basis[j] == 'Y':
                    temp_qc.sdg(self.qr[j])
                    temp_qc.h(self.qr[j])

            if self.backend == None:
                ket = Statevector([1, 0, 0, 0])
                ket = ket.from_instruction(temp_qc)
                results[basis] = ket.probabilities_dict()
            else:
                temp_qc.barrier(self.qr)
                temp_qc.measure(self.qr, self.cr)
                job = execute(temp_qc, backend=self.backend, shots=self.shots)
                results[basis] = job.result().get_counts()
                for string in results[basis]:
                    results[basis][
                        string] = results[basis][string] / self.shots

        prob = {}
        # prob of expectation value -1 for single qubit observables
        for j in range(2):

            for p in ps:
                pauli = {}
                for pp in ['I'] + ps:
                    pauli[pp] = (j == 1) * pp + p + (j == 0) * pp
                prob[pauli['I']] = 0
                for ppp in ps:
                    basis = pauli[ppp]
                    for string in results[basis]:
                        if string[(j + 1) % 2] == '1':
                            prob[pauli['I']] += results[basis][string] / (
                                2 + self.y_boxes)

        # prob of expectation value -1 for two qubit observables
        for basis in corr:
            prob[basis] = 0
            for string in results[basis]:
                if string[0] != string[1]:
                    prob[basis] += results[basis][string]

        for pauli in prob:
            self.rho[pauli] = 1 - 2 * prob[pauli]
Пример #2
0
    def solve_qiskit_qaoa(self, p, **kwargs):
        print("USING QISKIT CODE")
        point = kwargs.get("point", None)
        tqa = kwargs.get('tqa', False)
        points = kwargs.get("points", None)
        construct_circ = kwargs.get("construct_circ", False)
        fourier_parametrise = kwargs.get("fourier_parametrise", False)

        if tqa:
            deltas = np.arange(0.25, 0.91, 0.05)
            point = np.append([(i + 1) / p for i in range(p)],
                              [1 - (i + 1) / p for i in range(p)])
            points = [delta * point for delta in deltas]
            if fourier_parametrise:
                points = [
                    convert_to_fourier_point(point, len(point))
                    for point in points
                ]
            qaoa_results, circ = QiskitQAOA(
                self.operator,
                self.quantum_instance,
                self.optimizer,
                reps=p,
                initial_state=self.initial_state,
                mixer=self.mixer,
                list_points=points,
                construct_circ=construct_circ,
                fourier_parametrise=fourier_parametrise)
        elif points is not None:
            if point is not None:
                points.append(point)
            if fourier_parametrise:
                points = [
                    convert_to_fourier_point(point, len(point))
                    for point in points
                ]
            qaoa_results, circ = QiskitQAOA(
                self.operator,
                self.quantum_instance,
                self.optimizer,
                reps=p,
                initial_state=self.initial_state,
                mixer=self.mixer,
                list_points=points,
                construct_circ=construct_circ,
                fourier_parametrise=fourier_parametrise)
        elif point is not None:
            if fourier_parametrise:
                point = convert_to_fourier_point(point, 2 * p)
            qaoa_results, circ = QiskitQAOA(
                self.operator,
                self.quantum_instance,
                self.optimizer,
                reps=p,
                initial_state=self.initial_state,
                initial_point=point,
                mixer=self.mixer,
                construct_circ=construct_circ,
                fourier_parametrise=fourier_parametrise)
        else:
            points = [[0] * (2 * p)] + [[
                1.98 * np.pi * (np.random.rand() - 0.5) for _ in range(2 * p)
            ] for _ in range(10)]
            qaoa_results, circ = QiskitQAOA(
                self.operator,
                self.quantum_instance,
                self.optimizer,
                reps=p,
                initial_state=self.initial_state,
                list_points=points,
                mixer=self.mixer,
                construct_circ=construct_circ,
                fourier_parametrise=fourier_parametrise)
        if circ:
            print(circ.draw(fold=200))
        optimal_point = qaoa_results.optimal_point
        self.optimal_point = optimal_point
        self.qaoa_result = qaoa_results

        eigenstate = qaoa_results.eigenstate
        if self.quantum_instance.is_statevector:
            from qiskit.quantum_info import Statevector
            eigenstate = Statevector(eigenstate)
            eigenstate = eigenstate.probabilities_dict()
        else:
            eigenstate = dict([(u, v**2) for u, v in eigenstate.items()
                               ])  #Change to probabilities
        num_qubits = len(list(eigenstate.items())[0][0])
        solutions = []
        eigenvalue = 0
        for bitstr, sampling_probability in eigenstate.items():
            bitstr = bitstr[::-1]
            value = self.qubo.objective.evaluate([int(bit) for bit in bitstr])
            eigenvalue += value * sampling_probability
            solutions += [(bitstr, value, sampling_probability)]
        qaoa_results.eigenstate = solutions
        qaoa_results.eigenvalue = eigenvalue
        #Sort states by decreasing probability
        sorted_eigenstate_by_prob = sorted(qaoa_results.eigenstate,
                                           key=lambda x: x[2],
                                           reverse=True)

        #print sorted state in a table
        self.print_state(sorted_eigenstate_by_prob)

        #Other print stuff
        print("Eigenvalue: {}".format(eigenvalue))
        print("Optimal point: {}".format(optimal_point))
        print("Optimizer Evals: {}".format(qaoa_results.optimizer_evals))
        scale = self.random_energy - self.opt_value

        approx_quality_2 = np.round(
            (self.random_energy - sorted_eigenstate_by_prob[0][1]) / scale, 3)
        energy_prob = {}
        for x in qaoa_results.eigenstate:
            energy_prob[np.round(
                x[1], 6)] = energy_prob.get(np.round(x[1], 6), 0) + x[2]
        prob_s = np.round(energy_prob.get(np.round(self.opt_value, 6), 0), 6)
        self.prob_s.append(prob_s)
        self.eval_s.append(eigenvalue)
        self.approx_s.append(approx_quality_2)
        print("\nQAOA most probable solution: {}".format(
            sorted_eigenstate_by_prob[0]))
        print("Approx_quality: {}".format(approx_quality_2))
Пример #3
0
    def solve_qaoa(self, p, **kwargs):
        if self.optimal_point is not None and 'point' not in kwargs:
            point = self.optimal_point
        else:
            point = kwargs.get("point", None)
        fourier_parametrise = kwargs.get("fourier_parametrise", False)
        self.optimizer.set_options(maxeval = 1000)
        tqa = kwargs.get('tqa', False)
        points = kwargs.get("points", None)
        symmetrised = self.symmetrise
        
        #Can sometimes end up with zero operator when substituting variables when we only have ZZ terms (symmetrised qubo),
        #e.g. if H = ZIZ (=Z1Z3 for 3 qubit system) and we know <Z1 Z3> = 1, so after substition H = II for the 2 qubit system.
        #H = II is then treated as an offset and not a Pauli operator, so the QUBO.to_ising() method returns a zero (pauli) operator.
        #In such cases it means the QUBO is fully solved and any solution will do, so chose "0" string as the solution. 
        #This also makes sure that ancilla bit is in 0 state. (we could equivalently choose any other string with ancilla in 0 state)
        def valid_operator(qubo):
            num_vars = qubo.get_num_vars()
            operator, _ = qubo.to_ising()
            valid = False
            operator = [operator] if isinstance(operator, PauliOp) else operator #Make a list if only one single PauliOp
            for op_1 in operator:
                coeff, op_1 = op_1.to_pauli_op().coeff, op_1.to_pauli_op().primitive
                if coeff >= 1e-6 and op_1 != "I"*num_vars: #if at least one non-zero then return valid ( valid = True )
                    valid = True
            return valid
        
        valid_op = valid_operator(self.qubo)
        num_vars = self.qubo.get_num_vars()

        if num_vars >= 1 and symmetrised and not valid_op:
            qaoa_results = self.qaoa_result
            qaoa_results.eigenstate = np.array( [ 1 ] + [ 0 ]*(2**num_vars - 1) )
            qaoa_results.optimizer_evals = 0
            qaoa_results.eigenvalue = self.qubo.objective.evaluate([0]*num_vars)
            qc = QuantumCircuit(num_vars)
            
        elif tqa:
            deltas = np.arange(0.45, 0.91, 0.05)
            point = np.append( [ (i+1)/p for i in range(p) ] , [ 1-(i+1)/p for i in range(p) ] )
            points = [delta*point for delta in deltas]
            if fourier_parametrise:
                points = [ QAOAEx.convert_to_fourier_point(point, len(point)) for point in points ]
            qaoa_results, _ = QiskitQAOA( self.operator,
                                                        self.quantum_instance,
                                                        self.optimizer,
                                                        reps = p,
                                                        initial_state = self.initial_state,
                                                        mixer = self.mixer,
                                                        fourier_parametrise = fourier_parametrise,
                                                        list_points = points,
                                                        qubo = self.qubo
                                                        )
        
        elif points is not None:
            if fourier_parametrise:
                points = [ QAOAEx.convert_to_fourier_point(point, len(point)) for point in points ]
            qaoa_results, _ = QiskitQAOA( self.operator,
                                                        self.quantum_instance,
                                                        self.optimizer,
                                                        reps = p,
                                                        initial_state = self.initial_state,
                                                        mixer = self.mixer,
                                                        fourier_parametrise = fourier_parametrise,
                                                        list_points = points,
                                                        qubo = self.qubo
                                                        )
 
        elif point is None:
            points = [ [0]*(2*p) ] + [ [ 2 * np.pi* ( np.random.rand() - 0.5 ) for _ in range(2*p)] for _ in range(10) ]
            qaoa_results, _ = QiskitQAOA( self.operator,
                                        self.quantum_instance,
                                        self.optimizer,
                                        reps = p,
                                        initial_state = self.initial_state,
                                        list_points = points,
                                        mixer = self.mixer,
                                        fourier_parametrise = fourier_parametrise,
                                        qubo = self.qubo
                                        )
        else:
            if fourier_parametrise:
                point =  QAOAEx.convert_to_fourier_point(point, len(point))
            qaoa_results, _ = QiskitQAOA( self.operator,
                                        self.quantum_instance,
                                        self.optimizer,
                                        reps = p,
                                        initial_state = self.initial_state,
                                        initial_point = point,
                                        mixer = self.mixer,
                                        fourier_parametrise = fourier_parametrise,
                                        qubo = self.qubo
                                        )
            
        point = qaoa_results.optimal_point
        eigenstate = qaoa_results.eigenstate
        if self.quantum_instance.is_statevector:
            from qiskit.quantum_info import Statevector
            eigenstate = Statevector(eigenstate)
            eigenstate = eigenstate.probabilities_dict()
        else:
            eigenstate = dict([(u, v**2) for u, v in eigenstate.items()]) #Change to probabilities
        num_qubits = len(list(eigenstate.items())[0][0])
        solutions = []
        eigenvalue = 0
        for bitstr, sampling_probability in eigenstate.items():
            bitstr = bitstr[::-1]
            value = self.qubo.objective.evaluate([int(bit) for bit in bitstr])
            eigenvalue += value * sampling_probability
            solutions += [(bitstr, value, sampling_probability)]
        qaoa_results.eigenstate = solutions
        qaoa_results.eigenvalue = eigenvalue

        self.optimal_point = point
        self.qaoa_result = qaoa_results


        #Sort states by increasing energy and decreasing probability
        sorted_eigenstate_by_energy = sorted(qaoa_results.eigenstate, key = lambda x: x[1])
        sorted_eigenstate_by_prob = sorted(qaoa_results.eigenstate, key = lambda x: x[2], reverse = True)
        
        #print energy-sorted state in a table
        self.print_state(sorted_eigenstate_by_energy)

        #Other print stuff
        print("Eigenvalue: {}".format(qaoa_results.eigenvalue))
        print("Optimal point: {}".format(qaoa_results.optimal_point))
        print("Optimizer Evals: {}".format(qaoa_results.optimizer_evals))
        scale = self.random_energy - self.opt_value
        approx_quality = np.round( (self.random_energy - sorted_eigenstate_by_energy[0][1])/ scale, 3 )
        approx_quality_2 = np.round( ( self.random_energy - sorted_eigenstate_by_prob[0][1] ) / scale, 3 )
        energy_prob = {}
        for x in qaoa_results.eigenstate:
            energy_prob[ np.round(x[1], 6) ] = energy_prob.get(np.round(x[1], 6), 0) + x[2]
        prob_s = np.round( energy_prob.get(np.round(self.opt_value, 6), 0), 6 )
        self.prob_s.append( prob_s )
        self.approx_s.append( [approx_quality, approx_quality_2] )
        print( "\nQAOA lowest energy solution: {}".format(sorted_eigenstate_by_energy[0]) )
        print( "Approx_quality: {}".format(approx_quality) )
        print( "\nQAOA most probable solution: {}".format(sorted_eigenstate_by_prob[0]) )
        print( "Approx_quality: {}".format(approx_quality_2) ) 

        return qaoa_results
Пример #4
0
    def optimize_circuit_sgd(self, qc, quantum_circuit_parameter, angle_degrees, cost_function='mse', learning_rate = 2):
        '''
        This function is used for optimizing the values of angle_degrees, using Gradient Descent method.

        Parameters:
        -----------
        qc                          : Quantum Circuit object
        quantum_circuit_parameter   : parameter object
        angle_degrees               : Angle(in degrees) by which the parameterised gates will rotate
        cost_function               : The type of cost function to be used[default: mse]
        learning_rate               : The learning rate for optimization[default: 2]
        '''
        i = 0
        max_i = 500
        previous_step_size = 1
        precision = -1


        loss_function = []
        vn_entropy = []
        epochs = []
        epoch_var = 0
        while i<max_i and previous_step_size>precision: #iterating over until the error converges
            epoch_var+=1
            epochs.append(epoch_var)

            theta_radians = radians(angle_degrees) #converting the degrees to radians
            previous_angle = angle_degrees

            bell_state = execute(qc, backend = Aer.get_backend('statevector_simulator'), shots = self.shots, parameter_binds=[{quantum_circuit_parameter: theta_radians}]).result().get_statevector()
            #counts = job.result().get_counts()
            psi = Statevector(bell_state)
            counts = psi.probabilities_dict()
            print(counts)

            
            D = DensityMatrix(bell_state)
            vn_entropy_val = entropy(D, base=2)
            vn_entropy.append(vn_entropy_val)

            
            
            #print(counts)
            try:
                prob_avg_01 = counts['00']
                
            except:
                prob_avg_01 = 0
            try:
                prob_avg_10 = counts['11']
            except:
                prob_avg_10 = 0
            
            if cost_function == 'mse':
                loss_function.append(self.mse_cost_function(prob_avg_01, prob_avg_10))
                angle_degrees = angle_degrees - learning_rate*self.mse_cost_function(prob_avg_01, prob_avg_10)

            if cost_function == 'unsymmetrical':
                angle_degrees = angle_degrees - learning_rate*self.unsymmetrical_cost_function(prob_avg_01, prob_avg_10)

            previous_step_size = abs(angle_degrees - previous_angle)
            i+=1
    
        print(angle_degrees)
        
        return angle_degrees, counts, epochs, vn_entropy, loss_function