qgym.envs.initial_mapping.initial_mapping module

This module contains an environment for training an RL agent on the initial mapping problem of OpenQL. The initial mapping problem is aimed at mapping virtual qubits of a circuit to physical qubits that have a certain connection topology. The quantum circuit is represented as an interaction graph, where each node represent a qubit and each edge represent an interaction between two qubits as defined by the circuit (See the example below). The QPU structure is called the connection graph. In the connection graph each node represents a physical qubit and each edge represent a connection between two qubits in the QPU.

          QUANTUM CIRCUIT                        INTERACTION GRAPH
       ┌───┐               ┌───┐
|q3>───┤ R ├───┬───────────┤ M ╞══                 q1 ────── q2
       └───┘   │           └───┘                            ╱
       ┌───┐ ┌─┴─┐         ┌───┐                           ╱
|q2>───┤ R ├─┤ X ├───┬─────┤ M ╞══                        ╱
       └───┘ └───┘   │     └───┘                         ╱
       ┌───┐       ┌─┴─┐   ┌───┐                        ╱
|q1>───┤ R ├───┬───┤ X ├───┤ M ╞══                     ╱
       └───┘   │   └───┘   └───┘                      ╱
       ┌───┐ ┌─┴─┐         ┌───┐                     ╱
|q0>───┤ R ├─┤ X ├─────────┤ M ╞══                q3 ─────── q4
       └───┘ └───┘         └───┘

The goal is to create a mapping between the nodes of the interaction and connection graph, such that for every edge in the interaction graph, there is an edge in the connection graph. If this is impossible, then the number of mismatches should be penalized.

State Space:

The state space is described by a InitialMappingState with the following attributes:

  • steps_done: Number of steps done since the last reset.

  • n_nodes: Number of physical qubits.

  • graphs: Dictionary containing the graph and matrix representations of the both the interaction graph and connection graph.

  • mapping: Array of which the index represents a physical qubit, and the value a virtual qubit. A value of n_nodes + 1 represents the case when nothing is mapped to the physical qubit yet.

  • mapping_dict: Dictionary that maps logical qubits (keys) to physical qubit (values).

  • mapped_qubits: Dictionary with a two Sets containing all mapped physical and logical qubits.

Observation Space:

The observation space is a Dict with 2 entries:

  • mapping: The current state of the mapping.

  • interaction_matrix: The flattened adjacency matrix of the interaction graph.

Action Space:

A valid action is a tuple of integers \((i,j)\), such that \(0 \le i, j < n\), where \(n\) is the number of physical qubits. The action \((i,j)\) maps virtual qubit \(j\) to phyiscal qubit \(i\) when this action is legal. An action is legal when:

  1. virtual qubit \(i\) has not been mapped to another physical qubit; and

  2. no other virual qubit has been mapped to physical qubit \(j\).

Example 1:

Creating an environment with a gridlike connection graph is done by executing the following code:

>>> from qgym.envs.initial_mapping import InitialMapping
>>> env = InitialMapping(connection_graph=(3,3))

By default, InitialMapping uses the BasicRewarder. As an example, we would like to change the rewarder to the EpisodeRewarder. This can be done in the following way:

>>> from qgym.envs.initial_mapping import EpisodeRewarder
>>> env.rewarder = EpisodeRewarder()
Example 2:

In this example we use a custom connection graph depicted in the code block below.

q1──────q0──────q2



        q3

The graph has a non-gridlike structure. Such connection graphs can be given to the environment by giving an adjacency matrix representation of the graph, or a networkx representation of the graph. We will show the latter option in this example.

import networkx as nx
from qgym.envs.initial_mapping import InitialMapping

# Create a networkx representation of the connection graph
connection_graph = nx.Graph()
connection_graph.add_edge(0, 1)
connection_graph.add_edge(0, 2)
connection_graph.add_edge(0, 3)

# Initialize the environment with the custom connection graph
env = InitialMapping(connection_graph=connection_graph)
class qgym.envs.initial_mapping.initial_mapping.InitialMapping(connection_graph, graph_generator=None, *, rewarder=None, render_mode=None)[source]

Bases: Environment[Dict[str, ndarray[Any, dtype[int32]]], ndarray[Any, dtype[int32]]]

RL environment for the initial mapping problem of OpenQL.

__init__(connection_graph, graph_generator=None, *, rewarder=None, render_mode=None)[source]

Initialize the action space, observation space, and initial states. Furthermore, the connection graph and edge probability for the random interaction graph of each episode is defined.

The supported render modes of this environment are "human" and "rgb_array".

Parameters:
action_space: Space[Any]

The action space of this environment.

metadata: dict[str, Any]

Additional metadata of this environment.

observation_space: Space[Any]

The observation space of this environment.

reset(*, seed=None, options=None)[source]

Reset the state and set a new interaction graph.

To be used after an episode is finished.

Parameters:
  • seed (int | None) – Seed for the random number generator, should only be provided (optionally) on the first reset call i.e., before any learning is done.

  • return_info – Whether to receive debugging info. Default is False.

  • options (Mapping[str, Any] | None) – Mapping with keyword arguments with additional options for the reset. Keywords can be found in the description of InitialMappingState.reset().

Return type:

tuple[dict[str, ndarray[Any, dtype[int32]]], dict[str, Any]]

Returns:

Initial observation and debugging info.