Coverage for moptipy / api / mo_utils.py: 22%

27 statements  

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

1"""Utilities for multi-objective optimization.""" 

2 

3import numba # type: ignore 

4import numpy as np 

5 

6 

7@numba.njit(cache=True) 

8def dominates(a: np.ndarray, b: np.ndarray) -> int: 

9 """ 

10 Check if one objective vector dominates or is dominated by another one. 

11 

12 :param a: the first objective vector 

13 :param b: the second objective value 

14 :returns: an integer value indicating the domination relationship 

15 :retval -1: if `a` dominates `b` 

16 :retval 1: if `b` dominates `a` 

17 :retval 2: if `b` equals `a` 

18 :retval 0: if `a` and `b` are mutually non-dominated, i.e., if neither `a` 

19 dominates `b` not `b` dominates `a` and `b` is also different from `a` 

20 

21 >>> from numpy import array 

22 >>> dominates(array([1, 1, 1]), array([2, 2, 2])) 

23 -1 

24 >>> dominates(array([1.0, 1.0, 2.0]), array([2.0, 2.0, 1.0])) 

25 0 

26 >>> dominates(array([2, 2, 2]), array([1, 1, 1])) 

27 1 

28 >>> dominates(array([2, 2, 2]), array([2, 2, 2])) 

29 2 

30 """ 

31 res: int = 0 

32 for i, av in enumerate(a): 

33 bv = b[i] 

34 if av < bv: 

35 if res == 0: 

36 res = -1 

37 elif res == 1: 

38 return 0 

39 elif bv < av: 

40 if res == 0: 

41 res = 1 

42 elif res == -1: 

43 return 0 

44 return 2 if res == 0 else res 

45 

46 

47@numba.njit(cache=True) 

48def lexicographic(a: np.ndarray, b: np.ndarray) -> int: 

49 """ 

50 Compare two arrays lexicographically. 

51 

52 :param a: the first objective vector 

53 :param b: the second objective value 

54 :returns: `-1` if `a` is lexicographically less than `b`, `1` if `b` is 

55 less than `a`, `0` otherwise 

56 :retval -1: if `a` is lexicographically less than `b` 

57 :retval 1: if `b` is lexicographically less than `a` 

58 :retval 2: if `b` equals `a` 

59 

60 >>> from numpy import array 

61 >>> lexicographic(array([1, 1, 1]), array([2, 2, 2])) 

62 -1 

63 >>> lexicographic(array([1, 1, 1]), array([1, 1, 2])) 

64 -1 

65 >>> lexicographic(array([2, 2, 2]), array([1, 1, 1])) 

66 1 

67 >>> lexicographic(array([2, 2, 2]), array([2, 2, 1])) 

68 1 

69 >>> lexicographic(array([2, 2, 2]), array([2, 2, 2])) 

70 0 

71 """ 

72 for i, f in enumerate(a): 

73 k = b[i] 

74 if f < k: 

75 return -1 

76 if f > k: 

77 return 1 

78 return 0