class BaseChannel(ABC): def __init__(self, params, graph_type="chimera", n_nodes=None, n_edges=None): self.params = params self.graph_type = graph_type device_name = { 'chimera': 'DW_2000Q_6', 'pegasus': 'Advantage_system1.1', 'simulator': None } if graph_type == 'simulator': self.sampler = DWaveSampler(solver={'qpu': False}) else: self.sampler = DWaveSampler(solver={ 'qpu': True, 'name': device_name[graph_type] }) self.list_edges = np.array(self.sampler.edgelist) self.list_nodes = np.array(self.sampler.nodelist) nodes_file = "data/pegasus/list_nodes.npy" edges_file = "data/pegasus/list_edges.npy" if graph_type == 'pegasus': if n_nodes is not None: if os.path.exists(nodes_file): print("Loading list nodes...") self.list_nodes = np.load(nodes_file) else: print("Taking subgraph...") self.list_nodes = take_subgraph(self.sampler, n_nodes) np.save(nodes_file, self.list_nodes) self.graph = self.sampler.to_networkx_graph().subgraph( self.list_nodes) self.list_edges = np.array(self.graph.edges) if n_edges is not None: if os.path.exists(edges_file): print("Loading list edges...") self.list_edges = np.load(edges_file) else: print("Removing edges...") edges_idx = np.sort( np.random.choice(len(self.list_edges), n_edges, replace=False)) self.list_edges = self.list_edges[edges_idx] np.save(edges_file, self.list_edges) print("Number of qubits", len(self.list_nodes)) print("Number of edges", len(self.list_edges)) super().__init__() @abstractmethod def send(self, J_in, h_in): pass @abstractmethod def get_nishimori_temperature(self): pass @abstractmethod def conditional_density(self, y_out, y_in): pass def encode(self, x_in): x_dict = {node: x_in[i] for i, node in enumerate(self.list_nodes)} J = defaultdict(int) for (u, v) in self.list_edges: J[(u, v)] = -x_dict[u] * x_dict[v] h = {node: -x_dict[node] for node in x_dict.keys()} return J, h def decode(self, J_out, h_out, num_reads=1, num_spin_reversals=1): result = self.sampler.sample_ising( h_out, J_out, num_reads=num_reads, num_spin_reversal_transforms=num_spin_reversals) x_dec = np.array(list(list(result.data())[0].sample.values())) return x_dec def get_ber(self, x_in, x_dec): N = len(x_in) return np.sum(np.abs(x_in - x_dec)) / (2 * N)
def plot_working_graph(sampler: DWaveSampler, out_path: None or os.PathLike=None, figsize:tuple=(8, 8), ng_color:str="red", ok_color:str="blue", draw_rectangle:bool=False) -> None: """ QPUのworking graphをプロットする。 working graph については https://docs.dwavesys.com/docs/latest/c_gs_4.html?highlight=working%20graph を参考。 Parameters ---------- sampler : DWaveSampler プロット対象のQPUを保持するDWaveSamplerオブジェクト。 out_path : None or os.PathLike, optional 出力パス, by default None figsize : tuple, optional figsize, by default (8, 8) ng_color : str, optional 無効なqbit, couplerの描画色, by default "red" ok_color : str, optional 有効なqbit, couplerの描画色, by default "blue" draw_rectangle : bool, optional 無効なqbit, couplerが存在しない領域を示すか, by default False DWaveSampler.properties["chip_id"] が "DW_2000Q_6" である時のみ使える。 それ以外のSamplerに対しTrueを設定するとValueErrorが発生する。 矩形のサイズは手動で調整した。ハードコーディング。 """ # topologyに応じ関数を設定 topology_type = sampler.properties["topology"]["type"] if topology_type == "chimera": graph_func = dnx.chimera_graph draw_func = dnx.draw_chimera elif topology_type == "pegasus": graph_func = dnx.pegasus_graph draw_func = dnx.draw_pegasus else: raise ValueError(f"support chimera or pegasus, unsupported {topology_type}.") # working_graph の 無効なqbit, coupler を求め、colorリストを作成 G = sampler.to_networkx_graph() T = graph_func(*sampler.properties["topology"]["shape"]) error_node = set(T.nodes() - G.nodes()) node_color = [ng_color if v in error_node else ok_color for v in T.nodes()] error_edge = set(T.edges() - G.edges()) edge_color = [ng_color if e in error_edge else ok_color for e in T.edges()] # プロット plt.figure(figsize=figsize) ax = plt.axes() draw_func(T, node_color=node_color, edge_color=edge_color, node_size=1, ax=ax) if draw_rectangle: chip_id = sampler.properties["chip_id"] if chip_id != "DW_2000Q_6": raise ValueError(f"support DW_2000Q_6, unsupported {chip_id}.") # ハードコーディング。手動で調整した。 rectangle = patches.Rectangle(xy=(0.37, -0.82), width=0.64, height=0.83, ec='green', fill=False, ls="--", lw="2") ax.add_patch(rectangle) if out_path is None: plt.show() else: os.makedirs(Path(out_path).parent, exist_ok=True) plt.savefig(out_path) plt.clf()