• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

DIGNEA / DIGNEApy / 16416951177

21 Jul 2025 12:27PM UTC coverage: 90.447% (-0.6%) from 91.09%
16416951177

push

github

amarrerod
📌 Pins fcmaes to 1.6.11

2064 of 2282 relevant lines covered (90.45%)

1.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.27
/digneapy/_core/_instance.py
1
#!/usr/bin/env python
2
# -*-coding:utf-8 -*-
3
"""
4
@File    :   instance.py
5
@Time    :   2024/06/07 14:09:43
6
@Author  :   Alejandro Marrero
7
@Version :   1.0
8
@Contact :   amarrerd@ull.edu.es
9
@License :   (C)Copyright 2024, Alejandro Marrero
10
@Desc    :   None
11
"""
12

13
import operator
2✔
14
from typing import Optional, Self, Sequence
2✔
15

16
import numpy as np
2✔
17
import numpy.typing as npt
2✔
18
import pandas as pd
2✔
19

20

21
class Instance:
2✔
22
    __slots__ = ("_vars", "_fit", "_p", "_s", "_features", "_desc", "_pscores")
2✔
23

24
    def __init__(
2✔
25
        self,
26
        variables: Optional[npt.ArrayLike] = None,
27
        fitness: float = 0.0,
28
        p: float = 0.0,
29
        s: float = 0.0,
30
        features: Optional[tuple[float]] = None,
31
        descriptor: Optional[tuple[float]] = None,
32
        portfolio_scores: Optional[tuple[float]] = None,
33
    ):
34
        try:
2✔
35
            fitness = float(fitness)
2✔
36
            p = float(p)
2✔
37
            s = float(s)
2✔
38
        except ValueError:
2✔
39
            raise ValueError(
2✔
40
                "The fitness, p and s parameters must be convertible to float"
41
            )
42

43
        self._vars = np.array(variables) if variables is not None else np.empty(0)
2✔
44
        self._fit = fitness
2✔
45
        self._p = p
2✔
46
        self._s = s
2✔
47
        self._features = np.array(features) if features is not None else np.empty(0)
2✔
48
        self._pscores = (
2✔
49
            np.array(portfolio_scores) if portfolio_scores is not None else np.empty(0)
50
        )
51
        self._desc = np.array(descriptor) if descriptor is not None else np.empty(0)
2✔
52

53
    def clone(self) -> Self:
2✔
54
        return Instance(
2✔
55
            variables=list(self._vars),
56
            fitness=self._fit,
57
            p=self._p,
58
            s=self._s,
59
            features=tuple(self._features),
60
            portfolio_scores=tuple(self._pscores),
61
            descriptor=tuple(self._desc),
62
        )
63

64
    @property
2✔
65
    def variables(self):
2✔
66
        return self._vars
2✔
67

68
    @property
2✔
69
    def p(self) -> float:
2✔
70
        return self._p
2✔
71

72
    @p.setter
2✔
73
    def p(self, performance: float):
2✔
74
        try:
2✔
75
            performance = float(performance)
2✔
76
        except ValueError:
2✔
77
            # if performance != 0.0 and not float(performance):
78
            msg = f"The performance value {performance} is not a float in 'p' setter of class {self.__class__.__name__}"
2✔
79
            raise ValueError(msg)
2✔
80
        self._p = performance
2✔
81

82
    @property
2✔
83
    def s(self) -> float:
2✔
84
        return self._s
2✔
85

86
    @s.setter
2✔
87
    def s(self, novelty: float):
2✔
88
        try:
2✔
89
            novelty = float(novelty)
2✔
90
        except ValueError:
2✔
91
            # if novelty != 0.0 and not float(novelty):
92
            msg = f"The novelty value {novelty} is not a float in 's' setter of class {self.__class__.__name__}"
2✔
93
            raise ValueError(msg)
2✔
94
        self._s = novelty
2✔
95

96
    @property
2✔
97
    def fitness(self) -> float:
2✔
98
        return self._fit
2✔
99

100
    @fitness.setter
2✔
101
    def fitness(self, f: float):
2✔
102
        try:
2✔
103
            f = float(f)
2✔
104
        except ValueError:
2✔
105
            # if f != 0.0 and not float(f):
106
            msg = f"The fitness value {f} is not a float in fitness setter of class {self.__class__.__name__}"
2✔
107
            raise ValueError(msg)
2✔
108

109
        self._fit = f
2✔
110

111
    @property
2✔
112
    def features(self) -> np.ndarray:
2✔
113
        return self._features
2✔
114

115
    @features.setter
2✔
116
    def features(self, features: npt.ArrayLike):
2✔
117
        self._features = np.asarray(features)
2✔
118

119
    @property
2✔
120
    def descriptor(self) -> np.ndarray:
2✔
121
        return self._desc
2✔
122

123
    @descriptor.setter
2✔
124
    def descriptor(self, desc: npt.ArrayLike):
2✔
125
        self._desc = np.array(desc)
2✔
126

127
    @property
2✔
128
    def portfolio_scores(self):
2✔
129
        return self._pscores
2✔
130

131
    @portfolio_scores.setter
2✔
132
    def portfolio_scores(self, p: npt.ArrayLike):
2✔
133
        self._pscores = np.asarray(p)
2✔
134

135
    def __repr__(self):
2✔
136
        return f"Instance<f={self.fitness},p={self.p},s={self.s},vars={len(self._vars)},features={len(self.features)},descriptor={len(self.descriptor)},performance={len(self.portfolio_scores)}>"
2✔
137

138
    def __str__(self):
2✔
139
        import reprlib
2✔
140

141
        descriptor = reprlib.repr(self.descriptor)
2✔
142
        performance = reprlib.repr(self.portfolio_scores)
2✔
143
        performance = performance[performance.find("(") : performance.rfind(")") + 1]
2✔
144
        return f"Instance(f={self.fitness},p={self.p},s={self.s},features={len(self.features)},descriptor={descriptor},performance={performance})"
2✔
145

146
    def __iter__(self):
2✔
147
        return iter(self._vars)
2✔
148

149
    def __len__(self):
2✔
150
        return len(self._vars)
2✔
151

152
    def __getitem__(self, key):
2✔
153
        if isinstance(key, slice):
2✔
154
            cls = type(self)  # To facilitate subclassing
2✔
155
            return cls(self._vars[key])
2✔
156
        index = operator.index(key)
2✔
157
        return self._vars[index]
2✔
158

159
    def __setitem__(self, key, value):
2✔
160
        self._vars[key] = value
2✔
161

162
    def __eq__(self, other):
2✔
163
        if not isinstance(other, Instance):
2✔
164
            print(
2✔
165
                f"Other of type {other.__class__.__name__} can not be compared with with {self.__class__.__name__}"
166
            )
167
            return NotImplemented
2✔
168

169
        else:
170
            try:
2✔
171
                return all(a == b for a, b in zip(self, other, strict=True))
2✔
172
            except ValueError:
2✔
173
                return False
2✔
174

175
    def __gt__(self, other):
2✔
176
        if not isinstance(other, Instance):
2✔
177
            print(
2✔
178
                f"Other of type {other.__class__.__name__} can not be compared with with {self.__class__.__name__}"
179
            )
180
            return NotImplemented
2✔
181

182
        return self.fitness > other.fitness
2✔
183

184
    def __ge__(self, other):
2✔
185
        if not isinstance(other, Instance):
2✔
186
            print(
2✔
187
                f"Other of type {other.__class__.__name__} can not be compared with with {self.__class__.__name__}"
188
            )
189
            return NotImplemented
2✔
190

191
        return self.fitness >= other.fitness
2✔
192

193
    def __hash__(self):
2✔
194
        from functools import reduce
2✔
195

196
        hashes = (hash(x) for x in self)
2✔
197
        return reduce(operator.or_, hashes, 0)
2✔
198

199
    def __bool__(self):
2✔
200
        return self._vars.size != 0
2✔
201

202
    def __format__(self, fmt_spec=""):
2✔
203
        if fmt_spec.endswith("p"):
2✔
204
            # We are showing only the performances
205
            fmt_spec = fmt_spec[:-1]
2✔
206
            components = self.portfolio_scores
2✔
207
        else:
208
            fmt_spec = fmt_spec[:-1]
2✔
209
            components = self.descriptor
2✔
210

211
        components = (format(c, fmt_spec) for c in components)
2✔
212
        decriptor = "descriptor=({})".format(",".join(components))
2✔
213
        msg = f"Instance(f={self.fitness},p={format(self.p, fmt_spec)}, s={format(self.s, fmt_spec)}, {decriptor})"
2✔
214

215
        return msg
2✔
216

217
    def asdict(
2✔
218
        self,
219
        variables_names: Optional[Sequence[str]] = None,
220
        features_names: Optional[Sequence[str]] = None,
221
        score_names: Optional[Sequence[str]] = None,
222
    ) -> dict:
223
        sckeys = (
2✔
224
            [f"solver_{i}" for i in range(len(self._pscores))]
225
            if score_names is None
226
            else score_names
227
        )
228
        _data = {
2✔
229
            "fitness": self._fit,
230
            "s": self._s,
231
            "p": self._p,
232
            "portfolio_scores": {sk: v for sk, v in zip(sckeys, self._pscores)},
233
        }
234

235
        if len(self._desc) not in (
2✔
236
            len(self._vars),
237
            len(self._features),
238
            len(self._pscores),
239
        ):  # Transformed descriptor
240
            _data["descriptor"] = {f"d{i}": v for i, v in enumerate(self._desc)}
×
241
        if len(self.features) != 0:
2✔
242
            f_keys = (
×
243
                [f"f{i}" for i in range(len(self._features))]
244
                if features_names is None or len(features_names) == 0
245
                else features_names
246
            )
247
            _data["features"] = {fk: v for fk, v in zip(f_keys, self._features)}
×
248

249
        if variables_names:
2✔
250
            if len(variables_names) != len(self._vars):
×
251
                print(
×
252
                    f"Error in asdict(). len(variables_names) = {len(variables_names)} != len(variables) ({len(self._vars)}). Fallback to v#"
253
                )
254
                _data["variables"] = {f"v{i}": v for i, v in enumerate(self._vars)}
×
255
            else:
256
                _data["variables"] = {
×
257
                    vk: v for vk, v in zip(variables_names, self._vars)
258
                }
259

260
        else:
261
            _data["variables"] = {f"v{i}": v for i, v in enumerate(self._vars)}
2✔
262

263
        return _data
2✔
264

265
    def to_json(self) -> str:
2✔
266
        import json
×
267

268
        return json.dumps(self.asdict(), sort_keys=True, indent=4)
×
269

270
    def to_series(
2✔
271
        self,
272
        variables_names: Optional[Sequence[str]] = None,
273
        features_names: Optional[Sequence[str]] = None,
274
        score_names: Optional[Sequence[str]] = None,
275
    ) -> pd.Series:
276
        _flatten_data = {}
2✔
277
        for key, value in self.asdict(
2✔
278
            variables_names=variables_names,
279
            features_names=features_names,
280
            score_names=score_names,
281
        ).items():
282
            if isinstance(value, dict):  # Flatten nested dicts
2✔
283
                for sub_key, sub_value in value.items():
2✔
284
                    _flatten_data[f"{sub_key}"] = sub_value
2✔
285
            else:
286
                _flatten_data[key] = value
2✔
287
        return pd.Series(_flatten_data)
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc