Coverage for moptipy / mock / mo_problem.py: 90%

30 statements  

« prev     ^ index     » next       coverage.py v7.12.0, created at 2025-11-24 08:49 +0000

1"""The mock multi-objective optimization problem.""" 

2 

3from typing import Iterable, cast 

4 

5import numpy as np 

6from numpy.random import default_rng 

7from pycommons.types import check_int_range, type_error 

8 

9from moptipy.mo.problem.weighted_sum import WeightedSum 

10from moptipy.mock.objective import MockObjective 

11 

12 

13class MockMOProblem(WeightedSum): 

14 """A mock-up of a multi-objective optimization problem.""" 

15 

16 def __init__(self, objectives: Iterable[MockObjective], 

17 weights: Iterable[int | float]) -> None: 

18 """ 

19 Create the mock multi-objective problem. 

20 

21 :param objectives: the mock objectives 

22 :param weights: their weights 

23 """ 

24 super().__init__(objectives, weights) 

25 

26 @staticmethod 

27 def for_dtype(n: int, dtype: np.dtype) -> "MockMOProblem": 

28 """ 

29 Create a mock multi-objective problem. 

30 

31 :param n: the number of objectives 

32 :param dtype: the optional dtype 

33 :returns: the mock multi-objective problem 

34 """ 

35 check_int_range(n, "n", 1, 1_000) 

36 if not isinstance(dtype, np.dtype): 

37 raise type_error(dtype, "dtype", np.dtype) 

38 

39 random = default_rng() 

40 weights: list[int | float] =\ 

41 [int(w) for w in random.integers(1, 3, n)] \ 

42 if random.integers(2) <= 0 \ 

43 else [float(w) for w in random.uniform(0.2, 3, n)] 

44 max_trials: int = 1000 

45 while max_trials > 0: 

46 max_trials -= 1 

47 funcs = [MockObjective.for_type(dtype) for _ in range(n)] 

48 names = {str(o) for o in funcs} 

49 if len(names) >= n: 

50 return MockMOProblem(funcs, weights) 

51 raise ValueError("Huh?") 

52 

53 def get_objectives(self) -> tuple[MockObjective, ...]: 

54 """ 

55 Get the internal objective functions. 

56 

57 :return: the internal mock objective functions 

58 """ 

59 return cast("tuple[MockObjective, ...]", self._objectives) 

60 

61 def sample(self, fs: np.ndarray) -> int | float: 

62 """ 

63 Sample one vector of ojective values. 

64 

65 :param fs: the array to receive the objective values 

66 :returns: the scalarized objective values 

67 """ 

68 for i, o in enumerate(self._objectives): 

69 fs[i] = cast("MockObjective", o).sample() 

70 return self._scalarize(fs)