Coverage for moptipy / examples / bitstrings / trap.py: 83%

18 statements  

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

1""" 

2The well-known Trap problem. 

3 

4The Trap function is similar to OneMax, but swaps the worst possible solution 

5with the global optimum. This means that the best-possible objective value, 0, 

6is reached for the string of all `False` bits. The worst objective value, `n`, 

7is reached by the strings with exactly one `True` bit. 

8 

91. Stefan Droste, Thomas Jansen, and Ingo Wegener. On the Analysis of the 

10 (1+1) Evolutionary Algorithm. *Theoretical Computer Science.* 

11 276(1-2):51-81. April 2002. 

12 doi: https://doi.org/10.1016/S0304-3975(01)00182-7 

132. Siegfried Nijssen and Thomas Bäck. An Analysis of the Behavior of 

14 Simplified Evolutionary Algorithms on Trap Functions. IEEE Transactions on 

15 Evolutionary Computation. 7(1):11-22. 2003. 

16 doi: https://doi.org/10.1109/TEVC.2002.806169 

173. Thomas Weise, Zhize Wu, Xinlu Li, and Yan Chen. Frequency Fitness 

18 Assignment: Making Optimization Algorithms Invariant under Bijective 

19 Transformations of the Objective Function Value. *IEEE Transactions on 

20 Evolutionary Computation* 25(2):307-319. April 2021. Preprint available at 

21 arXiv:2001.01416v5 [cs.NE] 15 Oct 2020. 

22 https://dx.doi.org/10.1109/TEVC.2020.3032090 

234. Thomas Weise, Zhize Wu, Xinlu Li, Yan Chen, and Jörg Lässig. Frequency 

24 Fitness Assignment: Optimization without Bias for Good Solutions can be 

25 Efficient. *IEEE Transactions on Evolutionary Computation (TEVC)*. 

26 27(4):980-992. August 2023. 

27 doi: https://doi.org/10.1109/TEVC.2022.3191698 

28""" 

29from typing import Callable, Final, Iterator, cast 

30 

31import numba # type: ignore 

32import numpy as np 

33 

34from moptipy.examples.bitstrings.bitstring_problem import BitStringProblem 

35 

36 

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

38def trap(x: np.ndarray) -> int: 

39 """ 

40 Compute the trap objective value. 

41 

42 :param x: the np array 

43 :return: the trap function value 

44 

45 >>> print(trap(np.array([True, True, False, False, False]))) 

46 4 

47 >>> print(trap(np.array([True, False, True, False, False]))) 

48 4 

49 >>> print(trap(np.array([False, True, True, False, False]))) 

50 4 

51 >>> print(trap(np.array([True, True, True, True, True]))) 

52 1 

53 >>> print(trap(np.array([False, True, True, True, True]))) 

54 2 

55 >>> print(trap(np.array([False, False, False, False, False]))) 

56 0 

57 >>> print(trap(np.array([False, True, False, False, False]))) 

58 5 

59 >>> print(trap(np.array([False, True, True, True, False]))) 

60 3 

61 

62 # n = 1 and 0 true bits 

63 >>> trap(np.array([0])) 

64 0 

65 

66 # n = 1 and 1 true bit 

67 >>> trap(np.array([1])) 

68 1 

69 

70 # n = 2 and 0 true bits 

71 >>> trap(np.array([0, 0])) 

72 0 

73 

74 # n = 2 and 1 true bit 

75 >>> trap(np.array([0, 1])) 

76 2 

77 

78 # n = 2 and 1 true bit 

79 >>> trap(np.array([0, 1])) 

80 2 

81 

82 # n = 2 and 1 true bit 

83 >>> trap(np.array([0, 1])) 

84 2 

85 

86 # n = 2 and 2 true bits 

87 >>> trap(np.array([1, 1])) 

88 1 

89 

90 # n = 3 and 0 true bits 

91 >>> trap(np.array([0, 0, 0])) 

92 0 

93 

94 # n = 3 and 1 true bit 

95 >>> trap(np.array([0, 1, 0])) 

96 3 

97 

98 # n = 3 and 1 true bit 

99 >>> trap(np.array([1, 0, 0])) 

100 3 

101 

102 # n = 3 and 1 true bit 

103 >>> trap(np.array([0, 0, 1])) 

104 3 

105 

106 # n = 3 and 2 true bits 

107 >>> trap(np.array([0, 1, 1])) 

108 2 

109 

110 # n = 3 and 2 true bits 

111 >>> trap(np.array([1, 0, 1])) 

112 2 

113 

114 # n = 3 and 2 true bits 

115 >>> trap(np.array([0, 1, 1])) 

116 2 

117 

118 # n = 3 and 3 true bits 

119 >>> trap(np.array([1, 1, 1])) 

120 1 

121 

122 # n = 4 and 0 true bits 

123 >>> trap(np.array([0, 0, 0, 0])) 

124 0 

125 

126 # n = 4 and 1 true bit 

127 >>> trap(np.array([1, 0, 0, 0])) 

128 4 

129 

130 # n = 4 and 1 true bit 

131 >>> trap(np.array([1, 0, 0, 0])) 

132 4 

133 

134 # n = 4 and 1 true bit 

135 >>> trap(np.array([0, 0, 0, 1])) 

136 4 

137 

138 # n = 4 and 2 true bits 

139 >>> trap(np.array([1, 1, 0, 0])) 

140 3 

141 

142 # n = 4 and 2 true bits 

143 >>> trap(np.array([0, 0, 1, 1])) 

144 3 

145 

146 # n = 4 and 2 true bits 

147 >>> trap(np.array([0, 1, 1, 0])) 

148 3 

149 

150 # n = 4 and 3 true bits 

151 >>> trap(np.array([0, 1, 1, 1])) 

152 2 

153 

154 # n = 4 and 3 true bits 

155 >>> trap(np.array([1, 1, 1, 0])) 

156 2 

157 

158 # n = 4 and 3 true bits 

159 >>> trap(np.array([1, 1, 0, 1])) 

160 2 

161 

162 # n = 4 and 4 true bits 

163 >>> trap(np.array([1, 1, 1, 1])) 

164 1 

165 

166 # n = 5 and 0 true bits 

167 >>> trap(np.array([0, 0, 0, 0, 0])) 

168 0 

169 

170 # n = 5 and 1 true bit 

171 >>> trap(np.array([0, 0, 0, 0, 1])) 

172 5 

173 

174 # n = 5 and 1 true bit 

175 >>> trap(np.array([0, 0, 0, 1, 0])) 

176 5 

177 

178 # n = 5 and 1 true bit 

179 >>> trap(np.array([1, 0, 0, 0, 0])) 

180 5 

181 

182 # n = 5 and 2 true bits 

183 >>> trap(np.array([1, 0, 1, 0, 0])) 

184 4 

185 

186 # n = 5 and 2 true bits 

187 >>> trap(np.array([1, 0, 1, 0, 0])) 

188 4 

189 

190 # n = 5 and 2 true bits 

191 >>> trap(np.array([0, 1, 0, 0, 1])) 

192 4 

193 

194 # n = 5 and 3 true bits 

195 >>> trap(np.array([1, 0, 1, 1, 0])) 

196 3 

197 

198 # n = 5 and 3 true bits 

199 >>> trap(np.array([0, 1, 1, 0, 1])) 

200 3 

201 

202 # n = 5 and 3 true bits 

203 >>> trap(np.array([0, 1, 1, 0, 1])) 

204 3 

205 

206 # n = 5 and 4 true bits 

207 >>> trap(np.array([1, 0, 1, 1, 1])) 

208 2 

209 

210 # n = 5 and 4 true bits 

211 >>> trap(np.array([1, 1, 1, 0, 1])) 

212 2 

213 

214 # n = 5 and 4 true bits 

215 >>> trap(np.array([1, 1, 0, 1, 1])) 

216 2 

217 

218 # n = 5 and 5 true bits 

219 >>> trap(np.array([1, 1, 1, 1, 1])) 

220 1 

221 

222 # n = 6 and 0 true bits 

223 >>> trap(np.array([0, 0, 0, 0, 0, 0])) 

224 0 

225 

226 # n = 6 and 1 true bit 

227 >>> trap(np.array([0, 0, 0, 0, 1, 0])) 

228 6 

229 

230 # n = 6 and 1 true bit 

231 >>> trap(np.array([0, 0, 0, 0, 0, 1])) 

232 6 

233 

234 # n = 6 and 1 true bit 

235 >>> trap(np.array([0, 0, 1, 0, 0, 0])) 

236 6 

237 

238 # n = 6 and 2 true bits 

239 >>> trap(np.array([1, 0, 0, 1, 0, 0])) 

240 5 

241 

242 # n = 6 and 2 true bits 

243 >>> trap(np.array([1, 0, 0, 0, 1, 0])) 

244 5 

245 

246 # n = 6 and 2 true bits 

247 >>> trap(np.array([1, 0, 0, 0, 1, 0])) 

248 5 

249 

250 # n = 6 and 3 true bits 

251 >>> trap(np.array([0, 1, 1, 1, 0, 0])) 

252 4 

253 

254 # n = 6 and 3 true bits 

255 >>> trap(np.array([1, 1, 0, 0, 0, 1])) 

256 4 

257 

258 # n = 6 and 3 true bits 

259 >>> trap(np.array([0, 1, 1, 1, 0, 0])) 

260 4 

261 

262 # n = 6 and 4 true bits 

263 >>> trap(np.array([1, 0, 0, 1, 1, 1])) 

264 3 

265 

266 # n = 6 and 4 true bits 

267 >>> trap(np.array([1, 0, 0, 1, 1, 1])) 

268 3 

269 

270 # n = 6 and 4 true bits 

271 >>> trap(np.array([0, 1, 1, 1, 1, 0])) 

272 3 

273 

274 # n = 6 and 5 true bits 

275 >>> trap(np.array([0, 1, 1, 1, 1, 1])) 

276 2 

277 

278 # n = 6 and 5 true bits 

279 >>> trap(np.array([1, 1, 1, 1, 0, 1])) 

280 2 

281 

282 # n = 6 and 5 true bits 

283 >>> trap(np.array([1, 1, 1, 1, 1, 0])) 

284 2 

285 

286 # n = 6 and 6 true bits 

287 >>> trap(np.array([1, 1, 1, 1, 1, 1])) 

288 1 

289 

290 # n = 7 and 0 true bits 

291 >>> trap(np.array([0, 0, 0, 0, 0, 0, 0])) 

292 0 

293 

294 # n = 7 and 1 true bit 

295 >>> trap(np.array([0, 0, 1, 0, 0, 0, 0])) 

296 7 

297 

298 # n = 7 and 1 true bit 

299 >>> trap(np.array([0, 0, 0, 0, 0, 1, 0])) 

300 7 

301 

302 # n = 7 and 1 true bit 

303 >>> trap(np.array([0, 0, 0, 1, 0, 0, 0])) 

304 7 

305 

306 # n = 7 and 2 true bits 

307 >>> trap(np.array([0, 0, 1, 0, 0, 0, 1])) 

308 6 

309 

310 # n = 7 and 2 true bits 

311 >>> trap(np.array([0, 0, 1, 0, 0, 1, 0])) 

312 6 

313 

314 # n = 7 and 2 true bits 

315 >>> trap(np.array([1, 0, 1, 0, 0, 0, 0])) 

316 6 

317 

318 # n = 7 and 3 true bits 

319 >>> trap(np.array([0, 0, 1, 1, 0, 1, 0])) 

320 5 

321 

322 # n = 7 and 3 true bits 

323 >>> trap(np.array([1, 0, 0, 1, 1, 0, 0])) 

324 5 

325 

326 # n = 7 and 3 true bits 

327 >>> trap(np.array([1, 1, 0, 0, 0, 0, 1])) 

328 5 

329 

330 # n = 7 and 4 true bits 

331 >>> trap(np.array([0, 1, 0, 0, 1, 1, 1])) 

332 4 

333 

334 # n = 7 and 4 true bits 

335 >>> trap(np.array([1, 1, 0, 0, 1, 1, 0])) 

336 4 

337 

338 # n = 7 and 4 true bits 

339 >>> trap(np.array([1, 0, 1, 0, 0, 1, 1])) 

340 4 

341 

342 # n = 7 and 5 true bits 

343 >>> trap(np.array([1, 1, 0, 1, 1, 1, 0])) 

344 3 

345 

346 # n = 7 and 5 true bits 

347 >>> trap(np.array([1, 1, 1, 1, 1, 0, 0])) 

348 3 

349 

350 # n = 7 and 5 true bits 

351 >>> trap(np.array([1, 1, 0, 1, 0, 1, 1])) 

352 3 

353 

354 # n = 7 and 6 true bits 

355 >>> trap(np.array([1, 1, 1, 1, 1, 1, 0])) 

356 2 

357 

358 # n = 7 and 6 true bits 

359 >>> trap(np.array([1, 1, 0, 1, 1, 1, 1])) 

360 2 

361 

362 # n = 7 and 6 true bits 

363 >>> trap(np.array([1, 1, 1, 1, 1, 1, 0])) 

364 2 

365 

366 # n = 7 and 7 true bits 

367 >>> trap(np.array([1, 1, 1, 1, 1, 1, 1])) 

368 1 

369 

370 # n = 8 and 0 true bits 

371 >>> trap(np.array([0, 0, 0, 0, 0, 0, 0, 0])) 

372 0 

373 

374 # n = 8 and 1 true bit 

375 >>> trap(np.array([0, 0, 0, 0, 1, 0, 0, 0])) 

376 8 

377 

378 # n = 8 and 1 true bit 

379 >>> trap(np.array([0, 1, 0, 0, 0, 0, 0, 0])) 

380 8 

381 

382 # n = 8 and 1 true bit 

383 >>> trap(np.array([0, 0, 1, 0, 0, 0, 0, 0])) 

384 8 

385 

386 # n = 8 and 2 true bits 

387 >>> trap(np.array([1, 0, 0, 0, 0, 1, 0, 0])) 

388 7 

389 

390 # n = 8 and 2 true bits 

391 >>> trap(np.array([0, 1, 0, 0, 1, 0, 0, 0])) 

392 7 

393 

394 # n = 8 and 2 true bits 

395 >>> trap(np.array([0, 1, 0, 0, 1, 0, 0, 0])) 

396 7 

397 

398 # n = 8 and 3 true bits 

399 >>> trap(np.array([0, 1, 0, 0, 0, 1, 1, 0])) 

400 6 

401 

402 # n = 8 and 3 true bits 

403 >>> trap(np.array([0, 1, 1, 0, 0, 1, 0, 0])) 

404 6 

405 

406 # n = 8 and 3 true bits 

407 >>> trap(np.array([1, 1, 0, 0, 1, 0, 0, 0])) 

408 6 

409 

410 # n = 8 and 4 true bits 

411 >>> trap(np.array([1, 0, 1, 0, 1, 0, 0, 1])) 

412 5 

413 

414 # n = 8 and 4 true bits 

415 >>> trap(np.array([0, 1, 1, 1, 1, 0, 0, 0])) 

416 5 

417 

418 # n = 8 and 4 true bits 

419 >>> trap(np.array([1, 1, 1, 0, 0, 1, 0, 0])) 

420 5 

421 

422 # n = 8 and 5 true bits 

423 >>> trap(np.array([1, 1, 0, 0, 0, 1, 1, 1])) 

424 4 

425 

426 # n = 8 and 5 true bits 

427 >>> trap(np.array([1, 1, 1, 0, 0, 1, 1, 0])) 

428 4 

429 

430 # n = 8 and 5 true bits 

431 >>> trap(np.array([0, 0, 1, 1, 0, 1, 1, 1])) 

432 4 

433 

434 # n = 8 and 6 true bits 

435 >>> trap(np.array([0, 1, 1, 1, 1, 1, 1, 0])) 

436 3 

437 

438 # n = 8 and 6 true bits 

439 >>> trap(np.array([1, 1, 0, 1, 1, 1, 0, 1])) 

440 3 

441 

442 # n = 8 and 6 true bits 

443 >>> trap(np.array([1, 1, 1, 0, 0, 1, 1, 1])) 

444 3 

445 

446 # n = 8 and 7 true bits 

447 >>> trap(np.array([1, 1, 1, 1, 1, 1, 0, 1])) 

448 2 

449 

450 # n = 8 and 7 true bits 

451 >>> trap(np.array([1, 1, 1, 1, 1, 1, 1, 0])) 

452 2 

453 

454 # n = 8 and 7 true bits 

455 >>> trap(np.array([1, 0, 1, 1, 1, 1, 1, 1])) 

456 2 

457 

458 # n = 8 and 8 true bits 

459 >>> trap(np.array([1, 1, 1, 1, 1, 1, 1, 1])) 

460 1 

461 

462 # n = 9 and 0 true bits 

463 >>> trap(np.array([0, 0, 0, 0, 0, 0, 0, 0, 0])) 

464 0 

465 

466 # n = 9 and 1 true bit 

467 >>> trap(np.array([0, 0, 0, 0, 0, 1, 0, 0, 0])) 

468 9 

469 

470 # n = 9 and 1 true bit 

471 >>> trap(np.array([0, 0, 0, 0, 0, 0, 0, 1, 0])) 

472 9 

473 

474 # n = 9 and 1 true bit 

475 >>> trap(np.array([0, 1, 0, 0, 0, 0, 0, 0, 0])) 

476 9 

477 

478 # n = 9 and 2 true bits 

479 >>> trap(np.array([1, 0, 0, 0, 1, 0, 0, 0, 0])) 

480 8 

481 

482 # n = 9 and 2 true bits 

483 >>> trap(np.array([0, 0, 0, 0, 0, 0, 0, 1, 1])) 

484 8 

485 

486 # n = 9 and 2 true bits 

487 >>> trap(np.array([0, 0, 0, 1, 0, 0, 0, 1, 0])) 

488 8 

489 

490 # n = 9 and 3 true bits 

491 >>> trap(np.array([0, 1, 0, 0, 0, 1, 0, 0, 1])) 

492 7 

493 

494 # n = 9 and 3 true bits 

495 >>> trap(np.array([1, 0, 0, 1, 1, 0, 0, 0, 0])) 

496 7 

497 

498 # n = 9 and 3 true bits 

499 >>> trap(np.array([1, 1, 0, 0, 0, 0, 1, 0, 0])) 

500 7 

501 

502 # n = 9 and 4 true bits 

503 >>> trap(np.array([1, 0, 1, 1, 0, 0, 1, 0, 0])) 

504 6 

505 

506 # n = 9 and 4 true bits 

507 >>> trap(np.array([1, 0, 1, 0, 0, 0, 1, 1, 0])) 

508 6 

509 

510 # n = 9 and 4 true bits 

511 >>> trap(np.array([1, 0, 0, 1, 0, 0, 1, 1, 0])) 

512 6 

513 

514 # n = 9 and 5 true bits 

515 >>> trap(np.array([1, 0, 1, 1, 0, 0, 0, 1, 1])) 

516 5 

517 

518 # n = 9 and 5 true bits 

519 >>> trap(np.array([0, 1, 0, 1, 0, 1, 1, 0, 1])) 

520 5 

521 

522 # n = 9 and 5 true bits 

523 >>> trap(np.array([1, 0, 0, 0, 1, 0, 1, 1, 1])) 

524 5 

525 

526 # n = 9 and 6 true bits 

527 >>> trap(np.array([1, 1, 1, 0, 0, 1, 0, 1, 1])) 

528 4 

529 

530 # n = 9 and 6 true bits 

531 >>> trap(np.array([0, 1, 1, 0, 1, 1, 0, 1, 1])) 

532 4 

533 

534 # n = 9 and 6 true bits 

535 >>> trap(np.array([1, 0, 1, 0, 1, 1, 1, 0, 1])) 

536 4 

537 

538 # n = 9 and 7 true bits 

539 >>> trap(np.array([1, 1, 1, 1, 1, 1, 1, 0, 0])) 

540 3 

541 

542 # n = 9 and 7 true bits 

543 >>> trap(np.array([1, 0, 1, 1, 1, 1, 1, 0, 1])) 

544 3 

545 

546 # n = 9 and 7 true bits 

547 >>> trap(np.array([1, 1, 0, 1, 1, 1, 1, 0, 1])) 

548 3 

549 

550 # n = 9 and 8 true bits 

551 >>> trap(np.array([0, 1, 1, 1, 1, 1, 1, 1, 1])) 

552 2 

553 

554 # n = 9 and 8 true bits 

555 >>> trap(np.array([1, 1, 1, 1, 1, 1, 1, 1, 0])) 

556 2 

557 

558 # n = 9 and 8 true bits 

559 >>> trap(np.array([1, 1, 1, 1, 1, 0, 1, 1, 1])) 

560 2 

561 

562 # n = 9 and 9 true bits 

563 >>> trap(np.array([1, 1, 1, 1, 1, 1, 1, 1, 1])) 

564 1 

565 

566 # n = 10 and 0 true bits 

567 >>> trap(np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])) 

568 0 

569 

570 # n = 10 and 1 true bit 

571 >>> trap(np.array([0, 0, 0, 0, 0, 1, 0, 0, 0, 0])) 

572 10 

573 

574 # n = 10 and 1 true bit 

575 >>> trap(np.array([0, 0, 1, 0, 0, 0, 0, 0, 0, 0])) 

576 10 

577 

578 # n = 10 and 1 true bit 

579 >>> trap(np.array([0, 0, 0, 0, 1, 0, 0, 0, 0, 0])) 

580 10 

581 

582 # n = 10 and 2 true bits 

583 >>> trap(np.array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0])) 

584 9 

585 

586 # n = 10 and 2 true bits 

587 >>> trap(np.array([0, 1, 0, 0, 0, 0, 0, 0, 0, 1])) 

588 9 

589 

590 # n = 10 and 2 true bits 

591 >>> trap(np.array([0, 0, 0, 1, 0, 1, 0, 0, 0, 0])) 

592 9 

593 

594 # n = 10 and 3 true bits 

595 >>> trap(np.array([0, 1, 0, 0, 0, 0, 0, 1, 0, 1])) 

596 8 

597 

598 # n = 10 and 3 true bits 

599 >>> trap(np.array([0, 1, 0, 0, 0, 1, 0, 0, 0, 1])) 

600 8 

601 

602 # n = 10 and 3 true bits 

603 >>> trap(np.array([1, 0, 0, 1, 0, 0, 0, 1, 0, 0])) 

604 8 

605 

606 # n = 10 and 4 true bits 

607 >>> trap(np.array([0, 0, 1, 0, 1, 0, 0, 1, 1, 0])) 

608 7 

609 

610 # n = 10 and 4 true bits 

611 >>> trap(np.array([1, 0, 0, 0, 0, 0, 1, 0, 1, 1])) 

612 7 

613 

614 # n = 10 and 4 true bits 

615 >>> trap(np.array([1, 0, 0, 1, 0, 1, 0, 0, 1, 0])) 

616 7 

617 

618 # n = 10 and 5 true bits 

619 >>> trap(np.array([1, 1, 0, 1, 0, 1, 0, 0, 0, 1])) 

620 6 

621 

622 # n = 10 and 5 true bits 

623 >>> trap(np.array([1, 0, 1, 0, 1, 0, 0, 0, 1, 1])) 

624 6 

625 

626 # n = 10 and 5 true bits 

627 >>> trap(np.array([0, 1, 1, 1, 0, 1, 0, 0, 1, 0])) 

628 6 

629 

630 # n = 10 and 6 true bits 

631 >>> trap(np.array([0, 1, 1, 0, 0, 1, 1, 1, 0, 1])) 

632 5 

633 

634 # n = 10 and 6 true bits 

635 >>> trap(np.array([0, 0, 0, 1, 1, 0, 1, 1, 1, 1])) 

636 5 

637 

638 # n = 10 and 6 true bits 

639 >>> trap(np.array([1, 1, 0, 1, 0, 1, 1, 0, 0, 1])) 

640 5 

641 

642 # n = 10 and 7 true bits 

643 >>> trap(np.array([0, 1, 1, 0, 1, 1, 1, 1, 0, 1])) 

644 4 

645 

646 # n = 10 and 7 true bits 

647 >>> trap(np.array([0, 1, 1, 1, 1, 1, 1, 0, 1, 0])) 

648 4 

649 

650 # n = 10 and 7 true bits 

651 >>> trap(np.array([1, 1, 1, 1, 1, 0, 1, 1, 0, 0])) 

652 4 

653 

654 # n = 10 and 8 true bits 

655 >>> trap(np.array([1, 1, 0, 0, 1, 1, 1, 1, 1, 1])) 

656 3 

657 

658 # n = 10 and 8 true bits 

659 >>> trap(np.array([1, 0, 1, 1, 1, 0, 1, 1, 1, 1])) 

660 3 

661 

662 # n = 10 and 8 true bits 

663 >>> trap(np.array([1, 1, 1, 1, 0, 0, 1, 1, 1, 1])) 

664 3 

665 

666 # n = 10 and 9 true bits 

667 >>> trap(np.array([1, 1, 1, 1, 1, 1, 0, 1, 1, 1])) 

668 2 

669 

670 # n = 10 and 9 true bits 

671 >>> trap(np.array([1, 1, 1, 1, 0, 1, 1, 1, 1, 1])) 

672 2 

673 

674 # n = 10 and 9 true bits 

675 >>> trap(np.array([1, 1, 1, 1, 1, 1, 1, 1, 0, 1])) 

676 2 

677 

678 # n = 10 and 10 true bits 

679 >>> trap(np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1])) 

680 1 

681 """ 

682 n: Final[int] = len(x) 

683 res: Final[int] = int(x.sum()) 

684 return 0 if res <= 0 else n - res + 1 

685 

686 

687class Trap(BitStringProblem): 

688 """The trap problem.""" 

689 

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

691 """ 

692 Initialize the trap objective function. 

693 

694 :param n: the dimension of the problem 

695 

696 >>> print(Trap(55).n) 

697 55 

698 >>> print(Trap(4).evaluate(np.array([True, True, False, True]))) 

699 2 

700 """ 

701 super().__init__(n) 

702 self.evaluate = trap # type: ignore 

703 

704 def __str__(self) -> str: 

705 """ 

706 Get the name of the trap objective function. 

707 

708 :return: `trap_` + length of string 

709 

710 >>> print(Trap(33)) 

711 trap_33 

712 """ 

713 return f"trap_{self.n}" 

714 

715 @classmethod 

716 def default_instances( 

717 cls: type, scale_min: int = 3, scale_max: int = 333) \ 

718 -> Iterator[Callable[[], "Trap"]]: 

719 """ 

720 Get the 77 default instances of the :class:`Trap` problem. 

721 

722 :param scale_min: the minimum permitted scale, by default `3` 

723 :param scale_max: the maximum permitted scale, by default `333` 

724 :returns: a sequence of default :class:`Trap` instances 

725 

726 >>> len(list(Trap.default_instances())) 

727 77 

728 

729 >>> [x() for x in Trap.default_instances()] 

730 [trap_3, trap_4, trap_5, trap_6, trap_7, trap_8, trap_9, trap_10, \ 

731trap_11, trap_12, trap_13, trap_14, trap_15, trap_16, trap_17, trap_18, \ 

732trap_19, trap_20, trap_21, trap_22, trap_23, trap_24, trap_25, trap_26, \ 

733trap_27, trap_28, trap_29, trap_30, trap_31, trap_32, trap_33, trap_36, \ 

734trap_40, trap_41, trap_42, trap_44, trap_48, trap_49, trap_50, trap_55, \ 

735trap_59, trap_60, trap_64, trap_66, trap_70, trap_77, trap_79, trap_80, \ 

736trap_81, trap_85, trap_88, trap_90, trap_96, trap_99, trap_100, trap_107, \ 

737trap_111, trap_121, trap_125, trap_128, trap_144, trap_149, trap_169, \ 

738trap_170, trap_192, trap_196, trap_199, trap_200, trap_222, trap_225, \ 

739trap_243, trap_256, trap_269, trap_289, trap_300, trap_324, trap_333] 

740 """ 

741 return cast("Iterator[Callable[[], Trap]]", 

742 super().default_instances( # type: ignore 

743 scale_min, scale_max))