Skip to content

Commit

Permalink
Merge pull request #98 from eclipse-qrisp/ladder_op_measurement
Browse files Browse the repository at this point in the history
Ladder op measurement
  • Loading branch information
positr0nium authored Nov 12, 2024
2 parents 60fbff1 + 0a3a0dd commit 0c30633
Show file tree
Hide file tree
Showing 32 changed files with 739 additions and 291 deletions.
12 changes: 4 additions & 8 deletions documentation/source/reference/Hamiltonians/QubitOperator.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,11 @@ Methods
.. autosummary::
:toctree: generated/

QubitOperator.__add__
QubitOperator.__sub__
QubitOperator.__mul__
QubitOperator.__iadd__
QubitOperator.__isub__
QubitOperator.__imul__
QubitOperator.__str__
QubitOperator.ground_state_energy
QubitOperator.get_measurement
QubitOperator.commuting_groups
QubitOperator.commuting_qw_groups
QubitOperator.trotterization
QubitOperator.trotterization
QubitOperator.to_pauli
QubitOperator.adjoint
QubitOperator.hermitize

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
qrisp.operators.qubit.QubitOperator.adjoint
===========================================

.. currentmodule:: qrisp.operators.qubit

.. automethod:: QubitOperator.adjoint
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
qrisp.operators.qubit.QubitOperator.hermitize
=============================================

.. currentmodule:: qrisp.operators.qubit

.. automethod:: QubitOperator.hermitize
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
qrisp.operators.qubit.QubitOperator.to\_pauli
=============================================

.. currentmodule:: qrisp.operators.qubit

.. automethod:: QubitOperator.to_pauli
46 changes: 23 additions & 23 deletions src/qrisp/alg_primitives/logic_synthesis/truth_tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,25 +339,25 @@ def rw_spectrum(f):
return np.dot(T(n), f)


def C(f):
size = len(f)
# def C(f):
# size = len(f)

if np.log2(size) != int(np.log2(size)):
raise Exception(
"The given function does not have the length to properly represent "
"a truth table"
)
# if np.log2(size) != int(np.log2(size)):
# raise Exception(
# "The given function does not have the length to properly represent "
# "a truth table"
# )

n = int(np.log2(size))
# n = int(np.log2(size))

rw_spec = rw_spectrum(f)
sum_ = 0
for i in range(size):
sum_ += sum(int_as_array(i, n)) * rw_spec[i] ** 2
# rw_spec = rw_spectrum(f)
# sum_ = 0
# for i in range(size):
# sum_ += sum(int_as_array(i, n)) * rw_spec[i] ** 2

sum_ = sum_ / 2 ** (n - 2)
# sum_ = sum_ / 2 ** (n - 2)

return 1 / 2 * (n * size - sum_)
# return 1 / 2 * (n * size - sum_)


def NZ(f):
Expand All @@ -370,17 +370,17 @@ def NZ(f):
return sum_


def D(f):
size = len(f)
if np.log2(size) != int(np.log2(size)):
raise Exception(
"The given function does not have the length to properly represent "
"a truth table"
)
# def D(f):
# size = len(f)
# if np.log2(size) != int(np.log2(size)):
# raise Exception(
# "The given function does not have the length to properly represent "
# "a truth table"
# )

n = int(np.log2(size))
# n = int(np.log2(size))

return int(n * 2 ** (n - 3) * NZ(f) + C(f))
# return int(n * 2 ** (n - 3) * NZ(f) + C(f))


def synth_poly(truth_table, column=0, coeff=None):
Expand Down
23 changes: 7 additions & 16 deletions src/qrisp/algorithms/vqe/vqe_problem.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def compile_circuit(self, qarg, depth):

return compiled_qc, theta

def optimization_routine(self, qarg, depth, mes_kwargs, measurement, max_iter, init_type="random", init_point=None, optimizer="COBYLA"):
def optimization_routine(self, qarg, depth, mes_kwargs, max_iter, init_type="random", init_point=None, optimizer="COBYLA"):
"""
Wrapper subroutine for the optimization method used in QAOA. The initial values are set and the optimization via ``COBYLA`` is conducted here.
Expand All @@ -184,8 +184,6 @@ def optimization_routine(self, qarg, depth, mes_kwargs, measurement, max_iter, i
The amont of VQE layers.
mes_kwargs : dict
The keyword arguments for the measurement function.
measurement : PauliMeasurement
The measurement setttings for the measurement function.
max_iter : int
The maximum number of iterations for the optimization method.
init_type : string, optional
Expand All @@ -204,7 +202,7 @@ def optimization_routine(self, qarg, depth, mes_kwargs, measurement, max_iter, i
"""

# Define optimization wrapper function to be minimized using VQE
def optimization_wrapper(theta, qc, symbols, qarg, mes_kwargs, measurement):
def optimization_wrapper(theta, qc, symbols, qarg, mes_kwargs):
"""
Wrapper function for the optimization method used in VQE.
Expand All @@ -222,8 +220,6 @@ def optimization_wrapper(theta, qc, symbols, qarg, mes_kwargs, measurement):
The duplicated quantum variable to which the quantum circuit is applied.
mes_kwargs : dict
The keyword arguments for the measurement function.
measurement : PauliMeasurement
The measurement setttings for the measurement function.
Returns
-------
Expand All @@ -233,7 +229,7 @@ def optimization_wrapper(theta, qc, symbols, qarg, mes_kwargs, measurement):

subs_dic = {symbols[i] : theta[i] for i in range(len(symbols))}

expectation = self.hamiltonian.get_measurement(qarg, subs_dic = subs_dic, precompiled_qc = qc, _measurement=measurement, **mes_kwargs)
expectation = self.hamiltonian.get_measurement(qarg, subs_dic = subs_dic, precompiled_qc = qc, **mes_kwargs)

if self.callback:
self.optimization_costs.append(expectation)
Expand All @@ -257,7 +253,7 @@ def optimization_wrapper(theta, qc, symbols, qarg, mes_kwargs, measurement):
init_point,
method=optimizer,
options={'maxiter':max_iter},
args = (compiled_qc, symbols, qarg, mes_kwargs, measurement))
args = (compiled_qc, symbols, qarg, mes_kwargs))

return res_sample['x']

Expand Down Expand Up @@ -301,10 +297,8 @@ def run(self, qarg, depth, mes_kwargs = {}, max_iter = 50, init_type = "random",
if not "precision" in mes_kwargs:
mes_kwargs["precision"] = 0.01

# Measurement settings
measurement = self.hamiltonian.pauli_measurement()

optimal_theta = self.optimization_routine(qarg, depth, mes_kwargs, measurement, max_iter, init_type, init_point, optimizer)
optimal_theta = self.optimization_routine(qarg, depth, mes_kwargs, max_iter, init_type, init_point, optimizer)

# Prepare the initial state for particular problem instance, the default is the \ket{0} state
if self.init_function is not None:
Expand All @@ -314,7 +308,7 @@ def run(self, qarg, depth, mes_kwargs = {}, max_iter = 50, init_type = "random",
for i in range(depth):
self.ansatz_function(qarg,[optimal_theta[self.num_params*i+j] for j in range(self.num_params)])

opt_res = self.hamiltonian.get_measurement(qarg,_measurement=measurement,**mes_kwargs)
opt_res = self.hamiltonian.get_measurement(qarg,**mes_kwargs)

return opt_res

Expand Down Expand Up @@ -356,10 +350,7 @@ def train_function(self, qarg, depth, mes_kwargs = {}, max_iter = 50, init_type
if not "precision" in mes_kwargs:
mes_kwargs["precision"] = 0.01

# Measurement settings
measurement = self.hamiltonian.pauli_measurement()

optimal_theta = self.optimization_routine(qarg, depth, mes_kwargs, measurement, max_iter, init_type, init_point, optimizer)
optimal_theta = self.optimization_routine(qarg, depth, mes_kwargs, max_iter, init_type, init_point, optimizer)

def circuit_generator(qarg_gen):
# Prepare the initial state for particular problem instance, the default is the \ket{0} state
Expand Down
2 changes: 1 addition & 1 deletion src/qrisp/operators/qubit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@

from qrisp.operators.qubit.operator_factors import *
from qrisp.operators.qubit.bound_qubit_operator import *
from qrisp.operators.qubit.pauli_measurement import *
#from qrisp.operators.qubit.pauli_measurement import *
from qrisp.operators.qubit.operator_factors import *
47 changes: 36 additions & 11 deletions src/qrisp/operators/qubit/bound_qubit_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
"""
from qrisp.operators.hamiltonian import Hamiltonian
from qrisp.operators.qubit.bound_qubit_term import BoundQubitTerm
from qrisp.operators.qubit.pauli_measurement import PauliMeasurement
from qrisp.operators.qubit.measurement import get_measurement
from qrisp import h, sx, IterationEnvironment, conjugate, merge

Expand Down Expand Up @@ -644,20 +643,46 @@ def get_measurement(
#Yields 1.0
"""
return get_measurement(self,
qarg,
precision=precision,
backend=backend,
shots=shots,
compile=compile,
compilation_kwargs=compilation_kwargs,
subs_dic=subs_dic,
precompiled_qc=precompiled_qc,
_measurement=_measurement)

unbound_operator, qarg = self.unbind()

return unbound_operator.get_measurement(qarg,
precision=precision,
backend=backend,
shots=shots,
compile=compile,
compilation_kwargs=compilation_kwargs,
subs_dic=subs_dic,
precompiled_qc=precompiled_qc,
_measurement=_measurement)

def unbind(self):
from qrisp.operators import QubitTerm, QubitOperator

participating_qubits = []
for term, coeff in self.terms_dict.items():
for qb in term.factor_dict.keys():
if qb not in participating_qubits:
participating_qubits.append(qb)

index_inv = {participating_qubits[i] : i for i in range(len(participating_qubits))}

unbound_operator = 0

for term, coeff in self.terms_dict.items():
new_term_factor_dict = {}
for qb, factor in term.factor_dict.items():
new_term_factor_dict[index_inv[qb]] = factor

unbound_operator += QubitOperator({QubitTerm(new_term_factor_dict): coeff})

return unbound_operator, participating_qubits


#
# Trotterization
#


def trotterization(self):
r"""
Expand Down
4 changes: 1 addition & 3 deletions src/qrisp/operators/qubit/bound_qubit_term.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,4 @@ def commute_qw(self, other):
for key in keys:
if a.get(key,"I")!="I" and b.get(key,"I")!="I" and a.get(key,"I")!=b.get(key,"I"):
return False
return True


return True
Loading

0 comments on commit 0c30633

Please sign in to comment.