Source code for QHyper.problems

# This work was supported by the EuroHPC PL infrastructure funded at the
# Smart Growth Operational Programme (2014-2020), Measure 4.2
# under the grant agreement no. POIR.04.02.00-00-D014/20-00

"""
This module contains implementaions of different problems.
Problems are defined using :py:class:`~QHyper.polynomial.Polynomial` module.
No problem is imported by deafult to reduce number of dependencies.
To use any problem you can import it directly like

.. code-block:: python

    from QHyper.problems.knapsack import KnapsackProblem

or use function :py:func:`Problems.get` with the name of the problem.
Any problem that is in directory 'QHyper/custom' or 'custom' will be
also available in this function.

.. rubric:: Interface

.. autosummary::
    :toctree: generated

    Problem  -- Base class for problems.

.. rubric:: Available problems

.. autosummary::
    :toctree: generated

    knapsack.KnapsackProblem -- Knapsack problem.
    tsp.TravelingSalesmanProblem -- Traveling Salesman Problem.
    maxcut.MaxCutProblem -- Max-Cut problem.
    workflow_scheduling.WorkflowSchedulingProblem -- Workflow Scheduling problem.
    community_detection.CommunityDetectionProblem -- Community Detection problem.

.. rubric:: Additional functions

.. autoclass:: Problems
    :members:

"""

from typing import Type, Any
import copy

from QHyper.util import search_for

from QHyper.problems.base import Problem


[docs] class Problems: custom_problems: None | dict[str, type] = None
[docs] @staticmethod def get(name: str) -> Type[Problem]: """ Get problem class by name. Used for creating Problem objects from config. The problem will be available by the 'name' attribute if defined or by the class name. Letters case doesn't matter. """ if Problems.custom_problems is None: Problems.custom_problems = ( search_for(Problem, 'QHyper/custom') | search_for(Problem, 'custom')) name_ = name.lower() if name_ in Problems.custom_problems: return Problems.custom_problems[name_] elif name_ in ["knapsack", "knapsackproblem"]: from .knapsack import KnapsackProblem return KnapsackProblem elif name_ in ["tsp", "travelingsalesmanproblem"]: from .tsp import TravelingSalesmanProblem return TravelingSalesmanProblem elif name_ in ["maxcut", "maxcutproblem"]: from .maxcut import MaxCutProblem return MaxCutProblem elif name_ in ["workflow_scheduling", "workflowschedulingproblem"]: from .workflow_scheduling import WorkflowSchedulingProblem return WorkflowSchedulingProblem elif name_ in ["community_detection", "communitydetectionproblem"]: from .community_detection import CommunityDetectionProblem return CommunityDetectionProblem else: raise ValueError(f"Problem {name} not found")
class ProblemConfigException(Exception): """Exception raised when problem configuration is incorrect""" pass def problem_from_config(config: dict[str, Any]) -> Problem: """ Create Problem object from provided configuration. Parameters ---------- config : dict[str. Any] Configuration in form of dict Returns ------- Problem Initialized Problem object """ config_ = copy.deepcopy(config) if "type" not in config_: raise ProblemConfigException("Problem type was not provided") problem_type = config_.pop('type') problem_class = Problems.get(problem_type) return problem_class(**config_)