Skip to content

Commit

Permalink
Merge branch 'main' into zqs-1188-accelerate-qulacs-integratio
Browse files Browse the repository at this point in the history
  • Loading branch information
Athena Caesura authored Sep 28, 2022
2 parents 8a8b88c + 8b9ed8a commit 7784fa9
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 27 deletions.
10 changes: 3 additions & 7 deletions src/orquestra/quantum/distributions/target_thermal_states.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
from ..distributions import MeasurementOutcomeDistribution
from ..utils import (
bin2dec,
convert_tuples_to_bitstrings,
dec2bin,
sample_from_probability_distribution,
tuple_to_bitstring,
)


Expand Down Expand Up @@ -112,9 +112,7 @@ def get_thermal_target_measurement_outcome_distribution(
boltzmann_factor = np.exp(energy * beta)
partition_function += boltzmann_factor

binary_bitstring = convert_tuples_to_bitstrings(
[dec2bin(spin, n_spins)] # type: ignore
)[0]
binary_bitstring = tuple_to_bitstring(tuple(dec2bin(spin, n_spins)))
distribution[binary_bitstring] = boltzmann_factor

normalized_distribution: Dict[Union[str, Tuple[int, ...]], float] = {
Expand Down Expand Up @@ -155,9 +153,7 @@ def get_thermal_sampled_distribution(

sample_distribution_dict: Dict[Union[str, Tuple[int, ...]], float] = {}
for spin in range(int(2**n_spins)):
binary_bitstring = convert_tuples_to_bitstrings(
[dec2bin(spin, n_spins)] # type: ignore
)[0]
binary_bitstring = tuple_to_bitstring(tuple(dec2bin(spin, n_spins)))
sample_distribution_dict[binary_bitstring] = histogram_samples[spin]

return MeasurementOutcomeDistribution(sample_distribution_dict)
Expand Down
37 changes: 27 additions & 10 deletions src/orquestra/quantum/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import os
import sys
from contextlib import contextmanager
from functools import lru_cache
from typing import Any, Dict, Iterable, List, Optional, Tuple, Union

import numpy as np
Expand Down Expand Up @@ -215,16 +216,21 @@ def convert_bitstrings_to_tuples(bitstrings: Iterable[str]) -> List[Tuple[int, .
Returns:
A list of tuples
"""
# Convert from bitstrings to tuple format
measurements: List[Tuple[int, ...]] = []
for bitstring in bitstrings:
measurements = [bitstring_to_tuple(bitstring) for bitstring in bitstrings]
return measurements

measurement: Tuple[int, ...] = ()
for char in bitstring:
measurement = measurement + (int(char),)

measurements.append(measurement)
return measurements
@lru_cache()
def bitstring_to_tuple(bitstring: str) -> Tuple[int, ...]:
"""Given a bitstring, convert it to tuple format
Args:
bitstring (string): the measured bitstring
Returns:
A tuple of 0s and 1s
"""
measurement = tuple(int(bit) for bit in bitstring[::-1])
return measurement


def convert_tuples_to_bitstrings(tuples: List[Tuple[int]]) -> List[str]:
Expand All @@ -236,11 +242,22 @@ def convert_tuples_to_bitstrings(tuples: List[Tuple[int]]) -> List[str]:
Returns:
A list of bitstrings
"""
# Convert from tuples to bitstrings
bitstrings = ["".join(map(str, tup)) for tup in tuples]
bitstrings = [tuple_to_bitstring(tup) for tup in tuples]
return bitstrings


@lru_cache()
def tuple_to_bitstring(tup: Tuple[int, ...]) -> str:
"""Given a tuple, convert to an equivalent string.
Args:
tup (tuple): the measurement tuple
Returns:
A string with binary digits
"""
return "".join(map(str, tup))


class ValueEstimate(float):
"""A class representing a numerical value and its precision corresponding
to an observable or an objective function
Expand Down
15 changes: 10 additions & 5 deletions src/orquestra/quantum/wavefunction.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@
from sympy import Matrix, Symbol

from .typing import AnyPath, LoadSource, ParameterizedVector
from .utils import convert_array_to_dict, convert_dict_to_array, ensure_open
from .utils import (
convert_array_to_dict,
convert_bitstrings_to_tuples,
convert_dict_to_array,
ensure_open,
)


def _is_number(possible_number):
Expand Down Expand Up @@ -286,12 +291,12 @@ def sample_from_wavefunction(
]
# accelerate sampling by smartly choosing when formatting of samples is done
if len(wavefunction) < n_samples:
outcome_tuples: List[Union[Tuple[int, ...], int]]
outcome_tuples = [tuple(int(c) for c in s[::-1]) for s in outcome_strings]
outcome_tuples: List[Union[Tuple[int, ...], int]] = []
outcome_tuples += convert_bitstrings_to_tuples(outcome_strings)
outcome_tuples += [0] # adding non tuple forces rng.choice to return tuples
probabilities += [0] # need to add corresponding probability of 0
samples = rng.choice(a=outcome_tuples, size=n_samples, p=probabilities).tolist()
else:
samples_ndarray = rng.choice(a=outcome_strings, size=n_samples, p=probabilities)
samples = [tuple(int(y) for y in list(x)[::-1]) for x in list(samples_ndarray)]
string_samples = rng.choice(a=outcome_strings, size=n_samples, p=probabilities)
samples = convert_bitstrings_to_tuples(string_samples)
return samples
2 changes: 1 addition & 1 deletion tests/orquestra/quantum/utils_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ def test_scale_and_discretize(values, total, expected_result):
def test_ordered_bitstring(num_qubits):
bitstrings = get_ordered_list_of_bitstrings(num_qubits)
expected_bitstrings = convert_tuples_to_bitstrings(
[dec2bin(integer, num_qubits) for integer in range(2**num_qubits)]
[tuple(dec2bin(integer, num_qubits)) for integer in range(2**num_qubits)]
)
assert np.all(expected_bitstrings == bitstrings)
assert np.all([len(bitstring) == num_qubits for bitstring in bitstrings])
9 changes: 5 additions & 4 deletions tests/orquestra/quantum/wavefunction_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from orquestra.quantum.circuits._builtin_gates import RX, RY, U3, H, X
from orquestra.quantum.circuits._circuit import Circuit
from orquestra.quantum.testing import create_random_wavefunction
from orquestra.quantum.utils import RNDSEED, convert_bitstrings_to_tuples
from orquestra.quantum.utils import RNDSEED, bitstring_to_tuple
from orquestra.quantum.wavefunction import (
Wavefunction,
load_wavefunction,
Expand Down Expand Up @@ -316,17 +316,18 @@ def test_imag_wavefunction_io():

def test_sample_from_wavefunction():
wavefunction = create_random_wavefunction(4, seed=RNDSEED)
num_samples = 100000

samples = sample_from_wavefunction(wavefunction, 10000, seed=RNDSEED)
samples = sample_from_wavefunction(wavefunction, num_samples, seed=RNDSEED)
sampled_dict = Counter(samples)

sampled_probabilities = []
for num in range(len(wavefunction)):
bitstring = format(num, "b")
while len(bitstring) < wavefunction.n_qubits:
bitstring = "0" + bitstring
measurement = convert_bitstrings_to_tuples([bitstring])[0]
sampled_probabilities.append(sampled_dict[measurement] / 10000)
measurement = bitstring_to_tuple(bitstring)[::-1]
sampled_probabilities.append(sampled_dict[measurement] / num_samples)

probabilities = wavefunction.get_probabilities()
for sampled_prob, exact_prob in zip(sampled_probabilities, probabilities):
Expand Down

0 comments on commit 7784fa9

Please sign in to comment.