# 0->2 state schedule calibration routine
With this project I intend to use a higher energy state (the 2 state) to perform random number generation and afterwards a quantum random optimization of an objective function. The main difference between this implementation and an implementation using only the $ |0> $ and $ |1> $ states is the potential increase of available random numbers for the same amount of qubits. The random number generator implemented in this notebook already works on circuits to create any of $ 2^n $ different random numbers, where n is the amount of qubits. With the inclusion of the $ |2> $ state, the same algorithm may create any of $ 3^n $ different random numbers, an important increase that can be useful for creating more quality random numbers on NISQ computers with a small amount of qubits, like ibmq_bogota.

The project is comprised of three main activities:
- First a calibration routine of a |2> state schedule to access the higher energy state, leaving a ready-to-use three dimensional X gate. (Most of the code from this activity was found in https://qiskit.org/textbook/ch-quantum-hardware/accessing_higher_energy_states.html)
- I then demonstrate random number generation using the calibrated schedule.
- Finally a quantum random optimization is performed with random numbers generated in the same way.

# 0->1 state schedule

The first step is to calibrate a $ |1> $ state schedule using a frequency sweep and Rabi oscillations.

```python
import numpy as np
import matplotlib.pyplot as plt

from scipy.optimize import curve_fit
from scipy.signal import find_peaks

from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.model_selection import train_test_split

import qiskit.pulse as pulse
import qiskit.pulse.library as pulse_lib
from qiskit.compiler import assemble
from qiskit.pulse.library import SamplePulse

from qiskit.tools.monitor import job_monitor
```

```python
import warnings
warnings.filterwarnings('ignore')
from qiskit.tools.jupyter import *
%matplotlib inline

from qiskit import IBMQ
IBMQ.load_account()
provider = IBMQ.get_provider(hub='ibm-q-ornl', group='ornl', project='phy141')
backend = provider.get_backend('ibmq_bogota')

backend_config = backend.configuration()
assert backend_config.open_pulse, "Backend doesn't support Pulse"

dt = backend_config.dt

backend_defaults = backend.defaults()

# unit conversion factors -> all backend properties returned in SI (Hz, sec, etc)
GHz = 1.0e9 # Gigahertz
MHz = 1.0e6 # Megahertz
us = 1.0e-6 # Microseconds
ns = 1.0e-9 # Nanoseconds

qubit = 0 # qubit we will analyze
default_qubit_freq = backend_defaults.qubit_freq_est[qubit] # Default qubit frequency in Hz.
print(f"Qubit {qubit} has an estimated frequency of {default_qubit_freq/ GHz} GHz.")

# scale data (specific to each device)
scale_factor = 1e-14

# number of shots for our experiments
NUM_SHOTS = 1024

### Collect the necessary channels
drive_chan = pulse.DriveChannel(qubit)
meas_chan = pulse.MeasureChannel(qubit)
acq_chan = pulse.AcquireChannel(qubit)
```

    ibmqfactory.load_account:WARNING:2021-04-11 03:53:37,357: Credentials are already in use. The existing account in the session will be replaced.

    Qubit 0 has an estimated frequency of 5.00043029529132 GHz.

```python
def get_job_data(job, average):
    """Retrieve data from a job that has already run.
    Args:
        job (Job): The job whose data you want.
        average (bool): If True, gets the data assuming data is an average.
                        If False, gets the data assuming it is for single shots.
    Return:
        list: List containing job result data.
    """
    job_results = job.result(timeout=120) # timeout parameter set to 120 s
    result_data = []
    for i in range(len(job_results.results)):
        if average: # get avg data
            result_data.append(job_results.get_memory(i)[qubit]*scale_factor)
        else: # get single data
            result_data.append(job_results.get_memory(i)[:, qubit]*scale_factor)
    return result_data

def get_closest_multiple_of_16(num):
    """Compute the nearest multiple of 16. Needed because pulse enabled devices require
    durations which are multiples of 16 samples.
    """
    return (int(num) - (int(num)%16))
```

```python
# Drive pulse parameters (us = microseconds)
drive_sigma_us = 0.075                     # This determines the actual width of the gaussian
drive_samples_us = drive_sigma_us*8        # This is a truncating parameter, because gaussians don't have
                                           # a natural finite length

drive_sigma = get_closest_multiple_of_16(drive_sigma_us * us /dt)       # The width of the gaussian in units of dt
drive_samples = get_closest_multiple_of_16(drive_samples_us * us /dt)   # The truncating parameter in units of dt
```

```python
# Find out which measurement map index is needed for this qubit
meas_map_idx = None
for i, measure_group in enumerate(backend_config.meas_map):
    if qubit in measure_group:
        meas_map_idx = i
        break
assert meas_map_idx is not None, f"Couldn't find qubit {qubit} in the meas_map!"
```

```python
# Get default measurement pulse from instruction schedule map
inst_sched_map = backend_defaults.instruction_schedule_map
measure = inst_sched_map.get('measure', qubits=backend_config.meas_map[meas_map_idx])
```

```python
def create_ground_freq_sweep_program(freqs, drive_power):
    """Builds a program that does a freq sweep by exciting the ground state.
    Depending on drive power this can reveal the 0->1 frequency or the 0->2 frequency.
    Args:
        freqs (np.ndarray(dtype=float)): Numpy array of frequencies to sweep.
        drive_power (float) : Value of drive amplitude.
    Raises:
        ValueError: Raised if use more than 75 frequencies; currently, an error will be thrown on the backend
                    if you try to do this.
    Returns:
        Qobj: Program for ground freq sweep experiment.
    """
    if len(freqs) > 75:
        raise ValueError("You can only run 75 schedules at a time.")

    # print information on the sweep
    print(f"The frequency sweep will go from {freqs[0] / GHz} GHz to {freqs[-1]/ GHz} GHz \
using {len(freqs)} frequencies. The drive power is {drive_power}.")

    # Define the drive pulse
    ground_sweep_drive_pulse = pulse_lib.gaussian(duration=drive_samples,
                                                  sigma=drive_sigma,
                                                  amp=drive_power,
                                                  name='ground_sweep_drive_pulse')
    # Create the base schedule
    schedule = pulse.Schedule(name='Frequency sweep starting from ground state.')

    schedule |= pulse.Play(ground_sweep_drive_pulse, drive_chan)
    schedule |= measure << schedule.duration

    # define frequencies for the sweep
    schedule_freqs = [{drive_chan: freq} for freq in freqs]

    # assemble the program
    # Note: we only require a single schedule since each does the same thing;
    # for each schedule, the LO frequency that mixes down the drive changes
    # this enables our frequency sweep
    ground_freq_sweep_program = assemble(schedule,
                                         backend=backend,
                                         meas_level=1,
                                         meas_return='avg',
                                         shots=NUM_SHOTS,
                                         schedule_los=schedule_freqs)

    return ground_freq_sweep_program
```

```python
# We will sweep 40 MHz around the estimated frequency, with 75 frequencies
num_freqs = 75
ground_sweep_freqs = default_qubit_freq + np.linspace(-20*MHz, 20*MHz, num_freqs)
ground_freq_sweep_program = create_ground_freq_sweep_program(ground_sweep_freqs, drive_power=0.3)
```

    The frequency sweep will go from 4.9804302952913195 GHz to 5.02043029529132 GHz using 75 frequencies. The drive power is 0.3.

```python
ground_freq_sweep_job = backend.run(ground_freq_sweep_program)
```

```python
print(ground_freq_sweep_job.job_id())
job_monitor(ground_freq_sweep_job)
```

    6072b910b5717367cd97e68a
    Job Status: job has successfully run

```python
# Get the job data (average)
ground_freq_sweep_data = get_job_data(ground_freq_sweep_job, average=True)
```

```python
def fit_function(x_values, y_values, function, init_params):
    """Fit a function using scipy curve_fit."""
    fitparams, conv = curve_fit(function, x_values, y_values, init_params)
    y_fit = function(x_values, *fitparams)

    return fitparams, y_fit
```

```python
# do fit in Hz
(ground_sweep_fit_params,
 ground_sweep_y_fit) = fit_function(ground_sweep_freqs,
                                   ground_freq_sweep_data,
                                   lambda x, A, q_freq, B, C: (A / np.pi) * (B / ((x - q_freq)**2 + B**2)) + C,
                                   [7, 4.975*GHz, 1*GHz, 3*GHz] # initial parameters for curve_fit
                                   )
```

```python
# Note: we are only plotting the real part of the signal
plt.scatter(ground_sweep_freqs/GHz, ground_freq_sweep_data, color='black')
plt.plot(ground_sweep_freqs/GHz, ground_sweep_y_fit, color='red')
plt.xlim([min(ground_sweep_freqs/GHz), max(ground_sweep_freqs/GHz)])
plt.xlabel("Frequency [GHz]", fontsize=15)
plt.ylabel("Measured Signal [a.u.]", fontsize=15)
plt.title("0->1 Frequency Sweep", fontsize=15)
plt.show()
```

```python
index = np.array(ground_freq_sweep_data).argmax()
cal_qubit_freq = ground_sweep_freqs[index]
```

```python
cal_qubit_freq = default_qubit_freq
```

```python
#_, cal_qubit_freq, _, _ = ground_sweep_fit_params
print(f"We've updated our qubit frequency estimate from "
      f"{round(default_qubit_freq/GHz, 7)} GHz to {round(cal_qubit_freq/GHz, 7)} GHz.")
```

    We've updated our qubit frequency estimate from 5.0004303 GHz to 5.0004303 GHz.

```python
# experimental configuration
num_rabi_points = 50 # number of experiments (ie amplitudes to sweep out)

# Drive amplitude values to iterate over: 50 amplitudes evenly spaced from 0 to 0.75
drive_amp_min = 0
drive_amp_max = 0.75
drive_amps = np.linspace(drive_amp_min, drive_amp_max, num_rabi_points)
```

```python
# Create schedule
rabi_01_schedules = []
# loop over all drive amplitudes
for ii, drive_amp in enumerate(drive_amps):
    # drive pulse
    rabi_01_pulse = pulse_lib.gaussian(duration=drive_samples,
                                       amp=drive_amp,
                                       sigma=drive_sigma,
                                       name='rabi_01_pulse_%d' % ii)

    # add commands to schedule
    schedule = pulse.Schedule(name='Rabi Experiment at drive amp = %s' % drive_amp)
    schedule |= pulse.Play(rabi_01_pulse, drive_chan)
    schedule |= measure << schedule.duration # shift measurement to after drive pulse
    rabi_01_schedules.append(schedule)
```

```python
# Assemble the schedules into a program
# Note: We drive at the calibrated frequency.
rabi_01_expt_program = assemble(rabi_01_schedules,
                                backend=backend,
                                meas_level=1,
                                meas_return='avg',
                                shots=NUM_SHOTS,
                                schedule_los=[{drive_chan: cal_qubit_freq}]
                                               * num_rabi_points)
```

```python
rabi_01_job = backend.run(rabi_01_expt_program)
```

```python
print(rabi_01_job.job_id())
job_monitor(rabi_01_job)
```

    6072b9b02f5a612e488f6217
    Job Status: job has successfully run

```python
# Get the job data (average)
rabi_01_data = get_job_data(rabi_01_job, average=True)
```

```python
def baseline_remove(values):
    """Center data around 0."""
    return np.array(values) - np.mean(values)
```

```python
# Note: Only real part of data is plotted
rabi_01_data = np.real(baseline_remove(rabi_01_data))
(rabi_01_fit_params,
 rabi_01_y_fit) = fit_function(drive_amps,
                               rabi_01_data,
                               lambda x, A, B, drive_01_period, phi: (A*np.cos(2*np.pi*x/drive_01_period - phi) + B),
                               [4, -4, 0.5, 0])

plt.scatter(drive_amps, rabi_01_data, color='black')
plt.plot(drive_amps, rabi_01_y_fit, color='red')

drive_01_period = rabi_01_fit_params[2]
# account for phi in computing pi amp
pi_amp_01 = (drive_01_period/2/np.pi) *(np.pi+rabi_01_fit_params[3])

plt.axvline(pi_amp_01, color='red', linestyle='--')
plt.axvline(pi_amp_01+drive_01_period/2, color='red', linestyle='--')
plt.annotate("", xy=(pi_amp_01+drive_01_period/2, 0), xytext=(pi_amp_01,0), arrowprops=dict(arrowstyle="<->", color='red'))
#plt.annotate("$\pi$", xy=(pi_amp_01-0.03, 0.1), color='red')

plt.xlabel("Drive amp [a.u.]", fontsize=15)
plt.ylabel("Measured signal [a.u.]", fontsize=15)
plt.title('0->1 Rabi Experiment', fontsize=15)
plt.show()
```

```python
print(f"Pi Amplitude (0->1) = {pi_amp_01}")
```

    Pi Amplitude (0->1) = 0.2570383080839592

```python
pi_pulse_01 = pulse_lib.gaussian(duration=drive_samples,
                                 amp=pi_amp_01,
                                 sigma=drive_sigma,
                                 name='pi_pulse_01')
```

# 1->2 state schedule

The second step is to calibrate a $ |1> - |2> $ state schedule using a frequency sweep and Rabi oscillations too.

```python
def apply_sideband(pulse, freq):
    """Apply a sinusoidal sideband to this pulse at frequency freq.
    Args:
        pulse (SamplePulse): The pulse of interest.
        freq (float): LO frequency for which we want to apply the sweep.
    Return:
        SamplePulse: Pulse with a sideband applied (oscillates at difference between freq and cal_qubit_freq).
    """
    # time goes from 0 to dt*drive_samples, sine arg of form 2*pi*f*t
    t_samples = np.linspace(0, dt*drive_samples, drive_samples)
    sine_pulse = np.sin(2*np.pi*(freq-cal_qubit_freq)*t_samples) # no amp for the sine

    # create sample pulse w/ sideband applied
    # Note: need to make sq_pulse.samples real, multiply elementwise
    sideband_pulse = SamplePulse(np.multiply(np.real(pulse.samples), sine_pulse), name='sideband_pulse')

    return sideband_pulse
```

```python
def create_excited_freq_sweep_program(freqs, drive_power):
    """Builds a program that does a freq sweep by exciting the |1> state.
    This allows us to obtain the 1->2 frequency. We get from the |0> to |1>
    state via a pi pulse using the calibrated qubit frequency. To do the
    frequency sweep from |1> to |2>, we use a sideband method by tacking
    a sine factor onto the sweep drive pulse.
    Args:
        freqs (np.ndarray(dtype=float)): Numpy array of frequencies to sweep.
        drive_power (float) : Value of drive amplitude.
    Raises:
        ValueError: Thrown if use more than 75 frequencies; currently, an error will be thrown on the backend
                    if you try more than 75 frequencies.
    Returns:
        Qobj: Program for freq sweep experiment.
    """
    if len(freqs) > 75:
        raise ValueError("You can only run 75 schedules at a time.")

    print(f"The frequency sweep will go from {freqs[0] / GHz} GHz to {freqs[-1]/ GHz} GHz \
using {len(freqs)} frequencies. The drive power is {drive_power}.")

    base_12_pulse = pulse_lib.gaussian(duration=drive_samples,
                                        sigma=drive_sigma,
                                        amp=drive_power,
                                        name='base_12_pulse')
    schedules = []
    for jj, freq in enumerate(freqs):

        # add sideband to gaussian pulse
        freq_sweep_12_pulse = apply_sideband(base_12_pulse, freq)

        # add commands to schedule
        schedule = pulse.Schedule(name="Frequency = {}".format(freq))

        # Add 0->1 pulse, freq sweep pulse and measure
        schedule |= pulse.Play(pi_pulse_01, drive_chan)
        schedule |= pulse.Play(freq_sweep_12_pulse, drive_chan) << schedule.duration
        schedule |= measure << schedule.duration # shift measurement to after drive pulses

        schedules.append(schedule)

    num_freqs = len(freqs)

    # draw a schedule
    display(schedules[-1].draw(channels=[drive_chan, meas_chan], label=True, scale=1.0))

    # assemble freq sweep program
    # Note: LO is at cal_qubit_freq for each schedule; accounted for by sideband
    excited_freq_sweep_program = assemble(schedules,
                                          backend=backend,
                                          meas_level=1,
                                          meas_return='avg',
                                          shots=NUM_SHOTS,
                                          schedule_los=[{drive_chan: cal_qubit_freq}]
                                                         * num_freqs)

    return excited_freq_sweep_program
```

```python
# sweep 400 MHz below 0->1 frequency to catch the 1->2 frequency
num_freqs = 75
excited_sweep_freqs = cal_qubit_freq + np.linspace(-400*MHz, 30*MHz, num_freqs)
excited_freq_sweep_program = create_excited_freq_sweep_program(excited_sweep_freqs, drive_power=0.3)

# Plot an example schedule to make sure it's valid
```

```python
excited_freq_sweep_job = backend.run(excited_freq_sweep_program)
```

```python
print(excited_freq_sweep_job.job_id())
job_monitor(excited_freq_sweep_job)
```

    6072b9f5b10d9520a4609771
    Job Status: job has successfully run

```python
# Get job data (avg)
excited_freq_sweep_data = get_job_data(excited_freq_sweep_job, average=True)
```

```python
# Note: we are only plotting the real part of the signal
plt.scatter(excited_sweep_freqs/GHz, excited_freq_sweep_data, color='black')
plt.xlim([min(excited_sweep_freqs/GHz)+0.01, max(excited_sweep_freqs/GHz)]) # ignore min point (is off)
plt.xlabel("Frequency [GHz]", fontsize=15)
plt.ylabel("Measured Signal [a.u.]", fontsize=15)
plt.title("1->2 Frequency Sweep (first pass)", fontsize=15)
plt.show()
```

```python
# Prints out relative maxima frequencies in output_data; height gives lower bound (abs val)
def rel_maxima(freqs, output_data, height):
    """
    Prints out relative maxima frequencies in output_data (can see peaks); height gives upper bound (abs val).
    Be sure to set the height properly or the peak will be ignored!
    Args:
        freqs (list): frequency list
        output_data (list): list of resulting signals
        height (float): upper bound (abs val) on a peak
    Returns:
        list: List containing relative maxima frequencies
    """
    peaks, _ = find_peaks(output_data, height)
    print("Freq. dips: ", freqs[peaks])
    return freqs[peaks]
```

```python
maxima = rel_maxima(excited_sweep_freqs, np.real(excited_freq_sweep_data), 2.4e-7)
approx_12_freq = maxima[0]
```

    Freq. dips:  [4.66434921e+09 5.00137624e+09]

```python
# smaller range refined sweep
num_freqs = 75
refined_excited_sweep_freqs = approx_12_freq + np.linspace(-20*MHz, 20*MHz, num_freqs)
refined_excited_freq_sweep_program = create_excited_freq_sweep_program(refined_excited_sweep_freqs, drive_power=0.3)
```

```python
refined_excited_freq_sweep_job = backend.run(refined_excited_freq_sweep_program)
```

```python
print(refined_excited_freq_sweep_job.job_id())
job_monitor(refined_excited_freq_sweep_job)
```

    6072bb115b466e7d7b10a09a
    Job Status: job has successfully run

```python
# Get the refined data (average)
refined_excited_freq_sweep_data = get_job_data(refined_excited_freq_sweep_job, average=True)
```

```python
# do fit in Hz
(refined_excited_sweep_fit_params,
 refined_excited_sweep_y_fit) = fit_function(refined_excited_sweep_freqs,
                                     refined_excited_freq_sweep_data,
                                     lambda x, A, q_freq, B, C: (A / np.pi) * (B / ((x - q_freq)**2 + B**2)) + C,
                                     [-12, 4.625*GHz, 0.05*GHz, 3*GHz] # initial parameters for curve_fit
                                     )
```

```python
# Note: we are only plotting the real part of the signal
plt.scatter(refined_excited_sweep_freqs/GHz, refined_excited_freq_sweep_data, color='black')
plt.plot(refined_excited_sweep_freqs/GHz, refined_excited_sweep_y_fit, color='red')
plt.xlim([min(refined_excited_sweep_freqs/GHz), max(refined_excited_sweep_freqs/GHz)])
plt.xlabel("Frequency [GHz]", fontsize=15)
plt.ylabel("Measured Signal [a.u.]", fontsize=15)
plt.title("1->2 Frequency Sweep (refined pass)", fontsize=15)
plt.show()
```

```python
index = np.array(refined_excited_freq_sweep_data).argmax()
qubit_12_freq = refined_excited_sweep_freqs[index]
```

```python
#_, qubit_12_freq, _, _ = refined_excited_sweep_fit_params
print(f"Our updated estimate for the 1->2 transition frequency is "
      f"{round(qubit_12_freq/GHz, 7)} GHz.")
```

    Our updated estimate for the 1->2 transition frequency is 4.6627276 GHz.

```python
# experimental configuration
num_rabi_points = 75 # number of experiments (ie amplitudes to sweep out)

# Drive amplitude values to iterate over: 75 amplitudes evenly spaced from 0 to 1.0
drive_amp_min = 0
drive_amp_max = 1.0
drive_amps = np.linspace(drive_amp_min, drive_amp_max, num_rabi_points)
```

```python
# Create schedule
rabi_12_schedules = []

# loop over all drive amplitudes
for ii, drive_amp in enumerate(drive_amps):

    base_12_pulse = pulse_lib.gaussian(duration=drive_samples,
                                       sigma=drive_sigma,
                                       amp=drive_amp,
                                       name='base_12_pulse')
    # apply sideband at the 1->2 frequency
    rabi_12_pulse = apply_sideband(base_12_pulse, qubit_12_freq)

    # add commands to schedule
    schedule = pulse.Schedule(name='Rabi Experiment at drive amp = %s' % drive_amp)
    schedule |= pulse.Play(pi_pulse_01, drive_chan) # 0->1
    schedule |= pulse.Play(rabi_12_pulse, drive_chan) << schedule.duration # 1->2 Rabi pulse
    schedule |= measure << schedule.duration # shift measurement to after drive pulse

    rabi_12_schedules.append(schedule)
```

```python
# Assemble the schedules into a program
# Note: The LO frequency is at cal_qubit_freq to support the 0->1 pi pulse;
# it is modified for the 1->2 pulse using sidebanding
rabi_12_expt_program = assemble(rabi_12_schedules,
                                backend=backend,
                                meas_level=1,
                                meas_return='avg',
                                shots=NUM_SHOTS,
                                schedule_los=[{drive_chan: cal_qubit_freq}]
                                               * num_rabi_points)
```

```python
rabi_12_job = backend.run(rabi_12_expt_program)
```

```python
print(rabi_12_job.job_id())
job_monitor(rabi_12_job)
```

    6072bb96dbfb943a7e27a5e2
    Job Status: job has successfully run

```python
# Get the job data (average)
rabi_12_data = get_job_data(rabi_12_job, average=True)
```

```python
# Note: We only plot the real part of the signal.
rabi_12_data = np.real(baseline_remove(rabi_12_data))
(rabi_12_fit_params,
 rabi_12_y_fit) = fit_function(drive_amps,
                            rabi_12_data,
                            lambda x, A, B, drive_12_period, phi: (A*np.cos(2*np.pi*x/drive_12_period - phi) + B),
                            [3, 0.5, 0.9, 0])

plt.scatter(drive_amps, rabi_12_data, color='black')
plt.plot(drive_amps, rabi_12_y_fit, color='red')

drive_12_period = rabi_12_fit_params[2]
# account for phi in computing pi amp
pi_amp_12 = (drive_12_period/2/np.pi) *(np.pi+rabi_12_fit_params[3])

plt.axvline(pi_amp_12, color='red', linestyle='--')
plt.axvline(pi_amp_12+drive_12_period/2, color='red', linestyle='--')
plt.annotate("", xy=(pi_amp_12+drive_12_period/2, 0), xytext=(pi_amp_12,0), arrowprops=dict(arrowstyle="<->", color='red'))
#plt.annotate("$\pi$", xy=(pi_amp_12-0.03, 0.1), color='red')

plt.xlabel("Drive amp [a.u.]", fontsize=15)
plt.ylabel("Measured signal [a.u.]", fontsize=15)
plt.title('Rabi Experiment (1->2)', fontsize=20)
plt.show()
```

```python
print(f"Our updated estimate for the 1->2 transition frequency is "
      f"{round(qubit_12_freq/GHz, 7)} GHz.")
print(f"Pi Amplitude (1->2) = {pi_amp_12}")
```

    Our updated estimate for the 1->2 transition frequency is 4.6627276 GHz.
    Pi Amplitude (1->2) = 0.3675043942181431

```python
pi_pulse_12 = pulse_lib.gaussian(duration=drive_samples,
                                 amp=pi_amp_12,
                                 sigma=drive_sigma,
                                 name='pi_pulse_12')
# make sure this pulse is sidebanded
pi_pulse_12 = apply_sideband(pi_pulse_12, qubit_12_freq)
```

```python
# Create the three schedules

# Ground state schedule
zero_schedule = pulse.Schedule(name="zero schedule")
zero_schedule |= measure

# Excited state schedule
one_schedule = pulse.Schedule(name="one schedule")
one_schedule |= pulse.Play(pi_pulse_01, drive_chan)
one_schedule |= measure << one_schedule.duration

# Excited state schedule
two_schedule = pulse.Schedule(name="two schedule")
two_schedule |= pulse.Play(pi_pulse_01, drive_chan)
two_schedule |= pulse.Play(pi_pulse_12, drive_chan) << two_schedule.duration
two_schedule |= measure << two_schedule.duration
```

```python
# Assemble the schedules into a program
IQ_012_program = assemble([zero_schedule, one_schedule, two_schedule],
                           backend=backend,
                           meas_level=1,
                           meas_return='single',
                           shots=NUM_SHOTS,
                           schedule_los=[{drive_chan: cal_qubit_freq}] * 3)
```

```python
IQ_012_job = backend.run(IQ_012_program)
```

```python
print(IQ_012_job.job_id())
job_monitor(IQ_012_job)
```

    6072bbe701ba9616b9179ffb
    Job Status: job has successfully run

```python
# Get job data (single); split for zero, one and two
IQ_012_data = get_job_data(IQ_012_job, average=False)
zero_data = IQ_012_data[0]
one_data = IQ_012_data[1]
two_data = IQ_012_data[2]
```

```python
two_data
```

    array([-3.9115256e-07-1.04698424e-06j,  4.5560548e-07-8.93501360e-07j,
           -2.3081644e-07-7.17775520e-07j, ...,
            5.4394000e-07-4.66129840e-07j,  5.9252536e-07-2.20355360e-07j,
            2.0817464e-07-4.26374280e-07j])

```python
def IQ_012_plot(x_min, x_max, y_min, y_max):
    """Helper function for plotting IQ plane for 0, 1, 2. Limits of plot given
    as arguments."""
    # zero data plotted in blue
    plt.scatter(np.real(zero_data), np.imag(zero_data),
                    s=5, cmap='viridis', c='blue', alpha=0.5, label=r'$|0\rangle$')
    # one data plotted in red
    plt.scatter(np.real(one_data), np.imag(one_data),
                    s=5, cmap='viridis', c='red', alpha=0.5, label=r'$|1\rangle$')
    # two data plotted in green
    plt.scatter(np.real(two_data), np.imag(two_data),
                    s=5, cmap='viridis', c='green', alpha=0.5, label=r'$|2\rangle$')

    # Plot a large dot for the average result of the 0, 1 and 2 states.
    mean_zero = np.mean(zero_data) # takes mean of both real and imaginary parts
    mean_one = np.mean(one_data)
    mean_two = np.mean(two_data)
    plt.scatter(np.real(mean_zero), np.imag(mean_zero),
                s=200, cmap='viridis', c='black',alpha=1.0)
    plt.scatter(np.real(mean_one), np.imag(mean_one),
                s=200, cmap='viridis', c='black',alpha=1.0)
    plt.scatter(np.real(mean_two), np.imag(mean_two),
                s=200, cmap='viridis', c='black',alpha=1.0)

    plt.xlim(x_min, x_max)
    plt.ylim(y_min,y_max)
    plt.legend()
    plt.ylabel('I [a.u.]', fontsize=15)
    plt.xlabel('Q [a.u.]', fontsize=15)
    plt.title("0-1-2 discrimination", fontsize=15)
```

```python
x_min = -10e-7
x_max = 10e-7
y_min = -15e-7
y_max = 5e-7
IQ_012_plot(x_min, x_max, y_min, y_max)
```

```python
def reshape_complex_vec(vec):
    """Take in complex vector vec and return 2d array w/ real, imag entries. This is needed for the learning.
    Args:
        vec (list): complex vector of data
    Returns:
        list: vector w/ entries given by (real(vec], imag(vec))
    """
    length = len(vec)
    vec_reshaped = np.zeros((length, 2))
    for i in range(len(vec)):
        vec_reshaped[i]=[np.real(vec[i]), np.imag(vec[i])]
    return vec_reshaped
```

```python
# Create IQ vector (split real, imag parts)
zero_data_reshaped = reshape_complex_vec(zero_data)
one_data_reshaped = reshape_complex_vec(one_data)
two_data_reshaped = reshape_complex_vec(two_data)

IQ_012_data = np.concatenate((zero_data_reshaped, one_data_reshaped, two_data_reshaped))
print(IQ_012_data.shape) # verify IQ data shape
```

    (3072, 2)

```python
# construct vector w/ 0's, 1's and 2's (for testing)
state_012 = np.zeros(NUM_SHOTS) # shots gives number of experiments
state_012 = np.concatenate((state_012, np.ones(NUM_SHOTS)))
state_012 = np.concatenate((state_012, 2*np.ones(NUM_SHOTS)))
print(len(state_012))

# Shuffle and split data into training and test sets
IQ_012_train, IQ_012_test, state_012_train, state_012_test = train_test_split(IQ_012_data, state_012, test_size=0.5)
```

    3072

```python
# Set up the LDA
LDA_012 = LinearDiscriminantAnalysis()
LDA_012.fit(IQ_012_train, state_012_train)
```

    LinearDiscriminantAnalysis()

```python
# test on some simple data
print(LDA_012.predict([[0, 0], [-10, 0], [-15, -5]]))
```

    [2. 0. 0.]

```python
# Compute accuracy
score_012 = LDA_012.score(IQ_012_test, state_012_test)
print(score_012)
```

    0.7415364583333334

```python
# Plot separatrix on top of scatter
def separatrixPlot(lda, x_min, x_max, y_min, y_max, shots):
    nx, ny = shots, shots

    xx, yy = np.meshgrid(np.linspace(x_min, x_max, nx),
                         np.linspace(y_min, y_max, ny))
    Z = lda.predict_proba(np.c_[xx.ravel(), yy.ravel()])
    Z = Z[:, 1].reshape(xx.shape)

    plt.contour(xx, yy, Z, [0.5], linewidths=2., colors='black')
```

```python
IQ_012_plot(x_min, x_max, y_min, y_max)
separatrixPlot(LDA_012, x_min, x_max, y_min, y_max, NUM_SHOTS)
```

# Gate creation

```python
from qiskit.circuit import Gate
```

## X2 gate

```python
basis_gates = backend_config.basis_gates
inst_map = backend_defaults.instruction_schedule_map
gate_name = 'X2'
basis_gates += [gate_name]
inst_map.add(gate_name, qubit, one_schedule)
x2_gate = Gate(gate_name, 1, [])
```

## X3 gate

```python
gate_name = 'X3'
basis_gates += [gate_name]
inst_map.add(gate_name, qubit, two_schedule)
x3_gate = Gate(gate_name, 1, [])
```

## H2 gate

```python
pi_half_pulse_01 = pulse_lib.gaussian(duration=drive_samples,
                                 amp=pi_amp_01/2,
                                 sigma=drive_sigma,
                                 name='pi_half_pulse_01')
```

```python
# Excited half state schedule
one_half_schedule = pulse.Schedule(name="one half schedule")
one_half_schedule |= pulse.Play(pi_half_pulse_01, drive_chan)
one_half_schedule |= measure << one_half_schedule.duration
```

```python
basis_gates = backend_config.basis_gates
inst_map = backend_defaults.instruction_schedule_map
gate_name = 'H2'
basis_gates += [gate_name]
inst_map.add(gate_name, qubit, one_half_schedule)
h2_gate = Gate(gate_name, 1, [])
```

## H3 gate

```python
pi_half_pulse_12 = pulse_lib.gaussian(duration=drive_samples,
                                 amp=pi_amp_12/2,
                                 sigma=drive_sigma,
                                 name='pi_half_pulse_12')
```

```python
# Excited half state schedule
two_half_schedule = pulse.Schedule(name="two half schedule")
two_half_schedule |= pulse.Play(pi_half_pulse_01, drive_chan)
two_half_schedule |= pulse.Play(pi_half_pulse_12, drive_chan) << two_half_schedule.duration
two_half_schedule |= measure << two_half_schedule.duration
```

```python
basis_gates = backend_config.basis_gates
inst_map = backend_defaults.instruction_schedule_map
gate_name = 'H3'
basis_gates += [gate_name]
inst_map.add(gate_name, qubit, two_half_schedule)
h3_gate = Gate(gate_name, 1, [])
```

# Quantum Number Generator and Quantum random optimization algorithm
Can also be found in https://github.com/Raijeku/Optimization

Here I generate random numbers on 1 qubit of the ibmq_bogota device using the three state schedules previously prepared. At the end is the Quantum Random Optimization algorithm being used in a similar manner.

```python
from sympy import *
import pandas as pd
from qiskit import execute, IBMQ, circuit, QuantumCircuit
from qiskit.tools.monitor import job_monitor
from qiskit.compiler import assemble, schedule
from qiskit.pulse import DriveChannel

def quantum_random_optimization(xl, xu, n, function, backend_name, pulse, num_states, num_qubits):
    x = Symbol('x')
    f = parse_expr(function)
    iteration = 0
    data = pd.DataFrame(columns=['iteration','xl','xu','x','f(x)','max_x','max_f(x)','error'])
    rs = generate_random(n, backend_name, pulse, num_states, num_qubits)

    max_f = -1E9
    max_x = -1E9
    for i in range(n):
        r = rs[i]
        x0 = xl + (xu - xl)*r
        df = f.diff(x)
        fx = f.subs(x, x0)
        dfx = df.subs(x, x0)
        if fx > max_f:
            max_f = fx
            max_x = x0
        data = data.append(pd.DataFrame({'iteration':[iteration], 'xl':[xl], 'xu':[xu], 'x':[x0], 'f(x)':[fx], 'max_x':[max_x], 'max_f(x)':[max_f], 'error':[dfx]}), ignore_index = True)
        iteration += 1

    return data

def generate_random(n, backend_name, pulse=False, num_states=None, num_qubits=None):
    backend_config = backend.configuration()
    if num_qubits==None: num_qubits = backend_config.n_qubits

    if not pulse:
        circuit = QuantumCircuit(num_qubits,num_qubits)
        for i in range(num_qubits):
            circuit.h(i)

        circuit.measure([i for i in range(num_qubits)],[i for i in range(num_qubits)])
        job = execute(circuit, backend, shots = n, memory = True)
        job = backend.run(program)
        job_monitor(job)
        result = job.result()
        bits = result.get_memory(0)

        random_numbers = []
        for key in bits:
            if len(random_numbers) < n:
                random_numbers.append(int(key, 2)/(2**num_qubits))
            else:
                break

    else:
        drive_chan_0 = DriveChannel(0)
        backend_defaults = backend.defaults()
        center_frequency_Hz_0 = backend_defaults.qubit_freq_est[0]
        schedules = [zero_schedule, one_half_schedule, two_schedule]
        program = assemble(schedules,
            backend=backend,
            meas_level=1,
            meas_return='single',
            shots=n,
            schedule_los=[{drive_chan_0: center_frequency_Hz_0}] * len(schedules))
        job = backend.run(program)
        job_monitor(job)
        result = job.result()
        data = np.zeros((n*3,2))
        print(result.get_memory(0))
        data[:n,0] = result.get_memory(0)[:, 0].real
        data[:n,1] = result.get_memory(0)[:, 0].imag
        data[n:2*n,0] = result.get_memory(1)[:, 0].real
        data[n:2*n,1] = result.get_memory(1)[:, 0].imag
        data[2*n:,0] = result.get_memory(2)[:, 0].real
        data[2*n:,1] = result.get_memory(2)[:, 0].imag
        bits = LDA_012.predict(data)

        random_numbers = []
        for integer in bits:
            if len(random_numbers) < 3*n:
                random_numbers.append(integer/(3**num_qubits))
            else:
                break

    return random_numbers
```

```python
numbers = np.array(generate_random(100,'ibmq_bogota', pulse=True, num_states=3, num_qubits=1))
```

    Job Status: job has successfully run
    [[ 3.7371768e+07-9.68769840e+07j -3.4254336e+07-8.50884960e+07j
      -2.9093508e+07-9.74811120e+07j -1.7706748e+07-1.48551136e+08j
      -5.0767444e+07-1.10725112e+08j]
     [-5.5679400e+07-8.50822720e+07j -2.7031796e+07-5.44361440e+07j
      -4.1727432e+07-8.54240240e+07j -8.6979900e+06-1.22411920e+08j
      -4.4237652e+07-1.31726448e+08j]
     [-3.6982124e+07-9.97883520e+07j -5.3301584e+07-7.75967520e+07j
      -4.9099404e+07-8.78693760e+07j -4.9823204e+07-1.32570712e+08j
      -4.8252692e+07-1.39818000e+08j]
     [-4.3798244e+07-9.00195840e+07j -3.8710696e+07-7.65312880e+07j
      -4.0286368e+07-9.26656240e+07j -1.0721803e+07-1.30119024e+08j
      -5.8341660e+07-1.44003408e+08j]
     [-2.8505800e+07-8.60113360e+07j -3.0526470e+07-6.77946000e+07j
      -3.3606536e+07-6.56622040e+07j -2.2336110e+07-1.19311680e+08j
      -5.5173348e+07-1.41212752e+08j]
     [-4.5049584e+07-7.46000640e+07j  3.1732004e+07-5.57240440e+07j
      -2.7144536e+07-1.05583808e+08j -6.4595464e+07-1.24621712e+08j
      -7.4949752e+07-1.08613832e+08j]
     [-5.4060192e+07-9.65664720e+07j -3.8102048e+07-8.00728640e+07j
      -6.4390896e+07-5.63666080e+07j -5.8729112e+07-1.24568800e+08j
      -4.1944844e+07-1.21027504e+08j]
     [-5.3030440e+07-8.80643520e+07j -3.6019940e+07-6.53973720e+07j
      -5.0699024e+07-1.01853192e+08j -6.1943008e+07-1.39191808e+08j
      -4.0176784e+07-1.20847968e+08j]
     [-4.0565776e+07-9.68764400e+07j -2.6576748e+07-6.76749040e+07j
      -4.5528484e+07-1.02869256e+08j -3.1814078e+07-1.07297688e+08j
      -5.5258796e+07-1.38501440e+08j]
     [-4.4122792e+07-1.07541448e+08j -1.2320392e+07-7.23152640e+07j
      -4.3194160e+07-9.36555520e+07j -5.4877052e+07-1.21097256e+08j
      -6.5280560e+07-1.33212112e+08j]
     [-5.4200412e+07-8.76126240e+07j -5.6362200e+07-9.09816720e+07j
      -5.6644192e+07-1.04327488e+08j -2.0565280e+06-1.36344544e+08j
      -2.3052476e+07-1.25645512e+08j]
     [-6.1620496e+07-8.23092240e+07j -4.4339684e+07-5.84407720e+07j
      -3.5228624e+07-9.56240320e+07j -5.4756176e+07-1.48596736e+08j
      -5.1293676e+07-1.25152512e+08j]
     [-5.2431352e+07-7.92327840e+07j -1.6113734e+07-7.01243600e+07j
      -3.6520400e+07-9.15540160e+07j -4.3354004e+07-1.09485512e+08j
      -7.8656584e+07-1.62985296e+08j]
     [-3.6493436e+07-9.73612320e+07j -3.7116004e+07-9.25203120e+07j
      -3.4263684e+07-1.09542704e+08j -3.5469712e+07-1.28212480e+08j
      -6.9058104e+07-1.20178168e+08j]
     [-5.9160104e+07-9.92221040e+07j -2.7230524e+07-7.63625760e+07j
      -3.9230556e+07-8.25634160e+07j -6.3256784e+07-1.14038688e+08j
      -3.8363496e+07-1.54894784e+08j]
     [-6.7632640e+07-8.17767520e+07j -2.5427646e+07-7.51291520e+07j
      -4.3078812e+07-7.96072400e+07j -2.4883784e+07-1.38311472e+08j
      -6.6597384e+07-1.26867952e+08j]
     [-4.7593416e+07-7.54691840e+07j -1.5552532e+07-6.23322880e+07j
      -2.3038692e+07-8.22281440e+07j -5.7952240e+07-1.00365960e+08j
      -6.1579336e+07-1.36748624e+08j]
     [-5.4812564e+07-1.06493984e+08j -1.6899602e+07-4.66179440e+07j
      -4.7568708e+07-9.93494000e+07j -5.8606420e+06-1.40457920e+08j
      -4.0269456e+07-1.14877464e+08j]
     [-3.5259328e+07-8.79608240e+07j -2.7892236e+07-5.54166000e+07j
      -4.2393112e+07-8.78078000e+07j -3.7375476e+07-1.31108928e+08j
      -4.7193756e+07-1.35346000e+08j]
     [-4.4623148e+07-8.05711680e+07j -3.2396652e+07-6.18400960e+07j
      -2.8396106e+07-9.76755360e+07j -3.3173524e+07-1.16208184e+08j
      -5.2782228e+07-1.40413008e+08j]
     [-2.2178104e+07-9.32513920e+07j  2.4658334e+07-6.11620880e+07j
      -1.8113172e+07-6.96161360e+07j -2.5073102e+07-1.42816832e+08j
      -7.0098432e+07-1.18861736e+08j]
     [ 4.4131004e+07-7.50158000e+07j -2.6546628e+07-6.30555680e+07j
      -5.9392536e+07-1.12320200e+08j -2.3051742e+07-1.14771040e+08j
      -2.8826330e+07-1.44704848e+08j]
     [-5.7848424e+07-9.07793680e+07j -1.8995984e+07-7.05040000e+07j
      -2.1853760e+07-9.46601920e+07j -5.7244808e+07-1.29637024e+08j
      -2.5164940e+07-1.44442624e+08j]
     [-1.6240966e+07-8.67124240e+07j -3.6319880e+07-6.74961280e+07j
      -3.5798028e+07-8.91369200e+07j -4.1210136e+07-1.59811104e+08j
      -6.0603340e+07-1.49605200e+08j]
     [-5.7958688e+07-9.76945120e+07j -3.6035424e+07-8.43839760e+07j
      -2.5936316e+07-7.92338960e+07j -1.3752022e+07-1.28156896e+08j
      -5.7612444e+07-1.45335904e+08j]
     [-3.1123128e+07-7.27474960e+07j -1.1669196e+07-9.33100160e+07j
      -5.2525396e+07-8.49055680e+07j -5.5447724e+07-1.44855952e+08j
      -5.6694040e+07-1.51849824e+08j]
     [-3.8905648e+07-7.03379600e+07j -2.8258980e+07-5.86227280e+07j
      -3.9865600e+07-1.00230640e+08j -2.1089326e+07-1.17465640e+08j
      -7.0518560e+07-1.25791888e+08j]
     [-2.9370540e+07-7.19447440e+07j -2.4095266e+07-6.53056760e+07j
      -3.5894764e+07-9.16150720e+07j -2.0380304e+07-1.26303992e+08j
      -3.6238156e+07-1.41798448e+08j]
     [-3.2455856e+07-9.34930960e+07j -3.3308040e+07-6.34051920e+07j
      -3.2688932e+07-1.15234568e+08j -3.2458352e+07-1.17171168e+08j
      -5.9563644e+07-1.25110824e+08j]
     [-4.1903592e+07-8.56528240e+07j -4.0381568e+07-7.39231520e+07j
      -1.7938388e+07-1.31356824e+08j -2.3586180e+07-1.06459152e+08j
      -4.4704888e+07-1.43910272e+08j]
     [-3.2840948e+07-9.28890880e+07j -5.5244688e+07-6.70287840e+07j
      -1.7543104e+07-8.88934720e+07j -7.3903592e+07-1.40041792e+08j
      -7.5678608e+07-1.17529416e+08j]
     [-3.2987214e+07-1.08133208e+08j -2.9887272e+07-7.56726720e+07j
      -3.6615368e+07-8.41959120e+07j -4.1739820e+07-1.39348464e+08j
      -6.1666372e+07-1.40226896e+08j]
     [-4.7902188e+07-8.96578560e+07j -2.3870240e+07-6.16812840e+07j
      -3.1301040e+07-8.93762240e+07j -2.3279532e+07-1.13804160e+08j
      -3.3763812e+07-1.21347928e+08j]
     [-4.6620152e+07-9.18789440e+07j  7.5948400e+06-7.07497200e+07j
      -4.9339688e+07-8.40371040e+07j -2.7602876e+07-1.45124816e+08j
      -5.5919344e+07-1.18199080e+08j]
     [ 1.4143820e+07+4.75166500e+06j  2.1639416e+07-3.89559920e+07j
      -2.6880830e+06-1.19334304e+08j -2.4282960e+07-1.25554688e+08j
      -5.6976580e+07-1.17606640e+08j]
     [-4.7891360e+07-7.11120240e+07j -1.4561773e+07-8.45771040e+07j
      -5.1910588e+07-8.42496000e+07j -3.6754084e+07-1.26741280e+08j
      -4.9441672e+07-1.14905648e+08j]
     [-3.6224104e+07-9.55064960e+07j -5.1500184e+07-7.79432000e+07j
      -2.0372484e+07-9.68923200e+07j -4.5768064e+07-1.21796904e+08j
      -3.0636788e+07-1.17346176e+08j]
     [-4.1210008e+07-8.69598880e+07j -3.7956140e+07-7.41874640e+07j
      -4.5207676e+07-1.02905848e+08j -1.6321905e+07-1.13780360e+08j
      -3.6735952e+07-1.20845448e+08j]
     [-2.1665448e+07-1.10883288e+08j  9.9904450e+06-7.25869200e+07j
      -4.5648524e+07-7.87008160e+07j -1.7715048e+07-1.30865488e+08j
      -5.6385392e+07-1.18312144e+08j]
     [-5.4982196e+07-9.00892320e+07j -4.2132392e+07-8.27685440e+07j
      -2.8116970e+07-1.08709760e+08j -2.4398324e+07-1.56491008e+08j
      -7.4046384e+07-1.23188040e+08j]
     [-3.0054538e+07-7.75447920e+07j -5.7114944e+07-6.85929760e+07j
      -4.0593320e+07-9.69199200e+07j -4.8235792e+07-1.08910144e+08j
      -6.1215712e+07-1.37084768e+08j]
     [-4.4731472e+07-8.11116080e+07j -3.2595042e+07-7.35022640e+07j
      -4.4291272e+07-1.00290976e+08j -3.5156616e+07-1.38309632e+08j
      -3.6579100e+07-1.28877104e+08j]
     [-4.7541800e+07-9.48426080e+07j -4.3749996e+07-7.38541280e+07j
      -3.1342568e+07-9.57012080e+07j -3.2967592e+07-1.29143360e+08j
      -7.7294976e+07-1.19787496e+08j]
     [-2.6561244e+07-7.68345280e+07j -3.1214782e+07-7.52568320e+07j
      -3.8672144e+07-6.41128440e+07j -5.3988280e+07-1.40648000e+08j
      -4.3886260e+07-1.15257768e+08j]
     [-3.8038188e+07-9.25145920e+07j -2.8162992e+07-7.72596160e+07j
      -4.6316392e+07-1.08717640e+08j -7.0081224e+07-1.30078040e+08j
      -2.6643556e+07-1.43130160e+08j]
     [-1.1465727e+07-9.51208560e+07j -3.1978292e+07-6.60335760e+07j
      -5.0237584e+07-9.45173040e+07j -2.6475908e+07-1.29891296e+08j
      -4.4750408e+07-1.22221560e+08j]
     [-4.7942812e+07-8.53585280e+07j -3.8600024e+07-7.95954400e+07j
      -5.0754540e+07-9.50478240e+07j -4.3804632e+07-1.08170112e+08j
      -5.0667392e+07-1.50132320e+08j]
     [-5.3715900e+07-7.24821600e+07j -4.0371976e+07-7.08830400e+07j
      -3.6102636e+07-1.01162016e+08j -2.0479884e+07-8.43268160e+07j
      -6.6468552e+07-1.43193744e+08j]
     [ 4.7835388e+07-8.73810800e+07j -3.5587608e+07-7.20201520e+07j
      -3.2206816e+07-1.31586096e+08j -7.2711704e+07-1.13992032e+08j
      -3.2135612e+07-1.32596528e+08j]
     [-3.5897052e+07-1.04604480e+08j -2.9985544e+07-9.41997920e+07j
      -1.0472623e+07-1.15868952e+08j -3.4440352e+07-1.03503520e+08j
      -4.2490920e+07-1.55457648e+08j]
     [-4.3013052e+07-9.53010080e+07j -3.2593220e+07-5.55420280e+07j
      -2.9317798e+07-8.87101760e+07j -3.5980124e+07-1.49429984e+08j
      -5.1644664e+07-1.42793824e+08j]
     [-5.2983928e+07-1.02485984e+08j -1.1384377e+07-8.88951600e+07j
      -3.8250616e+07-9.92265520e+07j -3.8887736e+07-1.26766512e+08j
      -5.6469744e+07-1.46943488e+08j]
     [-6.6378216e+07-8.16214560e+07j -4.5065016e+07-7.37079520e+07j
      -8.5710480e+06-8.89967600e+07j -5.0177492e+07-1.14243496e+08j
      -7.0284624e+07-1.22635408e+08j]
     [-3.3840928e+07-7.94825680e+07j -1.3808996e+07-7.91067760e+07j
      -6.5825148e+07-9.02857200e+07j -5.4309636e+07-1.30821544e+08j
      -6.2112200e+07-1.49762992e+08j]
     [-2.7770244e+07-1.06372768e+08j -3.3356064e+07-7.11491040e+07j
      -2.4661766e+07-7.22239680e+07j -6.1551864e+07-1.06958320e+08j
      -7.0135184e+07-1.56266960e+08j]
     [-4.1416912e+07-7.54716640e+07j -1.1324217e+07-6.34744960e+07j
      -3.8304824e+07-7.66183840e+07j -4.3683268e+07-1.29187680e+08j
      -4.4329132e+07-1.29844304e+08j]
     [-3.9935388e+07-8.75456800e+07j -4.3613268e+07-7.97751680e+07j
      -3.4038148e+07-7.54371680e+07j -1.5551446e+07-1.60583472e+08j
      -7.8918352e+07-1.07354712e+08j]
     [-4.4192304e+07-7.35003200e+07j -2.0472548e+07-6.26204480e+07j
      -3.8503448e+07-8.04549680e+07j -2.1634448e+07-1.62565920e+08j
      -6.2729808e+07-1.35220272e+08j]
     [-3.9853192e+07-8.90064960e+07j -8.7385200e+06-5.59005400e+07j
      -3.4482856e+07-1.16872480e+08j -4.4923760e+07-1.37019552e+08j
      -5.4522416e+07-1.22736240e+08j]
     [-4.2459760e+07-7.47165280e+07j -2.2063912e+07-7.23386560e+07j
      -2.8244728e+07-9.24040960e+07j -2.6277684e+07-1.37457472e+08j
      -2.9793882e+07-1.15633544e+08j]
     [-3.7918736e+07-8.99383440e+07j -3.3524426e+07-8.88885280e+07j
      -1.4966687e+07-9.91980720e+07j -2.7383968e+07-1.39083136e+08j
      -4.9408104e+07-1.20202904e+08j]
     [-3.9555600e+07-8.22887600e+07j -1.7853348e+07-8.44507600e+07j
       1.7909120e+07-3.20189320e+07j -2.9064120e+07-1.28175856e+08j
      -5.6915648e+07-1.14295832e+08j]
     [-5.2038364e+07-8.31125920e+07j -3.5668208e+07-4.76981360e+07j
      -3.0110724e+07-1.15268352e+08j -4.5226216e+07-1.11248208e+08j
      -6.6681316e+07-1.39478784e+08j]
     [-3.1051904e+07-8.41311440e+07j -3.9961440e+07-5.24172040e+07j
      -6.4458800e+06-1.24769096e+08j -6.5330550e+06-1.45609760e+08j
      -4.2922200e+07-1.35083568e+08j]
     [-5.7371360e+07-8.08604960e+07j -3.6728800e+07-6.19774360e+07j
      -1.6891846e+07-8.57514960e+07j -2.1268874e+07-1.18678648e+08j
      -4.7639532e+07-1.04022272e+08j]
     [-3.0332252e+07-6.54244520e+07j -2.5114692e+07-6.15253120e+07j
      -3.6674508e+07-6.74614080e+07j -4.8744268e+07-1.07187088e+08j
      -4.7455948e+07-1.32882264e+08j]
     [-3.8205808e+07-8.50664720e+07j -4.2784172e+07-7.91759920e+07j
      -3.5640120e+07-9.50943760e+07j -4.3177472e+07-1.28454488e+08j
      -6.9795264e+07-1.29801256e+08j]
     [-3.9141920e+07-1.08087224e+08j -2.1428644e+07-6.47281200e+07j
      -5.6586436e+07-9.13557200e+07j -3.8644972e+07-1.53215328e+08j
      -6.4326992e+07-9.64569760e+07j]
     [-6.7132432e+07-8.51185920e+07j -3.3309292e+07-6.18729520e+07j
      -3.8993464e+07-8.98316720e+07j  1.9408470e+06-1.11505720e+08j
      -4.2148296e+07-1.20988424e+08j]
     [-2.8544680e+07-9.35039680e+07j -4.0218188e+07-5.86898680e+07j
      -1.0626431e+07-8.81101760e+07j -3.3613424e+07-1.50936416e+08j
      -3.8230528e+07-1.53225760e+08j]
     [-4.7968640e+07-7.69326400e+07j -4.6072160e+07-8.40665920e+07j
      -5.1520136e+07-9.25745840e+07j -3.2121008e+07-1.37057424e+08j
      -5.8122136e+07-1.24352432e+08j]
     [ 5.5006344e+07-4.21717520e+07j -2.8644810e+07-5.49378160e+07j
      -5.4326452e+07-8.95229840e+07j -6.8108256e+07-9.12183520e+07j
      -6.1210352e+07-1.32626336e+08j]
     [-4.2465280e+07-8.88994400e+07j -2.3525030e+07-5.32517600e+07j
      -1.9827750e+06-1.35882336e+08j -3.2507822e+07-1.34065928e+08j
      -4.2200952e+07-9.93832880e+07j]
     [-4.7604832e+07-1.01444184e+08j -3.9161088e+07-5.38972600e+07j
      -2.7261212e+07-8.66212800e+07j -4.6837672e+07-1.13267224e+08j
      -5.3256148e+07-1.30911592e+08j]
     [-3.6579488e+07-6.54274960e+07j -4.1684232e+07-7.75299280e+07j
      -4.6019048e+07-1.02320592e+08j -8.4060760e+06-1.25801080e+08j
      -4.4717840e+07-1.15774648e+08j]
     [-4.7434396e+07-1.02400584e+08j -2.0058926e+07-6.22218800e+07j
      -3.3361516e+07-1.00660848e+08j -4.5145896e+07-1.14572648e+08j
      -6.1940880e+07-1.25770992e+08j]
     [-4.1019492e+07-7.21391200e+07j -3.1759784e+07-7.01531440e+07j
      -4.2871752e+07-1.15805152e+08j -3.2576408e+07-1.42885616e+08j
      -4.6128804e+07-1.26717536e+08j]
     [-5.0989432e+07-9.40556480e+07j -3.3435256e+07-7.93401440e+07j
      -2.5104154e+07-9.51623600e+07j -3.3165160e+07-1.54925440e+08j
      -4.0308016e+07-1.33545576e+08j]
     [-5.2011700e+07-9.92853120e+07j  6.3362070e+06-5.14777320e+07j
      -1.5799431e+07-1.15703920e+08j -4.4247416e+07-1.56066784e+08j
      -7.5179712e+07-1.09919240e+08j]
     [-5.1313908e+07-9.08335840e+07j -2.3901812e+07-5.56288840e+07j
      -1.5294583e+07-9.68956320e+07j -5.2435848e+07-1.65758112e+08j
      -5.1512752e+07-1.39141600e+08j]
     [-3.6610928e+07-8.73746400e+07j -1.5774894e+07-7.09796240e+07j
      -3.5416968e+07-8.77812160e+07j -5.0706148e+07-1.56901280e+08j
      -4.6751496e+07-1.39493888e+08j]
     [-4.4674760e+07-7.99521520e+07j -9.9092030e+06-6.06374800e+07j
      -3.2726208e+07-1.03189232e+08j -5.8102136e+07-1.57878784e+08j
      -3.9503832e+07-1.21671312e+08j]
     [-4.4982356e+07-9.84142400e+07j -3.6987320e+07-8.59357920e+07j
      -2.2242960e+07-6.05383120e+07j -2.8228256e+07-1.40735328e+08j
      -4.1865920e+07-1.12144496e+08j]
     [-4.8257392e+07-8.11930240e+07j  4.1982000e+06-8.56072240e+07j
      -5.5363548e+07-9.17306720e+07j -2.9506658e+07-1.44658768e+08j
      -4.8859760e+07-1.31208752e+08j]
     [-4.7869580e+07-9.68510560e+07j -2.5853432e+07-4.75936320e+07j
      -1.7102672e+07-7.29719200e+07j -4.2968456e+07-1.25160176e+08j
      -3.9150072e+07-1.18650512e+08j]
     [-3.6792704e+07-1.05916488e+08j -9.5707530e+06-6.26645520e+07j
      -2.9215766e+07-9.67926000e+07j -1.8843064e+07-1.16232912e+08j
      -3.5206584e+07-1.61112608e+08j]
     [-1.9576320e+07-9.44449760e+07j -4.3878496e+07-4.87609040e+07j
      -4.6309632e+07-1.15947152e+08j -2.3856984e+07-9.60398880e+07j
      -6.4056948e+07-1.20449104e+08j]
     [-3.7468992e+07-8.22845920e+07j -3.0460036e+07-5.47805160e+07j
      -2.0525812e+07-9.99769600e+07j -4.8947064e+07-1.34154544e+08j
      -4.6475936e+07-1.28144712e+08j]
     [-4.5638452e+07-9.79142800e+07j -2.2475638e+07-7.13357920e+07j
      -5.0188460e+07-8.25308560e+07j -4.3042576e+07-1.43137568e+08j
      -5.9047584e+07-1.29128624e+08j]
     [-4.6575732e+07-1.08510160e+08j -4.2839960e+07-8.49888240e+07j
      -3.3595820e+07-9.44824160e+07j -3.0203476e+07-1.56991840e+08j
      -4.9312148e+07-1.46366112e+08j]
     [-4.5836368e+07-1.07973208e+08j -3.8904656e+07-8.60586080e+07j
      -3.9006760e+07-9.20365520e+07j -4.3065736e+07-1.22911984e+08j
      -4.8657280e+07-1.50434992e+08j]
     [-2.7487292e+07-7.86121840e+07j  2.6894000e+04-4.52145640e+07j
      -3.4873476e+07-9.37858880e+07j -3.7486540e+07-1.40567360e+08j
      -4.8487352e+07-1.52789792e+08j]
     [-4.9074352e+07-8.48416240e+07j  1.6238313e+07-4.85053960e+07j
      -4.6305404e+07-7.79691200e+07j -4.2091872e+07-1.50357728e+08j
      -7.0745920e+07-1.19392720e+08j]
     [-4.0921680e+07-8.61907040e+07j -2.3506040e+07-5.90025280e+07j
      -2.9780284e+07-8.83290480e+07j -7.3069496e+07-1.41348864e+08j
      -7.4483312e+07-1.14985760e+08j]
     [-3.2820096e+07-9.40329200e+07j -3.7439388e+07-6.06202200e+07j
      -2.9868948e+07-9.57319760e+07j -2.6810168e+07-1.12410248e+08j
      -6.4592292e+07-1.18890792e+08j]
     [-2.4864144e+07-8.90210400e+07j -3.2275028e+07-4.41055760e+07j
      -3.0907150e+06-9.96166320e+07j -4.5521200e+07-1.32023104e+08j
      -4.5681400e+07-1.48998192e+08j]
     [-3.5209168e+07-9.68080000e+07j -3.3308702e+07-8.45905440e+07j
      -4.5412800e+07-9.89920560e+07j -4.6602872e+07-1.65075344e+08j
      -7.6904512e+07-1.17849864e+08j]
     [-4.6177540e+07-8.45160320e+07j -8.2086040e+06-6.88054320e+07j
      -4.0229884e+07-1.16558352e+08j -2.2073630e+06-1.20033360e+08j
      -8.1057320e+07-1.30025072e+08j]
     [-3.9876600e+07-9.32928720e+07j -9.0624100e+06-5.69231920e+07j
      -2.0518364e+07-1.01396256e+08j -2.7614708e+07-9.91584720e+07j
      -4.8845232e+07-1.26749184e+08j]
     [-2.3172540e+07-6.08207600e+07j -4.4748508e+07-7.91162240e+07j
      -2.9113226e+07-8.44526160e+07j -7.9177950e+06-1.41762144e+08j
      -7.5762880e+07-1.38798768e+08j]]

    array([0.33333333, 0.        , 0.        , 0.        , 0.        ,
           0.        , 0.        , 0.        , 0.        , 0.        ,
           0.        , 0.        , 0.        , 0.        , 0.        ,
           0.        , 0.        , 0.        , 0.        , 0.        ,
           0.        , 0.33333333, 0.        , 0.        , 0.        ,
           0.        , 0.        , 0.        , 0.        , 0.        ,
           0.        , 0.        , 0.        , 0.        , 0.66666667,
           0.        , 0.        , 0.        , 0.        , 0.        ,
           0.        , 0.        , 0.        , 0.        , 0.        ,
           0.33333333, 0.        , 0.        , 0.33333333, 0.        ,
           0.        , 0.        , 0.        , 0.        , 0.        ,
           0.        , 0.        , 0.        , 0.        , 0.        ,
           0.        , 0.        , 0.        , 0.        , 0.        ,
           0.        , 0.        , 0.        , 0.        , 0.        ,
           0.        , 0.33333333, 0.        , 0.        , 0.        ,
           0.        , 0.        , 0.        , 0.        , 0.        ,
           0.        , 0.        , 0.        , 0.        , 0.        ,
           0.        , 0.        , 0.        , 0.        , 0.        ,
           0.        , 0.        , 0.        , 0.        , 0.        ,
           0.        , 0.        , 0.        , 0.        , 0.        ,
           0.33333333, 0.        , 0.        , 0.        , 0.33333333,
           0.        , 0.        , 0.33333333, 0.33333333, 0.        ,
           0.33333333, 0.        , 0.33333333, 0.33333333, 0.33333333,
           0.        , 0.        , 0.33333333, 0.        , 0.33333333,
           0.        , 0.        , 0.        , 0.33333333, 0.        ,
           0.        , 0.33333333, 0.        , 0.33333333, 0.        ,
           0.33333333, 0.        , 0.        , 0.        , 0.        ,
           0.        , 0.        , 0.        , 0.        , 0.        ,
           0.        , 0.        , 0.        , 0.33333333, 0.33333333,
           0.33333333, 0.        , 0.33333333, 0.        , 0.33333333,
           0.        , 0.        , 0.        , 0.33333333, 0.33333333,
           0.        , 0.        , 0.        , 0.33333333, 0.33333333,
           0.        , 0.        , 0.        , 0.        , 0.33333333,
           0.        , 0.        , 0.        , 0.33333333, 0.        ,
           0.        , 0.        , 0.        , 0.        , 0.        ,
           0.33333333, 0.        , 0.33333333, 0.        , 0.        ,
           0.        , 0.        , 0.33333333, 0.        , 0.33333333,
           0.        , 0.        , 0.        , 0.        , 0.        ,
           0.33333333, 0.        , 0.        , 0.        , 0.33333333,
           0.        , 0.33333333, 0.        , 0.33333333, 0.        ,
           0.33333333, 0.33333333, 0.33333333, 0.33333333, 0.33333333,
           0.        , 0.33333333, 0.33333333, 0.33333333, 0.33333333,
           0.        , 0.33333333, 0.33333333, 0.33333333, 0.33333333,
           0.33333333, 0.33333333, 0.33333333, 0.33333333, 0.33333333,
           0.33333333, 0.33333333, 0.        , 0.33333333, 0.33333333,
           0.33333333, 0.33333333, 0.33333333, 0.33333333, 0.33333333,
           0.        , 0.        , 0.33333333, 0.33333333, 0.33333333,
           0.33333333, 0.33333333, 0.33333333, 0.33333333, 0.        ,
           0.33333333, 0.33333333, 0.33333333, 0.33333333, 0.33333333,
           0.33333333, 0.33333333, 0.        , 0.33333333, 0.33333333,
           0.33333333, 0.33333333, 0.33333333, 0.33333333, 0.33333333,
           0.33333333, 0.33333333, 0.33333333, 0.33333333, 0.33333333,
           0.33333333, 0.33333333, 0.33333333, 0.        , 0.33333333,
           0.33333333, 0.33333333, 0.33333333, 0.33333333, 0.33333333,
           0.33333333, 0.33333333, 0.33333333, 0.33333333, 0.        ,
           0.33333333, 0.        , 0.33333333, 0.33333333, 0.        ,
           0.33333333, 0.33333333, 0.33333333, 0.33333333, 0.33333333,
           0.33333333, 0.33333333, 0.        , 0.33333333, 0.33333333,
           0.33333333, 0.        , 0.33333333, 0.33333333, 0.33333333,
           0.        , 0.33333333, 0.33333333, 0.33333333, 0.        ])

```python
print('Numbers are:',numbers)
```

    Numbers are: [0.33333333 0.         0.         0.         0.         0.
     0.         0.         0.         0.         0.         0.
     0.         0.         0.         0.         0.         0.
     0.         0.         0.         0.33333333 0.         0.
     0.         0.         0.         0.         0.         0.
     0.         0.         0.         0.         0.66666667 0.
     0.         0.         0.         0.         0.         0.
     0.         0.         0.         0.33333333 0.         0.
     0.33333333 0.         0.         0.         0.         0.
     0.         0.         0.         0.         0.         0.
     0.         0.         0.         0.         0.         0.
     0.         0.         0.         0.         0.         0.33333333
     0.         0.         0.         0.         0.         0.
     0.         0.         0.         0.         0.         0.
     0.         0.         0.         0.         0.         0.
     0.         0.         0.         0.         0.         0.
     0.         0.         0.         0.         0.33333333 0.
     0.         0.         0.33333333 0.         0.         0.33333333
     0.33333333 0.         0.33333333 0.         0.33333333 0.33333333
     0.33333333 0.         0.         0.33333333 0.         0.33333333
     0.         0.         0.         0.33333333 0.         0.
     0.33333333 0.         0.33333333 0.         0.33333333 0.
     0.         0.         0.         0.         0.         0.
     0.         0.         0.         0.         0.         0.33333333
     0.33333333 0.33333333 0.         0.33333333 0.         0.33333333
     0.         0.         0.         0.33333333 0.33333333 0.
     0.         0.         0.33333333 0.33333333 0.         0.
     0.         0.         0.33333333 0.         0.         0.
     0.33333333 0.         0.         0.         0.         0.
     0.         0.33333333 0.         0.33333333 0.         0.
     0.         0.         0.33333333 0.         0.33333333 0.
     0.         0.         0.         0.         0.33333333 0.
     0.         0.         0.33333333 0.         0.33333333 0.
     0.33333333 0.         0.33333333 0.33333333 0.33333333 0.33333333
     0.33333333 0.         0.33333333 0.33333333 0.33333333 0.33333333
     0.         0.33333333 0.33333333 0.33333333 0.33333333 0.33333333
     0.33333333 0.33333333 0.33333333 0.33333333 0.33333333 0.33333333
     0.         0.33333333 0.33333333 0.33333333 0.33333333 0.33333333
     0.33333333 0.33333333 0.         0.         0.33333333 0.33333333
     0.33333333 0.33333333 0.33333333 0.33333333 0.33333333 0.
     0.33333333 0.33333333 0.33333333 0.33333333 0.33333333 0.33333333
     0.33333333 0.         0.33333333 0.33333333 0.33333333 0.33333333
     0.33333333 0.33333333 0.33333333 0.33333333 0.33333333 0.33333333
     0.33333333 0.33333333 0.33333333 0.33333333 0.33333333 0.
     0.33333333 0.33333333 0.33333333 0.33333333 0.33333333 0.33333333
     0.33333333 0.33333333 0.33333333 0.33333333 0.         0.33333333
     0.         0.33333333 0.33333333 0.         0.33333333 0.33333333
     0.33333333 0.33333333 0.33333333 0.33333333 0.33333333 0.
     0.33333333 0.33333333 0.33333333 0.         0.33333333 0.33333333
     0.33333333 0.         0.33333333 0.33333333 0.33333333 0.        ]

We now perform an optimization of the $-x^2 $ function.

```python
results = quantum_random_optimization(-3,2,1000,'-x**2','ibmq_bogota', True, 3, 1)
```

    Job Status: job has successfully run
    [[-53065888.-9.95942160e+07j  12526852.-8.83355040e+07j
      -45737476.-8.78401520e+07j -18069768.-1.35313648e+08j
      -54956012.-1.39740816e+08j]
     [-44805456.-7.83008800e+07j -38067972.-6.56340840e+07j
      -34924432.-8.77824800e+07j -27510968.-1.31698568e+08j
      -58658688.-1.18382784e+08j]
     [-54034328.-9.41902560e+07j -33120974.-7.46284000e+07j
      -25283040.-7.65685840e+07j -25300256.-1.70250528e+08j
      -49047100.-1.45890528e+08j]
     ...
     [-30167272.-8.05575840e+07j -52607480.-6.54034960e+07j
      -33121920.-8.53363840e+07j -68748360.-1.41119392e+08j
      -59052456.-1.09183304e+08j]
     [-32798284.-8.35185840e+07j -28180596.-3.67491560e+07j
      -51425432.-1.07535304e+08j -31844488.-1.60568192e+08j
      -45734372.-1.07996096e+08j]
     [-49765528.-9.47291680e+07j -28781622.-6.83978640e+07j
       60580168.-5.00160880e+07j -50950140.-1.38491680e+08j
      -43629116.-1.02511088e+08j]]

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>iteration</th>
      <th>xl</th>
      <th>xu</th>
      <th>x</th>
      <th>f(x)</th>
      <th>max_x</th>
      <th>max_f(x)</th>
      <th>error</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>0</td>
      <td>-3</td>
      <td>2</td>
      <td>-3.0</td>
      <td>-9.00000000000000</td>
      <td>-3.000000</td>
      <td>-9.00000000000000</td>
      <td>6.00000000000000</td>
    </tr>
    <tr>
      <th>1</th>
      <td>1</td>
      <td>-3</td>
      <td>2</td>
      <td>-3.0</td>
      <td>-9.00000000000000</td>
      <td>-3.000000</td>
      <td>-9.00000000000000</td>
      <td>6.00000000000000</td>
    </tr>
    <tr>
      <th>2</th>
      <td>2</td>
      <td>-3</td>
      <td>2</td>
      <td>-3.0</td>
      <td>-9.00000000000000</td>
      <td>-3.000000</td>
      <td>-9.00000000000000</td>
      <td>6.00000000000000</td>
    </tr>
    <tr>
      <th>3</th>
      <td>3</td>
      <td>-3</td>
      <td>2</td>
      <td>-3.0</td>
      <td>-9.00000000000000</td>
      <td>-3.000000</td>
      <td>-9.00000000000000</td>
      <td>6.00000000000000</td>
    </tr>
    <tr>
      <th>4</th>
      <td>4</td>
      <td>-3</td>
      <td>2</td>
      <td>-3.0</td>
      <td>-9.00000000000000</td>
      <td>-3.000000</td>
      <td>-9.00000000000000</td>
      <td>6.00000000000000</td>
    </tr>
    <tr>
      <th>...</th>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
    </tr>
    <tr>
      <th>995</th>
      <td>995</td>
      <td>-3</td>
      <td>2</td>
      <td>-3.0</td>
      <td>-9.00000000000000</td>
      <td>-1.333333</td>
      <td>-1.77777777777778</td>
      <td>6.00000000000000</td>
    </tr>
    <tr>
      <th>996</th>
      <td>996</td>
      <td>-3</td>
      <td>2</td>
      <td>-3.0</td>
      <td>-9.00000000000000</td>
      <td>-1.333333</td>
      <td>-1.77777777777778</td>
      <td>6.00000000000000</td>
    </tr>
    <tr>
      <th>997</th>
      <td>997</td>
      <td>-3</td>
      <td>2</td>
      <td>-3.0</td>
      <td>-9.00000000000000</td>
      <td>-1.333333</td>
      <td>-1.77777777777778</td>
      <td>6.00000000000000</td>
    </tr>
    <tr>
      <th>998</th>
      <td>998</td>
      <td>-3</td>
      <td>2</td>
      <td>-3.0</td>
      <td>-9.00000000000000</td>
      <td>-1.333333</td>
      <td>-1.77777777777778</td>
      <td>6.00000000000000</td>
    </tr>
    <tr>
      <th>999</th>
      <td>999</td>
      <td>-3</td>
      <td>2</td>
      <td>-3.0</td>
      <td>-9.00000000000000</td>
      <td>-1.333333</td>
      <td>-1.77777777777778</td>
      <td>6.00000000000000</td>
    </tr>
  </tbody>
</table>
<p>1000 rows × 8 columns</p>
</div>

```python
results
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>iteration</th>
      <th>xl</th>
      <th>xu</th>
      <th>x</th>
      <th>f(x)</th>
      <th>max_x</th>
      <th>max_f(x)</th>
      <th>error</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>0</td>
      <td>-3</td>
      <td>2</td>
      <td>-3.0</td>
      <td>-9.00000000000000</td>
      <td>-3.000000</td>
      <td>-9.00000000000000</td>
      <td>6.00000000000000</td>
    </tr>
    <tr>
      <th>1</th>
      <td>1</td>
      <td>-3</td>
      <td>2</td>
      <td>-3.0</td>
      <td>-9.00000000000000</td>
      <td>-3.000000</td>
      <td>-9.00000000000000</td>
      <td>6.00000000000000</td>
    </tr>
    <tr>
      <th>2</th>
      <td>2</td>
      <td>-3</td>
      <td>2</td>
      <td>-3.0</td>
      <td>-9.00000000000000</td>
      <td>-3.000000</td>
      <td>-9.00000000000000</td>
      <td>6.00000000000000</td>
    </tr>
    <tr>
      <th>3</th>
      <td>3</td>
      <td>-3</td>
      <td>2</td>
      <td>-3.0</td>
      <td>-9.00000000000000</td>
      <td>-3.000000</td>
      <td>-9.00000000000000</td>
      <td>6.00000000000000</td>
    </tr>
    <tr>
      <th>4</th>
      <td>4</td>
      <td>-3</td>
      <td>2</td>
      <td>-3.0</td>
      <td>-9.00000000000000</td>
      <td>-3.000000</td>
      <td>-9.00000000000000</td>
      <td>6.00000000000000</td>
    </tr>
    <tr>
      <th>...</th>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
      <td>...</td>
    </tr>
    <tr>
      <th>995</th>
      <td>995</td>
      <td>-3</td>
      <td>2</td>
      <td>-3.0</td>
      <td>-9.00000000000000</td>
      <td>-1.333333</td>
      <td>-1.77777777777778</td>
      <td>6.00000000000000</td>
    </tr>
    <tr>
      <th>996</th>
      <td>996</td>
      <td>-3</td>
      <td>2</td>
      <td>-3.0</td>
      <td>-9.00000000000000</td>
      <td>-1.333333</td>
      <td>-1.77777777777778</td>
      <td>6.00000000000000</td>
    </tr>
    <tr>
      <th>997</th>
      <td>997</td>
      <td>-3</td>
      <td>2</td>
      <td>-3.0</td>
      <td>-9.00000000000000</td>
      <td>-1.333333</td>
      <td>-1.77777777777778</td>
      <td>6.00000000000000</td>
    </tr>
    <tr>
      <th>998</th>
      <td>998</td>
      <td>-3</td>
      <td>2</td>
      <td>-3.0</td>
      <td>-9.00000000000000</td>
      <td>-1.333333</td>
      <td>-1.77777777777778</td>
      <td>6.00000000000000</td>
    </tr>
    <tr>
      <th>999</th>
      <td>999</td>
      <td>-3</td>
      <td>2</td>
      <td>-3.0</td>
      <td>-9.00000000000000</td>
      <td>-1.333333</td>
      <td>-1.77777777777778</td>
      <td>6.00000000000000</td>
    </tr>
  </tbody>
</table>
<p>1000 rows × 8 columns</p>
</div>


# Quick Start Tutorial

Welcome to quick tutorial on FormulaLab, best environment for your formulas database!

```python
import numpy as np
import pandas as pd
import sympy as sp

import FormulaLab as fl
```

**FormulaLab allows you to:**

    1. Search for formula(s) in two ways:
      1. Direct search.

            `FormulaLab.FormulaSearch.find(function, [variables,])`

      2. Derivation: By going through the formulas database and algebraically
         solve for the desired formula.

            `FormulaLab.FormulaSearch.derive(function, variable)`

    2. Convert symbolic formulas into python functions.

          `FormulaLab.FormulaSearch.function(formula:symbolic expr)`
          `FormulaLab.FormulaSearch.find(function, [variables,], function=True)`

    3. Call stored formulas in a database by its ID number, and use it anywhere
       in your code with any form.

          `FormulaLab.FormulaSearch.find(function, id)`

**Below are four steps of how you may use FormulaLab**

    1. Import
    2. Initiate
    3. Search
    4. Implement

\* FormulaLab is bult upon [sympy](https://www.sympy.org/en/index.html)

## Step 1: Importing Formulas from a Database

**Data must ba a pandas.DataFrame, list, dict, tuple, or set**

```python
data_list = ['f=m*a','a=v/t']
data_dict = {'1':'f=m*a','2':'a=v/t'}
data_dict_2 = {'ID':[1, 2], 'Formula':['f=m*a','a=v/t']}
data_tuple = ('f=m*a','a=v/t')
data_set = {'f=m*a','a=v/t'}

data_list
```

    ['f=m*a', 'a=v/t']

**Data from external Database, should be imported as a DataFrame**

    This is the recommended way of storing and loading formulas, and pandas is
    one of the best python packages that can handle this.

```python
df = pd.read_csv('Quick Database.csv')
df
```

      ID
      Formula

      0
      1
      d = v * t

      1
      2
      a = v / t

      2
      3
      f = m * a

      3
      5
      p = m * v

## Step 2: Initiate the formula search engine

```python
phyfos = fl.FormulaSearch(data=data_list)
phyfos.data
# The new "Args" column is automatically generated
# to help speed the search algorithm.
```

      ID
      Formula
      Args

      0
      1
      f=m*a
      [a, m, f]

      1
      2
      a=v/t
      [v, t, a]

```python
phyfos = fl.FormulaSearch(data=data_dict)
phyfos.data
```

      ID
      Formula
      Args

      0
      1
      f=m*a
      [a, m, f]

      1
      2
      a=v/t
      [v, t, a]

```python
phyfos = fl.FormulaSearch(data=df, formula_col='Formula', id_col='ID')
#formula_col and id_col values should mathch the formulas database
phyfos.data
```

      ID
      Formula
      Args

      0
      1
      d = v * t
      [v, t, d]

      1
      2
      a = v / t
      [v, t, a]

      2
      3
      f = m * a
      [a, m, f]

      3
      5
      p = m * v
      [p, m, v]

## Step 3: Search for formula(s)

**1. Direct search**

```python
d = phyfos.find('d')  #Searching is case sensitivity
d
```

    [t*v]

```python
v = phyfos.find('v')
v
```

    [d/t, a*t, p/m]

```python
v_as_a_function_of_a = phyfos.find('v', 'a')
v_as_a_function_of_a
```

    [a*t]

```python
a_as_a_function_of_v = phyfos.find('a', 'v')
a_as_a_function_of_v
```

    [v/t]

```python
v_as_a_function_of_t_d = phyfos.find('v', ['t','d'])
v_as_a_function_of_t_d
```

    [d/t]

**2. Search by formula ID number**

    Each formula has a fixed id number that should not be changed. It
    is recomeneded to use this method when you know what formula to use
    in your code. It is faster than direct search, and the later could
    give you different result when the database is expanded or changed.

```python
f = phyfos.find('f', id=3)
f
```

    [a*m]

```python
# Say you want "m" to be the function, you do not have to rewrite your formula again!
m = phyfos.find('m', id=3)
m
```

    [f/a]

```python
# Also for 'a'. This is very helpful when there is a mistake
# in the formula! You only change it once in your database.
a = phyfos.find('a', id=3)
a
# You will see how to convert this to a python function in step 4
```

    [f/m]

**2. Deriving formulas, through algabric substitutions**

    This is the most interesting part! FormulaLab can do algebraic
    manibulations including integrals and derivatives using the power
    of sympy!

```python
phyfos.data
```

      ID
      Formula
      Args

      0
      1
      d = v * t
      [v, t, d]

      1
      2
      a = v / t
      [v, t, a]

      2
      3
      f = m * a
      [a, m, f]

      3
      5
      p = m * v
      [p, m, v]

```python
phyfos.find('d', 'a') # What if you want to know what is the d(a)??
#It is not in the database! So, find() is not helpful here, derive() is!
```

    []

```python
d = phyfos.derive('d', 'a', shortest_path=True)
# shortest_path=True is faster and the default.
d
```

    [a*t**2, v**2/a, a*p*t/f]

```python
# You can also see all of your traces:
phyfos.traces
```

    [[1, 'v', 2], [1, 't', 2], [1, 'v', 5, 'm', 3]]

```python
d = phyfos.derive('d', 'a', shortest_path=False)
d
# Sometimes you get more solutions when you turn off shortest_path,
# because derive() tries with all possible paths, with no shortcuts!
```

    [a*t**2, v**2/a, a*p*t/f]

```python
# You can also see the all of your traces:
phyfos.traces
# The extra path has a repetitive solution
```

    [[1, 'v', 2], [1, 't', 2], [1, 'v', 5, 'm', 3], [1, 't', 2, 'v', 5, 'm', 3]]

```python
# You can pretty print your solutions
# Latex print
d[1]
```

$\displaystyle \frac{v^{2}}{a}$

```python
sp.pretty_print(d[1])
```

     2
    v
    ──
    a

## Step 4: Use your formulas
    Once you get the formula(s) you want, you can use them in many different ways:
    1. Use them as a python functions.
    2. Interact with them in their symbolic form using sympy.

**1. Converting formulas expresion to a python functions**

```python
phyfos.data
```

      ID
      Formula
      Args

      0
      1
      d = v * t
      [v, t, d]

      1
      2
      a = v / t
      [v, t, a]

      2
      3
      f = m * a
      [a, m, f]

      3
      5
      p = m * v
      [p, m, v]

```python
f = phyfos.find('f', function=True)
f(m=10, a=2)
```

    20

```python
a = phyfos.find('a',id=3, function=True)
a(f=20, m=10)
```

    2.0

```python
# You can also convert symbolic expression to python function
d = phyfos.derive('d', 'a')[0]
d
```

$\displaystyle a t^{2}$

```python
d_func = phyfos.function(d)
d_func(t=2, a=1)
```

    4

**2. Use your formulas with sympy**

For more information about how to use sympy,
visit: [SymPy](https://www.sympy.org/en/index.html)

```python
d
```

$\displaystyle a t^{2}$

```python
sp.var('a x')
d = d.subs(a,sp.sin(x))
d
```

$\displaystyle t^{2} \sin{\left(x \right)}$

```python
d.series(x)
```

$\displaystyle t^{2} x - \frac{t^{2} x^{3}}{6} + \frac{t^{2} x^{5}}{120} + O\left(x^{6}\right)$

```python
d.diff(x) # take the derivative of d with respect to x
```

$\displaystyle t^{2} \cos{\left(x \right)}$

## Else can be done with FormulaLab

```python
#Find formula as string, by its id number
str_fo = phyfos.find_raw_formula(1)
str_fo
```

    'd = v * t'

```python
# Convert str expr to formula and solve for a variable
phyfos.solve_for(expr=str_fo, var='v')
```

    [d/t]

```python
# Tels you where to find certain variable in your database
phyfos.get_formula_ids('v')
```

    [1, 2, 5]

```python
phyfos.get_formula_ids(('v','a')) # --> 'v' and 'a' can be found in id = 2
```

    [2]

```python
# What if you want to know how your formulas are connected!
phyfos.trace([5,1,2])
```

    [[5, 'v', 1, 'v', 2], [5, 'v', 1, 't', 2]]

```python
# Once you are done, you can see all your derived formulas stored in
phyfos.all_derived_formulas
```

    {a*p*t/f, a*t**2, v**2/a}

docs/Tutorial 1. Quick Introduction.ipynb

doc/_build/html/_sources/Tutorial 1. Quick Introduction.ipynb.txt

doc/_build/html/Tutorial 1. Quick Introduction.ipynb