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

1""" 

2The TwoMax problem. 

3 

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`. 

9 

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)`. 

16 

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 

39 

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 

49 

50import numba # type: ignore 

51import numpy as np 

52 

53from moptipy.examples.bitstrings.bitstring_problem import BitStringProblem 

54 

55 

56@numba.njit(nogil=True, cache=True) 

57def twomax(x: np.ndarray) -> int: 

58 """ 

59 Compute the objective value of the TwoMax problem. 

60 

61 :param x: the np array 

62 :return: the sum of the indices of the first two ones 

63 

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 

90 

91 # n = 1 and 0 true bits 

92 >>> twomax(np.array([0])) 

93 1 

94 

95 # n = 1 and 1 true bit 

96 >>> twomax(np.array([1])) 

97 0 

98 

99 # n = 2 and 0 true bits 

100 >>> twomax(np.array([0, 0])) 

101 1 

102 

103 # n = 2 and 1 true bit 

104 >>> twomax(np.array([0, 1])) 

105 2 

106 

107 # n = 2 and 1 true bit 

108 >>> twomax(np.array([0, 1])) 

109 2 

110 

111 # n = 2 and 1 true bit 

112 >>> twomax(np.array([0, 1])) 

113 2 

114 

115 # n = 2 and 2 true bits 

116 >>> twomax(np.array([1, 1])) 

117 0 

118 

119 # n = 3 and 0 true bits 

120 >>> twomax(np.array([0, 0, 0])) 

121 1 

122 

123 # n = 3 and 1 true bit 

124 >>> twomax(np.array([1, 0, 0])) 

125 2 

126 

127 # n = 3 and 1 true bit 

128 >>> twomax(np.array([0, 1, 0])) 

129 2 

130 

131 # n = 3 and 1 true bit 

132 >>> twomax(np.array([0, 0, 1])) 

133 2 

134 

135 # n = 3 and 2 true bits 

136 >>> twomax(np.array([1, 0, 1])) 

137 2 

138 

139 # n = 3 and 2 true bits 

140 >>> twomax(np.array([0, 1, 1])) 

141 2 

142 

143 # n = 3 and 2 true bits 

144 >>> twomax(np.array([1, 1, 0])) 

145 2 

146 

147 # n = 3 and 3 true bits 

148 >>> twomax(np.array([1, 1, 1])) 

149 0 

150 

151 # n = 4 and 0 true bits 

152 >>> twomax(np.array([0, 0, 0, 0])) 

153 1 

154 

155 # n = 4 and 1 true bit 

156 >>> twomax(np.array([1, 0, 0, 0])) 

157 2 

158 

159 # n = 4 and 1 true bit 

160 >>> twomax(np.array([0, 0, 0, 1])) 

161 2 

162 

163 # n = 4 and 1 true bit 

164 >>> twomax(np.array([1, 0, 0, 0])) 

165 2 

166 

167 # n = 4 and 2 true bits 

168 >>> twomax(np.array([0, 1, 1, 0])) 

169 3 

170 

171 # n = 4 and 2 true bits 

172 >>> twomax(np.array([0, 1, 0, 1])) 

173 3 

174 

175 # n = 4 and 2 true bits 

176 >>> twomax(np.array([0, 0, 1, 1])) 

177 3 

178 

179 # n = 4 and 3 true bits 

180 >>> twomax(np.array([1, 0, 1, 1])) 

181 2 

182 

183 # n = 4 and 3 true bits 

184 >>> twomax(np.array([1, 1, 1, 0])) 

185 2 

186 

187 # n = 4 and 3 true bits 

188 >>> twomax(np.array([1, 1, 0, 1])) 

189 2 

190 

191 # n = 4 and 4 true bits 

192 >>> twomax(np.array([1, 1, 1, 1])) 

193 0 

194 

195 # n = 5 and 0 true bits 

196 >>> twomax(np.array([0, 0, 0, 0, 0])) 

197 1 

198 

199 # n = 5 and 1 true bit 

200 >>> twomax(np.array([0, 0, 0, 1, 0])) 

201 2 

202 

203 # n = 5 and 1 true bit 

204 >>> twomax(np.array([0, 1, 0, 0, 0])) 

205 2 

206 

207 # n = 5 and 1 true bit 

208 >>> twomax(np.array([1, 0, 0, 0, 0])) 

209 2 

210 

211 # n = 5 and 2 true bits 

212 >>> twomax(np.array([0, 1, 1, 0, 0])) 

213 3 

214 

215 # n = 5 and 2 true bits 

216 >>> twomax(np.array([0, 1, 0, 0, 1])) 

217 3 

218 

219 # n = 5 and 2 true bits 

220 >>> twomax(np.array([1, 1, 0, 0, 0])) 

221 3 

222 

223 # n = 5 and 3 true bits 

224 >>> twomax(np.array([1, 1, 0, 1, 0])) 

225 3 

226 

227 # n = 5 and 3 true bits 

228 >>> twomax(np.array([0, 1, 0, 1, 1])) 

229 3 

230 

231 # n = 5 and 3 true bits 

232 >>> twomax(np.array([1, 0, 1, 1, 0])) 

233 3 

234 

235 # n = 5 and 4 true bits 

236 >>> twomax(np.array([0, 1, 1, 1, 1])) 

237 2 

238 

239 # n = 5 and 4 true bits 

240 >>> twomax(np.array([0, 1, 1, 1, 1])) 

241 2 

242 

243 # n = 5 and 4 true bits 

244 >>> twomax(np.array([1, 1, 0, 1, 1])) 

245 2 

246 

247 # n = 5 and 5 true bits 

248 >>> twomax(np.array([1, 1, 1, 1, 1])) 

249 0 

250 

251 # n = 6 and 0 true bits 

252 >>> twomax(np.array([0, 0, 0, 0, 0, 0])) 

253 1 

254 

255 # n = 6 and 1 true bit 

256 >>> twomax(np.array([0, 0, 0, 0, 0, 1])) 

257 2 

258 

259 # n = 6 and 1 true bit 

260 >>> twomax(np.array([1, 0, 0, 0, 0, 0])) 

261 2 

262 

263 # n = 6 and 1 true bit 

264 >>> twomax(np.array([0, 0, 1, 0, 0, 0])) 

265 2 

266 

267 # n = 6 and 2 true bits 

268 >>> twomax(np.array([1, 1, 0, 0, 0, 0])) 

269 3 

270 

271 # n = 6 and 2 true bits 

272 >>> twomax(np.array([0, 0, 0, 1, 0, 1])) 

273 3 

274 

275 # n = 6 and 2 true bits 

276 >>> twomax(np.array([1, 0, 0, 0, 1, 0])) 

277 3 

278 

279 # n = 6 and 3 true bits 

280 >>> twomax(np.array([0, 1, 1, 0, 1, 0])) 

281 4 

282 

283 # n = 6 and 3 true bits 

284 >>> twomax(np.array([0, 1, 1, 0, 0, 1])) 

285 4 

286 

287 # n = 6 and 3 true bits 

288 >>> twomax(np.array([1, 0, 1, 0, 1, 0])) 

289 4 

290 

291 # n = 6 and 4 true bits 

292 >>> twomax(np.array([1, 0, 0, 1, 1, 1])) 

293 3 

294 

295 # n = 6 and 4 true bits 

296 >>> twomax(np.array([1, 0, 1, 1, 0, 1])) 

297 3 

298 

299 # n = 6 and 4 true bits 

300 >>> twomax(np.array([1, 0, 0, 1, 1, 1])) 

301 3 

302 

303 # n = 6 and 5 true bits 

304 >>> twomax(np.array([0, 1, 1, 1, 1, 1])) 

305 2 

306 

307 # n = 6 and 5 true bits 

308 >>> twomax(np.array([1, 1, 0, 1, 1, 1])) 

309 2 

310 

311 # n = 6 and 5 true bits 

312 >>> twomax(np.array([1, 1, 0, 1, 1, 1])) 

313 2 

314 

315 # n = 6 and 6 true bits 

316 >>> twomax(np.array([1, 1, 1, 1, 1, 1])) 

317 0 

318 

319 # n = 7 and 0 true bits 

320 >>> twomax(np.array([0, 0, 0, 0, 0, 0, 0])) 

321 1 

322 

323 # n = 7 and 1 true bit 

324 >>> twomax(np.array([0, 0, 0, 0, 0, 1, 0])) 

325 2 

326 

327 # n = 7 and 1 true bit 

328 >>> twomax(np.array([0, 1, 0, 0, 0, 0, 0])) 

329 2 

330 

331 # n = 7 and 1 true bit 

332 >>> twomax(np.array([0, 0, 0, 0, 0, 1, 0])) 

333 2 

334 

335 # n = 7 and 2 true bits 

336 >>> twomax(np.array([0, 0, 1, 0, 0, 1, 0])) 

337 3 

338 

339 # n = 7 and 2 true bits 

340 >>> twomax(np.array([1, 1, 0, 0, 0, 0, 0])) 

341 3 

342 

343 # n = 7 and 2 true bits 

344 >>> twomax(np.array([0, 1, 0, 0, 0, 0, 1])) 

345 3 

346 

347 # n = 7 and 3 true bits 

348 >>> twomax(np.array([0, 1, 1, 0, 0, 0, 1])) 

349 4 

350 

351 # n = 7 and 3 true bits 

352 >>> twomax(np.array([1, 0, 0, 0, 1, 1, 0])) 

353 4 

354 

355 # n = 7 and 3 true bits 

356 >>> twomax(np.array([1, 0, 0, 0, 1, 1, 0])) 

357 4 

358 

359 # n = 7 and 4 true bits 

360 >>> twomax(np.array([1, 1, 0, 0, 1, 1, 0])) 

361 4 

362 

363 # n = 7 and 4 true bits 

364 >>> twomax(np.array([1, 1, 0, 1, 0, 0, 1])) 

365 4 

366 

367 # n = 7 and 4 true bits 

368 >>> twomax(np.array([1, 1, 0, 1, 1, 0, 0])) 

369 4 

370 

371 # n = 7 and 5 true bits 

372 >>> twomax(np.array([1, 1, 1, 0, 1, 0, 1])) 

373 3 

374 

375 # n = 7 and 5 true bits 

376 >>> twomax(np.array([1, 1, 1, 0, 0, 1, 1])) 

377 3 

378 

379 # n = 7 and 5 true bits 

380 >>> twomax(np.array([1, 1, 0, 1, 0, 1, 1])) 

381 3 

382 

383 # n = 7 and 6 true bits 

384 >>> twomax(np.array([1, 1, 0, 1, 1, 1, 1])) 

385 2 

386 

387 # n = 7 and 6 true bits 

388 >>> twomax(np.array([1, 1, 1, 1, 0, 1, 1])) 

389 2 

390 

391 # n = 7 and 6 true bits 

392 >>> twomax(np.array([1, 1, 1, 0, 1, 1, 1])) 

393 2 

394 

395 # n = 7 and 7 true bits 

396 >>> twomax(np.array([1, 1, 1, 1, 1, 1, 1])) 

397 0 

398 

399 # n = 8 and 0 true bits 

400 >>> twomax(np.array([0, 0, 0, 0, 0, 0, 0, 0])) 

401 1 

402 

403 # n = 8 and 1 true bit 

404 >>> twomax(np.array([0, 0, 0, 0, 0, 0, 0, 1])) 

405 2 

406 

407 # n = 8 and 1 true bit 

408 >>> twomax(np.array([0, 0, 0, 0, 0, 0, 1, 0])) 

409 2 

410 

411 # n = 8 and 1 true bit 

412 >>> twomax(np.array([0, 0, 0, 0, 1, 0, 0, 0])) 

413 2 

414 

415 # n = 8 and 2 true bits 

416 >>> twomax(np.array([0, 1, 0, 1, 0, 0, 0, 0])) 

417 3 

418 

419 # n = 8 and 2 true bits 

420 >>> twomax(np.array([0, 1, 0, 0, 1, 0, 0, 0])) 

421 3 

422 

423 # n = 8 and 2 true bits 

424 >>> twomax(np.array([0, 0, 0, 0, 1, 0, 0, 1])) 

425 3 

426 

427 # n = 8 and 3 true bits 

428 >>> twomax(np.array([0, 0, 0, 0, 1, 0, 1, 1])) 

429 4 

430 

431 # n = 8 and 3 true bits 

432 >>> twomax(np.array([0, 0, 0, 0, 0, 1, 1, 1])) 

433 4 

434 

435 # n = 8 and 3 true bits 

436 >>> twomax(np.array([0, 0, 0, 1, 1, 1, 0, 0])) 

437 4 

438 

439 # n = 8 and 4 true bits 

440 >>> twomax(np.array([1, 1, 0, 0, 1, 1, 0, 0])) 

441 5 

442 

443 # n = 8 and 4 true bits 

444 >>> twomax(np.array([1, 1, 0, 0, 0, 1, 1, 0])) 

445 5 

446 

447 # n = 8 and 4 true bits 

448 >>> twomax(np.array([0, 1, 1, 0, 1, 0, 1, 0])) 

449 5 

450 

451 # n = 8 and 5 true bits 

452 >>> twomax(np.array([1, 1, 0, 1, 0, 1, 1, 0])) 

453 4 

454 

455 # n = 8 and 5 true bits 

456 >>> twomax(np.array([0, 1, 0, 1, 0, 1, 1, 1])) 

457 4 

458 

459 # n = 8 and 5 true bits 

460 >>> twomax(np.array([1, 1, 0, 0, 1, 1, 1, 0])) 

461 4 

462 

463 # n = 8 and 6 true bits 

464 >>> twomax(np.array([1, 1, 1, 1, 0, 1, 1, 0])) 

465 3 

466 

467 # n = 8 and 6 true bits 

468 >>> twomax(np.array([1, 1, 1, 1, 0, 1, 0, 1])) 

469 3 

470 

471 # n = 8 and 6 true bits 

472 >>> twomax(np.array([0, 1, 1, 1, 1, 1, 1, 0])) 

473 3 

474 

475 # n = 8 and 7 true bits 

476 >>> twomax(np.array([1, 1, 1, 1, 0, 1, 1, 1])) 

477 2 

478 

479 # n = 8 and 7 true bits 

480 >>> twomax(np.array([1, 1, 1, 0, 1, 1, 1, 1])) 

481 2 

482 

483 # n = 8 and 7 true bits 

484 >>> twomax(np.array([1, 1, 1, 1, 1, 1, 0, 1])) 

485 2 

486 

487 # n = 8 and 8 true bits 

488 >>> twomax(np.array([1, 1, 1, 1, 1, 1, 1, 1])) 

489 0 

490 

491 # n = 9 and 0 true bits 

492 >>> twomax(np.array([0, 0, 0, 0, 0, 0, 0, 0, 0])) 

493 1 

494 

495 # n = 9 and 1 true bit 

496 >>> twomax(np.array([0, 0, 0, 0, 0, 0, 0, 1, 0])) 

497 2 

498 

499 # n = 9 and 1 true bit 

500 >>> twomax(np.array([0, 1, 0, 0, 0, 0, 0, 0, 0])) 

501 2 

502 

503 # n = 9 and 1 true bit 

504 >>> twomax(np.array([0, 1, 0, 0, 0, 0, 0, 0, 0])) 

505 2 

506 

507 # n = 9 and 2 true bits 

508 >>> twomax(np.array([0, 0, 0, 1, 0, 0, 0, 1, 0])) 

509 3 

510 

511 # n = 9 and 2 true bits 

512 >>> twomax(np.array([0, 0, 0, 0, 0, 1, 0, 0, 1])) 

513 3 

514 

515 # n = 9 and 2 true bits 

516 >>> twomax(np.array([0, 1, 0, 0, 0, 0, 0, 1, 0])) 

517 3 

518 

519 # n = 9 and 3 true bits 

520 >>> twomax(np.array([0, 1, 0, 0, 0, 0, 1, 0, 1])) 

521 4 

522 

523 # n = 9 and 3 true bits 

524 >>> twomax(np.array([0, 1, 0, 1, 0, 0, 0, 0, 1])) 

525 4 

526 

527 # n = 9 and 3 true bits 

528 >>> twomax(np.array([0, 0, 1, 0, 0, 1, 0, 1, 0])) 

529 4 

530 

531 # n = 9 and 4 true bits 

532 >>> twomax(np.array([1, 1, 0, 0, 0, 0, 0, 1, 1])) 

533 5 

534 

535 # n = 9 and 4 true bits 

536 >>> twomax(np.array([0, 0, 1, 0, 0, 1, 1, 1, 0])) 

537 5 

538 

539 # n = 9 and 4 true bits 

540 >>> twomax(np.array([0, 1, 0, 1, 0, 1, 0, 0, 1])) 

541 5 

542 

543 # n = 9 and 5 true bits 

544 >>> twomax(np.array([1, 1, 1, 0, 0, 0, 0, 1, 1])) 

545 5 

546 

547 # n = 9 and 5 true bits 

548 >>> twomax(np.array([0, 0, 0, 1, 1, 1, 0, 1, 1])) 

549 5 

550 

551 # n = 9 and 5 true bits 

552 >>> twomax(np.array([0, 0, 1, 1, 0, 1, 1, 1, 0])) 

553 5 

554 

555 # n = 9 and 6 true bits 

556 >>> twomax(np.array([1, 1, 0, 1, 1, 0, 0, 1, 1])) 

557 4 

558 

559 # n = 9 and 6 true bits 

560 >>> twomax(np.array([1, 0, 1, 1, 0, 1, 1, 0, 1])) 

561 4 

562 

563 # n = 9 and 6 true bits 

564 >>> twomax(np.array([1, 0, 1, 1, 1, 0, 1, 0, 1])) 

565 4 

566 

567 # n = 9 and 7 true bits 

568 >>> twomax(np.array([1, 1, 1, 1, 1, 0, 0, 1, 1])) 

569 3 

570 

571 # n = 9 and 7 true bits 

572 >>> twomax(np.array([1, 1, 1, 0, 0, 1, 1, 1, 1])) 

573 3 

574 

575 # n = 9 and 7 true bits 

576 >>> twomax(np.array([1, 0, 1, 1, 1, 0, 1, 1, 1])) 

577 3 

578 

579 # n = 9 and 8 true bits 

580 >>> twomax(np.array([1, 1, 0, 1, 1, 1, 1, 1, 1])) 

581 2 

582 

583 # n = 9 and 8 true bits 

584 >>> twomax(np.array([1, 1, 1, 1, 1, 0, 1, 1, 1])) 

585 2 

586 

587 # n = 9 and 8 true bits 

588 >>> twomax(np.array([1, 1, 1, 1, 1, 1, 0, 1, 1])) 

589 2 

590 

591 # n = 9 and 9 true bits 

592 >>> twomax(np.array([1, 1, 1, 1, 1, 1, 1, 1, 1])) 

593 0 

594 

595 # n = 10 and 0 true bits 

596 >>> twomax(np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])) 

597 1 

598 

599 # n = 10 and 1 true bit 

600 >>> twomax(np.array([0, 0, 0, 0, 0, 0, 0, 1, 0, 0])) 

601 2 

602 

603 # n = 10 and 1 true bit 

604 >>> twomax(np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 1])) 

605 2 

606 

607 # n = 10 and 1 true bit 

608 >>> twomax(np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 1])) 

609 2 

610 

611 # n = 10 and 2 true bits 

612 >>> twomax(np.array([1, 0, 0, 0, 0, 0, 1, 0, 0, 0])) 

613 3 

614 

615 # n = 10 and 2 true bits 

616 >>> twomax(np.array([0, 0, 0, 1, 1, 0, 0, 0, 0, 0])) 

617 3 

618 

619 # n = 10 and 2 true bits 

620 >>> twomax(np.array([0, 0, 1, 0, 0, 0, 0, 0, 1, 0])) 

621 3 

622 

623 # n = 10 and 3 true bits 

624 >>> twomax(np.array([0, 0, 1, 0, 1, 0, 0, 0, 0, 1])) 

625 4 

626 

627 # n = 10 and 3 true bits 

628 >>> twomax(np.array([0, 1, 0, 0, 0, 0, 0, 0, 1, 1])) 

629 4 

630 

631 # n = 10 and 3 true bits 

632 >>> twomax(np.array([0, 1, 1, 0, 1, 0, 0, 0, 0, 0])) 

633 4 

634 

635 # n = 10 and 4 true bits 

636 >>> twomax(np.array([1, 1, 0, 1, 1, 0, 0, 0, 0, 0])) 

637 5 

638 

639 # n = 10 and 4 true bits 

640 >>> twomax(np.array([1, 1, 0, 0, 0, 0, 0, 0, 1, 1])) 

641 5 

642 

643 # n = 10 and 4 true bits 

644 >>> twomax(np.array([1, 0, 1, 0, 0, 1, 1, 0, 0, 0])) 

645 5 

646 

647 # n = 10 and 5 true bits 

648 >>> twomax(np.array([0, 0, 0, 1, 0, 1, 1, 1, 1, 0])) 

649 6 

650 

651 # n = 10 and 5 true bits 

652 >>> twomax(np.array([0, 1, 1, 1, 1, 0, 0, 0, 1, 0])) 

653 6 

654 

655 # n = 10 and 5 true bits 

656 >>> twomax(np.array([1, 0, 0, 1, 1, 1, 0, 1, 0, 0])) 

657 6 

658 

659 # n = 10 and 6 true bits 

660 >>> twomax(np.array([1, 1, 1, 1, 0, 0, 1, 0, 0, 1])) 

661 5 

662 

663 # n = 10 and 6 true bits 

664 >>> twomax(np.array([0, 1, 0, 1, 1, 1, 1, 0, 0, 1])) 

665 5 

666 

667 # n = 10 and 6 true bits 

668 >>> twomax(np.array([0, 1, 0, 1, 1, 0, 1, 1, 1, 0])) 

669 5 

670 

671 # n = 10 and 7 true bits 

672 >>> twomax(np.array([1, 0, 1, 1, 0, 1, 0, 1, 1, 1])) 

673 4 

674 

675 # n = 10 and 7 true bits 

676 >>> twomax(np.array([1, 1, 1, 0, 0, 1, 1, 1, 1, 0])) 

677 4 

678 

679 # n = 10 and 7 true bits 

680 >>> twomax(np.array([0, 1, 0, 1, 0, 1, 1, 1, 1, 1])) 

681 4 

682 

683 # n = 10 and 8 true bits 

684 >>> twomax(np.array([0, 1, 1, 1, 1, 1, 1, 0, 1, 1])) 

685 3 

686 

687 # n = 10 and 8 true bits 

688 >>> twomax(np.array([1, 1, 1, 1, 1, 1, 1, 1, 0, 0])) 

689 3 

690 

691 # n = 10 and 8 true bits 

692 >>> twomax(np.array([0, 0, 1, 1, 1, 1, 1, 1, 1, 1])) 

693 3 

694 

695 # n = 10 and 9 true bits 

696 >>> twomax(np.array([1, 1, 1, 1, 1, 1, 1, 1, 0, 1])) 

697 2 

698 

699 # n = 10 and 9 true bits 

700 >>> twomax(np.array([0, 1, 1, 1, 1, 1, 1, 1, 1, 1])) 

701 2 

702 

703 # n = 10 and 9 true bits 

704 >>> twomax(np.array([1, 0, 1, 1, 1, 1, 1, 1, 1, 1])) 

705 2 

706 

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)) 

715 

716 

717class TwoMax(BitStringProblem): 

718 """The TwoMax benchmark problem.""" 

719 

720 def __init__(self, n: int) -> None: 

721 """ 

722 Initialize the twomax objective function. 

723 

724 :param n: the dimension of the problem 

725 

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 

733 

734 def __str__(self) -> str: 

735 """ 

736 Get the name of the twomax objective function. 

737 

738 :return: `twomax_` + length of string 

739 

740 >>> print(TwoMax(13)) 

741 twomax_13 

742 """ 

743 return f"twomax_{self.n}" 

744 

745 def upper_bound(self) -> int: 

746 """ 

747 Get the upper bound of the twomax problem. 

748 

749 :return: the length of the bit string integer-divided by 2, plus 1 

750 

751 >>> TwoMax(15).upper_bound() 

752 8 

753 

754 >>> TwoMax(5).upper_bound() 

755 3 

756 """ 

757 return (self.n // 2) + 1 

758 

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. 

765 

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 

769 

770 >>> len(list(TwoMax.default_instances())) 

771 77 

772 

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))