Coverage for moptipy / examples / bitstrings / twomax.py: 85%
20 statements
« prev ^ index » next coverage.py v7.12.0, created at 2025-11-24 08:49 +0000
« prev ^ index » next coverage.py v7.12.0, created at 2025-11-24 08:49 +0000
1"""
2The TwoMax problem.
4TwoMax has two optima. The local optimum at the string with all `False` bits.
5The objective value of this local optimum is 1. The global optimum is the
6string with all `True` bits and its objective value is 0. The worst objective
7value is reached if half of the bits are `True` and the other half is `False`.
8Then, the objective value will be `(n // 2) + 1`.
10The TwoMax problem is based on OneMax but introduces deceptiveness in the
11objective function by having a local and a global optimum. Since their basins
12of attraction have the same size, a (1 + 1) EA can solve the problem in
13`Omega(n ln n)` steps with probability 0.5 while otherwise needing exponential
14runtime in expectation, leading to a total expected runtime in
15`Omega(n ** n)`.
171. Tobias Friedrich, Francesco Quinzan, and Markus Wagner. Escaping Large
18 Deceptive Basins of Attraction with Heavy-Tailed Mutation Operators.
19 GECCO 2018. ACM.
20 doi: https://doi.org/10.1145/3205455.3205515.
212. Clarissa Van Hoyweghen, David E. Goldberg, and Bart Naudts. From TwoMax to
22 the Ising Model: Easy and Hard Symmetrical Problems. GECCO 2002.
23 pp 626-633. Morgan Kaufmann.
243. Tobias Friedrich, Pietro S. Oliveto, Dirk Sudholt, and Carsten Witt.
25 Analysis of Diversity-Preserving Mechanisms for Global Exploration.
26 Evolutionary Computation. 17(4):455-476. 2009.
27 doi: https://doi.org/10.1162/evco.2009.17.4.17401.
284. Thomas Weise, Zhize Wu, Xinlu Li, and Yan Chen. Frequency Fitness
29 Assignment: Making Optimization Algorithms Invariant under Bijective
30 Transformations of the Objective Function Value. *IEEE Transactions on
31 Evolutionary Computation* 25(2):307-319. April 2021. Preprint available at
32 arXiv:2001.01416v5 [cs.NE] 15 Oct 2020.
33 https://dx.doi.org/10.1109/TEVC.2020.3032090
345. Thomas Weise, Zhize Wu, Xinlu Li, Yan Chen, and Jörg Lässig. Frequency
35 Fitness Assignment: Optimization without Bias for Good Solutions can be
36 Efficient. *IEEE Transactions on Evolutionary Computation (TEVC)*.
37 27(4):980-992. August 2023.
38 doi: https://doi.org/10.1109/TEVC.2022.3191698
40This is code is part of the research work of Mr. Jiazheng ZENG (曾嘉政),
41a Master's student at the Institute of Applied Optimization
42(应用优化研究所) of the School of Artificial
43Intelligence and Big Data (人工智能与大数据学院) at
44Hefei University (合肥大学) in
45Hefei, Anhui, China (中国安徽省合肥市) under the supervision of
46Prof. Dr. Thomas Weise (汤卫思教授).
47"""
48from typing import Callable, Final, Iterator, cast
50import numba # type: ignore
51import numpy as np
53from moptipy.examples.bitstrings.bitstring_problem import BitStringProblem
56@numba.njit(nogil=True, cache=True)
57def twomax(x: np.ndarray) -> int:
58 """
59 Compute the objective value of the TwoMax problem.
61 :param x: the np array
62 :return: the sum of the indices of the first two ones
64 >>> twomax(np.array([True, True, True, True, True]))
65 0
66 >>> twomax(np.array([False, False, False, False, False]))
67 1
68 >>> twomax(np.array([False, True, True, False, False]))
69 3
70 >>> twomax(np.array([True, True, True, True, True]))
71 0
72 >>> twomax(np.array([False, False, False, False, False]))
73 1
74 >>> twomax(np.array([False, True, False, False, False]))
75 2
76 >>> twomax(np.array([False, False, False, False, False, False]))
77 1
78 >>> twomax(np.array([False, False, True, False, False, False]))
79 2
80 >>> twomax(np.array([False, True, False, True, False, False]))
81 3
82 >>> twomax(np.array([False, True, False, True, False, True]))
83 4
84 >>> twomax(np.array([True, False, True, False, True, True]))
85 3
86 >>> twomax(np.array([False, True, True, True, True, True]))
87 2
88 >>> twomax(np.array([True, True, True, True, True, True]))
89 0
91 # n = 1 and 0 true bits
92 >>> twomax(np.array([0]))
93 1
95 # n = 1 and 1 true bit
96 >>> twomax(np.array([1]))
97 0
99 # n = 2 and 0 true bits
100 >>> twomax(np.array([0, 0]))
101 1
103 # n = 2 and 1 true bit
104 >>> twomax(np.array([0, 1]))
105 2
107 # n = 2 and 1 true bit
108 >>> twomax(np.array([0, 1]))
109 2
111 # n = 2 and 1 true bit
112 >>> twomax(np.array([0, 1]))
113 2
115 # n = 2 and 2 true bits
116 >>> twomax(np.array([1, 1]))
117 0
119 # n = 3 and 0 true bits
120 >>> twomax(np.array([0, 0, 0]))
121 1
123 # n = 3 and 1 true bit
124 >>> twomax(np.array([1, 0, 0]))
125 2
127 # n = 3 and 1 true bit
128 >>> twomax(np.array([0, 1, 0]))
129 2
131 # n = 3 and 1 true bit
132 >>> twomax(np.array([0, 0, 1]))
133 2
135 # n = 3 and 2 true bits
136 >>> twomax(np.array([1, 0, 1]))
137 2
139 # n = 3 and 2 true bits
140 >>> twomax(np.array([0, 1, 1]))
141 2
143 # n = 3 and 2 true bits
144 >>> twomax(np.array([1, 1, 0]))
145 2
147 # n = 3 and 3 true bits
148 >>> twomax(np.array([1, 1, 1]))
149 0
151 # n = 4 and 0 true bits
152 >>> twomax(np.array([0, 0, 0, 0]))
153 1
155 # n = 4 and 1 true bit
156 >>> twomax(np.array([1, 0, 0, 0]))
157 2
159 # n = 4 and 1 true bit
160 >>> twomax(np.array([0, 0, 0, 1]))
161 2
163 # n = 4 and 1 true bit
164 >>> twomax(np.array([1, 0, 0, 0]))
165 2
167 # n = 4 and 2 true bits
168 >>> twomax(np.array([0, 1, 1, 0]))
169 3
171 # n = 4 and 2 true bits
172 >>> twomax(np.array([0, 1, 0, 1]))
173 3
175 # n = 4 and 2 true bits
176 >>> twomax(np.array([0, 0, 1, 1]))
177 3
179 # n = 4 and 3 true bits
180 >>> twomax(np.array([1, 0, 1, 1]))
181 2
183 # n = 4 and 3 true bits
184 >>> twomax(np.array([1, 1, 1, 0]))
185 2
187 # n = 4 and 3 true bits
188 >>> twomax(np.array([1, 1, 0, 1]))
189 2
191 # n = 4 and 4 true bits
192 >>> twomax(np.array([1, 1, 1, 1]))
193 0
195 # n = 5 and 0 true bits
196 >>> twomax(np.array([0, 0, 0, 0, 0]))
197 1
199 # n = 5 and 1 true bit
200 >>> twomax(np.array([0, 0, 0, 1, 0]))
201 2
203 # n = 5 and 1 true bit
204 >>> twomax(np.array([0, 1, 0, 0, 0]))
205 2
207 # n = 5 and 1 true bit
208 >>> twomax(np.array([1, 0, 0, 0, 0]))
209 2
211 # n = 5 and 2 true bits
212 >>> twomax(np.array([0, 1, 1, 0, 0]))
213 3
215 # n = 5 and 2 true bits
216 >>> twomax(np.array([0, 1, 0, 0, 1]))
217 3
219 # n = 5 and 2 true bits
220 >>> twomax(np.array([1, 1, 0, 0, 0]))
221 3
223 # n = 5 and 3 true bits
224 >>> twomax(np.array([1, 1, 0, 1, 0]))
225 3
227 # n = 5 and 3 true bits
228 >>> twomax(np.array([0, 1, 0, 1, 1]))
229 3
231 # n = 5 and 3 true bits
232 >>> twomax(np.array([1, 0, 1, 1, 0]))
233 3
235 # n = 5 and 4 true bits
236 >>> twomax(np.array([0, 1, 1, 1, 1]))
237 2
239 # n = 5 and 4 true bits
240 >>> twomax(np.array([0, 1, 1, 1, 1]))
241 2
243 # n = 5 and 4 true bits
244 >>> twomax(np.array([1, 1, 0, 1, 1]))
245 2
247 # n = 5 and 5 true bits
248 >>> twomax(np.array([1, 1, 1, 1, 1]))
249 0
251 # n = 6 and 0 true bits
252 >>> twomax(np.array([0, 0, 0, 0, 0, 0]))
253 1
255 # n = 6 and 1 true bit
256 >>> twomax(np.array([0, 0, 0, 0, 0, 1]))
257 2
259 # n = 6 and 1 true bit
260 >>> twomax(np.array([1, 0, 0, 0, 0, 0]))
261 2
263 # n = 6 and 1 true bit
264 >>> twomax(np.array([0, 0, 1, 0, 0, 0]))
265 2
267 # n = 6 and 2 true bits
268 >>> twomax(np.array([1, 1, 0, 0, 0, 0]))
269 3
271 # n = 6 and 2 true bits
272 >>> twomax(np.array([0, 0, 0, 1, 0, 1]))
273 3
275 # n = 6 and 2 true bits
276 >>> twomax(np.array([1, 0, 0, 0, 1, 0]))
277 3
279 # n = 6 and 3 true bits
280 >>> twomax(np.array([0, 1, 1, 0, 1, 0]))
281 4
283 # n = 6 and 3 true bits
284 >>> twomax(np.array([0, 1, 1, 0, 0, 1]))
285 4
287 # n = 6 and 3 true bits
288 >>> twomax(np.array([1, 0, 1, 0, 1, 0]))
289 4
291 # n = 6 and 4 true bits
292 >>> twomax(np.array([1, 0, 0, 1, 1, 1]))
293 3
295 # n = 6 and 4 true bits
296 >>> twomax(np.array([1, 0, 1, 1, 0, 1]))
297 3
299 # n = 6 and 4 true bits
300 >>> twomax(np.array([1, 0, 0, 1, 1, 1]))
301 3
303 # n = 6 and 5 true bits
304 >>> twomax(np.array([0, 1, 1, 1, 1, 1]))
305 2
307 # n = 6 and 5 true bits
308 >>> twomax(np.array([1, 1, 0, 1, 1, 1]))
309 2
311 # n = 6 and 5 true bits
312 >>> twomax(np.array([1, 1, 0, 1, 1, 1]))
313 2
315 # n = 6 and 6 true bits
316 >>> twomax(np.array([1, 1, 1, 1, 1, 1]))
317 0
319 # n = 7 and 0 true bits
320 >>> twomax(np.array([0, 0, 0, 0, 0, 0, 0]))
321 1
323 # n = 7 and 1 true bit
324 >>> twomax(np.array([0, 0, 0, 0, 0, 1, 0]))
325 2
327 # n = 7 and 1 true bit
328 >>> twomax(np.array([0, 1, 0, 0, 0, 0, 0]))
329 2
331 # n = 7 and 1 true bit
332 >>> twomax(np.array([0, 0, 0, 0, 0, 1, 0]))
333 2
335 # n = 7 and 2 true bits
336 >>> twomax(np.array([0, 0, 1, 0, 0, 1, 0]))
337 3
339 # n = 7 and 2 true bits
340 >>> twomax(np.array([1, 1, 0, 0, 0, 0, 0]))
341 3
343 # n = 7 and 2 true bits
344 >>> twomax(np.array([0, 1, 0, 0, 0, 0, 1]))
345 3
347 # n = 7 and 3 true bits
348 >>> twomax(np.array([0, 1, 1, 0, 0, 0, 1]))
349 4
351 # n = 7 and 3 true bits
352 >>> twomax(np.array([1, 0, 0, 0, 1, 1, 0]))
353 4
355 # n = 7 and 3 true bits
356 >>> twomax(np.array([1, 0, 0, 0, 1, 1, 0]))
357 4
359 # n = 7 and 4 true bits
360 >>> twomax(np.array([1, 1, 0, 0, 1, 1, 0]))
361 4
363 # n = 7 and 4 true bits
364 >>> twomax(np.array([1, 1, 0, 1, 0, 0, 1]))
365 4
367 # n = 7 and 4 true bits
368 >>> twomax(np.array([1, 1, 0, 1, 1, 0, 0]))
369 4
371 # n = 7 and 5 true bits
372 >>> twomax(np.array([1, 1, 1, 0, 1, 0, 1]))
373 3
375 # n = 7 and 5 true bits
376 >>> twomax(np.array([1, 1, 1, 0, 0, 1, 1]))
377 3
379 # n = 7 and 5 true bits
380 >>> twomax(np.array([1, 1, 0, 1, 0, 1, 1]))
381 3
383 # n = 7 and 6 true bits
384 >>> twomax(np.array([1, 1, 0, 1, 1, 1, 1]))
385 2
387 # n = 7 and 6 true bits
388 >>> twomax(np.array([1, 1, 1, 1, 0, 1, 1]))
389 2
391 # n = 7 and 6 true bits
392 >>> twomax(np.array([1, 1, 1, 0, 1, 1, 1]))
393 2
395 # n = 7 and 7 true bits
396 >>> twomax(np.array([1, 1, 1, 1, 1, 1, 1]))
397 0
399 # n = 8 and 0 true bits
400 >>> twomax(np.array([0, 0, 0, 0, 0, 0, 0, 0]))
401 1
403 # n = 8 and 1 true bit
404 >>> twomax(np.array([0, 0, 0, 0, 0, 0, 0, 1]))
405 2
407 # n = 8 and 1 true bit
408 >>> twomax(np.array([0, 0, 0, 0, 0, 0, 1, 0]))
409 2
411 # n = 8 and 1 true bit
412 >>> twomax(np.array([0, 0, 0, 0, 1, 0, 0, 0]))
413 2
415 # n = 8 and 2 true bits
416 >>> twomax(np.array([0, 1, 0, 1, 0, 0, 0, 0]))
417 3
419 # n = 8 and 2 true bits
420 >>> twomax(np.array([0, 1, 0, 0, 1, 0, 0, 0]))
421 3
423 # n = 8 and 2 true bits
424 >>> twomax(np.array([0, 0, 0, 0, 1, 0, 0, 1]))
425 3
427 # n = 8 and 3 true bits
428 >>> twomax(np.array([0, 0, 0, 0, 1, 0, 1, 1]))
429 4
431 # n = 8 and 3 true bits
432 >>> twomax(np.array([0, 0, 0, 0, 0, 1, 1, 1]))
433 4
435 # n = 8 and 3 true bits
436 >>> twomax(np.array([0, 0, 0, 1, 1, 1, 0, 0]))
437 4
439 # n = 8 and 4 true bits
440 >>> twomax(np.array([1, 1, 0, 0, 1, 1, 0, 0]))
441 5
443 # n = 8 and 4 true bits
444 >>> twomax(np.array([1, 1, 0, 0, 0, 1, 1, 0]))
445 5
447 # n = 8 and 4 true bits
448 >>> twomax(np.array([0, 1, 1, 0, 1, 0, 1, 0]))
449 5
451 # n = 8 and 5 true bits
452 >>> twomax(np.array([1, 1, 0, 1, 0, 1, 1, 0]))
453 4
455 # n = 8 and 5 true bits
456 >>> twomax(np.array([0, 1, 0, 1, 0, 1, 1, 1]))
457 4
459 # n = 8 and 5 true bits
460 >>> twomax(np.array([1, 1, 0, 0, 1, 1, 1, 0]))
461 4
463 # n = 8 and 6 true bits
464 >>> twomax(np.array([1, 1, 1, 1, 0, 1, 1, 0]))
465 3
467 # n = 8 and 6 true bits
468 >>> twomax(np.array([1, 1, 1, 1, 0, 1, 0, 1]))
469 3
471 # n = 8 and 6 true bits
472 >>> twomax(np.array([0, 1, 1, 1, 1, 1, 1, 0]))
473 3
475 # n = 8 and 7 true bits
476 >>> twomax(np.array([1, 1, 1, 1, 0, 1, 1, 1]))
477 2
479 # n = 8 and 7 true bits
480 >>> twomax(np.array([1, 1, 1, 0, 1, 1, 1, 1]))
481 2
483 # n = 8 and 7 true bits
484 >>> twomax(np.array([1, 1, 1, 1, 1, 1, 0, 1]))
485 2
487 # n = 8 and 8 true bits
488 >>> twomax(np.array([1, 1, 1, 1, 1, 1, 1, 1]))
489 0
491 # n = 9 and 0 true bits
492 >>> twomax(np.array([0, 0, 0, 0, 0, 0, 0, 0, 0]))
493 1
495 # n = 9 and 1 true bit
496 >>> twomax(np.array([0, 0, 0, 0, 0, 0, 0, 1, 0]))
497 2
499 # n = 9 and 1 true bit
500 >>> twomax(np.array([0, 1, 0, 0, 0, 0, 0, 0, 0]))
501 2
503 # n = 9 and 1 true bit
504 >>> twomax(np.array([0, 1, 0, 0, 0, 0, 0, 0, 0]))
505 2
507 # n = 9 and 2 true bits
508 >>> twomax(np.array([0, 0, 0, 1, 0, 0, 0, 1, 0]))
509 3
511 # n = 9 and 2 true bits
512 >>> twomax(np.array([0, 0, 0, 0, 0, 1, 0, 0, 1]))
513 3
515 # n = 9 and 2 true bits
516 >>> twomax(np.array([0, 1, 0, 0, 0, 0, 0, 1, 0]))
517 3
519 # n = 9 and 3 true bits
520 >>> twomax(np.array([0, 1, 0, 0, 0, 0, 1, 0, 1]))
521 4
523 # n = 9 and 3 true bits
524 >>> twomax(np.array([0, 1, 0, 1, 0, 0, 0, 0, 1]))
525 4
527 # n = 9 and 3 true bits
528 >>> twomax(np.array([0, 0, 1, 0, 0, 1, 0, 1, 0]))
529 4
531 # n = 9 and 4 true bits
532 >>> twomax(np.array([1, 1, 0, 0, 0, 0, 0, 1, 1]))
533 5
535 # n = 9 and 4 true bits
536 >>> twomax(np.array([0, 0, 1, 0, 0, 1, 1, 1, 0]))
537 5
539 # n = 9 and 4 true bits
540 >>> twomax(np.array([0, 1, 0, 1, 0, 1, 0, 0, 1]))
541 5
543 # n = 9 and 5 true bits
544 >>> twomax(np.array([1, 1, 1, 0, 0, 0, 0, 1, 1]))
545 5
547 # n = 9 and 5 true bits
548 >>> twomax(np.array([0, 0, 0, 1, 1, 1, 0, 1, 1]))
549 5
551 # n = 9 and 5 true bits
552 >>> twomax(np.array([0, 0, 1, 1, 0, 1, 1, 1, 0]))
553 5
555 # n = 9 and 6 true bits
556 >>> twomax(np.array([1, 1, 0, 1, 1, 0, 0, 1, 1]))
557 4
559 # n = 9 and 6 true bits
560 >>> twomax(np.array([1, 0, 1, 1, 0, 1, 1, 0, 1]))
561 4
563 # n = 9 and 6 true bits
564 >>> twomax(np.array([1, 0, 1, 1, 1, 0, 1, 0, 1]))
565 4
567 # n = 9 and 7 true bits
568 >>> twomax(np.array([1, 1, 1, 1, 1, 0, 0, 1, 1]))
569 3
571 # n = 9 and 7 true bits
572 >>> twomax(np.array([1, 1, 1, 0, 0, 1, 1, 1, 1]))
573 3
575 # n = 9 and 7 true bits
576 >>> twomax(np.array([1, 0, 1, 1, 1, 0, 1, 1, 1]))
577 3
579 # n = 9 and 8 true bits
580 >>> twomax(np.array([1, 1, 0, 1, 1, 1, 1, 1, 1]))
581 2
583 # n = 9 and 8 true bits
584 >>> twomax(np.array([1, 1, 1, 1, 1, 0, 1, 1, 1]))
585 2
587 # n = 9 and 8 true bits
588 >>> twomax(np.array([1, 1, 1, 1, 1, 1, 0, 1, 1]))
589 2
591 # n = 9 and 9 true bits
592 >>> twomax(np.array([1, 1, 1, 1, 1, 1, 1, 1, 1]))
593 0
595 # n = 10 and 0 true bits
596 >>> twomax(np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]))
597 1
599 # n = 10 and 1 true bit
600 >>> twomax(np.array([0, 0, 0, 0, 0, 0, 0, 1, 0, 0]))
601 2
603 # n = 10 and 1 true bit
604 >>> twomax(np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 1]))
605 2
607 # n = 10 and 1 true bit
608 >>> twomax(np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 1]))
609 2
611 # n = 10 and 2 true bits
612 >>> twomax(np.array([1, 0, 0, 0, 0, 0, 1, 0, 0, 0]))
613 3
615 # n = 10 and 2 true bits
616 >>> twomax(np.array([0, 0, 0, 1, 1, 0, 0, 0, 0, 0]))
617 3
619 # n = 10 and 2 true bits
620 >>> twomax(np.array([0, 0, 1, 0, 0, 0, 0, 0, 1, 0]))
621 3
623 # n = 10 and 3 true bits
624 >>> twomax(np.array([0, 0, 1, 0, 1, 0, 0, 0, 0, 1]))
625 4
627 # n = 10 and 3 true bits
628 >>> twomax(np.array([0, 1, 0, 0, 0, 0, 0, 0, 1, 1]))
629 4
631 # n = 10 and 3 true bits
632 >>> twomax(np.array([0, 1, 1, 0, 1, 0, 0, 0, 0, 0]))
633 4
635 # n = 10 and 4 true bits
636 >>> twomax(np.array([1, 1, 0, 1, 1, 0, 0, 0, 0, 0]))
637 5
639 # n = 10 and 4 true bits
640 >>> twomax(np.array([1, 1, 0, 0, 0, 0, 0, 0, 1, 1]))
641 5
643 # n = 10 and 4 true bits
644 >>> twomax(np.array([1, 0, 1, 0, 0, 1, 1, 0, 0, 0]))
645 5
647 # n = 10 and 5 true bits
648 >>> twomax(np.array([0, 0, 0, 1, 0, 1, 1, 1, 1, 0]))
649 6
651 # n = 10 and 5 true bits
652 >>> twomax(np.array([0, 1, 1, 1, 1, 0, 0, 0, 1, 0]))
653 6
655 # n = 10 and 5 true bits
656 >>> twomax(np.array([1, 0, 0, 1, 1, 1, 0, 1, 0, 0]))
657 6
659 # n = 10 and 6 true bits
660 >>> twomax(np.array([1, 1, 1, 1, 0, 0, 1, 0, 0, 1]))
661 5
663 # n = 10 and 6 true bits
664 >>> twomax(np.array([0, 1, 0, 1, 1, 1, 1, 0, 0, 1]))
665 5
667 # n = 10 and 6 true bits
668 >>> twomax(np.array([0, 1, 0, 1, 1, 0, 1, 1, 1, 0]))
669 5
671 # n = 10 and 7 true bits
672 >>> twomax(np.array([1, 0, 1, 1, 0, 1, 0, 1, 1, 1]))
673 4
675 # n = 10 and 7 true bits
676 >>> twomax(np.array([1, 1, 1, 0, 0, 1, 1, 1, 1, 0]))
677 4
679 # n = 10 and 7 true bits
680 >>> twomax(np.array([0, 1, 0, 1, 0, 1, 1, 1, 1, 1]))
681 4
683 # n = 10 and 8 true bits
684 >>> twomax(np.array([0, 1, 1, 1, 1, 1, 1, 0, 1, 1]))
685 3
687 # n = 10 and 8 true bits
688 >>> twomax(np.array([1, 1, 1, 1, 1, 1, 1, 1, 0, 0]))
689 3
691 # n = 10 and 8 true bits
692 >>> twomax(np.array([0, 0, 1, 1, 1, 1, 1, 1, 1, 1]))
693 3
695 # n = 10 and 9 true bits
696 >>> twomax(np.array([1, 1, 1, 1, 1, 1, 1, 1, 0, 1]))
697 2
699 # n = 10 and 9 true bits
700 >>> twomax(np.array([0, 1, 1, 1, 1, 1, 1, 1, 1, 1]))
701 2
703 # n = 10 and 9 true bits
704 >>> twomax(np.array([1, 0, 1, 1, 1, 1, 1, 1, 1, 1]))
705 2
707 # n = 10 and 10 true bits
708 >>> twomax(np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]))
709 0
710 """
711 s: Final[int] = len(x)
712 number_of_ones: Final[int] = int(x.sum())
713 return 0 if s == number_of_ones else (
714 1 + s - max(number_of_ones, s - number_of_ones))
717class TwoMax(BitStringProblem):
718 """The TwoMax benchmark problem."""
720 def __init__(self, n: int) -> None:
721 """
722 Initialize the twomax objective function.
724 :param n: the dimension of the problem
726 >>> TwoMax(2).n
727 2
728 >>> TwoMax(4).evaluate(np.array([True, True, False, True]))
729 2
730 """
731 super().__init__(n)
732 self.evaluate = twomax # type: ignore
734 def __str__(self) -> str:
735 """
736 Get the name of the twomax objective function.
738 :return: `twomax_` + length of string
740 >>> print(TwoMax(13))
741 twomax_13
742 """
743 return f"twomax_{self.n}"
745 def upper_bound(self) -> int:
746 """
747 Get the upper bound of the twomax problem.
749 :return: the length of the bit string integer-divided by 2, plus 1
751 >>> TwoMax(15).upper_bound()
752 8
754 >>> TwoMax(5).upper_bound()
755 3
756 """
757 return (self.n // 2) + 1
759 @classmethod
760 def default_instances(
761 cls: type, scale_min: int = 3, scale_max: int = 333) \
762 -> Iterator[Callable[[], "TwoMax"]]:
763 """
764 Get the 77 default instances of the :class:`TwoMax` problem.
766 :param scale_min: the minimum permitted scale, by default `3`
767 :param scale_max: the maximum permitted scale, by default `333`
768 :returns: a sequence of default :class:`TwoMax` instances
770 >>> len(list(TwoMax.default_instances()))
771 77
773 >>> [x() for x in TwoMax.default_instances()]
774 [twomax_3, twomax_4, twomax_5, twomax_6, twomax_7, twomax_8, \
775twomax_9, twomax_10, twomax_11, twomax_12, twomax_13, twomax_14, twomax_15, \
776twomax_16, twomax_17, twomax_18, twomax_19, twomax_20, twomax_21, twomax_22, \
777twomax_23, twomax_24, twomax_25, twomax_26, twomax_27, twomax_28, twomax_29, \
778twomax_30, twomax_31, twomax_32, twomax_33, twomax_36, twomax_40, twomax_41, \
779twomax_42, twomax_44, twomax_48, twomax_49, twomax_50, twomax_55, twomax_59, \
780twomax_60, twomax_64, twomax_66, twomax_70, twomax_77, twomax_79, twomax_80, \
781twomax_81, twomax_85, twomax_88, twomax_90, twomax_96, twomax_99, \
782twomax_100, twomax_107, twomax_111, twomax_121, twomax_125, twomax_128, \
783twomax_144, twomax_149, twomax_169, twomax_170, twomax_192, twomax_196, \
784twomax_199, twomax_200, twomax_222, twomax_225, twomax_243, twomax_256, \
785twomax_269, twomax_289, twomax_300, twomax_324, twomax_333]
786 """
787 return cast("Iterator[Callable[[], TwoMax]]",
788 super().default_instances( # type: ignore
789 scale_min, scale_max))