Coverage for moptipyapps / order1d / space.py: 97%

34 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2025-12-11 04:40 +0000

1""" 

2An extension of the permutation space for one-dimensional ordering. 

3 

4The main difference is how the `to_str` result is noted, namely that it 

5contains the mapping of tags to locations. 

6 

7>>> def _dist(a, b): 

8... return abs(a - b) 

9>>> def _tags(a): 

10... return f"t{a}" 

11>>> the_instance = Instance.from_sequence_and_distance( 

12... [1, 2, 3, 3, 2, 3], _dist, 2, 10, ("x", ), _tags) 

13>>> the_space = OrderingSpace(the_instance) 

14>>> the_str = the_space.to_str(np.array([0, 2, 1])) 

15>>> the_str.splitlines() 

16['0;2;1', '', 'indexZeroBased;suggestedXin01;x', '0;0;t1', '2;1;t2', \ 

17'2;1;t2', '1;0.5;t3', '1;0.5;t3', '1;0.5;t3'] 

18>>> print(the_space.from_str(the_str)) 

19[0 2 1] 

20""" 

21 

22from typing import Final 

23 

24import numpy as np 

25from moptipy.spaces.permutations import Permutations 

26from moptipy.utils.logger import CSV_SEPARATOR 

27from moptipy.utils.strings import float_to_str 

28from pycommons.types import type_error 

29 

30from moptipyapps.order1d.instance import ( 

31 _SUGGESTED_X_IN_0_1, 

32 _ZERO_BASED_INDEX, 

33 Instance, 

34) 

35 

36 

37class OrderingSpace(Permutations): 

38 """A space for one-dimensional orderings.""" 

39 

40 def __init__(self, instance: Instance) -> None: 

41 """ 

42 Create an ordering space from an instance. 

43 

44 :param instance: the instance 

45 """ 

46 if not isinstance(instance, Instance): 

47 raise type_error(instance, "instance", Instance) 

48 super().__init__(range(instance.n)) 

49 #: the instance 

50 self.instance: Final[Instance] = instance 

51 

52 def to_str(self, x: np.ndarray) -> str: 

53 """ 

54 Convert a solution to a string. 

55 

56 :param x: the permutation 

57 :return: the string 

58 """ 

59 tags: Final[tuple[tuple[tuple[str, ...], int], ...]] \ 

60 = self.instance.tags 

61 

62 n: Final[int] = len(self.blueprint) - 1 

63 text: list[str] = [] 

64 

65 text.extend(super().to_str(x).split("\n")) 

66 text.append("") # noqa 

67 

68 row: list[str] = [_ZERO_BASED_INDEX, _SUGGESTED_X_IN_0_1] 

69 row.extend(self.instance.tag_titles) 

70 text.append(f"{CSV_SEPARATOR.join(row)}") 

71 

72 for tag, i in tags: 

73 row.clear() 

74 row.extend((str(x[i]), float_to_str(x[i] / n))) 

75 row.extend(tag) 

76 text.append(f"{CSV_SEPARATOR.join(row)}") 

77 return "\n".join(text) 

78 

79 def from_str(self, text: str) -> np.ndarray: 

80 """ 

81 Get the string version from the given text. 

82 

83 :param text: the text 

84 :return: the string 

85 """ 

86 text = text.lstrip() 

87 idx: int = text.find("\n") 

88 if idx > 0: 

89 text = text[:idx] 

90 return super().from_str(text.rstrip())