Skip to content

Commit

Permalink
Merge pull request #76 from Zhaoyilunnn/master
Browse files Browse the repository at this point in the history
Merge stable/0.3 into master
  • Loading branch information
chensgit169 authored Sep 6, 2023
2 parents fb76253 + f5c814f commit 3a1ef2c
Show file tree
Hide file tree
Showing 9 changed files with 375 additions and 54 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ thirdparty
MANIFEST.in
*.pyd
dev_*.py
*temp.*
62 changes: 58 additions & 4 deletions quafu/algorithms/hamiltonian.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,73 @@
from __future__ import annotations

from collections.abc import Iterable
import numpy as np
from quafu.exceptions import QuafuError


PAULI_MAT = {
"I": np.array([[1, 0], [0, 1]], dtype=complex),
"X": np.array([[0, 1], [1, 0]], dtype=complex),
"Y": np.array([[0, -1j], [1j, 0]], dtype=complex),
"Z": np.array([[1, 0], [0, -1]], dtype=complex)
}


class Hamiltonian:
"""TODO"""

def __init__(self) -> None:
pass
def __init__(self, pauli_str_list: list[str], coeffs: np.ndarray) -> None:
"""
Args:
pauli_str_list: List of Pauli strs, e.g., ['IIIZZ', "IIZIZ", ...]
coeffs: List of efficients
"""
self._pauli_str_list = pauli_str_list
self._coeffs = coeffs

@staticmethod
def from_pauli_list(pauli: Iterable[tuple[str, complex]]) -> Hamiltonian:
def from_pauli_list(pauli_list: Iterable[tuple[str, complex]]) -> Hamiltonian:
"""
Args:
pauli: The supported format of pauli list is [(<pauli-str>, <coefficient>)],
e.g., [('IIIZZ', 1), ("IIZIZ", 1), ...)], 0th qubit is farthest right
"""
return Hamiltonian()

pauli_list = list(pauli_list)

size = len(pauli_list)
if size == 0:
raise QuafuError("Pauli list cannot be empty.")

num_qubits = len(pauli_list[0][0])
coeffs = np.zeros(size, dtype=complex)

pauli_str_list = []
for i, (pauli_str, coef) in enumerate(pauli_list):
pauli_str_list.append(pauli_str)
coeffs[i] = coef

return Hamiltonian(pauli_str_list, coeffs)

def _get_pauli_mat(self, pauli_str: str):
"""Calculate the matrix of a pauli string"""
mat = None
for p in pauli_str[::-1]:
mat = PAULI_MAT[p] if mat is None else np.kron(PAULI_MAT[p], mat)
return mat

def matrix_generator(self):
"""Generating matrix for each Pauli str"""
for i, p in enumerate(self._pauli_str_list):
yield self._coeffs[i] * self._get_pauli_mat(p)

def get_matrix(self):
"""Generate matrix of Hamiltonian"""

mat = None
for m in self.matrix_generator():
if mat is None:
mat = m
continue
mat += m
return mat
6 changes: 5 additions & 1 deletion quafu/circuits/quantum_circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -557,13 +557,14 @@ def ct(self, ctrl: int, tar: int) -> "QuantumCircuit":
self.add_gate(qeg.CTGate(ctrl, tar))
return self

def cp(self, ctrl: int, tar: int, para) -> "QuantumCircuit":
def cp(self, ctrl: int, tar: int, para: float) -> "QuantumCircuit":
"""
Control-P gate.
Args:
ctrl (int): control qubit.
tar (int): target qubit.
para: theta
"""
self.add_gate(qeg.CPGate(ctrl, tar, para))
return self
Expand Down Expand Up @@ -733,6 +734,9 @@ def measure(self, pos: List[int] = None, cbits: List[int] = None) -> None:
if pos is None:
pos = list(range(self.num))

if np.any(np.array(pos) >= self.num):
raise ValueError("Index out of range.")

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)):
Expand Down
33 changes: 14 additions & 19 deletions quafu/results/results.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,21 @@ class ExecResult(Result):
transpiled_circuit (QuantumCircuit): Quantum circuit transpiled on backend.
"""

def __init__(self, input_dict, measures):
status_map = {
0: "In Queue",
1: "Running",
2: "Completed",
"Canceled": 3,
4: "Failed",
}
self.measures = measures
def __init__(self, input_dict):
status_map = {0: "In Queue", 1: "Running", 2: "Completed", "Canceled": 3, 4: "Failed"}
self.taskid = input_dict['task_id']
self.taskname = input_dict['task_name']
self.transpiled_openqasm = input_dict["openqasm"]
from ..circuits.quantum_circuit import QuantumCircuit
self.transpiled_circuit = QuantumCircuit(0)
self.transpiled_circuit.from_openqasm(self.transpiled_openqasm)
self.measure_base = []

self.measures = self.transpiled_circuit.measures
self.task_status = status_map[input_dict["status"]]
self.res = eval(input_dict["res"])
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))}
Expand All @@ -42,18 +45,10 @@ def __init__(self, input_dict, measures):
newkey = "".join([key[i] for i in squeezed_cbits])
self.logicalq_res[newkey] = values

self.taskid = input_dict["task_id"]
self.taskname = input_dict["task_name"]
self.transpiled_openqasm = input_dict["openqasm"]
from ..circuits.quantum_circuit import QuantumCircuit

self.transpiled_circuit = QuantumCircuit(0)
self.transpiled_circuit.from_openqasm(self.transpiled_openqasm)
self.measure_base = []
total_counts = sum(self.counts.values())
self.probabilities = {}
for key in self.counts:
self.probabilities[key] = self.counts[key] / total_counts
for bit_str in self.counts:
self.probabilities[bit_str] = self.counts[bit_str] / total_counts

def calculate_obs(self, pos):
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class QuafuTaskDatabase:
- Usage:
Use this class by 'with' statement. For example:
>>> with QuafuTaskDatabase(db_dir='./') as db:
... db.insert_task(1, "Done", "Group 1", "Task1", priority=2)
... db.insert_task(1, "Done", group_name="Group 1", task_name="Task1", priority=2)
... print("Task list:")
... for task_info in db.find_all_tasks():
... print_task_info(task_info)
Expand Down Expand Up @@ -86,7 +86,7 @@ def _create_table(self):
def insert_task(self,
task_id,
status,
send_time: str,
send_time: str = None,
priority=2,
group_name=None,
task_name=None,
Expand Down
42 changes: 18 additions & 24 deletions quafu/tasks/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,9 @@ def submit(

return exec_res, measure_results

def run(self, qc: QuantumCircuit, measure_base: List = None) -> ExecResult:
def run(self,
qc: QuantumCircuit,
measure_base: List = None) -> ExecResult:
"""Single run for measurement task.
Args:
Expand All @@ -181,13 +183,13 @@ def run(self, qc: QuantumCircuit, measure_base: List = None) -> ExecResult:

return res

def send(
self,
qc: QuantumCircuit,
name: str = "",
group: str = "",
wait: bool = True,
) -> ExecResult:
def send(self,
qc: QuantumCircuit,
name: str = "",
group: str = "",
wait: bool = True,
verbose: bool = False,
) -> ExecResult:
"""
Run the circuit on experimental device.
Expand All @@ -196,6 +198,7 @@ def send(
name: Task name.
group: The task belong which group.
wait: Whether wait until the execution return.
verbose:
Returns:
ExecResult object that contain the dict return from quantum device.
"""
Expand Down Expand Up @@ -269,7 +272,7 @@ def send(
else:
self.submit_history[group].append(task_id)

return ExecResult(res_dict, qc.measures)
return ExecResult(res_dict)

def retrieve(self, taskid: str) -> ExecResult:
"""
Expand All @@ -281,25 +284,16 @@ def retrieve(self, taskid: str) -> ExecResult:
data = {"task_id": taskid}
url = User.url + User.exec_recall_api

headers = {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
"api_token": self.user.api_token,
}
headers = {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 'api_token': self.user.api_token}
response = requests.post(url, headers=headers, data=data)

res_dict = response.json()
measures = eval(res_dict["measure"])
if measures is None:
raise Exception(
"Measure info returned is None. This may be the error under repairing."
" See https://github.com/ScQ-Cloud/pyquafu/issues/50"
)

return ExecResult(res_dict, measures)
return ExecResult(res_dict)

def retrieve_group(
self, group: str, history: Dict = None, verbose: bool = True
) -> List[ExecResult]:
def retrieve_group(self,
group: str,
history: Dict = None,
verbose: bool = True) -> List[ExecResult]:
"""
Retrieve the results of submited task by group name.
Expand Down
2 changes: 1 addition & 1 deletion quafu/visualisation/circuitPlot.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@

su2_gate_names = ['x', 'y', 'z', 'id', 'w',
'h', 't', 'tdg', 's', 'sdg', 'sx', 'sy', 'sw',
'phase',
'p',
'rx', 'ry', 'rz',
]

Expand Down
2 changes: 1 addition & 1 deletion tests/quafu/algorithms/estimator_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"task_id": "30EE7D5035E7CE02",
"task_name": "",
}
TEST_EXE_RES = ExecResult(MOCK_RES_DICT, {0: 0, 1: 1, 2: 2, 3: 3, 4: 4})
TEST_EXE_RES = ExecResult(MOCK_RES_DICT)


class TestEstimator:
Expand Down
Loading

0 comments on commit 3a1ef2c

Please sign in to comment.