Source code for qlauncher.problems.problem_initialization.qatm
1""" This module contains the QATM class."""
2import os
3
4from typing import Any
5
6import numpy as np
7import pandas as pd
8
9from qlauncher.base import Problem
10
11
[docs]
12class QATM(Problem):
13 """
14 Class for Quantum Aircraft Traffic Management (QATM) problem.
15
16 This class represents Quantum Aircraft Traffic Management (QATM) problem which is a combinatorial optimization problem
17 that involves scheduling a set of aircrafts on a set of manouvers. Each aircraft consists of a sequence of manouvers
18 that must be performed. The objective is to find a schedule that minimizes the number of collisions between aircrafts.
19 The class contains an instance of the problem, so it can be passed into QLauncher.
20
21 Attributes:
22 onehot (str): The one-hot encoding used for the problem.
23 instance (dict): The instance of the problem.
24 instance_name (str | None): The name of the instance.
25 instance_path (str): The path to the instance file.
26
27 """
28
29 def __init__(self, onehot: str = 'exact', instance: Any = None, instance_name: str | None = None,
30 optimization_problem: bool = False) -> None:
31 super().__init__(instance=instance, instance_name=instance_name if instance_name is not None else "QATM")
32 self.onehot = onehot
33 self.optimization_problem = optimization_problem
34
35 @property
36 def setup(self) -> dict:
37 return {
38 'onehot': self.onehot,
39 'instance_name': self.instance_name
40 }
41
42 def _get_path(self) -> str:
43 return f'{self.name}@{self.instance_name.split(".", 1)[0]}'
44
[docs]
45 @classmethod
46 def from_file(cls, path: str, instance_name: str = "QATM"):
47 cm_path = os.path.join(path, 'CM_' + instance_name)
48 aircrafts_path = os.path.join(
49 path, 'aircrafts_' + instance_name)
50
51 instance = {'cm': np.loadtxt(cm_path), 'aircrafts': pd.read_csv(aircrafts_path, delimiter=' ', names=['manouver', 'aircraft'])}
52 return QATM('exact', instance, instance_name)
53
[docs]
54 def analyze_result(self, result: dict):
55 """
56 Analyzes the result in terms of collisions and violations of onehot constraint.
57
58 Parameters:
59 result (dict): A dictionary where keys are bitstrings and values are probabilities.
60
61 Returns:
62 dict: A dictionary containing collisions, onehot violations, and changes as ndarrays.
63 """
64 keys = list(result.keys())
65 vectorized_result = (np.fromstring("".join(keys), 'u1') - ord('0')).reshape(len(result), -1)
66
67 cm = self.instance['cm'].copy().astype(int)
68 np.fill_diagonal(cm, 0)
69 collisions = np.einsum('ij,ij->i', vectorized_result @ cm, vectorized_result) / 2
70
71 df = pd.DataFrame(vectorized_result.transpose())
72 df['aircraft'] = self.instance['aircrafts']['aircraft']
73 onehot_violations = (df.groupby(by='aircraft').sum() != 1).sum(axis=0).to_numpy()
74
75 df['manouver'] = self.instance['aircrafts']['manouver']
76 no_changes = df[df['aircraft'] == df['manouver']]
77 changes = (len(no_changes) - no_changes.drop(['manouver', 'aircraft'], axis=1).sum()).to_numpy().astype(int)
78 changes[onehot_violations != 0] = -1
79
80 at_least_one = (df.loc[:, df.columns != 'manouver'].groupby('aircraft').sum() > 0).all().to_numpy().astype(int)
81
82 return {
83 'collisions': collisions,
84 'onehot_violations': onehot_violations,
85 'changes': changes,
86 'at_least_one': at_least_one
87 }