Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Development #28

Merged
merged 10 commits into from
Mar 10, 2024
10 changes: 6 additions & 4 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ name: Python application

on:
push:
branches: [ "main", "development" ]
branches: [ "main" ]
pull_request:
branches: [ "main", "development" ]
branches: [ "main" ]

permissions:
contents: read
Expand All @@ -24,9 +24,11 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
pip install pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Test with pytest
run: |
pytest
cd src
python -m pytest tests/
# python -m unittest discover -s ./test -p 'test*.py'
# python -m unittest tests.grammar_test
1 change: 1 addition & 0 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Qutes Lang
A **High Level programming language** for **quantum computing** that allows **everyone**, even those who do not know the theory behind quantum computing in detail, **to exploit its potential** and adapt it to their field of interest.

[![Python application](https://github.com/GabrieleMessina/qutes_lang/actions/workflows/python-app.yml/badge.svg)](https://github.com/GabrieleMessina/qutes_lang/actions/workflows/python-app.yml)
## How to Run - 🧭 Easy Start
> [!TIP]
> You can use a GitHub Codespace to start work with Qutes quickly.
Expand Down
12 changes: 11 additions & 1 deletion qutes.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,17 @@
"cSpell.words": [
"Antlr"
],
"pylint.importStrategy": "fromEnvironment"
"pylint.importStrategy": "fromEnvironment",
"python.testing.unittestArgs": [
"-v",
"-s",
"./src",
"-p",
"test*.py"
],
"python.testing.pytestEnabled": false,
"python.testing.unittestEnabled": true,
"python.testing.autoTestDiscoverOnSaveEnabled": true,
},
"extensions": {
"recommendations": [
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ antlr4-python3-runtime==4.13.0
qiskit<1.0
qiskit-aer
anytree
matplotlib
matplotlib
parameterized
2 changes: 2 additions & 0 deletions specification/grammar/qutes_lexer.g4
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ fragment
BOOL_LITERAL
: TRUE
| FALSE
| '1'
| '0'
;

INT_LITERAL
Expand Down
5 changes: 5 additions & 0 deletions src/grammar_frontend/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Aliasing for easy importing through the code
from grammar_frontend.qutes_lexer import QutesLexer
from grammar_frontend.qutes_parser import QutesParser
from grammar_frontend.qutes_grammar_visitor import QutesGrammarVisitor
from grammar_frontend.symbols_discovery_visitor import SymbolsDiscoveryVisitor
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""An antlr visitor for the qutes grammar."""

from qutes_parser import QutesParser as qutesParser
from grammar_frontend.qutes_parser import QutesParser as qutesParser
from qutes_antlr.qutes_parserVisitor import qutes_parserVisitor as qutesVisitor
from symbols.scope_tree_node import ScopeTreeNode
from symbols.symbol import Symbol, SymbolClass
Expand All @@ -15,19 +15,19 @@
class QutesGrammarVisitor(qutesVisitor):
"""An antlr visitor for the qutes grammar."""

def __init__(self, symbols_tree:ScopeTreeNode, quantum_cirtcuit_handler : QuantumCircuitHandler):
def __init__(self, symbols_tree:ScopeTreeNode, quantum_circuit_handler : QuantumCircuitHandler, scope_handler:ScopeHandlerForSymbolsUpdate, variables_handler:VariablesHandler):
if not symbols_tree:
raise ValueError("A symbols tree must be provided to the QutesGrammarVisitor.")
self.symbols_tree = symbols_tree
self.quantum_cirtcuit_handler = quantum_cirtcuit_handler
self.quantum_circuit_handler = quantum_circuit_handler
#We need to travers the symbols_tree going orderly like in a breadth first search
#Every time we need to create a new scope, we visit instead the next node in the tree
#And every time we need to close a scope, we return to the parent of the current node
#This way we know, at each moment, what symbols are defined.
self.scope_handler = ScopeHandlerForSymbolsUpdate(self.symbols_tree)
self.variables_handler = VariablesHandler(self.scope_handler, self.quantum_cirtcuit_handler)
self.scope_handler = scope_handler
self.variables_handler = variables_handler

self.qutes_gates = QutesGates(self.quantum_cirtcuit_handler, self.variables_handler)
self.qutes_gates = QutesGates(self.quantum_circuit_handler, self.variables_handler)

# Debug flags
self.allow_program_print = True
Expand Down Expand Up @@ -343,7 +343,7 @@ def __visit_test(self, ctx:qutesParser.TestContext):
if (first_term_symbol and QutesDataType.is_quantum_type(first_term_symbol.symbol_declaration_static_type)
and second_term_symbol and not QutesDataType.is_quantum_type(second_term_symbol.symbol_declaration_static_type)):
# At the moment this only works for comparing quantum variables to classical values.
result = self.quantum_cirtcuit_handler.push_equals_operation(first_term_symbol.quantum_register, second_term_symbol.value)
result = self.quantum_circuit_handler.push_equals_operation(first_term_symbol.quantum_register, second_term_symbol.value)
else:
result = first_term == second_term
elif(ctx.GREATEREQUAL()):
Expand All @@ -369,7 +369,7 @@ def __visitMultipleUnaryOperator(self, ctx:qutesParser.MultipleUnaryOperatorCont
if(ctx.MCZ()):
terms:list[Symbol] = self.visit(ctx.termList())
registers = [register.quantum_register for register in terms]
self.quantum_cirtcuit_handler.push_MCZ_operation(registers)
self.quantum_circuit_handler.push_MCZ_operation(registers)

# Visit a parse tree produced by qutes_parser#termList.
def visitTermList(self, ctx:qutesParser.TermListContext):
Expand All @@ -395,21 +395,21 @@ def __visitGroverOperator(self, ctx:qutesParser.GroverExprContext):
return
if(ctx.IN_STATEMENT()):
array_register = target_symbol.quantum_register
self.quantum_cirtcuit_handler.start_quantum_function()
self.quantum_circuit_handler.start_quantum_function()
self.grover_count = self.grover_count+1
termList:list[Symbol] = self.visit(ctx.termList())
block_size = target_symbol.value.default_block_size
array_size = len(target_symbol.quantum_register)/block_size
logn = int(math.log2(array_size))

rotation_register = self.quantum_cirtcuit_handler.declare_quantum_register("rotation", Quint.init_from_integer(0,logn,True))
grover_result = self.quantum_cirtcuit_handler.declare_quantum_register("grover_phase_ancilla", Qubit())
rotation_register = self.quantum_circuit_handler.declare_quantum_register("rotation", Quint.init_from_integer(0,logn,True))
grover_result = self.quantum_circuit_handler.declare_quantum_register("grover_phase_ancilla", Qubit())

for term in termList:
if(not QutesDataType.is_array_type(target_symbol.casted_static_type)):
self.quantum_cirtcuit_handler.push_equals_operation(array_register, term.value)
self.quantum_cirtcuit_handler.push_MCX_operation([*array_register, *grover_result])
self.quantum_cirtcuit_handler.push_equals_operation(array_register, term.value)
self.quantum_circuit_handler.push_equals_operation(array_register, term.value)
self.quantum_circuit_handler.push_MCX_operation([*array_register, *grover_result])
self.quantum_circuit_handler.push_equals_operation(array_register, term.value)
else:
array_size = len(target_symbol.quantum_register)
word_size = QutesDataType.get_array_word_bit(target_symbol.casted_static_type)
Expand All @@ -418,20 +418,20 @@ def __visitGroverOperator(self, ctx:qutesParser.GroverExprContext):
index = 0
while index < array_size:
array_element = QuantumRegister(None, target_symbol.name + f"[{index}]", None, target_symbol.quantum_register[index:index+word_size])
self.quantum_cirtcuit_handler.push_equals_operation(array_element, term.value)
self.quantum_cirtcuit_handler.push_MCX_operation([*array_element, *grover_result])
self.quantum_cirtcuit_handler.push_equals_operation(array_element, term.value)
self.quantum_circuit_handler.push_equals_operation(array_element, term.value)
self.quantum_circuit_handler.push_MCX_operation([*array_element, *grover_result])
self.quantum_circuit_handler.push_equals_operation(array_element, term.value)
index += word_size
else:
self.quantum_cirtcuit_handler.push_ESM_operation(array_register, grover_result, rotation_register, term_to_quantum)
self.quantum_circuit_handler.push_ESM_operation(array_register, grover_result, rotation_register, term_to_quantum)

quantum_function = self.quantum_cirtcuit_handler.end_quantum_function(array_register, rotation_register, grover_result , gate_name=f"grover_oracle_{self.grover_count}", create_gate=False)
quantum_function = self.quantum_circuit_handler.end_quantum_function(array_register, rotation_register, grover_result , gate_name=f"grover_oracle_{self.grover_count}", create_gate=False)

oracle_result = self.quantum_cirtcuit_handler.declare_quantum_register("oracle_phase_ancilla", Qubit())
oracle_result = self.quantum_circuit_handler.declare_quantum_register("oracle_phase_ancilla", Qubit())

for n_results in range(1, int(array_size/2)):
self.quantum_cirtcuit_handler.push_grover_operation(quantum_function, array_register, grover_result, oracle_result, rotation_register, array_size, n_results)
results = self.quantum_cirtcuit_handler.get_run_and_measure_results([rotation_register, oracle_result], max_results=1)[0]
self.quantum_circuit_handler.push_grover_operation(quantum_function, array_register, grover_result, oracle_result, rotation_register, array_size, n_results)
results = self.quantum_circuit_handler.get_run_and_measure_results([rotation_register, oracle_result], max_results=1)[0]
results_strings = results[0].split(" ")
results_counts = results[1]
if (results_strings[0] == "1"):
Expand Down Expand Up @@ -466,10 +466,10 @@ def __visit_identity_operator(self, ctx:qutesParser.IdentityOperatorContext):
if(self.log_trace_enabled): print("visitTerm -> string")
if(ctx.MEASURE()):
if(self.log_trace_enabled): print("visitTerm -> measure")
self.quantum_cirtcuit_handler.push_measure_operation()
self.quantum_circuit_handler.push_measure_operation()
if(ctx.BARRIER()):
if(self.log_trace_enabled): print("visitTerm -> barrier")
self.quantum_cirtcuit_handler.push_barrier_operation()
self.quantum_circuit_handler.push_barrier_operation()
return result


Expand All @@ -495,7 +495,7 @@ def __visit_unary_operator(self, ctx:qutesParser.UnaryOperatorContext):
if(self.log_trace_enabled): print("visitUnaryOperator -> PRINT")
if(first_term_symbol):
if(QutesDataType.is_quantum_type(first_term_symbol.symbol_declaration_static_type)):
classical_register = self.quantum_cirtcuit_handler.run_and_measure([first_term_symbol.quantum_register])
classical_register = self.quantum_circuit_handler.run_and_measure([first_term_symbol.quantum_register])
bytes_str = [reg.measured_values[0] for reg in classical_register if first_term_symbol.quantum_register.name in reg.name][0]
if(first_term_symbol.symbol_declaration_static_type == QutesDataType.qustring):
index = 0
Expand All @@ -521,35 +521,35 @@ def __visit_unary_operator(self, ctx:qutesParser.UnaryOperatorContext):
if(self.log_code_structure): print(f"-{first_term_print}", end=None)
if(self.log_trace_enabled): print("visitUnaryOperator -> SUB")
if (first_term_symbol and QutesDataType.is_quantum_type(first_term_symbol.symbol_declaration_static_type)):
result = self.quantum_cirtcuit_handler.push_pauliz_operation(first_term_symbol.quantum_register)
result = self.quantum_circuit_handler.push_pauliz_operation(first_term_symbol.quantum_register)
result = -first_term
if(ctx.NOT()):
if(self.log_code_structure): print(f"NOT{first_term_print}", end=None)
if(self.log_trace_enabled): print("visitUnaryOperator -> NOT")
if (first_term_symbol and QutesDataType.is_quantum_type(first_term_symbol.symbol_declaration_static_type)):
result = self.quantum_cirtcuit_handler.push_not_operation(first_term_symbol.quantum_register)
result = self.quantum_circuit_handler.push_not_operation(first_term_symbol.quantum_register)
else:
result = not first_term
if(ctx.PAULIY()):
if(self.log_code_structure): print(f"NOT{first_term_print}", end=None)
if(self.log_trace_enabled): print("visitUnaryOperator -> NOT")
if (first_term_symbol and QutesDataType.is_quantum_type(first_term_symbol.symbol_declaration_static_type)):
result = self.quantum_cirtcuit_handler.push_pauliy_operation(first_term_symbol.quantum_register)
result = self.quantum_circuit_handler.push_pauliy_operation(first_term_symbol.quantum_register)
if(ctx.PAULIZ()):
if(self.log_code_structure): print(f"PAULIZ{first_term_print}", end=None)
if(self.log_trace_enabled): print("visitUnaryOperator -> PAULIZ")
if (first_term_symbol and QutesDataType.is_quantum_type(first_term_symbol.symbol_declaration_static_type)):
result = self.quantum_cirtcuit_handler.push_pauliz_operation(first_term_symbol.quantum_register)
result = self.quantum_circuit_handler.push_pauliz_operation(first_term_symbol.quantum_register)
if(ctx.HADAMARD()):
if(self.log_code_structure): print(f"HADAMARD{first_term_print}", end=None)
if(self.log_trace_enabled): print("visitUnaryOperator -> HADAMARD")
if (first_term_symbol and QutesDataType.is_quantum_type(first_term_symbol.symbol_declaration_static_type)):
result = self.quantum_cirtcuit_handler.push_hadamard_operation(first_term_symbol.quantum_register)
result = self.quantum_circuit_handler.push_hadamard_operation(first_term_symbol.quantum_register)
if(ctx.MEASURE()):
if(self.log_code_structure): print(f"MEASURE{first_term_print}", end=None)
if(self.log_trace_enabled): print("visitUnaryOperator -> MEASURE")
if (first_term_symbol and QutesDataType.is_quantum_type(first_term_symbol.symbol_declaration_static_type)):
result = self.quantum_cirtcuit_handler.push_measure_operation([first_term_symbol.quantum_register])
result = self.quantum_circuit_handler.push_measure_operation([first_term_symbol.quantum_register])
return result


Expand Down
File renamed without changes.
File renamed without changes.
31 changes: 16 additions & 15 deletions src/qutes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

import sys
import argparse
from antlr4 import FileStream, CommonTokenStream, ParseTreeWalker
from antlr4 import FileStream, CommonTokenStream
from anytree import RenderTree
from qutes_lexer import QutesLexer
from qutes_parser import QutesParser
from qutes_grammar_visitor import QutesGrammarVisitor
from symbols_discovery_visitor import SymbolsDiscoveryVisitor
from grammar_frontend.qutes_lexer import QutesLexer
from grammar_frontend.qutes_parser import QutesParser
from grammar_frontend.qutes_grammar_visitor import QutesGrammarVisitor
from grammar_frontend.symbols_discovery_visitor import SymbolsDiscoveryVisitor
from symbols.scope_handler import ScopeHandlerForSymbolsUpdate
from symbols.variables_handler import VariablesHandler
from quantum_circuit import QuantumCircuitHandler

def main(argv):
Expand All @@ -31,18 +33,17 @@ def main(argv):
if parser.getNumberOfSyntaxErrors() > 0:
print("syntax errors")
else:
quantum_cirtcuit_handler = QuantumCircuitHandler()
quantum_circuit_handler = QuantumCircuitHandler()

grammar_listener = SymbolsDiscoveryVisitor(quantum_cirtcuit_handler)
grammar_listener = SymbolsDiscoveryVisitor(quantum_circuit_handler)
grammar_listener.visit(tree)

# grammar_listener = SymbolsDiscoveryListener(quantum_cirtcuit_handler)
# walker = ParseTreeWalker()
# walker.walk(grammar_listener, tree)

symbols_tree = grammar_listener.scope_handler.symbols_tree

grammar_visitor = QutesGrammarVisitor(symbols_tree, quantum_cirtcuit_handler)
scope_handler = ScopeHandlerForSymbolsUpdate(symbols_tree)
variables_handler = VariablesHandler(scope_handler, quantum_circuit_handler)

grammar_visitor = QutesGrammarVisitor(symbols_tree, quantum_circuit_handler, scope_handler, variables_handler)
result = str(grammar_visitor.visit(tree))

print()
Expand All @@ -64,9 +65,9 @@ def main(argv):
if(log_quantum_circuit):
print()
print("----Quantum Circuit----")
circuit = quantum_cirtcuit_handler.create_circuit()
quantum_cirtcuit_handler.print_circuit(circuit)
quantum_cirtcuit_handler.run_circuit(circuit, number_of_iterations)
circuit = quantum_circuit_handler.create_circuit()
quantum_circuit_handler.print_circuit(circuit)
quantum_circuit_handler.run_circuit(circuit, number_of_iterations)

print()

Expand Down
Empty file added src/qutes_antlr/__init__.py
Empty file.
Loading
Loading