From 619d58cfbf2695e358e995831f0c8b2043800fe0 Mon Sep 17 00:00:00 2001 From: Mica Date: Fri, 18 Aug 2023 18:00:07 +0200 Subject: [PATCH 01/13] setup module --- .github/workflows/tests.yml | 30 +++ quantum_glasses.py | 300 +--------------------------- quantum_glasses/__init__.py | 3 + quantum_glasses/quantum_glasses.py | 302 +++++++++++++++++++++++++++++ requirements.txt | 27 +-- setup.py | 18 ++ tests/test_quantum_glasses.py | 5 +- tox.ini | 16 ++ 8 files changed, 379 insertions(+), 322 deletions(-) create mode 100644 .github/workflows/tests.yml create mode 100644 quantum_glasses/__init__.py create mode 100644 quantum_glasses/quantum_glasses.py create mode 100644 setup.py create mode 100644 tox.ini diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 000000000..7f3990594 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,30 @@ +name: Tests + +on: [push, pull_request, workflow_dispatch] + +jobs: + tests: + runs-on: ubuntu-latest + strategy: + max-parallel: 2 + matrix: + python-version: [3.9] + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Set up tox env + run: | + pver=${{ matrix.python-version }} + tox_env="-epy${pver/./}" + echo tox_env + echo TOX_ENV=$tox_env >> $GITHUB_ENV + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + - name: Test using tox envs + run: | + tox ${{ env.TOX_ENV }} diff --git a/quantum_glasses.py b/quantum_glasses.py index 8f6a841ab..d47e97a0f 100644 --- a/quantum_glasses.py +++ b/quantum_glasses.py @@ -1,299 +1,7 @@ -import tkinter -from tkinter import LEFT, END, DISABLED, NORMAL -import warnings -import numpy as np -import qiskit -from qiskit import QuantumCircuit -from qiskit.visualization import visualize_transition +import fire -# Ignore unnecessary warnings -warnings.simplefilter("ignore") +from quantum_glasses import QuantumGlasses -# # Define Window -# root = tkinter.Tk() -# root.title('Quantum Glasses') -# # set the icon -# root.iconbitmap(default='logo.ico') -# root.geometry('399x410') -# root.resizable(0,0) # Blocking the resizing feature - -# # Define the colors and fonts -background = '#2c94c8' -buttons = '#834558' -special_buttons = '#bc3454' -button_font = ('Arial', 18) -display_font = ('Arial', 32) - -# Initialize the Quantum Circuit -def initialize_circuit(): - global circuit - circuit = QuantumCircuit(1) - -initialize_circuit() - - -theta = 0 - -# Define Functions - - - - -def about(): - """ - Displays the info about the project! - """ - info = tkinter.Tk() - info.title('About') - info.geometry('650x470') - info.resizable(0,0) - - text = tkinter.Text(info, height = 20, width = 20) - - # Create label - label = tkinter.Label(info, text = "About Quantum Glasses:") - label.config(font =("Arial", 14)) - - - text_to_display = """ - About: Visualization tool for Single Qubit Rotation on Bloch Sphere - - Created by : Jay Shah - Created using: Python, Tkinter, Qiskit - - Info about the gate buttons and corresponding qiskit commands: - - X = flips the state of qubit - circuit.x() - Y = rotates the state vector about Y-axis - circuit.y() - Z = flips the phase by PI radians - circuit.z() - Rx = parameterized rotation about the X axis - circuit.rx() - Ry = parameterized rotation about the Y axis. circuit.ry() - Rz = parameterized rotation about the Z axis. circuit.rz() - S = rotates the state vector about Z axis by PI/2 radians - circuit.s() - T = rotates the state vector about Z axis by PI/4 radians - circuit.t() - Sd = rotates the state vector about Z axis by -PI/2 radians - circuit.sdg() - Td = rotates the state vector about Z axis by -PI/4 radians - circuit.tdg() - H = creates the state of superposition - circuit.h() - - For Rx, Ry and Rz, - theta(rotation_angle) allowed range in the app is [-2*PI,2*PI] - - In case of a Visualization Error, the app closes automatically. - This indicates that visualization of your circuit is not possible. - - At a time, only ten operations can be visualized. - """ - - label.pack() - text.pack(fill='both',expand=True) - - # Insert the text - text.insert(END,text_to_display) - - # run - info.mainloop() - - -def change_theta(num,window,circuit,key): - """ - CHanges the global variable theta and destroys the window - """ - global theta - theta = num * np.pi - if key=='x': - circuit.rx(theta,0) - theta = 0 - elif key=='y': - circuit.ry(theta,0) - theta = 0 - else: - circuit.rz(theta,0) - theta = 0 - window.destroy() - -def user_input(circuit,key): - """ - Take the user input for rotation angle for parameterized - Rotation gates Rx, Ry, Rz. - """ - - # Initialize and define the properties of window - get_input = tkinter.Tk() - get_input.title('Get Theta') - get_input.geometry('360x160') - get_input.resizable(0,0) - - val1 = tkinter.Button(get_input,height=2,width=10,bg=buttons,font=("Arial",10),text='PI/4',command=lambda:change_theta(0.25,get_input,circuit,key)) - val1.grid(row=0, column=0) - - val2 = tkinter.Button(get_input,height=2,width=10,bg=buttons,font=("Arial",10),text='PI/2',command=lambda:change_theta(0.50,get_input,circuit,key)) - val2.grid(row=0, column=1) - - val3 = tkinter.Button(get_input,height=2,width=10,bg=buttons,font=("Arial",10),text='PI',command=lambda:change_theta(1.0,get_input,circuit,key)) - val3.grid(row=0, column=2) - - val4 = tkinter.Button(get_input,height=2,width=10,bg=buttons,font=("Arial",10),text='2*PI',command=lambda:change_theta(2.0,get_input,circuit,key)) - val4.grid(row=0, column=3,sticky='W') - - nval1 = tkinter.Button(get_input,height=2,width=10,bg=buttons,font=("Arial",10),text='-PI/4',command=lambda:change_theta(-0.25,get_input,circuit,key)) - nval1.grid(row=1, column=0) - - nval2 = tkinter.Button(get_input,height=2,width=10,bg=buttons,font=("Arial",10),text='-PI/2',command=lambda:change_theta(-0.50,get_input,circuit,key)) - nval2.grid(row=1, column=1) - - nval3 = tkinter.Button(get_input,height=2,width=10,bg=buttons,font=("Arial",10),text='-PI',command=lambda:change_theta(-1.0,get_input,circuit,key)) - nval3.grid(row=1, column=2) - - nval4 = tkinter.Button(get_input,height=2,width=10,bg=buttons,font=("Arial",10),text='-2*PI',command=lambda:change_theta(-2.0,get_input,circuit,key)) - nval4.grid(row=1, column=3,sticky='W') - - text_object = tkinter.Text(get_input, height = 20, width = 20,bg="light cyan") - - note = """ - GIVE THE VALUE FOR THETA - The value has the range [-2*PI,2*PI] - """ - - text_object.grid(sticky='WE',columnspan=4) - text_object.insert(END,note) - - - get_input.mainloop() - -# Define functions for qiskit-based buttons -# Define the function for visualize button -def visualize_circuit(circuit,window): - """ - Visualizes the single qubit rotations corresponding to applied gates in a separate tkinter window. - Handles any possible visualization error - """ - try: - visualize_transition(circuit=circuit) - except qiskit.visualization.exceptions.VisualizationError: - window.destroy() - - -def main(): - ''' - Args: - - Returns: - True if the software is invoked correctly and opens the software automatically. - False if exception is occured - ''' - try: - # Define Window - root = tkinter.Tk() - root.title('Quantum Glasses') - - # set the icon - root.iconbitmap(default='logo.ico') - root.geometry('399x410') - root.resizable(0,0) # Blocking the resizing feature - - # Define Layout - # Define the Frames - display_frame = tkinter.LabelFrame(root) - button_frame = tkinter.LabelFrame(root,bg='black') - display_frame.pack() - button_frame.pack(fill='both',expand=True) - - # Define the Display Frame Layout - display = tkinter.Entry(display_frame, width=120, font=display_font, bg=background, borderwidth=2, justify=LEFT) - display.pack(padx=3,pady=4) - - # Define functions for non-qiskit buttons - def display_gate(gate_input): - """ - Adds a corresponding gate notation in the display to track the operations. - If the number of operation reach ten, all gate buttons are disabled. - """ - # Insert the defined gate - display.insert(END,gate_input) - - # Check if the number of operations has reached ten, if yes, - # disable all the gate buttons - input_gates = display.get() - num_gates_pressed = len(input_gates) - list_input_gates = list(input_gates) - search_word = ["R","D"] - count_double_valued_gates = [list_input_gates.count(i) for i in search_word] - num_gates_pressed-=sum(count_double_valued_gates) - if num_gates_pressed==10: - gates = [x_gate, y_gate, z_gate, Rx_gate, Ry_gate, Rz_gate, s_gate, sd_gate, t_gate, td_gate, hadamard] - for gate in gates: - gate.config(state=DISABLED) - - # Define the first row of buttons - x_gate = tkinter.Button(button_frame, font=button_font, bg=buttons, text='X',command=lambda:[display_gate('x'),circuit.x(0)]) - y_gate = tkinter.Button(button_frame, font=button_font, bg=buttons, text='Y',command=lambda:[display_gate('y'),circuit.y(0)]) - z_gate = tkinter.Button(button_frame, font=button_font, bg=buttons, text='Z',command=lambda:[display_gate('z'),circuit.z(0)]) - x_gate.grid(row=0,column=0,ipadx=45, pady=1) - y_gate.grid(row=0,column=1,ipadx=45, pady=1) - z_gate.grid(row=0,column=2,ipadx=53, pady=1, sticky='E') - - # Define the second row of buttons - Rx_gate = tkinter.Button(button_frame, font=button_font, bg=buttons, text='RX',command=lambda:[display_gate('Rx'),user_input(circuit,'x')]) - Ry_gate = tkinter.Button(button_frame, font=button_font, bg=buttons, text='RY',command=lambda:[display_gate('Ry'),user_input(circuit,'y')]) - Rz_gate = tkinter.Button(button_frame, font=button_font, bg=buttons, text='RZ',command=lambda:[display_gate('Rz'),user_input(circuit,'z')]) - Rx_gate.grid(row=1,column=0,columnspan=1,sticky='WE', pady=1) - Ry_gate.grid(row=1,column=1,columnspan=1,sticky='WE', pady=1) - Rz_gate.grid(row=1,column=2,columnspan=1,sticky='WE', pady=1) - - # Define the third row of buttons - s_gate = tkinter.Button(button_frame, font=button_font, bg=buttons, text='S',command=lambda:[display_gate('s'),circuit.s(0)]) - sd_gate = tkinter.Button(button_frame, font=button_font, bg=buttons, text='SD',command=lambda:[display_gate('SD'),circuit.sdg(0)]) - hadamard = tkinter.Button(button_frame, font=button_font, bg=buttons, text='H',command=lambda:[display_gate('H'),circuit.h(0)]) - s_gate.grid(row=2,column=0,columnspan=1,sticky='WE', pady=1) - sd_gate.grid(row=2,column=1,sticky='WE', pady=1) - hadamard.grid(row=2, column=2, rowspan=2,sticky='WENS', pady=1) - - # Define the fifth row of buttons - t_gate = tkinter.Button(button_frame, font=button_font, bg=buttons, text='T', command=lambda:[display_gate('t'),circuit.t(0)]) - td_gate = tkinter.Button(button_frame, font=button_font, bg=buttons, text='TD',command=lambda:[display_gate('TD'),circuit.tdg(0)]) - t_gate.grid(row=3,column=0,sticky='WE', pady=1) - td_gate.grid(row=3,column=1,sticky='WE', pady=1) - - def clear(circuit): - """ - Clears the display! - Reintializes the Quantum Circuit for fresh calculation! - Checks if the gate buttons are disabled, if so, enables the buttons - """ - # clear the display - display.delete(0, END) - - # reset the circuit to initial state |0> - initialize_circuit() - - # Checks if the buttons are disabled and if so, enables them - if x_gate['state']==DISABLED: - gates = [x_gate, y_gate, z_gate, Rx_gate, Ry_gate, Rz_gate, s_gate, sd_gate, t_gate, td_gate, hadamard] - for gate in gates: - gate.config(state=NORMAL) - - # Define the Quit and Visualize buttons - quit = tkinter.Button(button_frame, font=button_font, bg=special_buttons, text='Quit',command=root.destroy) - visualize = tkinter.Button(button_frame, font=button_font, bg=special_buttons, text='Visualize',command=lambda:visualize_circuit(circuit,root)) - quit.grid(row=4,column=0,columnspan=2,sticky='WE',ipadx=5, pady=1) - visualize.grid(row=4,column=2,columnspan=1,sticky='WE',ipadx=8, pady=1) - - # Define the clear button - clear_button = tkinter.Button(button_frame, font=button_font, bg=special_buttons, text='Clear',command=lambda:clear(circuit)) - clear_button.grid(row=5,column=0,columnspan=3,sticky='WE') - - # Define the about button - about_button = tkinter.Button(button_frame, font=button_font, bg=special_buttons, text='About',command=about) - about_button.grid(row=6,column=0,columnspan=3,sticky='WE') - - # Run the main loop - root.mainloop() - - return True - except Exception as e: - print('Exception occured: \n') - print(e) - return False - -if __name__=='__main__': - _ = main() +if __name__ == "__main__": + fire.Fire(QuantumGlasses().main()) diff --git a/quantum_glasses/__init__.py b/quantum_glasses/__init__.py new file mode 100644 index 000000000..dce883e77 --- /dev/null +++ b/quantum_glasses/__init__.py @@ -0,0 +1,3 @@ +"""Main module.""" + +from .quantum_glasses import QuantumGlasses diff --git a/quantum_glasses/quantum_glasses.py b/quantum_glasses/quantum_glasses.py new file mode 100644 index 000000000..40b17c273 --- /dev/null +++ b/quantum_glasses/quantum_glasses.py @@ -0,0 +1,302 @@ +import tkinter +from tkinter import LEFT, END, DISABLED, NORMAL +import warnings +import numpy as np +import qiskit +from qiskit import QuantumCircuit +from qiskit.visualization import visualize_transition + +# Ignore unnecessary warnings +warnings.simplefilter("ignore") + +# # Define Window +# root = tkinter.Tk() +# root.title('Quantum Glasses') + +# # set the icon +# root.iconbitmap(default='logo.ico') +# root.geometry('399x410') +# root.resizable(0,0) # Blocking the resizing feature + +# # Define the colors and fonts +background = '#2c94c8' +buttons = '#834558' +special_buttons = '#bc3454' +button_font = ('Arial', 18) +display_font = ('Arial', 32) + + +class QuantumGlasses: + """Main object.""" + + def __init__(self): + pass + + # Initialize the Quantum Circuit + @staticmethod + def initialize_circuit(): + global circuit + circuit = QuantumCircuit(1) + + initialize_circuit() + + + theta = 0 + + # Define Functions + + @staticmethod + def about(): + """ + Displays the info about the project! + """ + info = tkinter.Tk() + info.title('About') + info.geometry('650x470') + info.resizable(0,0) + + text = tkinter.Text(info, height = 20, width = 20) + + # Create label + label = tkinter.Label(info, text = "About Quantum Glasses:") + label.config(font =("Arial", 14)) + + + text_to_display = """ + About: Visualization tool for Single Qubit Rotation on Bloch Sphere + + Created by : Jay Shah + Created using: Python, Tkinter, Qiskit + + Info about the gate buttons and corresponding qiskit commands: + + X = flips the state of qubit - circuit.x() + Y = rotates the state vector about Y-axis - circuit.y() + Z = flips the phase by PI radians - circuit.z() + Rx = parameterized rotation about the X axis - circuit.rx() + Ry = parameterized rotation about the Y axis. circuit.ry() + Rz = parameterized rotation about the Z axis. circuit.rz() + S = rotates the state vector about Z axis by PI/2 radians - circuit.s() + T = rotates the state vector about Z axis by PI/4 radians - circuit.t() + Sd = rotates the state vector about Z axis by -PI/2 radians - circuit.sdg() + Td = rotates the state vector about Z axis by -PI/4 radians - circuit.tdg() + H = creates the state of superposition - circuit.h() + + For Rx, Ry and Rz, + theta(rotation_angle) allowed range in the app is [-2*PI,2*PI] + + In case of a Visualization Error, the app closes automatically. + This indicates that visualization of your circuit is not possible. + + At a time, only ten operations can be visualized. + """ + + label.pack() + text.pack(fill='both',expand=True) + + # Insert the text + text.insert(END,text_to_display) + + # run + info.mainloop() + + @staticmethod + def change_theta(num,window,circuit,key): + """ + CHanges the global variable theta and destroys the window + """ + global theta + theta = num * np.pi + if key=='x': + circuit.rx(theta,0) + theta = 0 + elif key=='y': + circuit.ry(theta,0) + theta = 0 + else: + circuit.rz(theta,0) + theta = 0 + window.destroy() + + def user_input(self, circuit,key): + """ + Take the user input for rotation angle for parameterized + Rotation gates Rx, Ry, Rz. + """ + + # Initialize and define the properties of window + get_input = tkinter.Tk() + get_input.title('Get Theta') + get_input.geometry('360x160') + get_input.resizable(0,0) + + val1 = tkinter.Button(get_input,height=2,width=10,bg=buttons,font=("Arial",10),text='PI/4',command=lambda:self.change_theta(0.25,get_input,circuit,key)) + val1.grid(row=0, column=0) + + val2 = tkinter.Button(get_input,height=2,width=10,bg=buttons,font=("Arial",10),text='PI/2',command=lambda:self.change_theta(0.50,get_input,circuit,key)) + val2.grid(row=0, column=1) + + val3 = tkinter.Button(get_input,height=2,width=10,bg=buttons,font=("Arial",10),text='PI',command=lambda:self.change_theta(1.0,get_input,circuit,key)) + val3.grid(row=0, column=2) + + val4 = tkinter.Button(get_input,height=2,width=10,bg=buttons,font=("Arial",10),text='2*PI',command=lambda:self.change_theta(2.0,get_input,circuit,key)) + val4.grid(row=0, column=3,sticky='W') + + nval1 = tkinter.Button(get_input,height=2,width=10,bg=buttons,font=("Arial",10),text='-PI/4',command=lambda:self.change_theta(-0.25,get_input,circuit,key)) + nval1.grid(row=1, column=0) + + nval2 = tkinter.Button(get_input,height=2,width=10,bg=buttons,font=("Arial",10),text='-PI/2',command=lambda:self.change_theta(-0.50,get_input,circuit,key)) + nval2.grid(row=1, column=1) + + nval3 = tkinter.Button(get_input,height=2,width=10,bg=buttons,font=("Arial",10),text='-PI',command=lambda:self.change_theta(-1.0,get_input,circuit,key)) + nval3.grid(row=1, column=2) + + nval4 = tkinter.Button(get_input,height=2,width=10,bg=buttons,font=("Arial",10),text='-2*PI',command=lambda:self.change_theta(-2.0,get_input,circuit,key)) + nval4.grid(row=1, column=3,sticky='W') + + text_object = tkinter.Text(get_input, height = 20, width = 20,bg="light cyan") + + note = """ + GIVE THE VALUE FOR THETA + The value has the range [-2*PI,2*PI] + """ + + text_object.grid(sticky='WE',columnspan=4) + text_object.insert(END,note) + + + get_input.mainloop() + + # Define functions for qiskit-based buttons + # Define the function for visualize button + @staticmethod + def visualize_circuit(circuit,window): + """ + Visualizes the single qubit rotations corresponding to applied gates in a separate tkinter window. + Handles any possible visualization error + """ + try: + visualize_transition(circuit=circuit) + except qiskit.visualization.exceptions.VisualizationError: + window.destroy() + + def main(self): + ''' + Args: - + Returns: + True if the software is invoked correctly and opens the software automatically. + False if exception is occured + ''' + try: + # Define Window + root = tkinter.Tk() + root.title('Quantum Glasses') + + # set the icon + root.iconbitmap(default='logo.ico') + root.geometry('399x410') + root.resizable(0,0) # Blocking the resizing feature + + # Define Layout + # Define the Frames + display_frame = tkinter.LabelFrame(root) + button_frame = tkinter.LabelFrame(root,bg='black') + display_frame.pack() + button_frame.pack(fill='both',expand=True) + + # Define the Display Frame Layout + display = tkinter.Entry(display_frame, width=120, font=display_font, bg=background, borderwidth=2, justify=LEFT) + display.pack(padx=3,pady=4) + + # Define functions for non-qiskit buttons + def display_gate(gate_input): + """ + Adds a corresponding gate notation in the display to track the operations. + If the number of operation reach ten, all gate buttons are disabled. + """ + # Insert the defined gate + display.insert(END,gate_input) + + # Check if the number of operations has reached ten, if yes, + # disable all the gate buttons + input_gates = display.get() + num_gates_pressed = len(input_gates) + list_input_gates = list(input_gates) + search_word = ["R","D"] + count_double_valued_gates = [list_input_gates.count(i) for i in search_word] + num_gates_pressed-=sum(count_double_valued_gates) + if num_gates_pressed==10: + gates = [x_gate, y_gate, z_gate, Rx_gate, Ry_gate, Rz_gate, s_gate, sd_gate, t_gate, td_gate, hadamard] + for gate in gates: + gate.config(state=DISABLED) + + # Define the first row of buttons + x_gate = tkinter.Button(button_frame, font=button_font, bg=buttons, text='X',command=lambda:[display_gate('x'),circuit.x(0)]) + y_gate = tkinter.Button(button_frame, font=button_font, bg=buttons, text='Y',command=lambda:[display_gate('y'),circuit.y(0)]) + z_gate = tkinter.Button(button_frame, font=button_font, bg=buttons, text='Z',command=lambda:[display_gate('z'),circuit.z(0)]) + x_gate.grid(row=0,column=0,ipadx=45, pady=1) + y_gate.grid(row=0,column=1,ipadx=45, pady=1) + z_gate.grid(row=0,column=2,ipadx=53, pady=1, sticky='E') + + # Define the second row of buttons + Rx_gate = tkinter.Button(button_frame, font=button_font, bg=buttons, text='RX',command=lambda:[display_gate('Rx'),self.user_input(circuit,'x')]) + Ry_gate = tkinter.Button(button_frame, font=button_font, bg=buttons, text='RY',command=lambda:[display_gate('Ry'),self.user_input(circuit,'y')]) + Rz_gate = tkinter.Button(button_frame, font=button_font, bg=buttons, text='RZ',command=lambda:[display_gate('Rz'),self.user_input(circuit,'z')]) + Rx_gate.grid(row=1,column=0,columnspan=1,sticky='WE', pady=1) + Ry_gate.grid(row=1,column=1,columnspan=1,sticky='WE', pady=1) + Rz_gate.grid(row=1,column=2,columnspan=1,sticky='WE', pady=1) + + # Define the third row of buttons + s_gate = tkinter.Button(button_frame, font=button_font, bg=buttons, text='S',command=lambda:[display_gate('s'),circuit.s(0)]) + sd_gate = tkinter.Button(button_frame, font=button_font, bg=buttons, text='SD',command=lambda:[display_gate('SD'),circuit.sdg(0)]) + hadamard = tkinter.Button(button_frame, font=button_font, bg=buttons, text='H',command=lambda:[display_gate('H'),circuit.h(0)]) + s_gate.grid(row=2,column=0,columnspan=1,sticky='WE', pady=1) + sd_gate.grid(row=2,column=1,sticky='WE', pady=1) + hadamard.grid(row=2, column=2, rowspan=2,sticky='WENS', pady=1) + + # Define the fifth row of buttons + t_gate = tkinter.Button(button_frame, font=button_font, bg=buttons, text='T', command=lambda:[display_gate('t'),circuit.t(0)]) + td_gate = tkinter.Button(button_frame, font=button_font, bg=buttons, text='TD',command=lambda:[display_gate('TD'),circuit.tdg(0)]) + t_gate.grid(row=3,column=0,sticky='WE', pady=1) + td_gate.grid(row=3,column=1,sticky='WE', pady=1) + + def clear(circuit): + """ + Clears the display! + Reintializes the Quantum Circuit for fresh calculation! + Checks if the gate buttons are disabled, if so, enables the buttons + """ + # clear the display + display.delete(0, END) + + # reset the circuit to initial state |0> + self.initialize_circuit() + + # Checks if the buttons are disabled and if so, enables them + if x_gate['state']==DISABLED: + gates = [x_gate, y_gate, z_gate, Rx_gate, Ry_gate, Rz_gate, s_gate, sd_gate, t_gate, td_gate, hadamard] + for gate in gates: + gate.config(state=NORMAL) + + # Define the Quit and Visualize buttons + quit = tkinter.Button(button_frame, font=button_font, bg=special_buttons, text='Quit',command=root.destroy) + visualize = tkinter.Button(button_frame, font=button_font, bg=special_buttons, text='Visualize',command=lambda:self.visualize_circuit(circuit,root)) + quit.grid(row=4,column=0,columnspan=2,sticky='WE',ipadx=5, pady=1) + visualize.grid(row=4,column=2,columnspan=1,sticky='WE',ipadx=8, pady=1) + + # Define the clear button + clear_button = tkinter.Button(button_frame, font=button_font, bg=special_buttons, text='Clear',command=lambda:clear(circuit)) + clear_button.grid(row=5,column=0,columnspan=3,sticky='WE') + + # Define the about button + about_button = tkinter.Button(button_frame, font=button_font, bg=special_buttons, text='About',command=self.about) + about_button.grid(row=6,column=0,columnspan=3,sticky='WE') + + # Run the main loop + root.mainloop() + + return True + except Exception as e: + print('Exception occured: \n') + print(e) + return False diff --git a/requirements.txt b/requirements.txt index 3af7cc4ff..92044eec3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,25 +1,4 @@ -contourpy==1.1.0 -cycler==0.11.0 -dill==0.3.7 -exceptiongroup==1.1.2 -fonttools==4.42.0 -iniconfig==2.0.0 -kiwisolver==1.4.4 -matplotlib==3.7.2 -mpmath==1.3.0 -numpy==1.25.2 -packaging==23.1 -Pillow==10.0.0 -pluggy==1.2.0 -ply==3.11 -psutil==5.9.5 -pyparsing==3.0.9 +fire==0.5.0 +qiskit==0.44.1 +qiskit[visualization]==0.44.1 pytest==7.4.0 -python-dateutil==2.8.2 -qiskit==0.44.0 -qiskit-terra==0.25.0 -rustworkx==0.13.1 -six==1.16.0 -stevedore==5.1.0 -sympy==1.12 -typing_extensions==4.7.1 diff --git a/setup.py b/setup.py new file mode 100644 index 000000000..ed96312be --- /dev/null +++ b/setup.py @@ -0,0 +1,18 @@ +"""Setup file.""" + +import setuptools + +with open("README.md", "r") as fh: + long_description = fh.read() + +with open('requirements.txt') as fp: + install_requires = fp.read() + +setuptools.setup( + name="quantum_glasses", + description="Quantum Glasses", + long_description=long_description, + packages=setuptools.find_packages(), + install_requires=install_requires, + python_requires='>=3.9' +) diff --git a/tests/test_quantum_glasses.py b/tests/test_quantum_glasses.py index c95959d0f..7a6a356e7 100644 --- a/tests/test_quantum_glasses.py +++ b/tests/test_quantum_glasses.py @@ -1,7 +1,8 @@ -import quantum_glasses +from quantum_glasses import QuantumGlasses import unittest class TestQuantumGlasses(unittest.TestCase): def test_main(self): - self.assertEqual(quantum_glasses.main(),True) \ No newline at end of file + my_qglases = QuantumGlasses() + self.assertEqual(my_qglases.main(), True) diff --git a/tox.ini b/tox.ini new file mode 100644 index 000000000..76ff7a527 --- /dev/null +++ b/tox.ini @@ -0,0 +1,16 @@ +[tox] +minversion = 3.9 +envlist = py39 +skipsdist = True + +[testenv] +usedevelop = true +install_command = pip install -U {opts} {packages} +setenv = + VIRTUAL_ENV={envdir} + LANGUAGE=en_US + LC_ALL=en_US.utf-8 +deps = -r requirements.txt +commands = + pip check + python -m unittest -v From 7b2a5d91e3162184a6a775e8da78f50e43949fb8 Mon Sep 17 00:00:00 2001 From: Mica Date: Fri, 18 Aug 2023 18:05:00 +0200 Subject: [PATCH 02/13] update requirements --- requirements.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 92044eec3..c7a7dbbbf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ fire==0.5.0 -qiskit==0.44.1 -qiskit[visualization]==0.44.1 +qiskit>=0.44.1 +qiskit[visualization]>=0.44.1 +tox==4.9.0 pytest==7.4.0 From b66a5db793e6b96dd66ba133296717830654354c Mon Sep 17 00:00:00 2001 From: Mica Date: Fri, 18 Aug 2023 19:33:46 +0200 Subject: [PATCH 03/13] update tests --- quantum_glasses/quantum_glasses.py | 41 ++++++++++-------- tests/__pycache__/__init__.cpython-310.pyc | Bin 129 -> 0 bytes tests/__pycache__/__init__.cpython-39.pyc | Bin 127 -> 0 bytes ...antum_glasses.cpython-310-pytest-7.4.0.pyc | Bin 646 -> 0 bytes ...uantum_glasses.cpython-39-pytest-7.1.2.pyc | Bin 642 -> 0 bytes tests/test_quantum_glasses.py | 2 +- 6 files changed, 25 insertions(+), 18 deletions(-) delete mode 100644 tests/__pycache__/__init__.cpython-310.pyc delete mode 100644 tests/__pycache__/__init__.cpython-39.pyc delete mode 100644 tests/__pycache__/test_quantum_glasses.cpython-310-pytest-7.4.0.pyc delete mode 100644 tests/__pycache__/test_quantum_glasses.cpython-39-pytest-7.1.2.pyc diff --git a/quantum_glasses/quantum_glasses.py b/quantum_glasses/quantum_glasses.py index 40b17c273..d5506a4eb 100644 --- a/quantum_glasses/quantum_glasses.py +++ b/quantum_glasses/quantum_glasses.py @@ -1,3 +1,5 @@ +import os +from platform import system import tkinter from tkinter import LEFT, END, DISABLED, NORMAL import warnings @@ -14,7 +16,7 @@ # root.title('Quantum Glasses') # # set the icon -# root.iconbitmap(default='logo.ico') +# root.iconbitmap(default='../logo.ico') # root.geometry('399x410') # root.resizable(0,0) # Blocking the resizing feature @@ -25,6 +27,16 @@ button_font = ('Arial', 18) display_font = ('Arial', 32) +# Initialize the Quantum Circuit +def initialize_circuit(): + global circuit + circuit = QuantumCircuit(1) + +initialize_circuit() + +theta = 0 + +# Define Functions class QuantumGlasses: """Main object.""" @@ -32,18 +44,6 @@ class QuantumGlasses: def __init__(self): pass - # Initialize the Quantum Circuit - @staticmethod - def initialize_circuit(): - global circuit - circuit = QuantumCircuit(1) - - initialize_circuit() - - - theta = 0 - - # Define Functions @staticmethod def about(): @@ -180,7 +180,7 @@ def visualize_circuit(circuit,window): except qiskit.visualization.exceptions.VisualizationError: window.destroy() - def main(self): + def main(self, testing: bool = False): ''' Args: - Returns: @@ -193,7 +193,11 @@ def main(self): root.title('Quantum Glasses') # set the icon - root.iconbitmap(default='logo.ico') + current_directory = os.path.dirname(os.path.abspath(__file__)) + if system() == 'Windows': + logo_path = os.path.join(current_directory, "../logo.ico") + root.iconbitmap(default=logo_path) + root.geometry('399x410') root.resizable(0,0) # Blocking the resizing feature @@ -270,7 +274,7 @@ def clear(circuit): display.delete(0, END) # reset the circuit to initial state |0> - self.initialize_circuit() + initialize_circuit() # Checks if the buttons are disabled and if so, enables them if x_gate['state']==DISABLED: @@ -293,7 +297,10 @@ def clear(circuit): about_button.grid(row=6,column=0,columnspan=3,sticky='WE') # Run the main loop - root.mainloop() + if testing: + root.dooneevent() + else: + root.mainloop() return True except Exception as e: diff --git a/tests/__pycache__/__init__.cpython-310.pyc b/tests/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index e66482084e0a13bef18e09c3735043114b957497..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 129 zcmd1j<>g`k0@uf_SYH>+%OniK1US>&ryk0@&Ee@O9{FKt1R6CIFVkRKL!Tg`k0@uf_SYH>+%OniK1US>&ryk0@&Ee@O9{FKt1R6CIF&p^xo0AZ>dlK=n! diff --git a/tests/__pycache__/test_quantum_glasses.cpython-310-pytest-7.4.0.pyc b/tests/__pycache__/test_quantum_glasses.cpython-310-pytest-7.4.0.pyc deleted file mode 100644 index 709418f70e37535d2ca40129fd87124efc42ddad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 646 zcmZWm!AiqG5Z&FxW*b`sDT3h1TMh=#B2uW*TS4q86qeYH5=qjyn;;c$_5=Kc_Nd?D z7wpxOzu?K4q%A=Q_U+Eh?wdEWvu@WVVENmp{DA!nou=8~^kHcPNhD23K&zdl79*6T zcCbV1Oe<(r87FXtL^5eDh_oW-fxlWoThbfi+26oIMpMM5F>v~@bPph^Dg;bY$rdEA zq=hfd{y5Ubbs1(wnGTas>qt*2T;CX;QSAU$#q&azq@YW-0@W*q8i9w6#-3$%@wqCl z9?LK>dw@tP?rTo zC1H;}`h4`i4S#!a1buQLvM`N=Fs=~kOqL0rI|552bw;&;tCH0Kjxj8PL(mAEbXXPf zT*Gh6I4R;xn@&HUi>-Gk@;R3G>xsm(%vaHqii^m!w;|(fVlF(c)P_o73B$`QE-+&F g7;q56Tv0?r7>-Y&I>XQFelGB@G*0E1aC*Rg0hS@9DF6Tf diff --git a/tests/__pycache__/test_quantum_glasses.cpython-39-pytest-7.1.2.pyc b/tests/__pycache__/test_quantum_glasses.cpython-39-pytest-7.1.2.pyc deleted file mode 100644 index d84d4e2d74b878c66ee72e28d4d56c8b03531c81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 642 zcmZWm%}T>S5Z<5IY-5WcUIb6xaxi!nkwTT;3Sv*8u*7bZNRq~Ef>gZO2k;TvqdtpI zuvbsMf+uG-Z7Dji-)3fZzwet()a`l%qImmMAFzL6vKj3-X4=@6$b|$N zXC(Cb=>HhO=HL+K6jJ6<7E5V7DYL1nQ~d5olt`OSDS*n_+5#7AD1wh*)daJ-?-_Ah zCux=B+H`uwOm4D6S`^Q6Lx5hK8U b1h0w~wrt_-C3-XByqV?#|CC0T$5gOiT9%|% diff --git a/tests/test_quantum_glasses.py b/tests/test_quantum_glasses.py index 7a6a356e7..62ffe2cb0 100644 --- a/tests/test_quantum_glasses.py +++ b/tests/test_quantum_glasses.py @@ -5,4 +5,4 @@ class TestQuantumGlasses(unittest.TestCase): def test_main(self): my_qglases = QuantumGlasses() - self.assertEqual(my_qglases.main(), True) + self.assertEqual(my_qglases.main(testing=True), True) From 9721ab3a41bcecf449ce9a748111c55803cf63c8 Mon Sep 17 00:00:00 2001 From: Mica Date: Fri, 18 Aug 2023 19:44:36 +0200 Subject: [PATCH 04/13] add mpl --- README.md | 7 +++++++ quantum_glasses/quantum_glasses.py | 4 ++++ requirements.txt | 1 + 3 files changed, 12 insertions(+) diff --git a/README.md b/README.md index 2a540dfc9..4dc0e7e7a 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,13 @@ Points to remember while recreating Built using: Python, Tkinter, Qiskit +### Launch + +To launch just run : +```python +python quantum_glasses.py +``` + How the Visualizer looks? diff --git a/quantum_glasses/quantum_glasses.py b/quantum_glasses/quantum_glasses.py index d5506a4eb..00bd63481 100644 --- a/quantum_glasses/quantum_glasses.py +++ b/quantum_glasses/quantum_glasses.py @@ -8,6 +8,10 @@ from qiskit import QuantumCircuit from qiskit.visualization import visualize_transition + +import matplotlib +matplotlib.use('Agg') + # Ignore unnecessary warnings warnings.simplefilter("ignore") diff --git a/requirements.txt b/requirements.txt index c7a7dbbbf..7b18d3103 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ qiskit>=0.44.1 qiskit[visualization]>=0.44.1 tox==4.9.0 pytest==7.4.0 +matplotlib==3.7.2 From b1aa0061b003fe77b8d7423ad3368968649e96a6 Mon Sep 17 00:00:00 2001 From: Mica Date: Fri, 18 Aug 2023 19:52:11 +0200 Subject: [PATCH 05/13] DISPLAY var --- quantum_glasses/quantum_glasses.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/quantum_glasses/quantum_glasses.py b/quantum_glasses/quantum_glasses.py index 00bd63481..30dbcbde1 100644 --- a/quantum_glasses/quantum_glasses.py +++ b/quantum_glasses/quantum_glasses.py @@ -1,4 +1,5 @@ import os +import matplotlib from platform import system import tkinter from tkinter import LEFT, END, DISABLED, NORMAL @@ -9,8 +10,8 @@ from qiskit.visualization import visualize_transition -import matplotlib matplotlib.use('Agg') +os.environ["DISPLAY"] = "0.0" # Ignore unnecessary warnings warnings.simplefilter("ignore") From 3c4afda7d003b8d676fb7ec2719aefe586047424 Mon Sep 17 00:00:00 2001 From: Mica Date: Fri, 18 Aug 2023 20:00:21 +0200 Subject: [PATCH 06/13] DISPLAY var --- quantum_glasses/quantum_glasses.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/quantum_glasses/quantum_glasses.py b/quantum_glasses/quantum_glasses.py index 30dbcbde1..0ebc938fc 100644 --- a/quantum_glasses/quantum_glasses.py +++ b/quantum_glasses/quantum_glasses.py @@ -10,8 +10,10 @@ from qiskit.visualization import visualize_transition -matplotlib.use('Agg') -os.environ["DISPLAY"] = "0.0" +if os.environ.get('DISPLAY','') == '': + print('no display found. Using non-interactive Agg backend') + matplotlib.use('Agg') + os.environ.__setitem__('DISPLAY', ':0.0') # Ignore unnecessary warnings warnings.simplefilter("ignore") From ec735178df1c4a31ebe2c9276f7f5c3870a4e203 Mon Sep 17 00:00:00 2001 From: Mica Date: Fri, 18 Aug 2023 20:28:05 +0200 Subject: [PATCH 07/13] ignore X server --- quantum_glasses/quantum_glasses.py | 13 +++++-------- tests/test_quantum_glasses.py | 5 +++++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/quantum_glasses/quantum_glasses.py b/quantum_glasses/quantum_glasses.py index 0ebc938fc..379fc8c73 100644 --- a/quantum_glasses/quantum_glasses.py +++ b/quantum_glasses/quantum_glasses.py @@ -1,5 +1,4 @@ import os -import matplotlib from platform import system import tkinter from tkinter import LEFT, END, DISABLED, NORMAL @@ -9,12 +8,6 @@ from qiskit import QuantumCircuit from qiskit.visualization import visualize_transition - -if os.environ.get('DISPLAY','') == '': - print('no display found. Using non-interactive Agg backend') - matplotlib.use('Agg') - os.environ.__setitem__('DISPLAY', ':0.0') - # Ignore unnecessary warnings warnings.simplefilter("ignore") @@ -305,7 +298,11 @@ def clear(circuit): # Run the main loop if testing: - root.dooneevent() + if os.getenv('DISPLAY') is None: + print("No X server available !") + root.event_info() + else: + root.dooneevent() else: root.mainloop() diff --git a/tests/test_quantum_glasses.py b/tests/test_quantum_glasses.py index 62ffe2cb0..e13d4b071 100644 --- a/tests/test_quantum_glasses.py +++ b/tests/test_quantum_glasses.py @@ -1,8 +1,13 @@ from quantum_glasses import QuantumGlasses +import matplotlib import unittest +import os class TestQuantumGlasses(unittest.TestCase): def test_main(self): + if os.getenv('DISPLAY') is None: + matplotlib.use('Agg') + my_qglases = QuantumGlasses() self.assertEqual(my_qglases.main(testing=True), True) From d35c53367e51f31bc09604031f3f44c0d5833560 Mon Sep 17 00:00:00 2001 From: Mica Date: Fri, 18 Aug 2023 20:39:37 +0200 Subject: [PATCH 08/13] make test coherent --- quantum_glasses/quantum_glasses.py | 9 ++------- tests/test_quantum_glasses.py | 6 +++++- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/quantum_glasses/quantum_glasses.py b/quantum_glasses/quantum_glasses.py index 379fc8c73..1657ac915 100644 --- a/quantum_glasses/quantum_glasses.py +++ b/quantum_glasses/quantum_glasses.py @@ -298,16 +298,11 @@ def clear(circuit): # Run the main loop if testing: - if os.getenv('DISPLAY') is None: - print("No X server available !") - root.event_info() - else: - root.dooneevent() + root.dooneevent() else: root.mainloop() return True except Exception as e: - print('Exception occured: \n') - print(e) + print(f"Exception occured: {e}") return False diff --git a/tests/test_quantum_glasses.py b/tests/test_quantum_glasses.py index e13d4b071..5459683c9 100644 --- a/tests/test_quantum_glasses.py +++ b/tests/test_quantum_glasses.py @@ -6,8 +6,12 @@ class TestQuantumGlasses(unittest.TestCase): def test_main(self): + my_qglases = QuantumGlasses() + if os.getenv('DISPLAY') is None: matplotlib.use('Agg') + os.environ.__setitem__('DISPLAY', ':0.0') + with self.assertRaises(Exception): + self.assertEqual(my_qglases.main(testing=True), False) - my_qglases = QuantumGlasses() self.assertEqual(my_qglases.main(testing=True), True) From cbe792fa1d69b5229d4ab02b7557382337a19139 Mon Sep 17 00:00:00 2001 From: Mica Date: Fri, 18 Aug 2023 20:48:05 +0200 Subject: [PATCH 09/13] raise exception --- quantum_glasses/quantum_glasses.py | 5 ++--- requirements.txt | 1 - tests/test_quantum_glasses.py | 6 ++---- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/quantum_glasses/quantum_glasses.py b/quantum_glasses/quantum_glasses.py index 1657ac915..17d53818e 100644 --- a/quantum_glasses/quantum_glasses.py +++ b/quantum_glasses/quantum_glasses.py @@ -303,6 +303,5 @@ def clear(circuit): root.mainloop() return True - except Exception as e: - print(f"Exception occured: {e}") - return False + except Exception as get_exception: + raise Exception from get_exception diff --git a/requirements.txt b/requirements.txt index 7b18d3103..c7a7dbbbf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,3 @@ qiskit>=0.44.1 qiskit[visualization]>=0.44.1 tox==4.9.0 pytest==7.4.0 -matplotlib==3.7.2 diff --git a/tests/test_quantum_glasses.py b/tests/test_quantum_glasses.py index 5459683c9..86a6aa091 100644 --- a/tests/test_quantum_glasses.py +++ b/tests/test_quantum_glasses.py @@ -1,17 +1,15 @@ from quantum_glasses import QuantumGlasses -import matplotlib import unittest import os class TestQuantumGlasses(unittest.TestCase): def test_main(self): + """Global test.""" my_qglases = QuantumGlasses() if os.getenv('DISPLAY') is None: - matplotlib.use('Agg') - os.environ.__setitem__('DISPLAY', ':0.0') with self.assertRaises(Exception): - self.assertEqual(my_qglases.main(testing=True), False) + my_qglases.main(testing=True) self.assertEqual(my_qglases.main(testing=True), True) From d93a43757c519f131b03455e6fd2d25ee608cc6c Mon Sep 17 00:00:00 2001 From: Mica Date: Fri, 18 Aug 2023 20:51:48 +0200 Subject: [PATCH 10/13] raise exception --- tests/test_quantum_glasses.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_quantum_glasses.py b/tests/test_quantum_glasses.py index 86a6aa091..6f2e28d56 100644 --- a/tests/test_quantum_glasses.py +++ b/tests/test_quantum_glasses.py @@ -9,6 +9,7 @@ def test_main(self): my_qglases = QuantumGlasses() if os.getenv('DISPLAY') is None: + os.environ.__setitem__('DISPLAY', ':0.0') with self.assertRaises(Exception): my_qglases.main(testing=True) From 2d51acf19a4502a4731e1365b20321c58a25a873 Mon Sep 17 00:00:00 2001 From: Mica Date: Fri, 18 Aug 2023 20:55:09 +0200 Subject: [PATCH 11/13] raise exception --- tests/test_quantum_glasses.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_quantum_glasses.py b/tests/test_quantum_glasses.py index 6f2e28d56..fd2f53167 100644 --- a/tests/test_quantum_glasses.py +++ b/tests/test_quantum_glasses.py @@ -12,5 +12,5 @@ def test_main(self): os.environ.__setitem__('DISPLAY', ':0.0') with self.assertRaises(Exception): my_qglases.main(testing=True) - - self.assertEqual(my_qglases.main(testing=True), True) + else: + self.assertEqual(my_qglases.main(testing=True), True) From 2c808ec970c155f077e5b0c39ccd5359a83c2561 Mon Sep 17 00:00:00 2001 From: Mica Date: Fri, 18 Aug 2023 21:00:24 +0200 Subject: [PATCH 12/13] clean --- __pycache__/quantum_glasses.cpython-310.pyc | Bin 9985 -> 0 bytes __pycache__/quantum_glasses.cpython-39.pyc | Bin 10209 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 __pycache__/quantum_glasses.cpython-310.pyc delete mode 100644 __pycache__/quantum_glasses.cpython-39.pyc diff --git a/__pycache__/quantum_glasses.cpython-310.pyc b/__pycache__/quantum_glasses.cpython-310.pyc deleted file mode 100644 index 7c8ab3110618e73d6a3cbd753444619f9f8ba1f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9985 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 A1^@s6 diff --git a/__pycache__/quantum_glasses.cpython-39.pyc b/__pycache__/quantum_glasses.cpython-39.pyc deleted file mode 100644 index 5bcaa126fd851875064369388b761bd84692dc4e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10209 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 Q-Y6U^Tqq0{S_S?80j;w$)c^nh From dfcf0d08a24dd20ffb0cfe1d9d61a9186f6ba9c5 Mon Sep 17 00:00:00 2001 From: Mica Date: Fri, 18 Aug 2023 21:13:25 +0200 Subject: [PATCH 13/13] update doc --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4dc0e7e7a..6eb07681b 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,16 @@ Built using: Python, Tkinter, Qiskit ### Launch -To launch just run : -```python +To launch the app just run : +```bash python quantum_glasses.py ``` +To launch unittests just run : +```bash +tox -epy39 +``` + How the Visualizer looks?