Пример #1
0
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)
Пример #2
0
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()