Skip to content

Commit

Permalink
Merge pull request #36 from chensgit169/master
Browse files Browse the repository at this point in the history
user guide doc is to be updated
  • Loading branch information
chensgit169 committed Jul 26, 2023
2 parents 85072b2 + 43295fb commit 48bb8e2
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 70 deletions.
9 changes: 4 additions & 5 deletions src/quafu/backends/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import networkx as nx
import numpy as np
import matplotlib.pyplot as plt

from quafu.users.userapi import User


Expand All @@ -18,11 +19,10 @@ def __init__(self, backend_info: dict):
# self.task_in_queue = backend_info["task_in_queue"]

def get_chip_info(self, user=User()):
api_token = user.apitoken
url = user._url
api_token = user.api_token
data = {"system_name": self.name.lower()}
headers = {"api_token": api_token}
chip_info = requests.post(url=url + user.chip_api, data=data,
chip_info = requests.post(url=User.chip_api, data=data,
headers=headers)
chip_info = json.loads(chip_info.text)
json_topo_struct = chip_info["topological_structure"]
Expand Down Expand Up @@ -62,7 +62,6 @@ def get_chip_info(self, user=User()):
weighted_edges.append([qubit1, qubit2, np.round(fidelity, 3)])

# draw topology

G = nx.Graph()
for key, value in int_to_qubit.items():
G.add_node(key, name=value)
Expand All @@ -84,7 +83,7 @@ def get_chip_info(self, user=User()):
, ax=ax)

nx.draw_networkx_labels(G, pos, font_size=14, font_family="sans-serif", ax=ax)
edge_labels = nx.get_edge_attributes(G, "weight")
# edge_labels = nx.get_edge_attributes(G, "weight")
nx.draw_networkx_edge_labels(G, pos, elarge_labels, font_size=12, font_color="green", ax=ax)
nx.draw_networkx_edge_labels(G, pos, esmall_labels, font_size=12, font_color="red", ax=ax)
fig.set_figwidth(14)
Expand Down
8 changes: 4 additions & 4 deletions src/quafu/tasks/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,11 @@ def send(self,
"pyquafu_version": version, "runtime_job_id": self.runtime_job_id}

if wait:
url = self.user._url + self.user.exec_api
url = User.exec_api
else:
url = self.user._url + self.user.exec_async_api
url = User.exec_async_api

headers = {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 'api_token': self.user.apitoken}
headers = {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 'api_token': self.user.api_token}
data = parse.urlencode(data)
data = data.replace("%27", "'")
res = requests.post(url, headers=headers, data=data)
Expand Down Expand Up @@ -227,7 +227,7 @@ def retrieve(self, taskid: str) -> ExecResult:
taskid: The taskid of the task need to be retrieved.
"""
data = {"task_id": taskid}
url = self.user._url + self.user.exec_recall_api
url = User.exec_recall_api

headers = {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 'api_token': self.token}
res = requests.post(url, headers=headers, data=data)
Expand Down
1 change: 1 addition & 0 deletions src/quafu/users/_quafu_url.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
QUAFU_URL = "https://quafu.baqis.ac.cn/"
13 changes: 13 additions & 0 deletions src/quafu/users/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
from ..exceptions import QuafuError


class UserError(QuafuError):
pass


class APITokenNotFound(UserError):
pass


class InvalidAPIToken(UserError):
pass


class BackendNotAvailable(UserError):
pass
115 changes: 64 additions & 51 deletions src/quafu/users/userapi.py
Original file line number Diff line number Diff line change
@@ -1,85 +1,98 @@
from ..utils.platform import get_homedir
import json
import os

import requests
import json
from urllib import parse

from .exceptions import UserError
from ..utils.platform import get_homedir


class User(object):
def __init__(self):
self.apitoken = ""
self._url = "http://quafu.baqis.ac.cn/"

if self.check_account_data():
self.load_account()

self.backends_api = "qbackend/get_backends/"
self.chip_api = "qbackend/scq_get_chip_info/"
self.exec_api = "qbackend/scq_kit/"
self.exec_async_api = "qbackend/scq_kit_asyc/"
self.exec_recall_api = "qbackend/scq_task_recall/"
self.priority = 2
url = "https://quafu.baqis.ac.cn/"
backends_api = url + "qbackend/get_backends/"
chip_api = url + "qbackend/scq_get_chip_info/"
exec_api = url + "qbackend/scq_kit/"
exec_async_api = url + "qbackend/scq_kit_asyc/"
exec_recall_api = url + "qbackend/scq_task_recall/"

def check_account_data(self):
homedir = get_homedir()
file_dir = homedir + "/.quafu/"
if not os.path.exists(file_dir):
print("Your user information is not configured. Remember to configure it by User.save_apitoken(<your api_token>)")
return False
return True
# TODO: Check if the user's basic data file is formated
def __init__(self, api_token: str = None, token_dir: str = None):
"""
Initialize user account and load backend information.
:param api_token: if provided
:param token_dir: where api token is found or saved
"""
self._available_backends = {}

def save_apitoken(self, apitoken):
if token_dir is None:
self.token_dir = get_homedir() + "/.quafu/"
else:
self.token_dir = token_dir

if api_token is None:
self.api_token = self._load_account_token()
else:
self.api_token = api_token

self.priority = 2

def save_apitoken(self, apitoken=None):
"""
Save your apitoken associate your Quafu account.
Save api-token associate your Quafu account.
"""
self.apitoken = apitoken
homedir = get_homedir()
file_dir = homedir + "/.quafu/"
if apitoken is not None:
import warnings
warnings.warn("The argument 'apitoken' in this function will be deprecated "
"in the future, please set api token by providing 'api_token' "
"or 'token_dir' when initialize User()."
)
self.api_token = apitoken

file_dir = self.token_dir
if not os.path.exists(file_dir):
os.mkdir(file_dir)
with open(file_dir + "api", "w") as f:
f.write(self.apitoken+"\n")
f.write("http://quafu.baqis.ac.cn/")
f.write(self.api_token + "\n")
f.write(self.url)

def load_account(self):
def _load_account_token(self):
"""
Load Quafu account.
Load Quafu account, only api at present.
TODO: expand to load more user information
"""
homedir = get_homedir()
file_dir = homedir + "/.quafu/"
try:
f = open(file_dir + "api", "r")
data = f.readlines()
token = data[0].strip("\n")
url = data[1].strip("\n")
self.apitoken = token
self._url = url
return token, url
except:
raise UserError("User configure error. Please set up your token.")

def get_backends_info(self):
f = open(self.token_dir + "api", "r")
token = f.readline()
except FileNotFoundError:
raise UserError(f"API token file not found at: '{self.token_dir}'. "
"Please set up by providing api_token/token_dir when initializing User.")
return token

def _get_backends_info(self):
"""
Get available backends information
"""

backends_info = requests.post(url=self._url+self.backends_api, headers={"api_token" : self.apitoken})
backends_info = requests.post(url=self.backends_api, headers={"api_token": self.api_token})
backends_info_dict = json.loads(backends_info.text)
if backends_info_dict["status"] == 201:
raise UserError(backends_info_dict["message"])
else:
return backends_info_dict["data"]

def get_available_backends(self, print_info=True):
"""
Get available backends
"""
from quafu.backends.backends import Backend
backends_info = self.get_backends_info()
self._available_backends = {info["system_name"]:Backend(info) for info in backends_info}
backends_info = self._get_backends_info()
self._available_backends = {info["system_name"]: Backend(info) for info in backends_info}

if print_info:
print((" "*5).join(["system_name".ljust(10), "qubits".ljust(10), "status".ljust(10)]))
print((" " * 5).join(["system_name".ljust(10), "qubits".ljust(10), "status".ljust(10)]))
for backend in self._available_backends.values():
print((" "*5).join([backend.name.ljust(10), str(backend.qubit_num).ljust(10), backend.status.ljust(10)]))
print((" " * 5).join(
[backend.name.ljust(10), str(backend.qubit_num).ljust(10), backend.status.ljust(10)]))

return self._available_backends
9 changes: 5 additions & 4 deletions src/quafu/utils/platform.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import os
import sys
from ..exceptions import QuafuError


def get_homedir():
if sys.platform == 'win32':
homedir = os.environ['USERPROFILE']
elif sys.platform == 'linux' or sys.platform == 'darwin':
homedir = os.environ['HOME']

else:
raise QuafuError(f'unsupported platform:{sys.platform}. '
f'You may raise a request issue on github.')
return homedir



15 changes: 9 additions & 6 deletions src/quafu/visualisation/circuitPlot.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ def __init__(self, qc):
procedure will be much simplified, and more functions will be developed.
(TODO)
"""
self.qbit_num = qc.num
# step0: containers of graphical elements

self._h_wire_points = []
Expand All @@ -99,19 +98,23 @@ def __init__(self, qc):
for gate in qc.gates:
assert isinstance(gate, Instruction)
self._process_ins(gate)
qubits_used = self.dorders > 0
self.used_qbit_num = qc.num
# TODO: drop off unused-qubits
# self.used_qbit_num = np.sum(qubits_used)

self.depth = np.max(self.dorders) + 1

for q, c in qc.measures.items():
self._proc_measure(self.depth - 1, q)

# step2: initialize bit-label
self.q_label = {i: f'q_{i}' for i in range(qc.num)}
self.c_label = {iq: f'c_{ic}' for iq, ic in qc.measures.items()}
self.q_label = {i: r'$|q_{%d}\rangle$' % i for i in range(qc.num) if qubits_used[i]}
self.c_label = {iq: f'c_{ic}' for iq, ic in qc.measures.items() if qubits_used[iq]}

# step3: figure coordination
self.xs = np.arange(-3 / 2, self.depth + 3 / 2)
self.ys = np.arange(-2, self.qbit_num + 1 / 2)
self.ys = np.arange(-2, self.used_qbit_num + 1 / 2)

def __call__(self,
title=None,
Expand Down Expand Up @@ -203,12 +206,13 @@ def _circuit_wires(self):
"""
plot horizontal circuit wires
"""
for y in range(self.qbit_num):
for y in range(self.used_qbit_num):
x0 = self.xs[0] + 1
x1 = self.xs[-1] - 1
self._h_wire_points.append([[x0, y], [x1, y]])

def _gate_bbox(self, x, y, fc: str):
""" Single qubit gate box """
a = self._a
from matplotlib.patches import FancyBboxPatch
bbox = FancyBboxPatch((-a / 2 + x, -a / 2 + y), a, a, # this warning belongs to matplotlib
Expand All @@ -224,7 +228,6 @@ def _inits_label(self, labels: dict[int: str] = None):
labels = self.q_label

for i, label in labels.items():
label = r'$|%s\rangle$' % label
txt = Text(-2 / 3, i,
label,
size=18,
Expand Down

0 comments on commit 48bb8e2

Please sign in to comment.