Skip to content

Commit

Permalink
Merge pull request #28 from Jij-Inc/hotfix/num_occurrences
Browse files Browse the repository at this point in the history
Fixing the issue where num_occurences cannot be set at decoding
  • Loading branch information
yuyamashiro authored Nov 22, 2023
2 parents 933f161 + 0a9563b commit bb87a6c
Show file tree
Hide file tree
Showing 20 changed files with 2,139 additions and 1,378 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from __future__ import annotations
from collections.abc import Callable

import itertools
import typing as typ
from collections.abc import Callable

import numpy as np
import qiskit as qk
import qiskit.quantum_info as qk_info
Expand Down Expand Up @@ -36,7 +38,8 @@ def define_pauli_op(
one_op = qk_info.SparsePauliOp(
qk_info.PauliList.from_symplectic(z, x), coeffs=[1 / 2, -1 / 2]
)
identity_op = qk_info.SparsePauliOp(qk_info.Pauli([0], [0]))

identity_op = qk_info.SparsePauliOp(qk_info.Pauli(([0], [0])))

ancilla_operator = one_op if ancilla else identity_op

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
from __future__ import annotations

import typing as typ
from collections.abc import Callable, Sequence

import jijmodeling as jm
import jijmodeling_transpiler as jmt
import numpy as np
import qiskit as qk
import qiskit.quantum_info as qk_info
from qiskit.primitives import Estimator
import jijmodeling as jm
import jijmodeling_transpiler as jmt
from .cost_function import (
initialize_cost_function,
define_pauli_op,
)

from .cost_function import define_pauli_op, initialize_cost_function


class MinimalEncodingBuilder:
Expand Down Expand Up @@ -203,5 +203,15 @@ def _decode_from_binary_values(
self.minimal_encoding_builder.compiled_instance,
)
)
# decoded.record.num_occurrences = [[1]] * len(binary_results)

num_occurrences = [1] * len(binary_results)
decoded = jm.SampleSet(
record=jm.Record(
num_occurrences=num_occurrences,
solution=decoded.record.solution,
),
evaluation=decoded.evaluation,
measuring_time=decoded.measuring_time,
metadata=decoded.metadata,
)
return decoded
30 changes: 23 additions & 7 deletions jijmodeling_transpiler_quantum/qiskit/qaoa/to_qaoa.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
from __future__ import annotations

import typing as typ
import qiskit as qk
import qiskit.quantum_info as qk_info

import jijmodeling as jm
import jijmodeling_transpiler as jmt
import qiskit as qk
import qiskit.quantum_info as qk_info

from jijmodeling_transpiler_quantum.core import qubo_to_ising

from .ising_hamiltonian import to_ising_operator_from_qubo


Expand Down Expand Up @@ -33,7 +37,9 @@ def get_hamiltonian(
qubo, constant = self.pubo_builder.get_qubo_dict(
multipliers=multipliers, detail_parameters=detail_parameters
)
ising_operator, ising_const = to_ising_operator_from_qubo(qubo, self.num_vars)
ising_operator, ising_const = to_ising_operator_from_qubo(
qubo, self.num_vars
)
return ising_operator, ising_const + constant

def get_qaoa_ansatz(
Expand All @@ -52,19 +58,27 @@ def get_qaoa_ansatz(

def decode_from_counts(self, counts: dict[str, int]) -> jm.SampleSet:
samples = []
num_occurances = []
num_occurrences = []
for binary_str, count_num in counts.items():
binary_values = {idx: int(b) for idx, b in enumerate(binary_str)}
samples.append(binary_values)
num_occurances.append(count_num)
num_occurrences.append(count_num)

binary_encoder = self.pubo_builder.binary_encoder
decoded: jm.SampleSet = (
jmt.core.pubo.binary_decode.decode_from_dict_binary_result(
samples, binary_encoder, self.compiled_instance
)
)
decoded.record.num_occurrences = num_occurances
decoded = jm.SampleSet(
record=jm.Record(
num_occurrences=num_occurrences,
solution=decoded.record.solution,
),
evaluation=decoded.evaluation,
measuring_time=decoded.measuring_time,
metadata=decoded.metadata,
)
return decoded

def decode_from_quasi_dist(
Expand All @@ -81,7 +95,9 @@ def decode_from_quasi_dist(
else:
shots = 30000

binary_counts = {key: int(prob * shots) for key, prob in binary_prob.items()}
binary_counts = {
key: int(prob * shots) for key, prob in binary_prob.items()
}

return self.decode_from_counts(binary_counts)

Expand Down
12 changes: 11 additions & 1 deletion jijmodeling_transpiler_quantum/qiskit/qrao/to_qrac.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,17 @@ def decode_from_binary_values(
binary_results, binary_encoder, self.compiled_instance
)
)
decoded.record.num_occurrences = [[1]] * len(binary_results)

num_occurrences = [1] * len(binary_results)
decoded = jm.SampleSet(
record=jm.Record(
num_occurrences=num_occurrences,
solution=decoded.record.solution,
),
evaluation=decoded.evaluation,
measuring_time=decoded.measuring_time,
metadata=decoded.metadata,
)
return decoded


Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from __future__ import annotations

import numpy as np
from quri_parts.core.operator import PAULI_IDENTITY, Operator, pauli_label

from jijmodeling_transpiler_quantum.core import qubo_to_ising
from quri_parts.core.operator import pauli_label, PAULI_IDENTITY, Operator


def to_ising_operator_from_qubo(
Expand Down
64 changes: 45 additions & 19 deletions jijmodeling_transpiler_quantum/quri_parts/qaoa/to_qaoa.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
from __future__ import annotations

from math import pi

import jijmodeling as jm
import jijmodeling_transpiler as jmt
from jijmodeling_transpiler_quantum.core import qubo_to_ising
from .ising_hamiltonian import to_ising_operator_from_qubo
import numpy as np
from quri_parts.circuit import LinearMappedUnboundParametricQuantumCircuit
from quri_parts.core.operator import Operator
from math import pi

from .ising_hamiltonian import to_ising_operator_from_qubo


class QAOAAnsatzBuilder:
Expand Down Expand Up @@ -47,15 +50,17 @@ def get_hamiltonian(
qubo, constant = self.pubo_builder.get_qubo_dict(
multipliers=multipliers, detail_parameters=detail_parameters
)
ising_operator, ising_const = to_ising_operator_from_qubo(qubo, self.num_vars)
ising_operator, ising_const = to_ising_operator_from_qubo(
qubo, self.num_vars
)
return ising_operator, ising_const + constant

def get_qaoa_ansatz(
self,
p: int,
multipliers: dict = None,
detail_parameters: dict = None,
) -> tuple[UnboundParametricQuantumCircuit, operator, float]:
) -> tuple[LinearMappedUnboundParametricQuantumCircuit, Operator, float]:
"""Get the QAOA ansatz.
Args:
Expand All @@ -64,7 +69,7 @@ def get_qaoa_ansatz(
detail_parameters (dict, optional): Detailed parameters for the Ising Hamiltonian. Defaults to None.
Returns:
tuple[UnboundParametricQuantumCircuit, operator, float]: The QAOA ansatz, the Ising operator, and the constant offset.
tuple[LinearMappedUnboundParametricQuantumCircuit, Operator, float]: The QAOA ansatz, the Ising operator, and the constant offset.
"""
ising_operator, constant = self.get_hamiltonian(
multipliers=multipliers, detail_parameters=detail_parameters
Expand All @@ -73,12 +78,15 @@ def get_qaoa_ansatz(
keys = list(ising_operator.keys())
items = list(ising_operator.items())
num_terms = ising_operator.n_terms - 1
pauli_terms = [keys[i].index_and_pauli_id_list[0] for i in range(num_terms)]
pauli_terms = [
keys[i].index_and_pauli_id_list[0] for i in range(num_terms)
]
coeff_terms = [items[i][1] for i in range(num_terms)]
QAOAAnsatz = LinearMappedUnboundParametricQuantumCircuit(self.num_vars)
pauli_z_terms = pauli_terms[: self.num_vars]
pauli_zz_terms = [
sorted(sublist, reverse=True) for sublist in pauli_terms[self.num_vars :]
sorted(sublist, reverse=True)
for sublist in pauli_terms[self.num_vars :]
]

for term in pauli_z_terms:
Expand All @@ -88,7 +96,9 @@ def get_qaoa_ansatz(
Gamma = QAOAAnsatz.add_parameters(f"gamma{p_level}")
Beta = QAOAAnsatz.add_parameters(f"beta{p_level}")

for pauli_z_info, coeff in zip(pauli_z_terms, coeff_terms[: self.num_vars]):
for pauli_z_info, coeff in zip(
pauli_z_terms, coeff_terms[: self.num_vars]
):
QAOAAnsatz.add_ParametricRZ_gate(
pauli_z_info[0], {Gamma[-1]: 2 * coeff}
)
Expand All @@ -97,11 +107,15 @@ def get_qaoa_ansatz(
pauli_zz_terms, coeff_terms[self.num_vars :]
):
QAOAAnsatz.add_ParametricPauliRotation_gate(
pauli_zz_info, pauli_ids=(3, 3), angle={Gamma[-1]: 2 * coeff}
pauli_zz_info,
pauli_ids=(3, 3),
angle={Gamma[-1]: 2 * coeff},
)

for pauli_z_info in pauli_z_terms:
QAOAAnsatz.add_ParametricRX_gate(pauli_z_info[0], {Beta[-1]: 2})
QAOAAnsatz.add_ParametricRX_gate(
pauli_z_info[0], {Beta[-1]: 2}
)

return QAOAAnsatz, ising_operator, constant

Expand All @@ -115,19 +129,27 @@ def decode_from_counts(self, counts: dict[str, int]) -> jm.SampleSet:
jm.SampleSet: The decoded sample set.
"""
samples = []
num_occurances = []
num_occurrences = []
for binary_str, count_num in counts.items():
binary_values = {idx: int(b) for idx, b in enumerate(binary_str)}
samples.append(binary_values)
num_occurances.append(count_num)
num_occurrences.append(count_num)

binary_encoder = self.pubo_builder.binary_encoder
decoded: jm.SampleSet = (
jmt.core.pubo.binary_decode.decode_from_dict_binary_result(
samples, binary_encoder, self.compiled_instance
)
)
decoded.record.num_occurrences = num_occurances
decoded = jm.SampleSet(
record=jm.Record(
num_occurrences=num_occurrences,
solution=decoded.record.solution,
),
evaluation=decoded.evaluation,
measuring_time=decoded.measuring_time,
metadata=decoded.metadata,
)
return decoded

def decode_from_probs(self, probs: np.array) -> jm.SampleSet:
Expand All @@ -140,8 +162,12 @@ def decode_from_probs(self, probs: np.array) -> jm.SampleSet:
jm.SampleSet: The decoded sample set.
"""
shots = 10000
z_basis = [format(i, "b").zfill(self.num_vars) for i in range(len(probs))]
binary_counts = {i: int(value * shots) for i, value in zip(z_basis, probs)}
z_basis = [
format(i, "b").zfill(self.num_vars) for i in range(len(probs))
]
binary_counts = {
i: int(value * shots) for i, value in zip(z_basis, probs)
}

return self.decode_from_counts(binary_counts)

Expand All @@ -150,7 +176,7 @@ def transpile_to_qaoa_ansatz(
compiled_instance: jmt.core.CompiledInstance,
normalize: bool = True,
relax_method=jmt.core.pubo.RelaxationMethod.AugmentedLagrangian,
) -> quriQAOAAnsatzBuilder:
) -> QAOAAnsatzBuilder:
"""Transpile to a QAOA ansatz builder.
Args:
Expand All @@ -159,10 +185,10 @@ def transpile_to_qaoa_ansatz(
relax_method (jmt.core.pubo.RelaxationMethod, optional): The relaxation method to be used. Defaults to AugmentedLagrangian.
Returns:
quriQAOAAnsatzBuilder: The QAOA ansatz builder.
QAOAAnsatzBuilder: The QAOA ansatz builder.
"""
pubo_builder = jmt.core.pubo.transpile_to_pubo(
compiled_instance, normalize=True, relax_method=relax_method
compiled_instance, normalize=normalize, relax_method=relax_method
)
var_num = compiled_instance.var_map.var_num
return QAOAAnsatzBuilder(pubo_builder, var_num, compiled_instance)
9 changes: 7 additions & 2 deletions jijmodeling_transpiler_quantum/quri_parts/qrao/qrao21.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from __future__ import annotations

import numpy as np
from quri_parts.core.operator import PAULI_IDENTITY, Operator, pauli_label

from jijmodeling_transpiler_quantum.core.ising_qubo import IsingModel

from .qrao31 import Pauli, color_group_to_qrac_encode, create_pauli_term
from quri_parts.core.operator import pauli_label, PAULI_IDENTITY, Operator


def qrac21_encode_ising(
Expand Down Expand Up @@ -33,7 +36,9 @@ def qrac21_encode_ising(

color, pauli_kind = encoded_ope[idx]
pauli_str = create_pauli_term([pauli_kind], [color], n_qubit)
pauli_terms.append(Operator({pauli_label(pauli_str): np.sqrt(2) * coeff}))
pauli_terms.append(
Operator({pauli_label(pauli_str): np.sqrt(2) * coeff})
)

for (i, j), coeff in ising.quad.items():
if coeff == 0.0:
Expand Down
13 changes: 10 additions & 3 deletions jijmodeling_transpiler_quantum/quri_parts/qrao/qrao31.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from __future__ import annotations

import enum

import numpy as np
from quri_parts.core.operator import PAULI_IDENTITY, Operator, pauli_label

from jijmodeling_transpiler_quantum.core.ising_qubo import IsingModel
from quri_parts.core.operator import pauli_label, PAULI_IDENTITY, Operator


class Pauli(enum.Enum):
Expand Down Expand Up @@ -36,7 +39,9 @@ def color_group_to_qrac_encode(
return qrac31


def create_pauli_term(operators: list[Pauli], indices: list[int], n_qubit: int) -> str:
def create_pauli_term(
operators: list[Pauli], indices: list[int], n_qubit: int
) -> str:
"""Create a Pauli term string given a list of operators and indices.
Args:
Expand Down Expand Up @@ -85,7 +90,9 @@ def qrac31_encode_ising(
color, pauli_kind = encoded_ope[idx]
pauli_operator = create_pauli_term([pauli_kind], [color], n_qubit)

pauli_terms.append(Operator({pauli_label(pauli_operator): np.sqrt(3) * coeff}))
pauli_terms.append(
Operator({pauli_label(pauli_operator): np.sqrt(3) * coeff})
)

for (i, j), coeff in ising.quad.items():
if coeff == 0.0:
Expand Down
Loading

0 comments on commit bb87a6c

Please sign in to comment.