Skip to content

Commit 64063ab

Browse files
committed
some improvements in the bit-string based benchmark problems
1 parent d50f286 commit 64063ab

20 files changed

+994
-70
lines changed

moptipy/algorithms/so/ffa/__init__.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@
1616
https://dx.doi.org/10.1109/TEVC.2020.3032090
1717
2. Thomas Weise, Zhize Wu, Xinlu Li, Yan Chen, and Jörg Lässig. Frequency
1818
Fitness Assignment: Optimization without Bias for Good Solutions can be
19-
Efficient. *IEEE Transactions on Evolutionary Computation (TEVC)*. 2022.
20-
Early Access. https://dx.doi.org/10.1109/TEVC.2022.3191698
19+
Efficient. *IEEE Transactions on Evolutionary Computation (TEVC)*.
20+
27(4):980-992. August 2023.
21+
doi: https://doi.org/10.1109/TEVC.2022.3191698
2122
3. Thomas Weise, Mingxu Wan, Ke Tang, Pu Wang, Alexandre Devert, and Xin
2223
Yao. Frequency Fitness Assignment. *IEEE Transactions on Evolutionary
2324
Computation (IEEE-EC),* 18(2):226-243, April 2014.

moptipy/algorithms/so/ffa/eafea.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
44
1. Thomas Weise, Zhize Wu, Xinlu Li, Yan Chen, and Jörg Lässig. Frequency
55
Fitness Assignment: Optimization without Bias for Good Solutions can be
6-
Efficient. *IEEE Transactions on Evolutionary Computation (TEVC)*. 2022.
7-
Early Access. https://dx.doi.org/10.1109/TEVC.2022.3191698
6+
Efficient. *IEEE Transactions on Evolutionary Computation (TEVC)*.
7+
27(4):980-992. August 2023.
8+
doi: https://doi.org/10.1109/TEVC.2022.3191698
89
"""
910
from collections import Counter
1011
from typing import Callable, Final

moptipy/algorithms/so/ffa/fea1plus1.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,9 @@
6363
https://dx.doi.org/10.1109/TEVC.2020.3032090
6464
2. Thomas Weise, Zhize Wu, Xinlu Li, Yan Chen, and Jörg Lässig. Frequency
6565
Fitness Assignment: Optimization without Bias for Good Solutions can be
66-
Efficient. *IEEE Transactions on Evolutionary Computation (TEVC)*. 2022.
67-
Early Access. https://dx.doi.org/10.1109/TEVC.2022.3191698
66+
Efficient. *IEEE Transactions on Evolutionary Computation (TEVC)*.
67+
27(4):980-992. August 2023.
68+
doi: https://doi.org/10.1109/TEVC.2022.3191698
6869
3. Thomas Weise, Mingxu Wan, Ke Tang, Pu Wang, Alexandre Devert, and Xin
6970
Yao. Frequency Fitness Assignment. *IEEE Transactions on Evolutionary
7071
Computation (IEEE-EC),* 18(2):226-243, April 2014.

moptipy/algorithms/so/ffa/ffa_fitness.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@
2828
https://dx.doi.org/10.1109/TEVC.2020.3032090
2929
2. Thomas Weise, Zhize Wu, Xinlu Li, Yan Chen, and Jörg Lässig. Frequency
3030
Fitness Assignment: Optimization without Bias for Good Solutions can be
31-
Efficient. *IEEE Transactions on Evolutionary Computation (TEVC)*. 2022.
32-
Early Access. https://dx.doi.org/10.1109/TEVC.2022.3191698
31+
Efficient. *IEEE Transactions on Evolutionary Computation (TEVC)*.
32+
27(4):980-992. August 2023.
33+
doi: https://doi.org/10.1109/TEVC.2022.3191698
3334
3. Thomas Weise, Mingxu Wan, Ke Tang, Pu Wang, Alexandre Devert, and Xin
3435
Yao. Frequency Fitness Assignment. *IEEE Transactions on Evolutionary
3536
Computation (IEEE-EC),* 18(2):226-243, April 2014.

moptipy/examples/bitstrings/__init__.py

+77-23
Original file line numberDiff line numberDiff line change
@@ -8,40 +8,44 @@
88
99
The following benchmark problems are provided:
1010
11-
1. :mod:`~moptipy.examples.bitstrings.ising1d`, the one-dimensional
12-
Ising model, where the goal is that all bits should have the same value as
13-
their neighbors in a ring.
14-
2. :mod:`~moptipy.examples.bitstrings.ising2d`, the two-dimensional
15-
Ising model, where the goal is that all bits should have the same value as
16-
their neighbors on a torus.
17-
3. The :mod:`~moptipy.examples.bitstrings.jump` problem is equivalent
18-
to :mod:`~moptipy.examples.bitstrings.onemax`, but has a deceptive
19-
region right before the optimum.
20-
4. The :mod:`~moptipy.examples.bitstrings.leadingones` problem,
11+
1. The :mod:`~moptipy.examples.bitstrings.onemax` problem, where the
12+
goal is to find a bit string with the maximum number of ones.
13+
2. The :mod:`~moptipy.examples.bitstrings.leadingones` problem,
2114
where the goal is to find a bit string with the maximum number of leading
2215
ones.
23-
5. The :mod:`~moptipy.examples.bitstrings.linearharmonic` problem,
16+
3. The :mod:`~moptipy.examples.bitstrings.linearharmonic` problem,
2417
where the goal is to find a bit string with the all ones, like in
2518
:mod:`~moptipy.examples.bitstrings.onemax`, but this time all bits have
2619
a different weight (namely their index, starting at 1).
27-
6. The :mod:`~moptipy.examples.bitstrings.nqueens`, where the goal is to
28-
place `k` queens on a `k * k`-sized chess board such that no queen can
29-
beat any other queen.
30-
7. The :mod:`~moptipy.examples.bitstrings.onemax` problem, where the
31-
goal is to find a bit string with the maximum number of ones.
32-
8. The :mod:`~moptipy.examples.bitstrings.plateau` problem similar to the
33-
:mod:`~moptipy.examples.bitstrings.jump` problem, but this time the
34-
optimum is surrounded by a region of neutrality.
35-
9. The :mod:`~moptipy.examples.bitstrings.trap` problem, which is like
20+
4. The :mod:`~moptipy.examples.bitstrings.binint` problem,
21+
is again similar to :mod:`~moptipy.examples.bitstrings.onemax`, but the
22+
bits have exponential weight. Basically, we just decode the bit string
23+
into an integer.
24+
5. The :mod:`~moptipy.examples.bitstrings.trap` problem, which is like
3625
OneMax, but with the optimum and worst-possible solution swapped. This
3726
problem is therefore highly deceptive.
38-
10. The :mod:`~moptipy.examples.bitstrings.twomax` problem has the global
27+
6. The :mod:`~moptipy.examples.bitstrings.twomax` problem has the global
3928
optimum at the string of all `1` bits and a local optimum at the string
4029
of all `0` bits. Both have basins of attraction of about the same size.
41-
11. The :mod:`~moptipy.examples.bitstrings.w_model`, a benchmark
30+
7. :mod:`~moptipy.examples.bitstrings.ising1d`, the one-dimensional
31+
Ising model, where the goal is that all bits should have the same value as
32+
their neighbors in a ring.
33+
8. :mod:`~moptipy.examples.bitstrings.ising2d`, the two-dimensional
34+
Ising model, where the goal is that all bits should have the same value as
35+
their neighbors on a torus.
36+
9. The :mod:`~moptipy.examples.bitstrings.jump` problem is equivalent
37+
to :mod:`~moptipy.examples.bitstrings.onemax`, but has a deceptive
38+
region right before the optimum.
39+
10. The :mod:`~moptipy.examples.bitstrings.plateau` problem similar to the
40+
:mod:`~moptipy.examples.bitstrings.jump` problem, but this time the
41+
optimum is surrounded by a region of neutrality.
42+
11. The :mod:`~moptipy.examples.bitstrings.nqueens`, where the goal is to
43+
place `k` queens on a `k * k`-sized chess board such that no queen can
44+
beat any other queen.
45+
12. The :mod:`~moptipy.examples.bitstrings.w_model`, a benchmark
4246
problem with tunable epistasis, uniform neutrality, and
4347
ruggedness/deceptiveness.
44-
12. The :mod:`~moptipy.examples.bitstrings.zeromax` problem, where the
48+
13. The :mod:`~moptipy.examples.bitstrings.zeromax` problem, where the
4549
goal is to find a bit string with the maximum number of zeros. This is the
4650
opposite of the OneMax problem.
4751
@@ -53,3 +57,53 @@
5357
Hefei, Anhui, China (中国安徽省合肥市) under the supervision of
5458
Prof. Dr. Thomas Weise (汤卫思教授).
5559
"""
60+
from itertools import chain
61+
from typing import Callable, Iterator, cast
62+
63+
from moptipy.examples.bitstrings.binint import BinInt
64+
from moptipy.examples.bitstrings.bitstring_problem import BitStringProblem
65+
from moptipy.examples.bitstrings.ising1d import Ising1d
66+
from moptipy.examples.bitstrings.ising2d import Ising2d
67+
from moptipy.examples.bitstrings.jump import Jump
68+
from moptipy.examples.bitstrings.leadingones import LeadingOnes
69+
from moptipy.examples.bitstrings.linearharmonic import LinearHarmonic
70+
from moptipy.examples.bitstrings.nqueens import NQueens
71+
from moptipy.examples.bitstrings.onemax import OneMax
72+
from moptipy.examples.bitstrings.plateau import Plateau
73+
from moptipy.examples.bitstrings.trap import Trap
74+
from moptipy.examples.bitstrings.twomax import TwoMax
75+
from moptipy.examples.bitstrings.w_model import WModel
76+
77+
78+
def default_instances(
79+
class_scales: Callable[[
80+
type], Iterator[int]] = lambda s: cast(Iterator[int], ())) \
81+
-> Iterator[Callable[[], BitStringProblem]]:
82+
"""
83+
Get the default bit-string based benchmark instances.
84+
85+
:param class_scales: a function that can override the minimum and
86+
maximimum problem scales on a per-benchmark-function-class
87+
basis. If this function returns an empty iterator, then the default
88+
scales are used.
89+
:return: an :class:`Iterator` with the default bit-string
90+
benchmark instances
91+
92+
>>> len(list(default_instances()))
93+
963
94+
"""
95+
return chain(
96+
BinInt.default_instances(*class_scales(BinInt)), # type: ignore
97+
Ising1d.default_instances(*class_scales(Ising1d)), # type: ignore
98+
Ising2d.default_instances(*class_scales(Ising2d)), # type: ignore
99+
Jump.default_instances(*class_scales(Jump)), # type: ignore
100+
LeadingOnes.default_instances( # type: ignore
101+
*class_scales(LeadingOnes)),
102+
LinearHarmonic.default_instances( # type: ignore
103+
*class_scales(LinearHarmonic)),
104+
NQueens.default_instances(*class_scales(NQueens)), # type: ignore
105+
OneMax.default_instances(*class_scales(OneMax)), # type: ignore
106+
Plateau.default_instances(*class_scales(Plateau)), # type: ignore
107+
Trap.default_instances(*class_scales(Trap)), # type: ignore
108+
TwoMax.default_instances(*class_scales(TwoMax)), # type: ignore
109+
WModel.default_instances(*class_scales(WModel))) # type: ignore

moptipy/examples/bitstrings/binint.py

+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
"""
2+
The BinInt problem maximizes the binary value of a bit string.
3+
4+
The BinInt problem is similar to the OneMax and LinearHarmonic in that it
5+
tries to maximize the number of `True` bits in a string.
6+
Different from these problems, however, it assigns exponentially increasing
7+
weights to the bits.
8+
The bit at index `1` has weight `2 ** (n - 1)`.
9+
The bit at the last position has weight 1.
10+
The upper bound for the objective function, reached when all bits are `False`,
11+
therefore is `2 ** n - 1`. The lower bound, reached when all bits are `True`,
12+
is `0`.
13+
14+
1. William Michael Rudnick. Genetic Algorithms and Fitness Variance with an
15+
Application to the Automated Design of Artificial Neural Networks.
16+
PhD thesis, Oregon Graduate Institute of Science & Technology: Beaverton,
17+
OR, USA, 1992. UMI Order No.: GAX92-22642.
18+
2. Dirk Thierens, David Edward Goldberg, and Ângela Guimarães Pereira. Domino
19+
Convergence, Drift, and the Temporal-Salience Structure of Problems. In
20+
CEC'98, pages 535-540, 1998.
21+
doi: https://doi.org/10.1109/ICEC.1998.700085.
22+
3. Kumara Sastry and David Edward Goldberg. Let's Get Ready to Rumble Redux:
23+
Crossover versus Mutation Head to Head on Exponentially Scaled Problems.
24+
In GECCO'07-I, pages 1380-1387, 2007.
25+
doi: https://doi.org10.1145/1276958.1277215.
26+
4. Kumara Sastry and David Edward Goldberg. Let's Get Ready to Rumble Redux:
27+
Crossover versus Mutation Head to Head on Exponentially Scaled Problems.
28+
IlliGAL Report 2007005, Illinois Genetic Algorithms Laboratory (IlliGAL),
29+
Department of Computer Science, Department of General Engineering,
30+
University of Illinois at Urbana-Champaign: Urbana-Champaign, IL, USA,
31+
February 11, 2007.
32+
"""
33+
34+
from typing import Callable, Final, Iterator, cast
35+
36+
import numba # type: ignore
37+
import numpy as np
38+
39+
from moptipy.examples.bitstrings.bitstring_problem import BitStringProblem
40+
41+
42+
@numba.njit(nogil=True, cache=True)
43+
def binint(x: np.ndarray) -> int:
44+
"""
45+
Get the binint objective value: decode the inverted bit string as integer.
46+
47+
:param x: the np array
48+
:return: the inverted bit string represented as integer
49+
50+
>>> binint(np.array([0]))
51+
1
52+
>>> binint(np.array([1]))
53+
0
54+
55+
>>> binint(np.array([0, 0]))
56+
3
57+
>>> binint(np.array([0, 1]))
58+
2
59+
>>> binint(np.array([1, 0]))
60+
1
61+
>>> binint(np.array([1, 1]))
62+
0
63+
64+
>>> binint(np.array([0, 0, 0]))
65+
7
66+
>>> binint(np.array([0, 0, 1]))
67+
6
68+
>>> binint(np.array([0, 1, 0]))
69+
5
70+
>>> binint(np.array([0, 1, 1]))
71+
4
72+
>>> binint(np.array([1, 0, 0]))
73+
3
74+
>>> binint(np.array([1, 0, 1]))
75+
2
76+
>>> binint(np.array([1, 1, 0]))
77+
1
78+
>>> binint(np.array([1, 1, 1]))
79+
0
80+
"""
81+
n: Final[int] = len(x)
82+
weight: int = 1 << n
83+
result: int = weight - 1
84+
for xx in x:
85+
weight >>= 1
86+
if xx:
87+
result -= weight
88+
return result
89+
90+
91+
class BinInt(BitStringProblem):
92+
"""Maximize the binary value of a bit string."""
93+
94+
def __init__(self, n: int) -> None: # +book
95+
"""
96+
Initialize the binint objective function.
97+
98+
:param n: the dimension of the problem
99+
100+
>>> print(BinInt(2).n)
101+
2
102+
>>> print(BinInt(4).evaluate(np.array([True, True, False, True])))
103+
2
104+
"""
105+
super().__init__(n)
106+
self.evaluate = binint # type: ignore
107+
108+
def __str__(self) -> str:
109+
"""
110+
Get the name of the binint objective function.
111+
112+
:return: `binint_` + length of string
113+
114+
>>> BinInt(13)
115+
binint_13
116+
"""
117+
return f"binint_{self.n}"
118+
119+
def upper_bound(self) -> int:
120+
"""
121+
Get the upper bound of the :class:`BinInt` problem.
122+
123+
:returns: `(1 << n) - 1`
124+
125+
>>> BinInt(4).upper_bound()
126+
15
127+
>>> BinInt(4).evaluate(np.array([0, 0, 0, 0]))
128+
15
129+
"""
130+
return (1 << self.n) - 1
131+
132+
@classmethod
133+
def default_instances(
134+
cls: type, scale_min: int = 2, scale_max: int = 30) \
135+
-> Iterator[Callable[[], "BinInt"]]:
136+
"""
137+
Get the 29 default instances of the :class:`BinInt` problem.
138+
139+
:param scale_min: the minimum permitted scale, by default `2`
140+
:param scale_max: the maximum permitted scale, by default `32`
141+
:returns: a sequence of default :class:`BinInt` instances
142+
143+
>>> len(list(BinInt.default_instances()))
144+
29
145+
146+
>>> [x() for x in BinInt.default_instances()]
147+
[binint_2, binint_3, binint_4, binint_5, binint_6, binint_7, \
148+
binint_8, binint_9, binint_10, binint_11, binint_12, binint_13, binint_14, \
149+
binint_15, binint_16, binint_17, binint_18, binint_19, binint_20, binint_21, \
150+
binint_22, binint_23, binint_24, binint_25, binint_26, binint_27, binint_28, \
151+
binint_29, binint_30]
152+
"""
153+
return cast(Iterator[Callable[[], "BinInt"]],
154+
super().default_instances( # type: ignore
155+
scale_min, scale_max))

0 commit comments

Comments
 (0)