Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stable/0.3 #55

Merged
merged 11 commits into from
Aug 16, 2023
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

setup(
name="pyquafu",
version="0.3.3",
version="0.3.5",
author="ssli",
author_email="[email protected]",
url="https://github.com/ScQ-Cloud/pyquafu",
Expand Down
2 changes: 1 addition & 1 deletion src/quafu/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@


def get_version():
return "0.3.3"
return "0.3.5"
20 changes: 17 additions & 3 deletions src/quafu/backends/backends.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
# (C) Copyright 2023 Beijing Academy of Quantum Information Sciences
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import requests
import json
import re
Expand All @@ -18,9 +32,9 @@ def __init__(self, backend_info: dict):
self.qv = backend_info["QV"]
# self.task_in_queue = backend_info["task_in_queue"]

def get_chip_info(self, user=User()):
# update api-token, a patch to be deleted in the future
api_token = user._load_account_token()
def get_chip_info(self, user: User = None):
user = User() if user is None else user
api_token = user.api_token
data = {"system_name": self.name.lower()}
headers = {"api_token": api_token}
chip_info = requests.post(url=User.chip_api, data=data,
Expand Down
71 changes: 51 additions & 20 deletions src/quafu/circuits/quantum_circuit.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,37 @@
# (C) Copyright 2023 Beijing Academy of Quantum Information Sciences
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import List

import numpy as np

import quafu.elements.element_gates.clifford
import quafu.elements.element_gates.pauli
from quafu.elements.quantum_element.pulses.quantum_pulse import QuantumPulse
from ..elements.quantum_element import Barrier, Delay, MultiQubitGate, QuantumGate, ControlledGate, \
SingleQubitGate, XYResonance
import quafu.elements.element_gates as qeg
from quafu.elements.quantum_element.pulses.quantum_pulse import QuantumPulse
from ..elements.quantum_element import (
Barrier,
Delay,
MultiQubitGate,
QuantumGate,
ControlledGate,
SingleQubitGate,
XYResonance,
)
from ..exceptions import CircuitError


class QuantumCircuit(object):
def __init__(self, num: int):
def __init__(self, num: int, *args, **kwargs):
"""
Initialize a QuantumCircuit object

Expand Down Expand Up @@ -356,7 +376,7 @@ def h(self, pos: int) -> "QuantumCircuit":
Args:
pos (int): qubit the gate act.
"""
gate = quafu.elements.element_gates.clifford.HGate(pos)
gate = qeg.HGate(pos)
self.add_gate(gate)
return self

Expand Down Expand Up @@ -399,7 +419,7 @@ def t(self, pos: int) -> "QuantumCircuit":
Args:
pos (int): qubit the gate act.
"""
self.add_gate(quafu.elements.element_gates.clifford.TGate(pos))
self.add_gate(qeg.TGate(pos))
return self

def tdg(self, pos: int) -> "QuantumCircuit":
Expand All @@ -409,7 +429,7 @@ def tdg(self, pos: int) -> "QuantumCircuit":
Args:
pos (int): qubit the gate act.
"""
self.add_gate(quafu.elements.element_gates.clifford.TdgGate(pos))
self.add_gate(qeg.TdgGate(pos))
return self

def s(self, pos: int) -> "QuantumCircuit":
Expand All @@ -419,7 +439,7 @@ def s(self, pos: int) -> "QuantumCircuit":
Args:
pos (int): qubit the gate act.
"""
self.add_gate(quafu.elements.element_gates.clifford.SGate(pos))
self.add_gate(qeg.SGate(pos))
return self

def sdg(self, pos: int) -> "QuantumCircuit":
Expand All @@ -429,7 +449,7 @@ def sdg(self, pos: int) -> "QuantumCircuit":
Args:
pos (int): qubit the gate act.
"""
self.add_gate(quafu.elements.element_gates.clifford.SdgGate(pos))
self.add_gate(qeg.SdgGate(pos))
return self

def sx(self, pos: int) -> "QuantumCircuit":
Expand All @@ -439,7 +459,7 @@ def sx(self, pos: int) -> "QuantumCircuit":
Args:
pos (int): qubit the gate act.
"""
self.add_gate(quafu.elements.element_gates.pauli.SXGate(pos))
self.add_gate(qeg.SXGate(pos))
return self

def sxdg(self, pos: int) -> "QuantumCircuit":
Expand All @@ -449,7 +469,7 @@ def sxdg(self, pos: int) -> "QuantumCircuit":
Args:
pos (int): qubit the gate act.
"""
gate = quafu.elements.element_gates.pauli.SXdgGate(pos)
gate = qeg.SXdgGate(pos)
self.add_gate(gate)
return self

Expand All @@ -460,7 +480,7 @@ def sy(self, pos: int) -> "QuantumCircuit":
Args:
pos (int): qubit the gate act.
"""
self.add_gate(quafu.elements.element_gates.pauli.SYGate(pos))
self.add_gate(qeg.SYGate(pos))
return self

def sydg(self, pos: int) -> "QuantumCircuit":
Expand All @@ -470,7 +490,7 @@ def sydg(self, pos: int) -> "QuantumCircuit":
Args:
pos (int): qubit the gate act.
"""
gate = quafu.elements.element_gates.pauli.SYdgGate(pos)
gate = qeg.SYdgGate(pos)
self.add_gate(gate)
return self

Expand Down Expand Up @@ -771,16 +791,27 @@ def measure(self, pos: List[int] = None, cbits: List[int] = None) -> None:
if pos is None:
pos = list(range(self.num))

e_num = len(self.measures) # existing num of measures
n_num = len(pos) # newly added num of measures
if not set(self.measures.keys()).isdisjoint(set(pos)):
raise ValueError("Measured qubits overlap with existing measurements.")

if n_num > len(set(pos)):
raise ValueError("Measured qubits not uniquely assigned.")

if cbits:
if not len(cbits) == len(pos):
raise CircuitError("Number of measured bits should equal to the number of classical bits")
if not len(set(cbits)) == len(cbits):
raise ValueError("Classical bits not uniquely assigned.")
if not len(cbits) == n_num:
raise ValueError("Number of measured bits should equal to the number of classical bits")
else:
cbits = pos
cbits = list(range(e_num, e_num + n_num))

_sorted_indices = sorted(range(n_num), key=lambda k: cbits[k])
cbits = [_sorted_indices.index(i) + e_num for i in range(n_num)]

newly_measures = dict(zip(pos, cbits))
self.measures = {**self.measures, **newly_measures}
if not len(self.measures.values()) == len(set(self.measures.values())):
raise ValueError("Measured bits not uniquely assigned.")

def add_pulse(self,
pulse: QuantumPulse,
Expand Down
14 changes: 8 additions & 6 deletions src/quafu/results/results.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ class Result(object):


class ExecResult(Result):
"""
"""
Class that save the execute results returned from backend.

Attributes:
counts (dict): Samples counts on each bitstring.
probabilities (dict): Calculated probabilities on each bitstring.
Expand All @@ -29,8 +29,10 @@ def __init__(self, input_dict, measures):
self.counts = OrderedDict(sorted(self.res.items(), key=lambda s: s[0]))
self.logicalq_res = {}
cbits = list(self.measures.values())
indexed_cbits = {bit: i for i, bit in enumerate(sorted(cbits))}
squeezed_cbits = [indexed_cbits[bit] for bit in cbits]
for key, values in self.counts.items():
newkey = "".join([key[i] for i in cbits])
newkey = "".join([key[i] for i in squeezed_cbits])
self.logicalq_res[newkey] = values

self.taskid = input_dict['task_id']
Expand All @@ -49,7 +51,7 @@ def calculate_obs(self, pos):
"""
Calculate observables Z on input position using probabilities

Args:
Args:
pos (list[int]): Positions of observalbes.
"""
return measure_obs(pos, self.logicalq_res)
Expand Down Expand Up @@ -89,11 +91,11 @@ def __init__(self, input, input_form):
def plot_probabilities(self, full: bool = False, reverse_basis: bool = False, sort: bool = None):
"""
Plot the probabilities from simulated results, ordered in big endian convention.

Args:
full: Whether plot on the full basis of measured qubits.
reverse_basis: Whether reverse the bitstring of basis. (Little endian convention).
sort: Sort the results by probabilities values. Can be `"ascend"` order or `"descend"` order.
sort: Sort the results by probabilities values. Can be `"ascend"` order or `"descend"` order.
"""

probs = self.probabilities
Expand Down
Loading