Skip to content

Commit

Permalink
Merge pull request #205 from BQSKit/more-small-updates
Browse files Browse the repository at this point in the history
More small updates
  • Loading branch information
edyounis authored Nov 29, 2023
2 parents 839e0e3 + b9ba3b4 commit 2b305df
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 6 deletions.
9 changes: 8 additions & 1 deletion bqskit/ir/gates/composed/embedded.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ class EmbeddedGate(ComposedGate, DifferentiableUnitary):
This concept can be generalized to multiple qudits and even
mixed-radix systems.
Note:
- Global phase inconsistencies in gates will become local phase
inconsistencies in the embedded gate. For example, if the
global phase difference between the U1Gate and the RZGate
will become local phase differences in the corresponding
subspaces when embedded into a higher-dimensional qudit.
"""

def __init__(
Expand Down Expand Up @@ -201,7 +208,7 @@ def __init__(
self.gate = gate
self.level_maps = tuple([tuple(list(lmap)) for lmap in level_maps])
self._num_qudits = gate._num_qudits
self._name = 'Embedded(%s)' % self.gate.name # TODO: include radixes and level maps # noqa: E501
self._name = f'Embedded({self.gate.name}){self.level_maps}'
self._num_params = self.gate._num_params
self._radixes = tuple(radixes)
self._dim = int(np.prod(self.radixes))
Expand Down
4 changes: 2 additions & 2 deletions bqskit/ir/gates/parameterized/rz.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ class RZGate(QubitGate, DifferentiableUnitary, CachedClass):
.. math::
\\begin{pmatrix}
\\exp({i\\frac{\\theta}{2}}) & 0 \\\\
0 & \\exp({-i\\frac{\\theta}{2}}) \\\\
\\exp({-i\\frac{\\theta}{2}}) & 0 \\\\
0 & \\exp({i\\frac{\\theta}{2}}) \\\\
\\end{pmatrix}
"""

Expand Down
54 changes: 51 additions & 3 deletions bqskit/ir/opt/instantiaters/minimization.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@
from bqskit.ir.opt.instantiater import Instantiater
from bqskit.ir.opt.minimizer import Minimizer
from bqskit.ir.opt.minimizers.ceres import CeresMinimizer
from bqskit.ir.opt.multistartgens.random import RandomStartGenerator
from bqskit.qis.state.state import StateLike
from bqskit.qis.state.state import StateVector
from bqskit.qis.state.system import StateSystem
from bqskit.qis.unitary.unitarymatrix import UnitaryMatrix

if TYPE_CHECKING:
from bqskit.ir.circuit import Circuit
from bqskit.qis.state.system import StateSystem
from bqskit.qis.state.system import StateSystemLike
from bqskit.qis.unitary.unitarymatrix import UnitaryLike
from bqskit.qis.unitary.unitarymatrix import UnitaryMatrix


class Minimization(Instantiater):
Expand Down Expand Up @@ -61,7 +65,6 @@ def instantiate(
) -> npt.NDArray[np.float64]:
"""Instantiate `circuit`, see Instantiater for more info."""
cost = self.cost_fn_gen.gen_cost(circuit, target)
# print(x0, circuit.num_params, circuit.gate_counts)
return self.minimizer.minimize(cost, x0)

@staticmethod
Expand All @@ -88,3 +91,48 @@ def get_violation_report(circuit: Circuit) -> str:
def get_method_name() -> str:
"""Return the name of this method."""
return 'minimization'

def multi_start_instantiate_inplace(
self,
circuit: Circuit,
target: UnitaryLike | StateLike | StateSystemLike,
num_starts: int,
) -> None:
"""
Instantiate `circuit` to best implement `target` with multiple starts.
See Instantiater for more info.
"""
target = self.check_target(target)
start_gen = RandomStartGenerator()
starts = start_gen.gen_starting_points(num_starts, circuit, target)
cost_fn = self.cost_fn_gen.gen_cost(circuit, target)
params_list = [self.instantiate(circuit, target, x0) for x0 in starts]
params = sorted(params_list, key=lambda x: cost_fn(x))[0]
circuit.set_params(params)

async def multi_start_instantiate_async(
self,
circuit: Circuit,
target: UnitaryLike | StateLike | StateSystemLike,
num_starts: int,
) -> Circuit:
"""
Instantiate `circuit` to best implement `target` with multiple starts.
See Instantiater for more info.
"""
from bqskit.runtime import get_runtime
target = self.check_target(target)
start_gen = RandomStartGenerator()
starts = start_gen.gen_starting_points(num_starts, circuit, target)
cost_fn = self.cost_fn_gen.gen_cost(circuit, target)
params_list = await get_runtime().map(
self.instantiate,
[circuit] * num_starts,
[target] * num_starts,
starts,
)
params = sorted(params_list, key=lambda x: cost_fn(x))[0]
circuit.set_params(params)
return circuit
13 changes: 13 additions & 0 deletions bqskit/qis/unitary/unitarymatrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,19 @@ def dagger(self) -> UnitaryMatrix:
"""The conjugate transpose of the unitary."""
return self.conj().T

def to_special(self) -> UnitaryMatrix:
"""Return a special unitary matrix verson of this one."""
determinant = np.linalg.det(self)
dimension = len(self)
global_phase = np.angle(determinant) / dimension
global_phase = global_phase % (2 * np.pi / dimension)
global_phase_factor = np.exp(-1j * global_phase)
return global_phase_factor * self

def is_special(self) -> bool:
"""Return true if this unitary is special."""
return 1 - np.abs(np.linalg.det(self)) < 1e-8

def __len__(self) -> int:
"""The dimension of the square unitary matrix."""
return self.shape[0]
Expand Down

0 comments on commit 2b305df

Please sign in to comment.