Problem

The Problem class hierarchy in pyHMS provides the foundation for defining optimization problems and wrapping them with additional functionality.

Base Classes

class pyhms.core.problem.Problem
class pyhms.core.problem.FunctionProblem(fitness_function: Callable, bounds: ndarray, maximize: bool, use_cache: bool = False)
class pyhms.core.problem.ProblemWrapper(decorated_problem: Problem)

Problem Wrappers

pyHMS provides various Problem wrappers. These wrappers enhance problem instances with additional functionality without modifying their core behavior. Common use cases include:

  1. Monitoring optimization performance (counting evaluations, measuring time)

  2. Enforcing constraints (maximum evaluations, precision thresholds)

  3. Collecting statistics for analysis

Available Wrappers

class pyhms.core.problem.EvalCountingProblem(decorated_problem: Problem)

A decorator for a Problem instance that counts the number of evaluations performed.

This class wraps around any instance of Problem and counts how many times the evaluate method is called. This is useful for monitoring and limiting the computational cost of optimization processes.

Parameters:

decorated_problem (Problem) – The problem to be decorated.

>>> from pyhms import EvalCountingProblem, Problem
>>> import numpy as np
>>> problem = Problem(lambda x: -x**2, maximize=True)
>>> counting_problem = EvalCountingProblem(problem)
>>> counting_problem.evaluate(2.0)
>>> print(counting_problem.n_evaluations)
1

A wrapper that counts the number of function evaluations performed.

class pyhms.core.problem.EvalCutoffProblem(decorated_problem: Problem, eval_cutoff: int)

A decorator for a Problem instance that imposes a cutoff on the number of evaluations.

This class extends EvalCountingProblem by adding a functionality to stop evaluations once a specified cutoff limit is reached. Evaluations beyond this limit will return a predefined value, effectively simulating an infinite cost or penalty. This can be useful in scenarios where computational resources are limited or when implementing certain types of optimization algorithms that require evaluation limits.

Note:

It returns np.inf for evaluations beyond the cutoff if the problem is a minimization one, and -np.inf for maximization.

>>> from pyhms import EvalCutoffProblem, Problem
>>> import numpy as np
>>> problem = Problem(lambda x: -x**2, maximize=True)
>>> cutoff_problem = EvalCutoffProblem(problem, eval_cutoff=1)
>>> cutoff_problem.evaluate(2.0)
>>> cutoff_problem.evaluate(1.0)
inf

A wrapper that stops evaluations after a specified limit is reached, returning infinity (or negative infinity for maximization problems).

class pyhms.core.problem.PrecisionCutoffProblem(decorated_problem: Problem, global_optima: float, precision: float)

A decorator for a Problem instance that introduces a precision-based cutoff criterion.

The class extends EvalCountingProblem and tracks whether the specified precision relative to the global optimum has been achieved and records the evaluation count (ETA) when this occurs for the first time.

This class is useful for optimization problems where the goal is to find a solution that is close enough to the known global optimum within a certain precision threshold.

>>> from pyhms import PrecisionCutoffProblem, Problem
>>> import numpy as np
>>> problem = Problem(lambda x: -x**2, maximize=True)
>>> precision_cutoff_problem = PrecisionCutoffProblem(problem, 0, 1e-4)
>>> precision_cutoff_problem.evaluate(0)
>>> print(precision_cutoff_problem.ETA)
0

A wrapper that tracks when the solution reaches a specified precision threshold relative to the known global optimum.

class pyhms.core.problem.StatsGatheringProblem(decorated_problem: Problem)

A decorator for a Problem instance that gathers statistics about evaluation times.

This class wraps around any instance of Problem to record the duration of each evaluation performed on the decorated problem. It’s particularly useful for performance analysis, enabling the monitoring of how long each call to evaluate takes.

>>> from pyhms import StatsGatheringProblem, Problem
>>> import numpy as np
>>> problem = FunctionProblem(lambda x: -x**2, maximize=True)
>>> stats_gathering_problem = StatsGatheringProblem(problem)
>>> stats_gathering_problem.evaluate(2.0)
>>> print(stats_gathering_problem.durations)
[1.2750009773299098e-05]

A wrapper that collects statistics about evaluation times, useful for performance analysis.

Helper Functions

pyhms.core.problem.get_function_problem(problem: Problem | ProblemWrapper | FunctionProblem) FunctionProblem

Recursively unwraps a ProblemWrapper instance to get the inner FunctionProblem.