Coverage for moptipy / examples / bitstrings / linearharmonic.py: 71%

24 statements  

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

1""" 

2The linear harmonic objective function. 

3 

4The bit at index `i` for `i` in `0..n-1` has weight `i+1`. This is the penalty 

5that is incurred if the bit is set to `False`. 

6The best objective value, 0, is hence obtained if all bits are `True`. 

7The worst objective value, i.e., `n * (n + 1) // 2`, is obtained if all bits 

8are `False`. 

9 

101. Carola Doerr, Furong Ye, Naama Horesh, Hao Wang, Ofer M. Shir, and Thomas 

11 Bäck. Benchmarking Discrete Optimization Heuristics with IOHprofiler. 

12 Applied Soft Computing Journal. 88:106027. 2020. 

13 doi: https://doi.org/10.1016/j.asoc.2019.106027 

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

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

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

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

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

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

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

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

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

23 

24This is code is part of the research work of Mr. Jiazheng ZENG (曾嘉政), 

25a Master's student at the Institute of Applied Optimization 

26(应用优化研究所) of the School of Artificial 

27Intelligence and Big Data (人工智能与大数据学院) at 

28Hefei University (合肥大学) in 

29Hefei, Anhui, China (中国安徽省合肥市) under the supervision of 

30Prof. Dr. Thomas Weise (汤卫思教授). 

31""" 

32 

33from typing import Callable, Iterator, cast 

34 

35import numba # type: ignore 

36import numpy as np 

37 

38from moptipy.examples.bitstrings.bitstring_problem import BitStringProblem 

39 

40 

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

42def linear_harmonic(x: np.ndarray) -> float: 

43 """ 

44 Evaluate the linear function with harmonic weights. 

45 

46 :param x: np array representing the bit string 

47 :return: the objective value 

48 

49 >>> linear_harmonic(np.array([True, True, True])) 

50 0 

51 >>> linear_harmonic(np.array([False, True, True])) 

52 1 

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

54 2 

55 >>> linear_harmonic(np.array([True, True, False])) 

56 3 

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

58 3 

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

60 4 

61 >>> linear_harmonic(np.array([True, False, False])) 

62 5 

63 >>> linear_harmonic(np.array([False, False, False])) 

64 6 

65 >>> (3 * (3 + 1)) // 2 

66 6 

67 

68 >>> linear_harmonic(np.array([True, True, True, True])) 

69 0 

70 >>> linear_harmonic(np.array([False, True, True, True])) 

71 1 

72 >>> linear_harmonic(np.array([True, False, True, True])) 

73 2 

74 >>> linear_harmonic(np.array([True, True, False, True])) 

75 3 

76 >>> linear_harmonic(np.array([True, True, True, False])) 

77 4 

78 >>> linear_harmonic(np.array([False, False, True, True])) 

79 3 

80 >>> linear_harmonic(np.array([False, True, False, True])) 

81 4 

82 >>> linear_harmonic(np.array([False, True, True, False])) 

83 5 

84 >>> linear_harmonic(np.array([True, False, False, True])) 

85 5 

86 >>> linear_harmonic(np.array([True, False, True, False])) 

87 6 

88 >>> linear_harmonic(np.array([True, True, False, False])) 

89 7 

90 >>> linear_harmonic(np.array([False, False, False, True])) 

91 6 

92 >>> linear_harmonic(np.array([False, False, True, False])) 

93 7 

94 >>> linear_harmonic(np.array([False, True, False, False])) 

95 8 

96 >>> linear_harmonic(np.array([True, False, False, False])) 

97 9 

98 >>> linear_harmonic(np.array([False, False, False, False])) 

99 10 

100 >>> 4 * (4 + 1) // 2 

101 10 

102 

103 # n = 1 and 0 true bits 

104 >>> linear_harmonic(np.array([0])) 

105 1 

106 

107 # n = 1 and 1 true bit 

108 >>> linear_harmonic(np.array([1])) 

109 0 

110 

111 # n = 2 and 0 true bits 

112 >>> linear_harmonic(np.array([0, 0])) 

113 3 

114 

115 # n = 2 and 1 true bit 

116 >>> linear_harmonic(np.array([1, 0])) 

117 2 

118 

119 # n = 2 and 1 true bit 

120 >>> linear_harmonic(np.array([1, 0])) 

121 2 

122 

123 # n = 2 and 1 true bit 

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

125 2 

126 

127 # n = 2 and 2 true bits 

128 >>> linear_harmonic(np.array([1, 1])) 

129 0 

130 

131 # n = 3 and 0 true bits 

132 >>> linear_harmonic(np.array([0, 0, 0])) 

133 6 

134 

135 # n = 3 and 1 true bit 

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

137 4 

138 

139 # n = 3 and 1 true bit 

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

141 3 

142 

143 # n = 3 and 1 true bit 

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

145 5 

146 

147 # n = 3 and 2 true bits 

148 >>> linear_harmonic(np.array([0, 1, 1])) 

149 1 

150 

151 # n = 3 and 2 true bits 

152 >>> linear_harmonic(np.array([1, 0, 1])) 

153 2 

154 

155 # n = 3 and 2 true bits 

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

157 3 

158 

159 # n = 3 and 3 true bits 

160 >>> linear_harmonic(np.array([1, 1, 1])) 

161 0 

162 

163 # n = 4 and 0 true bits 

164 >>> linear_harmonic(np.array([0, 0, 0, 0])) 

165 10 

166 

167 # n = 4 and 1 true bit 

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

169 9 

170 

171 # n = 4 and 1 true bit 

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

173 9 

174 

175 # n = 4 and 1 true bit 

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

177 9 

178 

179 # n = 4 and 2 true bits 

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

181 5 

182 

183 # n = 4 and 2 true bits 

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

185 4 

186 

187 # n = 4 and 2 true bits 

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

189 5 

190 

191 # n = 4 and 3 true bits 

192 >>> linear_harmonic(np.array([1, 1, 0, 1])) 

193 3 

194 

195 # n = 4 and 3 true bits 

196 >>> linear_harmonic(np.array([0, 1, 1, 1])) 

197 1 

198 

199 # n = 4 and 3 true bits 

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

201 2 

202 

203 # n = 4 and 4 true bits 

204 >>> linear_harmonic(np.array([1, 1, 1, 1])) 

205 0 

206 

207 # n = 5 and 0 true bits 

208 >>> linear_harmonic(np.array([0, 0, 0, 0, 0])) 

209 15 

210 

211 # n = 5 and 1 true bit 

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

213 13 

214 

215 # n = 5 and 1 true bit 

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

217 14 

218 

219 # n = 5 and 2 true bits 

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

221 7 

222 

223 # n = 5 and 2 true bits 

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

225 9 

226 

227 # n = 5 and 2 true bits 

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

229 10 

230 

231 # n = 5 and 3 true bits 

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

233 3 

234 

235 # n = 5 and 3 true bits 

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

237 3 

238 

239 # n = 5 and 3 true bits 

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

241 6 

242 

243 # n = 5 and 4 true bits 

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

245 5 

246 

247 # n = 5 and 4 true bits 

248 >>> linear_harmonic(np.array([1, 1, 1, 1, 0])) 

249 5 

250 

251 # n = 5 and 4 true bits 

252 >>> linear_harmonic(np.array([1, 1, 1, 1, 0])) 

253 5 

254 

255 # n = 5 and 5 true bits 

256 >>> linear_harmonic(np.array([1, 1, 1, 1, 1])) 

257 0 

258 

259 # n = 6 and 0 true bits 

260 >>> linear_harmonic(np.array([0, 0, 0, 0, 0, 0])) 

261 21 

262 

263 # n = 6 and 1 true bit 

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

265 16 

266 

267 # n = 6 and 1 true bit 

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

269 18 

270 

271 # n = 6 and 1 true bit 

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

273 15 

274 

275 # n = 6 and 2 true bits 

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

277 17 

278 

279 # n = 6 and 2 true bits 

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

281 13 

282 

283 # n = 6 and 2 true bits 

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

285 10 

286 

287 # n = 6 and 3 true bits 

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

289 8 

290 

291 # n = 6 and 3 true bits 

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

293 12 

294 

295 # n = 6 and 3 true bits 

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

297 13 

298 

299 # n = 6 and 4 true bits 

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

301 11 

302 

303 # n = 6 and 4 true bits 

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

305 9 

306 

307 # n = 6 and 4 true bits 

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

309 9 

310 

311 # n = 6 and 5 true bits 

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

313 3 

314 

315 # n = 6 and 5 true bits 

316 >>> linear_harmonic(np.array([1, 1, 1, 1, 1, 0])) 

317 6 

318 

319 # n = 6 and 5 true bits 

320 >>> linear_harmonic(np.array([1, 1, 1, 1, 0, 1])) 

321 5 

322 

323 # n = 6 and 6 true bits 

324 >>> linear_harmonic(np.array([1, 1, 1, 1, 1, 1])) 

325 0 

326 

327 # n = 7 and 0 true bits 

328 >>> linear_harmonic(np.array([0, 0, 0, 0, 0, 0, 0])) 

329 28 

330 

331 # n = 7 and 1 true bit 

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

333 25 

334 

335 # n = 7 and 1 true bit 

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

337 24 

338 

339 # n = 7 and 1 true bit 

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

341 27 

342 

343 # n = 7 and 2 true bits 

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

345 20 

346 

347 # n = 7 and 2 true bits 

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

349 16 

350 

351 # n = 7 and 2 true bits 

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

353 21 

354 

355 # n = 7 and 3 true bits 

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

357 13 

358 

359 # n = 7 and 3 true bits 

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

361 16 

362 

363 # n = 7 and 3 true bits 

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

365 13 

366 

367 # n = 7 and 4 true bits 

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

369 14 

370 

371 # n = 7 and 4 true bits 

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

373 12 

374 

375 # n = 7 and 4 true bits 

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

377 10 

378 

379 # n = 7 and 5 true bits 

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

381 9 

382 

383 # n = 7 and 5 true bits 

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

385 12 

386 

387 # n = 7 and 5 true bits 

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

389 8 

390 

391 # n = 7 and 6 true bits 

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

393 7 

394 

395 # n = 7 and 6 true bits 

396 >>> linear_harmonic(np.array([1, 1, 1, 1, 1, 1, 0])) 

397 7 

398 

399 # n = 7 and 6 true bits 

400 >>> linear_harmonic(np.array([1, 1, 0, 1, 1, 1, 1])) 

401 3 

402 

403 # n = 7 and 7 true bits 

404 >>> linear_harmonic(np.array([1, 1, 1, 1, 1, 1, 1])) 

405 0 

406 

407 # n = 8 and 0 true bits 

408 >>> linear_harmonic(np.array([0, 0, 0, 0, 0, 0, 0, 0])) 

409 36 

410 

411 # n = 8 and 1 true bit 

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

413 34 

414 

415 # n = 8 and 1 true bit 

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

417 31 

418 

419 # n = 8 and 1 true bit 

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

421 34 

422 

423 # n = 8 and 2 true bits 

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

425 29 

426 

427 # n = 8 and 2 true bits 

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

429 26 

430 

431 # n = 8 and 2 true bits 

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

433 22 

434 

435 # n = 8 and 3 true bits 

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

437 25 

438 

439 # n = 8 and 3 true bits 

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

441 25 

442 

443 # n = 8 and 3 true bits 

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

445 17 

446 

447 # n = 8 and 4 true bits 

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

449 22 

450 

451 # n = 8 and 4 true bits 

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

453 22 

454 

455 # n = 8 and 4 true bits 

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

457 18 

458 

459 # n = 8 and 5 true bits 

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

461 13 

462 

463 # n = 8 and 5 true bits 

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

465 7 

466 

467 # n = 8 and 5 true bits 

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

469 19 

470 

471 # n = 8 and 6 true bits 

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

473 7 

474 

475 # n = 8 and 6 true bits 

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

477 9 

478 

479 # n = 8 and 6 true bits 

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

481 13 

482 

483 # n = 8 and 7 true bits 

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

485 7 

486 

487 # n = 8 and 7 true bits 

488 >>> linear_harmonic(np.array([1, 1, 1, 0, 1, 1, 1, 1])) 

489 4 

490 

491 # n = 8 and 7 true bits 

492 >>> linear_harmonic(np.array([1, 0, 1, 1, 1, 1, 1, 1])) 

493 2 

494 

495 # n = 8 and 8 true bits 

496 >>> linear_harmonic(np.array([1, 1, 1, 1, 1, 1, 1, 1])) 

497 0 

498 

499 # n = 9 and 0 true bits 

500 >>> linear_harmonic(np.array([0, 0, 0, 0, 0, 0, 0, 0, 0])) 

501 45 

502 

503 # n = 9 and 1 true bit 

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

505 43 

506 

507 # n = 9 and 1 true bit 

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

509 37 

510 

511 # n = 9 and 1 true bit 

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

513 39 

514 

515 # n = 9 and 2 true bits 

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

517 35 

518 

519 # n = 9 and 2 true bits 

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

521 40 

522 

523 # n = 9 and 2 true bits 

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

525 42 

526 

527 # n = 9 and 3 true bits 

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

529 23 

530 

531 # n = 9 and 3 true bits 

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

533 33 

534 

535 # n = 9 and 3 true bits 

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

537 33 

538 

539 # n = 9 and 4 true bits 

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

541 27 

542 

543 # n = 9 and 4 true bits 

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

545 23 

546 

547 # n = 9 and 4 true bits 

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

549 24 

550 

551 # n = 9 and 5 true bits 

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

553 18 

554 

555 # n = 9 and 5 true bits 

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

557 18 

558 

559 # n = 9 and 5 true bits 

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

561 21 

562 

563 # n = 9 and 6 true bits 

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

565 16 

566 

567 # n = 9 and 6 true bits 

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

569 16 

570 

571 # n = 9 and 6 true bits 

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

573 19 

574 

575 # n = 9 and 7 true bits 

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

577 16 

578 

579 # n = 9 and 7 true bits 

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

581 17 

582 

583 # n = 9 and 7 true bits 

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

585 4 

586 

587 # n = 9 and 8 true bits 

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

589 6 

590 

591 # n = 9 and 8 true bits 

592 >>> linear_harmonic(np.array([0, 1, 1, 1, 1, 1, 1, 1, 1])) 

593 1 

594 

595 # n = 9 and 8 true bits 

596 >>> linear_harmonic(np.array([1, 1, 1, 1, 1, 1, 0, 1, 1])) 

597 7 

598 

599 # n = 9 and 9 true bits 

600 >>> linear_harmonic(np.array([1, 1, 1, 1, 1, 1, 1, 1, 1])) 

601 0 

602 

603 # n = 10 and 0 true bits 

604 >>> linear_harmonic(np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])) 

605 55 

606 

607 # n = 10 and 1 true bit 

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

609 46 

610 

611 # n = 10 and 1 true bit 

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

613 50 

614 

615 # n = 10 and 1 true bit 

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

617 53 

618 

619 # n = 10 and 2 true bits 

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

621 46 

622 

623 # n = 10 and 2 true bits 

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

625 47 

626 

627 # n = 10 and 2 true bits 

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

629 36 

630 

631 # n = 10 and 3 true bits 

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

633 37 

634 

635 # n = 10 and 3 true bits 

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

637 34 

638 

639 # n = 10 and 3 true bits 

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

641 38 

642 

643 # n = 10 and 4 true bits 

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

645 33 

646 

647 # n = 10 and 4 true bits 

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

649 31 

650 

651 # n = 10 and 4 true bits 

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

653 34 

654 

655 # n = 10 and 5 true bits 

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

657 26 

658 

659 # n = 10 and 5 true bits 

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

661 25 

662 

663 # n = 10 and 5 true bits 

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

665 19 

666 

667 # n = 10 and 6 true bits 

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

669 24 

670 

671 # n = 10 and 6 true bits 

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

673 24 

674 

675 # n = 10 and 6 true bits 

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

677 16 

678 

679 # n = 10 and 7 true bits 

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

681 18 

682 

683 # n = 10 and 7 true bits 

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

685 13 

686 

687 # n = 10 and 7 true bits 

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

689 26 

690 

691 # n = 10 and 8 true bits 

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

693 13 

694 

695 # n = 10 and 8 true bits 

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

697 11 

698 

699 # n = 10 and 8 true bits 

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

701 8 

702 

703 # n = 10 and 9 true bits 

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

705 9 

706 

707 # n = 10 and 9 true bits 

708 >>> linear_harmonic(np.array([1, 1, 0, 1, 1, 1, 1, 1, 1, 1])) 

709 3 

710 

711 # n = 10 and 9 true bits 

712 >>> linear_harmonic(np.array([1, 1, 0, 1, 1, 1, 1, 1, 1, 1])) 

713 3 

714 

715 # n = 10 and 10 true bits 

716 >>> linear_harmonic(np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1])) 

717 0 

718 """ 

719 result: int = 0 # The sum of the penalty weights 

720 weight: int = 1 # The current penalty weight. 

721 

722 for xx in x: # Iterate over all the bits in the array. 

723 if not xx: # If the bit is False, then 

724 result += weight # add the penalty weight to the result. 

725 weight += 1 # Increment the penalty weight by 1. # noqa: SIM113 

726 

727 return result # Return the result. 

728 

729 

730class LinearHarmonic(BitStringProblem): 

731 """The objective function of the linear harmonic benchmark problem.""" 

732 

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

734 """ 

735 Initialize the Linear Harmonic problem instance. 

736 

737 :param n: length of the bit string 

738 

739 >>> LinearHarmonic(5).evaluate(np.array([ 

740 ... False, True, False, True])) 

741 4 

742 """ 

743 super().__init__(n) 

744 self.evaluate = linear_harmonic # type: ignore 

745 

746 def upper_bound(self) -> int: 

747 """ 

748 Return the upper bound of the linear harmonic function. 

749 

750 :returns: `n * (n + 1) // 2` 

751 

752 >>> LinearHarmonic(5).upper_bound() 

753 15 

754 """ 

755 return (self.n * (self.n + 1)) // 2 

756 

757 def __str__(self) -> str: 

758 """ 

759 Get the name of the Linear Harmonic problem instance. 

760 

761 :return: 'linearharmonic_' + n value 

762 

763 >>> print(LinearHarmonic(8)) 

764 linharm_8 

765 """ 

766 return f"linharm_{self.n}" 

767 

768 @classmethod 

769 def default_instances( 

770 cls: type, scale_min: int = 2, scale_max: int = 333) \ 

771 -> Iterator[Callable[[], "LinearHarmonic"]]: 

772 """ 

773 Get the 78 default instances of the :class:`LinearHarmonic` problem. 

774 

775 :param scale_min: the minimum permitted scale, by default `2` 

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

777 :returns: a sequence of default :class:`LinearHarmonic` instances 

778 

779 >>> len(list(LinearHarmonic.default_instances())) 

780 78 

781 

782 >>> [x() for x in LinearHarmonic.default_instances()] 

783 [linharm_2, linharm_3, linharm_4, linharm_5, linharm_6, linharm_7, \ 

784linharm_8, linharm_9, linharm_10, linharm_11, linharm_12, linharm_13, \ 

785linharm_14, linharm_15, linharm_16, linharm_17, linharm_18, linharm_19, \ 

786linharm_20, linharm_21, linharm_22, linharm_23, linharm_24, linharm_25, \ 

787linharm_26, linharm_27, linharm_28, linharm_29, linharm_30, linharm_31, \ 

788linharm_32, linharm_33, linharm_36, linharm_40, linharm_41, linharm_42, \ 

789linharm_44, linharm_48, linharm_49, linharm_50, linharm_55, linharm_59, \ 

790linharm_60, linharm_64, linharm_66, linharm_70, linharm_77, linharm_79, \ 

791linharm_80, linharm_81, linharm_85, linharm_88, linharm_90, linharm_96, \ 

792linharm_99, linharm_100, linharm_107, linharm_111, linharm_121, linharm_125, \ 

793linharm_128, linharm_144, linharm_149, linharm_169, linharm_170, \ 

794linharm_192, linharm_196, linharm_199, linharm_200, linharm_222, \ 

795linharm_225, linharm_243, linharm_256, linharm_269, linharm_289, linharm_300, \ 

796linharm_324, linharm_333] 

797 """ 

798 return cast("Iterator[Callable[[], LinearHarmonic]]", 

799 super().default_instances( # type: ignore 

800 scale_min, scale_max))