Skip to content

Commit

Permalink
Array assignment create new quantum register without removing the ano…
Browse files Browse the repository at this point in the history
…nymous ones

Closes #86
  • Loading branch information
GabrieleMessina authored Sep 21, 2024
1 parent 2695031 commit 6a2c638
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 31 deletions.
2 changes: 1 addition & 1 deletion src/grammar_frontend/expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def visitArrayAccessExpression(self, ctx:qutes_parser.ArrayAccessExpressionConte
array_symbol:Symbol = self.visit(ctx.expr(0))
index_symbol:Symbol = self.visit(ctx.expr(1))

array_value = self.variables_handler.get_value(array_symbol)
array_value = self.variables_handler.get_value(array_symbol).array
index_value = self.variables_handler.get_value(index_symbol)

value = array_value[index_value]
Expand Down
2 changes: 1 addition & 1 deletion src/grammar_frontend/statement.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def __visit_assignment_statement(self, var_name : str | Symbol, var_value, ctx:(
var_symbol = self.variables_handler.get_variable_symbol(var_name, ctx.start.tokenIndex)

if(isinstance(var_value, list)):
var_value = QuantumArrayType(QutesDataType.get_unit_class_from_array_type(QutesDataType.type_of(var_value)), [symbol.value for symbol in var_value])
var_value = QuantumArrayType(QutesDataType.get_unit_class_from_array_type(QutesDataType.type_of(var_value)), [symbol for symbol in var_value])

if(var_value == None):
var_value = QutesDataType.get_default_value(var_symbol.symbol_declaration_static_type)
Expand Down
34 changes: 20 additions & 14 deletions src/quantum_circuit/quantum_circuit_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,6 @@ def declare_classical_register(self, variable_name : str, bits_number : int) ->
self._classic_registers.append(new_register)
return new_register

def delete_variable(self, variable_name : str) -> None:
register = self._varname_to_register[variable_name]
if(register not in self._varname_to_register.values()):
self._classic_registers.remove(register)

def declare_quantum_register(self, variable_name : str, quantum_variable : Qubit|Quint|Qustring|QuantumArrayType) -> QuantumRegister:
new_register = None
new_register = QuantumRegister(quantum_variable.size, variable_name)
Expand All @@ -50,7 +45,8 @@ def declare_quantum_register(self, variable_name : str, quantum_variable : Qubit

self._varname_to_register[variable_name] = new_register
self._quantum_registers.append(new_register)
self._registers_states[new_register] = quantum_variable.qubit_state
if not isinstance(quantum_variable, QuantumArrayType):
self._registers_states[new_register] = quantum_variable.qubit_state
return new_register

# TODO: this should be a correlation operation, or a measure and then update,
Expand All @@ -60,13 +56,23 @@ def create_and_assign_quantum_register(self, variable_name : str, quantum_varia
if(register_to_update is None):
raise SystemError("Error trying to update an undeclared quantum register")

quantum_register = QuantumRegister(quantum_variable.size, variable_name)

if(QutesDataType.is_quantum_type(QutesDataType.type_of(quantum_variable))):
#TODO-CRITICAL: this update actually change the reference, so all the old references around the code are still there. For now i hack this returning the new value and changing the name from update to replace.
if(isinstance(quantum_variable, QuantumArrayType)):
bits = []
quantum_registers:list[QuantumRegister] = [symbol.quantum_register for symbol in quantum_variable.array]
for index, reg in enumerate(quantum_registers):
reg._name = f"{variable_name}_{index}"
bits.extend(reg)
quantum_register = QuantumRegister(None, variable_name, bits=bits)
#Add new quantum register
register_to_update = self.assign_quantum_register_to_variable(variable_name, QuantumRegister(quantum_variable.size, variable_name))
#this update actually change the reference, so all the old references around the code are still there. For now i hack this returning the new value.
register_to_update = self.assign_quantum_register_to_variable(variable_name, quantum_register)
if register_to_update not in self._quantum_registers:
self._quantum_registers.append(register_to_update)
self._registers_states[register_to_update] = quantum_variable.qubit_state
if not isinstance(quantum_variable, QuantumArrayType):
self._registers_states[register_to_update] = quantum_variable.qubit_state
self.__cleanup_orphan_registers()
else:
raise SystemError("Error trying to update a quantum register with an unsupported type")
Expand All @@ -78,7 +84,6 @@ def assign_quantum_register_to_variable(self, variable_name : str, quantum_regi
if(register_to_update is None):
raise SystemError("Error trying to update an undeclared quantum register")

#TODO-CRITICAL(pasted from above, i don't know if this applies here too): this update actually change the reference, so all the old references around the code are still there. For now i hack this returning the new value and changing the name from update to replace.
if(register_to_update != quantum_register):
self._varname_to_register[variable_name] = quantum_register
self.__cleanup_orphan_registers()
Expand Down Expand Up @@ -116,10 +121,11 @@ def create_circuit(self, *regs, do_initialization:bool = True) -> QuantumCircuit

for register in self._quantum_registers:
if(do_initialization):
if(isinstance(self._registers_states[register], Gate)):
circuit.compose(self._registers_states[register], register, inplace=True)
else:
raise SystemError("Error trying to initialize a quantum register with an unsupported type")
if register in self._registers_states:
if(isinstance(self._registers_states[register], Gate)):
circuit.compose(self._registers_states[register], register, inplace=True)
else:
raise SystemError("Error trying to initialize a quantum register with an unsupported type")
for operation in self._current_operation_stack:
operation(circuit)
return circuit
Expand Down
12 changes: 3 additions & 9 deletions src/symbols/types/quantum_array_type.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
from typing import TypeVar
from symbols.types import QuantumType
from symbols.types.qubit import Qubit
from quantum_circuit.state_preparation import StatePreparation

T = TypeVar("T")

class QuantumArrayType(QuantumType[T]):
def __init__(self, unit_type: QuantumType[T], array:list[QuantumType]): #array is a list of Symbol
super().__init__(unit_type, sum([a.size for a in array]))
def __init__(self, unit_type: QuantumType[T], array:list['Symbol']):
super().__init__(unit_type, sum([a.value.size for a in array]))
self.unit_type = unit_type
self.array = array
self.size = sum([a.size for a in array])
state_preparation = str()
array_elements_state_preparation = [a.qubit_state._params_arg for a in array]
for element in array_elements_state_preparation:
state_preparation = state_preparation + element
self.qubit_state = StatePreparation(state_preparation)
self.size = sum([a.value.size for a in array])

def get_default_value():
return QuantumArrayType(Qubit, [Qubit.get_default_value()])
Expand Down
6 changes: 3 additions & 3 deletions src/symbols/types/qutes_data_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,11 @@ def get_default_value(var_type : 'QutesDataType'):
case QutesDataType.string_array:
return []
case QutesDataType.qubit_array:
return QuantumArrayType(Qubit, [Qubit()])
return QuantumArrayType(Qubit, [])
case QutesDataType.quint_array:
return QuantumArrayType(Quint, [Quint()])
return QuantumArrayType(Quint, [])
case QutesDataType.qustring_array:
return QuantumArrayType(Qustring, [Qustring()])
return QuantumArrayType(Qustring, [])
case QutesDataType.void:
return None
case _:
Expand Down
6 changes: 3 additions & 3 deletions src/symbols/variables_handler.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from uuid import uuid4
from symbols.types.type_casting_handler import TypeCastingHandler
from symbols.types.qutes_data_type import QutesDataType
from symbols.types.qutes_data_type import QutesDataType, QuantumArrayType
from symbols.scope_handler import ScopeHandler
from symbols.symbol import Symbol, SymbolClass
from quantum_circuit import QuantumCircuitHandler
Expand All @@ -15,7 +15,7 @@ def __init__(self, scope_handler : ScopeHandler, quantum_cirtcuit_handler : Quan
def update_variable_state(self, variable_name : str, new_state) -> Symbol:
eligible_symbols_to_update = [symbol for symbol in self.scope_handler.current_symbols_scope.symbols if symbol.name == variable_name]
if len(eligible_symbols_to_update) > 0:
# In case multiple scopes declare a varialble with the same name we take the last one, that is the one from the nearest scope.
# In case multiple scopes declare a variable with the same name we take the last one, that is the one from the nearest scope.
symbol_index_in_scope = self.scope_handler.current_symbols_scope.symbols.index(eligible_symbols_to_update[-1])
symbol_to_update = self.scope_handler.current_symbols_scope.symbols[symbol_index_in_scope]

Expand Down Expand Up @@ -52,7 +52,7 @@ def update_variable_state(self, variable_name : str, new_state) -> Symbol:
if(new_state.is_anonymous):
symbol_to_update.quantum_register = self.quantum_cirtcuit_handler.create_and_assign_quantum_register(variable_name, value_to_assign)
if(new_state.is_quantum()):
self.quantum_cirtcuit_handler.delete_variable(new_state.name)
self.quantum_cirtcuit_handler.remove_quantum_register(new_state.quantum_register)
else:
pass #being classic it was not added to circuit handler and there is no need to delete it.
else:
Expand Down

0 comments on commit 6a2c638

Please sign in to comment.