def main(encoding='denseangle_param'): qc_name = '1q-qvm' qc = get_qc(qc_name) num_shots = 1024 device_qubits = qc.qubits() classifier_qubits = device_qubits if encoding.lower() == 'wavefunction_param': params = np.array([0.45811744, 0.2575122, 0.52902198]) else: params = np.random.rand(3) n_layers = 1 if encoding.lower() == 'denseangle_param': encoding_choice = 'denseangle_param' init_encoding_params = [np.pi, 2*np.pi] elif encoding.lower() == 'wavefunction_param': encoding_choice = 'wavefunction_param' init_encoding_params = [0] elif encoding.lower() == 'superdenseangle_param': encoding_choice = 'superdenseangle_param' init_encoding_params = [np.pi, 2*np.pi] else: raise NotImplementedError ''' # Generate Grid of datapoints to determine and visualise ideal decision boundary ''' data_choice = 'full_vertical_boundary' num_grid_points = 2000 data_grid, grid_true_labels = generate_data(data_choice, num_grid_points) data_grid, grid_true_labels = remove_zeros(data_grid, grid_true_labels) predicted_labels_grid = ClassificationCircuit(classifier_qubits, data_grid).make_predictions(params, n_layers, encoding_choice, init_encoding_params, \ num_shots, qc) plot_params = {'colors': ['blue', 'orange'], 'alpha': 1, 'size': 70} scatter(data_grid, predicted_labels_grid, **plot_params) plt.show()
def main(train=False, retrain=False, data_choice='moons', noise_choice='amp_damp_before_measurement', noise_values=0.3): ### Firstly, generate the dataset: data_train, data_test, true_labels_train, true_labels_test = generate_data( data_choice, num_points=500, split=True) data_train, true_labels_train = remove_zeros(data_train, true_labels_train) data_test, true_labels_test = remove_zeros(data_test, true_labels_test) encodings = [ 'denseangle_param', 'wavefunction_param', 'superdenseangle_param' ] minimal_costs, ideal_costs, noisy_costs, noisy_costs_uncorrected = [ np.ones(len(encodings)) for _ in range(4) ] qc_name = '1q-qvm' n_layers = 1 qc = get_qc(qc_name) num_shots = 1024 classifier_qubits = qc.qubits() init_params = np.random.rand(3) ideal_params = [] ideal_encoding_params = [] init_encoding_params = [] for ii, encoding_choice in enumerate(encodings): print('\n**********************************') print('\nThe encoding is:', encoding_choice) print('\n**********************************') if encoding_choice.lower() == 'wavefunction_param': init_encoding_params.append( [0] ) # Generalized Wavefunction Encoding initialised to Wavefunction encoding else: init_encoding_params.append([np.pi, 2 * np.pi]) if train: optimiser = 'Powell' params, result_unitary_param = train_classifier( qc, num_shots, init_params, encoding_choice, init_encoding_params[ii], optimiser, data_train, true_labels_train) print('The optimised parameters are:', result_unitary_param.x) print( 'These give a cost of:', ClassificationCircuit(classifier_qubits, data_train).build_classifier( result_unitary_param.x, encoding_choice, init_encoding_params[ii], num_shots, qc, true_labels_train)) ideal_params.append(result_unitary_param.x) else: if data_choice.lower() == 'moons': if encoding_choice.lower() == 'denseangle_param': ideal_params.append([2.19342064, 1.32972029, -0.18308298]) elif encoding_choice.lower() == 'superdenseangle_param': ideal_params.append([-0.27365492, 0.83278854, 3.00092961]) elif encoding_choice.lower() == 'wavefunction': ideal_params.append([0.81647273, 0.41996708, 2.20603541]) elif encoding_choice.lower() == 'wavefunction_param': ideal_params.append([0.81647273, 0.41996708, 2.20603541]) elif data_choice.lower() == 'random_vertical_boundary': if encoding_choice.lower() == 'denseangle_param': ideal_params.append([1.67814786, 1.56516469, 1.77820848]) elif encoding_choice.lower() == 'superdenseangle_param': ideal_params.append([1.60642225, 0.23401504, 5.69422628]) elif encoding_choice.lower() == 'wavefunction': ideal_params.append([0.96291484, 0.18133714, 0.35436732]) elif encoding_choice.lower() == 'wavefunction_param': ideal_params.append([0.96291484, 0.18133714, 0.35436732]) elif data_choice.lower() == 'random_diagonal_boundary': if encoding_choice.lower() == 'denseangle_param': ideal_params.append([0.8579214, 1.22952647, 4.99408074]) elif encoding_choice.lower() == 'superdenseangle_param': ideal_params.append([2.0101407, 1.05916291, 1.14570489]) elif encoding_choice.lower() == 'wavefunction': ideal_params.append([0.69409285, 0.0862859, 0.42872711]) elif encoding_choice.lower() == 'wavefunction_param': ideal_params.append([0.69409285, 0.0862859, 0.42872711]) else: print('THIS DATASET HAS NOT BEEN TRAINED FOR') if encoding_choice.lower() == 'denseangle_param': ideal_params.append(init_params) elif encoding_choice.lower() == 'superdenseangle_param': ideal_params.append(init_params) elif encoding_choice.lower() == 'wavefunction': ideal_params.append(init_params) elif encoding_choice.lower() == 'wavefunction_param': ideal_params.append(init_params) ideal_costs[ii] = ClassificationCircuit( classifier_qubits, data_test, qc).build_classifier(ideal_params[ii], n_layers, encoding_choice, init_encoding_params[ii], num_shots, true_labels_test) print('In the ideal case, the cost is:', ideal_costs[ii]) predicted_labels_ideal = ClassificationCircuit( classifier_qubits, data_test, qc).make_predictions(ideal_params[ii], n_layers, encoding_choice, init_encoding_params[ii], num_shots) noisy_costs_uncorrected[ii] = ClassificationCircuit(classifier_qubits, data_test, qc, noise_choice, noise_values).build_classifier(ideal_params[ii], n_layers,\ encoding_choice, init_encoding_params[ii],\ num_shots, true_labels_test) print('\nWithout encoding training, the noisy cost is:', noisy_costs_uncorrected[ii]) noisy_predictions, number_classified_same = generate_noisy_classification(ideal_params[ii], n_layers, noise_choice, noise_values, \ encoding_choice, init_encoding_params[ii],\ qc, classifier_qubits, num_shots, data_test, predicted_labels_ideal) print('The proportion classified differently after noise is:', 1 - number_classified_same) if retrain: if encoding_choice.lower() == 'wavefunction_param': optimiser = 'L-BFGS-B' else: optimiser = 'Powell' encoding_params, result_encoding_param = train_classifier_encoding( qc, noise_choice, noise_values, num_shots, ideal_params[ii], encoding_choice, init_encoding_params[ii], optimiser, data_train, true_labels_train) print('The optimised encoding parameters with noise are:', result_encoding_param.x) ideal_encoding_params.append(result_encoding_param.x) else: if data_choice.lower() == 'moons' and noise_choice.lower( ) == 'amp_damp_before_measurement' and isclose( noise_values, 0.3, abs_tol=1e-8): if encoding_choice.lower() == 'denseangle_param': ideal_encoding_params.append([2.23855329, 7.57781576]) elif encoding_choice.lower() == 'superdenseangle_param': ideal_encoding_params.append([3.31296568, 6.34142188]) elif encoding_choice.lower() == 'wavefunction_param': ideal_encoding_params.append([0.02884417]) elif data_choice.lower() == 'random_vertical_boundary': if encoding_choice.lower() == 'denseangle_param': ideal_encoding_params.append([2.26042559, 8.99138928]) elif encoding_choice.lower() == 'superdenseangle_param': ideal_encoding_params.append([3.1786475, 8.36712745]) elif encoding_choice.lower() == 'wavefunction_param': ideal_encoding_params.append([0.01503151]) elif data_choice.lower() == 'random_diagonal_boundary': if encoding_choice.lower() == 'denseangle_param': ideal_encoding_params.append([2.11708966, 5.69354627]) elif encoding_choice.lower() == 'superdenseangle_param': ideal_encoding_params.append([0.08689283, 6.21166815]) elif encoding_choice.lower() == 'wavefunction_param': ideal_encoding_params.append([0.0]) else: print('THIS DATASET HAS NOT BEEN TRAINED FOR') if encoding_choice.lower() == 'denseangle_param': ideal_encoding_params.append(init_encoding_params[ii]) elif encoding_choice.lower() == 'superdenseangle_param': ideal_encoding_params.append(init_encoding_params[ii]) elif encoding_choice.lower() == 'wavefunction_param': ideal_encoding_params.append(init_encoding_params[ii]) noisy_costs[ii] = ClassificationCircuit(classifier_qubits, data_test, qc, noise_choice, noise_values).build_classifier(ideal_params[ii], n_layers,\ encoding_choice, ideal_encoding_params[ii],\ num_shots, true_labels_test) print('\nWith encoding training, the noisy cost is:', noisy_costs[ii]) noisy_predictions, number_classified_same = generate_noisy_classification(ideal_params[ii], n_layers, noise_choice, noise_values, \ encoding_choice, ideal_encoding_params[ii], qc, classifier_qubits, num_shots,\ data_test, predicted_labels_ideal) print( 'The proportion classified differently after noise with learned encoding is:', 1 - number_classified_same) for ii, encoding_choice in enumerate(encodings): print('\nThe encoding is:', encodings[ii]) print('The ideal params are:', ideal_params[ii]) print('The ideal encoding params are', ideal_encoding_params[ii]) print('The ideal cost for encoding', ideal_costs[ii]) print('The noisy cost with untrained encoding', noisy_costs_uncorrected[ii]) print('The noisy cost with trained encoding', noisy_costs[ii]) return encodings, ideal_params, init_encoding_params, ideal_encoding_params, ideal_costs, noisy_costs_uncorrected, noisy_costs
def main(train=False, encoding_choice='denseangle_param', retrain=False, data_choice='moons', noise=False): ### Firstly, generate for dataset: ''' # We use the transpose of the (scaled to unit square) Moons dataset in order to see a non-linear decision boundary ''' data_train, data_test, true_labels_train, true_labels_test = generate_data(data_choice, num_points=500, split=True) # data_train, true_labels_train = remove_zeros(data_train, true_labels_train) # data_test, true_labels_test = remove_zeros(data_test, true_labels_test) ### Next, generate correct classification parameters for dataset (perfect classification): ''' # Define parameters of model. Start with DenseAngle encoding with fixed parameters. ''' qc_name = '1q-qvm' qc = get_qc(qc_name) num_shots = 1024 qubits = qc.qubits() init_params = np.random.rand(3) if encoding_choice.lower() == 'wavefunction_param': init_encoding_params = [ 0 ] # Generalized Wavefunction Encoding initialised to Wavefunction encoding else: init_encoding_params = [np.pi, 2*np.pi] if train: optimiser = 'Powell' params, result_unitary_param = train_classifier(qc, num_shots, init_params, encoding_choice, init_encoding_params, optimiser, data_train, true_labels_train) print('The optimised parameters are:', result_unitary_param.x) print('These give a cost of:', ClassificationCircuit(qubits, data_train).build_classifier(result_unitary_param.x, encoding_choice, init_encoding_params, num_shots, qc, true_labels_train)) ideal_params = result_unitary_param.x else: if data_choice.lower() == 'moons': ### Define Ideal parameters for trained model. Simple model can acheieve classification of about 90 % ''' # 90% Classification parameters for dense angle encoding ''' if encoding_choice.lower() == 'denseangle_param': ideal_params= [ 2.19342064 , 1.32972029, -0.18308298] ### Define Ideal parameters for trained model. Simple model can acheieve classification of about 75 % ''' # 73% Classification parameters for superdense angle encoding ''' if encoding_choice.lower() == 'superdenseangle_param': ideal_params = [-0.27365492, 0.83278854, 3.00092961] ### Define Ideal parameters for trained model. Simple model can acheieve classification of about % ''' # 85% Classification parameters for wavefunction encoding ''' if encoding_choice.lower() == 'wavefunction': ideal_params = [0.81647273, 0.41996708, 2.20603541] if encoding_choice.lower() == 'wavefunction_param': ideal_params = [0.81647273, 0.41996708, 2.20603541] elif data_choice.lower() == 'random_vertical_boundary': if encoding_choice.lower() == 'superdenseangle_param': ideal_params = [1.606422245361118, 0.23401504261014927, 5.694226283697996] elif data_choice.lower() == 'random_diagonal_boundary': ### Define Ideal parameters for trained model. Simple model can acheieve classification of about 90 % ''' # 90% Classification parameters for dense angle encoding ''' if encoding_choice.lower() == 'denseangle_param': ideal_params = [0.8579214, 1.22952647, 4.99408074] ### Define Ideal parameters for trained model. Simple model can acheieve classification of about % ''' # % Classification parameters for superdense angle encoding ''' if encoding_choice.lower() == 'superdenseangle_param': ideal_params = [2.0101407, 1.05916291, 1.14570489] ### Define Ideal parameters for trained model. Simple model can acheieve classification of about 97% ''' # 97% Classification parameters for wavefunction encoding ''' if encoding_choice.lower() == 'wavefunction': ideal_params = [0.69409285 0.0862859 0.42872711] if encoding_choice.lower() == 'wavefunction_param': ideal_params = [0.69409285 0.0862859 0.42872711] print('These give a cost of:', ClassificationCircuit(qubits, data_test).build_classifier(ideal_params, encoding_choice, init_encoding_params, num_shots, qc, true_labels_test)) predicted_labels_ideal = ClassificationCircuit(qubits, data_test).make_predictions(ideal_params, encoding_choice, init_encoding_params, num_shots, qc) # nisqai.visual.scatter(data_test, true_labels_test, predicted_labels) ### Overlay decision bounday ''' # Generate Grid of datapoints to determine and visualise ideal decision boundary ''' num_points = 400 data_grid, grid_true_labels = generate_data('full_vertical_boundary', num_points) data_grid, grid_true_labels = remove_zeros(data_grid, grid_true_labels) predicted_labels = ClassificationCircuit(qubits, data_test).make_predictions(ideal_params, encoding_choice, init_encoding_params, num_shots, qc) plot_params = {'colors': ['blue', 'orange'], 'alpha': 1} scatter(data_test, true_labels_test, predicted_labels, **plot_params) predicted_labels_grid = ClassificationCircuit(qubits, data_grid).make_predictions(ideal_params, encoding_choice, init_encoding_params, num_shots, qc) plot_params = {'colors': ['red', 'green'], 'alpha': 0.2} scatter(data_grid, predicted_labels_grid, **plot_params) plt.show() ## Define noise parameters ''' # Define noise parameters to add to model to determine how classification is affected. ''' if noise: noise_choice = 'amp_damp_before_measurement' noise_values = 0.3 ### Add noise to circuit and classify ''' # Add noise to circuit, and determine number of points classified differently (not mis-classified since we can't achieve perfect classification) ''' if noise: noisy_predictions, number_classified_same = generate_noisy_classification(ideal_params, noise_choice, noise_values, encoding_choice, init_encoding_params, qc, num_shots, data_test, predicted_labels_ideal) print('The proportion classified differently after noise is:', 1- number_classified_same) ## Overlay decision boundary ''' # Generate Grid of datapoints to determine and visualise ideal decision boundary WITH noise added ''' if noise: print(noise_choice) predicted_labels = ClassificationCircuit(qubits, data_test, noise_choice, noise_values).make_predictions(ideal_params, encoding_choice, init_encoding_params, num_shots, qc) plot_params = {'colors': ['blue', 'orange'], 'alpha': 1} scatter(data_test, true_labels_test, predicted_labels, **plot_params) predicted_labels_grid = ClassificationCircuit(qubits, data_grid, noise_choice, noise_values).make_predictions(ideal_params, encoding_choice, init_encoding_params, num_shots, qc) plot_params = {'colors': ['red', 'green'], 'alpha': 0.2} scatter(data_grid, predicted_labels_grid, **plot_params) plt.show() ### Retrain circuit with noise ''' # Given the noise in the circuit, train the parameters of encoding unitary to account for noise. Parameterised unitary parameters are fixed as the ideal ones learned. ''' if retrain: if encoding_choice.lower() == 'wavefunction_param': optimiser = 'L-BFGS-B' else: optimiser = 'Powell' if noise: encoding_params, result_encoding_param = train_classifier_encoding(qc, noise_choice, noise_values, num_shots, ideal_params, encoding_choice, init_encoding_params, optimiser, data_train, true_labels_train) print('The optimised encoding parameters with noise are:', result_encoding_param.x) ideal_encoding_params = result_encoding_param.x else: encoding_params, result_encoding_param = train_classifier_encoding(qc, None, None, num_shots, ideal_params, encoding_choice, init_encoding_params, optimiser, data_train, true_labels_train) print('The optimised encoding parameters without noise are:', result_encoding_param.x) ideal_encoding_params = result_encoding_param.x else: ### Define Ideal ENCODING parameters for trained model. Simple model can acheieve classification of about 90 with noise, 93% without noise % ''' # 90% Classification parameters for dense angle encoding ''' if data_choice.lower() == 'moons' and encoding_choice.lower() == 'denseangle_param' and noise: ideal_encoding_params = [2.23855329, 7.57781576] ''' # 93% Classification parameters for dense angle encoding without noise ''' elif data_choice.lower() == 'moons' and encoding_choice.lower() == 'denseangle_param': ideal_encoding_params = [3.05615259, 7.61215138] # No noise ### Define Ideal ENCODING parameters for trained model. Simple model can acheieve classification of about 90 % ''' # NO NOISE - 74-77% Classification parameters with training for superdense angle encoding # NOISE - Classification parameters for superdense angle encoding (0.3 amp damp = 20% different classification - 69% accuracy with noise before encoding training) # With learned encoding - ''' if data_choice.lower() == 'moons' and encoding_choice.lower() == 'superdenseangle_param' and noise: ideal_encoding_params = [3.31296568, 6.34142188] elif data_choice.lower() == 'moons' and encoding_choice.lower() == 'superdenseangle_param': ideal_encoding_params = [2.86603822, 6.14328274] # No noise ### Define Ideal ENCODING parameters for trained model. Simple model can acheieve classification of about 90 % ''' # NO NOISE - 82-84% Classification parameters with training for generalised wavefunction encoding # NOISE - Classification parameters for superdense angle encoding (0.3 amp damp = 20% different classification - 78% accuracy with noise before encoding training) # With learned encoding - ''' print(data_choice.lower(), encoding_choice.lower()) if data_choice.lower() == 'moons' and encoding_choice.lower() == 'wavefunction_param' and noise: ideal_encoding_params = [0.02884417] elif data_choice.lower() == 'moons' and encoding_choice.lower() == 'wavefunction_param': ideal_encoding_params = [0.01582773] # No noise if noise: print('These give a cost with the noisy circuit of:',\ ClassificationCircuit(qubits, data_test, noise_choice, noise_values).build_classifier(ideal_params, encoding_choice, ideal_encoding_params , num_shots, qc, true_labels_test) ) else: print('These give a cost with the ideal circuit of:',\ ClassificationCircuit(qubits, data_test).build_classifier(ideal_params, encoding_choice, ideal_encoding_params , num_shots, qc, true_labels_test) ) ### Add noise to circuit and classify ''' # Using learned encoding parameters, check again proportion misclassified ''' if noise: noisy_predictions, number_classified_same = generate_noisy_classification(ideal_params, noise_choice, noise_values, encoding_choice, ideal_encoding_params, qc, num_shots, data_test, predicted_labels) print('The proportion classified differently after noise with learned encoding is:', 1 - number_classified_same) ## Overlay decision boundary ''' # Generate Grid of datapoints to determine and visualise ideal decision boundary WITH/WITHOUT noise added ''' if noise: predicted_labels = ClassificationCircuit(qubits, data_test, noise_choice, noise_values).make_predictions(ideal_params, encoding_choice, ideal_encoding_params, num_shots, qc) plot_params = {'colors': ['blue', 'orange'], 'alpha': 1} scatter(data_test, true_labels_test, predicted_labels, **plot_params) predicted_labels_grid = ClassificationCircuit(qubits, data_grid, noise_choice, noise_values).make_predictions(ideal_params, encoding_choice, ideal_encoding_params, num_shots, qc) plot_params = {'colors': ['red', 'green'], 'alpha': 0.2} scatter(data_grid, predicted_labels_grid, **plot_params) plt.show() else: predicted_labels = ClassificationCircuit(qubits, data_test).make_predictions(ideal_params, encoding_choice, ideal_encoding_params, num_shots, qc) plot_params = {'colors': ['blue', 'orange'], 'alpha': 1} scatter(data_test, true_labels_test, predicted_labels, **plot_params) predicted_labels_grid = ClassificationCircuit(qubits, data_grid).make_predictions(ideal_params, encoding_choice, ideal_encoding_params, num_shots, qc) plot_params = {'colors': ['red', 'green'], 'alpha': 0.2} scatter(data_grid, predicted_labels_grid, **plot_params) plt.show()
def main(train=False, encoding='denseangle_param', ideal=False, noise=False, analytic=False, compare=False): """ # Find optimal parameters for linear decision boundary and add noise """ ### Firstly, generate for dataset: ''' # We use the transpose of the (scaled to unit square) Moons dataset in order to see a non-linear decision boundary ''' data_vertical_train, data_vertical_test, true_labels_train, true_labels_test = generate_data( 'random_vertical_boundary', num_points=500, split=True) ### Next, generate correct classification parameters for dataset (perfect classification): ''' # Define parameters of model. Start with DenseAngle encoding with fixed parameters. ''' qc_name = '1q-qvm' qc = get_qc(qc_name) num_shots = 1024 device_qubits = qc.qubits() classifier_qubits = device_qubits n_layers = 1 init_params = np.random.rand(3) if encoding.lower() == 'denseangle_param': encoding_choice = 'denseangle_param' # init_encoding_params = [np.pi, 2*np.pi] init_encoding_params = [np.pi, 2 * np.pi] elif encoding.lower() == 'wavefunction' or encoding.lower( ) == 'wavefunction_param': encoding_choice = 'wavefunction_param' init_encoding_params = [0] optimiser = 'Powell' if train: ### Train model, and check classification result of ideal parameters found ''' # Train model using scipy.optimize ''' params, result_unitary_param = train_classifier( qc, num_shots, init_params, encoding_choice, init_encoding_params, optimiser, data_vertical_train, true_labels_train) print('The optimised parameters are:', result_unitary_param.x) print('These give a cost of:', ClassificationCircuit(classifier_qubits, data_vertical_train).build_classifier(result_unitary_param.x, n_layers, \ encoding_choice, init_encoding_params, num_shots, qc, true_labels_train)) ideal_params_vertical = result_unitary_param.x else: ### Define Ideal parameters for trained model learned from previous. Simple model can acheieve classification of about 90 % if encoding_choice.lower() == 'denseangle_param': ''' # 100% Classification parameters (modulo points on the boundary) ''' # ideal_params_vertical = [3.8208,1.525,0.0808] ideal_params_vertical = [1.67814786, 1.56516469, 1.77820848] elif encoding_choice.lower() == 'wavefunction_param': ''' # 78% Classification parameters (modulo points on the boundary) ''' ideal_params_vertical = [2.2921198, 0.61375299, -5.15252796] plt.rcParams.update({ "font.size": 20, "font.serif": "Computer Modern Roman" }) ### Overlay decision bounday ''' # Generate Grid of datapoints to determine and visualise ideal decision boundary ''' data_choice = 'full_vertical_boundary' num__grid_points = 1000 data_grid, grid_true_labels = generate_data(data_choice, num__grid_points) data_grid, grid_true_labels = remove_zeros(data_grid, grid_true_labels) if ideal: predicted_labels_test = ClassificationCircuit(classifier_qubits, data_vertical_test, qc).make_predictions(ideal_params_vertical, n_layers, \ encoding_choice, init_encoding_params, num_shots) plot_params = {'colors': ['blue', 'orange'], 'alpha': 1} scatter(data_vertical_test, true_labels_test, predicted_labels_test, **plot_params) predicted_labels_grid = ClassificationCircuit(classifier_qubits, data_grid, qc).make_predictions(ideal_params_vertical, n_layers,\ encoding_choice, init_encoding_params, num_shots) plot_params = {'colors': ['red', 'green'], 'alpha': 0.2} scatter(data_grid, predicted_labels_grid, **plot_params) plt.show() ### Define noise parameters ''' # Define noise parameters to add to model to determine how classification is affected. ''' noise_choice = 'amp_damp_before_measurement' noise_values = 0.4 ### Add noise to circuit and classify ''' # Add noise to circuit, and determine number of points classified differently (not mis-classified since we can't achieve perfect classification) ''' if noise: ## Overlay decision boundary ''' # Generate Grid of datapoints to determine and visualise ideal decision boundary WITH noise added ''' predicted_labels_test_noise = ClassificationCircuit(classifier_qubits, data_vertical_test, qc,\ noise_choice, noise_values).make_predictions(ideal_params_vertical, n_layers, encoding_choice, init_encoding_params, num_shots) plot_params = {'colors': ['blue', 'orange'], 'alpha': 1} scatter(data_vertical_test, true_labels_test, predicted_labels_test_noise, **plot_params) predicted_labels_grid_noise = ClassificationCircuit(classifier_qubits, data_grid, qc,\ noise_choice, noise_values).make_predictions(ideal_params_vertical, n_layers, \ encoding_choice, init_encoding_params, num_shots) plot_params = {'colors': ['red', 'green'], 'alpha': 0.2} scatter(data_grid, predicted_labels_grid_noise, **plot_params) plt.show() ''' # Define function to compute points which will remian correctly classified after noise is added ''' def correct_function(data_point, params, encoding_choice, encoding_params): [alpha_1, alpha_2, alpha_3] = params [x_1, x_2] = data_point if encoding_choice.lower() == 'denseangle_param': [theta, phi] = encoding_params function = (np.sin(alpha_2) )**2 * ( np.cos(theta * x_1) )**2 + (np.cos(alpha_2))**2 * (np.sin(theta * x_1))**2 \ + ((1/2)*(np.sin(2 * alpha_2) * np.sin(2 * theta * x_1) * np.exp(-1j*(2 * alpha_3 + phi * x_2)))).real elif encoding_choice.lower() == 'wavefunction_param': [theta] = encoding_params l2_norm = np.linalg.norm(np.array([x_1, x_2]))**2 function = (np.sin(alpha_2)**2 ) * ( x_1**2/(l2_norm) ) + (np.cos(alpha_2)**2) * (x_2**2/(l2_norm)) \ + ((1/(2*l2_norm))*(np.sin(2 * alpha_2) * (x_1) * (x_2) * np.exp(-1j*(2 * alpha_3)))).real return function def compute_analytic_misclassifed_condition(data, params, encoding_choice, encoding_params, noise_strength, true_labels): correct_classification_labels = [] for ii, data_point in enumerate(data): function = correct_function(data_point, params, encoding_choice, encoding_params) if true_labels[ii] == 0: correct_classification_labels.append( 0 ) # If datapoint was zero originally, it will be correctly classified regardless of noise else: if function > 1 / ( 2 * (1 - noise_strength) ): # If data point was classified as 1, it will be correctly classified if condition is met. correct_classification_labels.append(0) else: correct_classification_labels.append(1) number_robust = 1 - sum(correct_classification_labels) / len( correct_classification_labels) # percentage of misclassified points return np.array(correct_classification_labels), number_robust def plot_number_misclassified_amp_damp(ideal_params, num_shots, num_points, qc, noise_values): points_noise_inc = [] data_vertical_train, data_vertical_test, true_labels_train, true_labels_test = generate_data('random_vertical_boundary',\ num_points=num_points, split=True) interval = 0.2 encoding_choice = 'denseangle_param' theta = np.arange(0, 2 * np.pi, interval) phi = np.arange(0, 2 * np.pi, interval) X, Y = np.meshgrid(theta, phi) noise_choice = 'amp_damp_before_measurement' test_acc_ideal = np.zeros((theta.shape[0], phi.shape[0]), dtype=float) test_acc_noise = np.zeros((theta.shape[0], phi.shape[0]), dtype=float) number_robust = np.zeros((theta.shape[0], phi.shape[0]), dtype=float) for ii, t in enumerate(theta): for jj, p in enumerate(phi): temp_encoding_params = [t, p] # Classification of encoding parameters *without* noise ideal_predictions, test_acc_ideal[ii,jj] = generate_noisy_classification(ideal_params, 1, None, None,\ encoding_choice, temp_encoding_params, qc,\ classifier_qubits, num_shots, data_vertical_test, true_labels_test) # Learned encoding parameters *with* noise noisy_predictions, test_acc_noise[ii,jj] = generate_noisy_classification(ideal_params, 1, noise_choice, noise_values,\ encoding_choice, temp_encoding_params, qc,\ classifier_qubits, num_shots, data_vertical_test, true_labels_test) # Number expected to be robust under analytic condition correct_classification_labels, number_robust[ii, jj] = compute_analytic_misclassifed_condition(data_vertical_test, ideal_params_vertical,\ encoding_choice, temp_encoding_params,\ noise_values, true_labels_test) print('Theta, Phi is:', t, p) print('Test accuracy ideal:', test_acc_ideal[ii, jj]) print('Test accuracy with noise:', test_acc_noise[ii, jj]) print('Proportion robust:', number_robust[ii, jj]) max_acc_indices_ideal = np.unravel_index( np.argmax(test_acc_ideal, axis=None), test_acc_ideal.shape) max_acc_indices = np.unravel_index( np.argmax(test_acc_noise, axis=None), test_acc_noise.shape) max_robust_indices = np.unravel_index( np.argmax(number_robust, axis=None), number_robust.shape) plt.rcParams.update({"font.size": 14, "font.family": "serif"}) # ---------------------- # Uncomment below for 3d plots # ---------------------- # fig = plt.figure(figsize=plt.figaspect(0.33)) # ax1 = fig.add_subplot(1, 3, 1, projection='3d') # surf1 = ax1.plot_surface(X, Y, test_acc_ideal, cmap=cm.coolwarm_r,linewidth=0, antialiased=False) # # ax1.set_zlim(0.45, 1.01) # cbar1 =fig.colorbar(surf1) # cbar1.ax.set_ylabel('Test Accuracy') # ax2 = fig.add_subplot(1, 3, 2, projection='3d') # surf2 = ax2.plot_surface(X, Y, test_acc_noise, cmap=cm.coolwarm_r, linewidth=0, antialiased=False) # # ax2.set_zlim(0.45, 1.01) # cbar2 = fig.colorbar(surf2) # cbar2.ax.set_ylabel('Test Accuracy') # ax3 = fig.add_subplot(1, 3, 3, projection='3d') # surf3 = ax3.plot_surface(X, Y, number_robust, cmap=cm.PuOr, linewidth=0, antialiased=False) # cbar3 = fig.colorbar(surf3) # cbar3.ax.set_ylabel('Proportion robust') # ax1.set_ylabel(r'$\theta (rads)$') # ax1.set_xlabel(r'$\phi (rads)$' ) # ax1.set_title( 'Best accuracy ideal: ' + str( round( test_acc_ideal[max_acc_indices_ideal] , 2) ) \ # + '\nBest accuracy with noise: ' + str( round( test_acc_noise[max_acc_indices_ideal] , 2) ) \ # + '\nRobustness: ' + str( round( number_robust[max_acc_indices_ideal] , 2) ) + '\n' \ # + r'$[\theta, \phi]$ = ' + '['+str(round(theta [ max_acc_indices_ideal[0] ], 2) )+ ', ' + str( round( phi [ max_acc_indices_ideal[1] ] , 2) ) + ']' ) # ax2.set_ylabel(r'$\theta (rads)$') # ax2.set_xlabel(r'$\phi (rads)$' ) # ax2.set_title( 'Best accuracy with noise: ' + str( round( test_acc_noise[max_acc_indices] , 2) ) \ # + '\nBest accuracy ideal: ' + str( round( test_acc_ideal[max_acc_indices] , 2) ) \ # + '\nRobustness: ' + str( round( number_robust[max_acc_indices] , 2) ) + '\n' \ # + r'$[\theta, \phi]$ = ' + '['+str(theta [ max_acc_indices[0] ])+ ', ' + str(round( phi [ max_acc_indices[1] ], 2) ) + ']' ) # ax3.set_ylabel(r'$\theta (rads)$') # ax3.set_xlabel(r'$\phi (rads)$' ) # ax3.set_title('Max. robustness: ' + str( round( number_robust[max_robust_indices] , 2) ) \ # +'\nBest accuracy with noise: ' + str( round( test_acc_noise[max_robust_indices] , 2) ) \ # +'\nBest accuracy ideal: ' + str( round( test_acc_ideal[max_robust_indices] , 2) ) + '\n'\ # +r'$[\theta, \phi]$ = ' + '[' + str(theta [ max_robust_indices[0] ]) \ # + ', ' + str(phi [ max_robust_indices[1] ] ) + ']' ) ## 2D PLOTS fig, ax = plt.subplots(1, 3) im0 = ax[0].imshow(test_acc_ideal, cmap=cm.coolwarm_r, extent=[0, 2 * np.pi, 2 * np.pi, 0]) divider = make_axes_locatable(ax[0]) cax = divider.append_axes('right', size='5%', pad=0.1) cbar0 = fig.colorbar(im0, cax=cax, orientation='vertical') cbar0.ax.set_ylabel('Test Accuracy') im1 = ax[1].imshow(test_acc_noise, cmap=cm.coolwarm_r, extent=[0, 2 * np.pi, 2 * np.pi, 0]) divider = make_axes_locatable(ax[1]) cax = divider.append_axes('right', size='5%', pad=0.1) cbar1 = fig.colorbar(im1, cax=cax, orientation='vertical') cbar1.ax.set_ylabel('Test Accuracy') im2 = ax[2].imshow(number_robust, cmap=cm.PuOr, extent=[0, 2 * np.pi, 2 * np.pi, 0]) divider = make_axes_locatable(ax[2]) cax = divider.append_axes('right', size='5%', pad=0.1) cbar2 = fig.colorbar(im2, cax=cax, orientation='vertical') cbar2.ax.set_ylabel('Proportion robust') ax[0].set_title( 'Best accuracy ideal: ' + str( round( test_acc_ideal[max_acc_indices_ideal] , 2) ) \ + '\nBest accuracy with noise: ' + str( round( test_acc_noise[max_acc_indices_ideal] , 2) ) \ + '\nRobustness: ' + str( round( number_robust[max_acc_indices_ideal] , 2) ) + '\n' \ + r'$[\theta, \phi]$ = ' + '['+str(round(theta [ max_acc_indices_ideal[0] ], 2) )+ ', ' + str( round( phi [ max_acc_indices_ideal[1] ] , 2) ) + ']' ) ax[1].set_title( 'Best accuracy with noise: ' + str( round( test_acc_noise[max_acc_indices] , 2) ) \ + '\nBest accuracy ideal: ' + str( round( test_acc_ideal[max_acc_indices] , 2) ) \ + '\nRobustness: ' + str( round( number_robust[max_acc_indices] , 2) ) + '\n' \ + r'$[\theta, \phi]$ = ' + '['+str(theta [ max_acc_indices[0] ])+ ', ' + str(round( phi [ max_acc_indices[1] ], 2) ) + ']' ) ax[2].set_title('Max. robustness: ' + str( round( number_robust[max_robust_indices] , 2) ) \ +'\nBest accuracy with noise: ' + str( round( test_acc_noise[max_robust_indices] , 2) ) \ +'\nBest accuracy ideal: ' + str( round( test_acc_ideal[max_robust_indices] , 2) ) + '\n'\ +r'$[\theta, \phi]$ = ' + '[' + str(theta [ max_robust_indices[0] ]) \ + ', ' + str(phi [ max_robust_indices[1] ] ) + ']' ) return if analytic: correct_classification_labels, number_robust = compute_analytic_misclassifed_condition(data_grid, ideal_params_vertical,\ encoding_choice, init_encoding_params,\ noise_values, grid_true_labels) plot_params = {'colors': ['blue', 'black'], 'alpha': 0.3} scatter(data_grid, correct_classification_labels, **plot_params) plt.show() if compare: plot_number_misclassified_amp_damp(ideal_params_vertical, num_shots, 500, qc, noise_values) plt.show()
def main(train=False, retrain=False, qc_name='2q-qvm', data_choice='iris', noise_choice='decoherence_symmetric_ro', noise_values=None): ### Firstly, generate for dataset: data_train, data_test, true_labels_train, true_labels_test = generate_data( data_choice, num_points=500, split=True) data_train, true_labels_train = remove_zeros(data_train, true_labels_train) data_test, true_labels_test = remove_zeros(data_test, true_labels_test) # encodings = [ 'denseangle_param','superdenseangle_param', 'wavefunction_param' ] encodings = ['superdenseangle_param'] minimal_costs, ideal_costs, noisy_costs, noisy_costs_uncorrected = [ np.ones(len(encodings)) for _ in range(4) ] # qc_name = '2q-qvm' qc = get_qc(qc_name) num_shots = 1024 device_qubits = qc.qubits() classifier_qubits = device_qubits n_layers = 1 # init_params = np.random.rand(len(qubits),n_layers, 3) # init_params = np.random.rand(len(qubits),n_layers, 3) # init_params = np.random.rand((7)) # TTN init_params = np.random.rand((12)) # General 2 qubit unitary ideal_params = [] ideal_encoding_params = [] init_encoding_params = [] for ii, encoding_choice in enumerate(encodings): print('\n**********************************') print('\nThe encoding is:', encoding_choice) print('\n**********************************') if encoding_choice.lower() == 'wavefunction_param': init_encoding_params.append( [0] ) # Generalized Wavefunction Encoding initialised to Wavefunction encoding else: init_encoding_params.append([np.pi, 2 * np.pi]) if train: optimiser = 'Powell' params, result_unitary_param = train_classifier(qc, classifier_qubits, num_shots, init_params, n_layers,\ encoding_choice, init_encoding_params[ii],\ optimiser, data_train, true_labels_train) print('The optimised parameters are:', result_unitary_param.x) print('These give a cost of:', ClassificationCircuit(classifier_qubits, data_train, qc).build_classifier(result_unitary_param.x, n_layers,\ encoding_choice, init_encoding_params[ii],\ num_shots, true_labels_train)) ideal_params.append(result_unitary_param.x) else: if data_choice.lower() == 'iris': if encoding_choice.lower() == 'denseangle_param': ideal_params.append([ 2.02589489, 1.24358318, -0.6929718,\ 0.85764484, 2.7572075, 1.12317156, \ 4.01974889, 0.30921738, 0.88106973,\ 1.461694, 0.367226, 5.01508911 ]) # elif encoding_choice.lower() == 'superdenseangle_param': ideal_params.append([1.1617383, -0.05837820, -0.7216498,\ # 1.3195103, 0.52933357, 1.2854939, # 1.2097700, 0.26920745, 0.4239539, # 1.2999367, 0.37921617, 0.790320211]) elif encoding_choice.lower() == 'superdenseangle_param': ideal_params.append([ 2.91988765, 1.85012634, 1.75234515, 0.81420946,\ 1.286217,0.62223565, 0.8356422, 1.36681893, 0.58494563,\ -0.02031075, 0.80183355, 6.92525521]) elif encoding_choice.lower() == 'wavefunction': ideal_params.append([ 2.37732073, 1.01449711, 1.12025344,\ -0.087440021, 0.46937127, 2.14387135, \ 0.4696964, 1.444409282, 0.14412614,\ 1.4825742, 1.0817654, 6.30943537 ]) elif encoding_choice.lower() == 'wavefunction_param': ideal_params.append([ 2.37732073, 1.01449711, 1.12025344,\ -0.087440021, 0.46937127, 2.14387135, \ 0.4696964, 1.444409282, 0.14412614,\ 1.4825742, 1.0817654, 6.30943537 ]) ideal_costs[ii] = ClassificationCircuit(classifier_qubits, data_test, qc).build_classifier(ideal_params[ii], n_layers, \ encoding_choice, init_encoding_params[ii], \ num_shots, true_labels_test) print('In the ideal case, the cost is:', ideal_costs[ii]) predicted_labels_ideal = ClassificationCircuit(classifier_qubits, data_test, qc).make_predictions(ideal_params[ii], n_layers,\ encoding_choice, init_encoding_params[ii],\ num_shots) if noise_choice is not None: noisy_costs_uncorrected[ii] = ClassificationCircuit(classifier_qubits, data_test, qc, \ noise_choice, noise_values).build_classifier(ideal_params[ii], n_layers,\ encoding_choice, init_encoding_params[ii],\ num_shots, true_labels_test) print('\nWithout encoding training, the noisy cost is:', noisy_costs_uncorrected[ii]) noisy_predictions, number_classified_same = generate_noisy_classification(ideal_params[ii], n_layers,\ noise_choice, noise_values,\ encoding_choice, init_encoding_params[ii],\ qc, classifier_qubits, num_shots, data_test, predicted_labels_ideal) print('The proportion classified differently after noise is:', 1 - number_classified_same) if retrain: if encoding_choice.lower() == 'wavefunction_param': optimiser = 'L-BFGS-B' else: optimiser = 'Powell' encoding_params, result_encoding_param = train_classifier_encoding( qc, noise_choice, noise_values, num_shots, ideal_params[ii], encoding_choice, init_encoding_params[ii], optimiser, data_train, true_labels_train) print('The optimised encoding parameters with noise are:', result_encoding_param.x) ideal_encoding_params.append(result_encoding_param.x) else: if data_choice.lower() == 'iris' and noise_choice.lower( ) == 'decoherence_symmetric_ro': if encoding_choice.lower() == 'denseangle_param': ideal_encoding_params.append(init_encoding_params[ii]) elif encoding_choice.lower() == 'superdenseangle_param': ideal_encoding_params.append(init_encoding_params[ii]) elif encoding_choice.lower() == 'wavefunction_param': ideal_encoding_params.append(init_encoding_params[ii]) else: print('THIS DATASET HAS NOT BEEN TRAINED FOR') if encoding_choice.lower() == 'denseangle_param': ideal_encoding_params.append(init_encoding_params[ii]) elif encoding_choice.lower() == 'superdenseangle_param': ideal_encoding_params.append(init_encoding_params[ii]) elif encoding_choice.lower() == 'wavefunction_param': ideal_encoding_params.append(init_encoding_params[ii]) noisy_costs[ii] = ClassificationCircuit(classifier_qubits, data_test, qc, \ noise_choice, noise_values).build_classifier(ideal_params[ii], n_layers, \ encoding_choice, ideal_encoding_params[ii],\ num_shots, true_labels_test) print('\nWith encoding training, the noisy cost is:', noisy_costs[ii]) noisy_predictions, number_classified_same = generate_noisy_classification(ideal_params[ii], n_layers, \ noise_choice, noise_values,\ encoding_choice, ideal_encoding_params[ii],\ qc, classifier_qubits, num_shots, data_test, predicted_labels_ideal) print( 'The proportion classified differently after noise with learned encoding is:', 1 - number_classified_same) # for ii, encoding_choice in enumerate(encodings): # print('\nThe encoding is:' , encodings[ii] ) # print('The ideal params are:' , ideal_params[ii] ) # print('The ideal encoding params are' , ideal_encoding_params[ii] ) # print('The ideal cost for encoding' , ideal_costs[ii] ) # print('The noisy cost with untrained encoding' , noisy_costs_uncorrected[ii] ) # print('The noisy cost with trained encoding' , noisy_costs[ii] ) return encodings, ideal_params, init_encoding_params, ideal_encoding_params, ideal_costs, noisy_costs_uncorrected, noisy_costs