-
Notifications
You must be signed in to change notification settings - Fork 150
/
CompositeAlterer.java
147 lines (132 loc) · 4 KB
/
CompositeAlterer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
* Java Genetic Algorithm Library (@__identifier__@).
* Copyright (c) @__year__@ Franz Wilhelmstötter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Author:
* Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
*/
package io.jenetics;
import static java.lang.String.format;
import static io.jenetics.util.ISeq.toISeq;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import io.jenetics.util.ISeq;
import io.jenetics.util.Seq;
/**
* Combines several alterers to one.
*
* @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
* @since 1.0
* @version 5.0
*/
final class CompositeAlterer<
G extends Gene<?, G>,
C extends Comparable<? super C>
>
extends AbstractAlterer<G, C>
{
private final ISeq<Alterer<G, C>> _alterers;
/**
* Combine the given alterers.
*
* @param alterers the alterers to combine.
* @throws NullPointerException if one of the alterers is {@code null}.
*/
CompositeAlterer(final Seq<Alterer<G, C>> alterers) {
super(1.0);
_alterers = normalize(alterers);
}
private static <G extends Gene<?, G>, C extends Comparable<? super C>>
ISeq<Alterer<G, C>> normalize(final Seq<Alterer<G, C>> alterers) {
final Function<Alterer<G, C>, Stream<Alterer<G, C>>> mapper =
a -> a instanceof CompositeAlterer
? ((CompositeAlterer<G, C>)a).alterers().stream()
: Stream.of(a);
return alterers.stream()
.flatMap(mapper)
.collect(toISeq());
}
@Override
public AltererResult<G, C> alter(
final Seq<Phenotype<G, C>> population,
final long generation
) {
AltererResult<G, C> result = new AltererResult<>(population.asISeq(), 0);
for (var alterer : _alterers) {
final AltererResult<G, C> as = alterer.alter(
result.population(),
generation
);
result = new AltererResult<>(
as.population(),
as.alterations() + result.alterations()
);
}
return result;
}
/**
* Return the alterers this alterer consists of. The returned array is sealed
* and cannot be changed.
*
* @return the alterers this alterer consists of.
*/
ISeq<Alterer<G, C>> alterers() {
return _alterers;
}
@Override
public String toString() {
return format(
"%s:\n%s", getClass().getSimpleName(),
_alterers.stream()
.map(a -> " - " + a)
.collect(Collectors.joining("\n"))
);
}
/**
* Combine the given alterers.
*
* @param <G> the gene type
* @param <C> the fitness function result type
* @param alterers the alterers to combine.
* @return a new alterer which consists of the given one
* @throws NullPointerException if one of the alterers is {@code null}.
*/
@SafeVarargs
static <G extends Gene<?, G>, C extends Comparable<? super C>>
CompositeAlterer<G, C> of(final Alterer<G, C>... alterers) {
return new CompositeAlterer<>(ISeq.of(alterers));
}
/**
* Joins the given alterer and returns a new CompositeAlterer object. If one
* of the given alterers is a CompositeAlterer the sub alterers of it are
* unpacked and appended to the newly created CompositeAlterer.
*
* @param <T> the gene type of the alterers.
*
* @param <C> the fitness function result type
* @param a1 the first alterer.
* @param a2 the second alterer.
* @return a new CompositeAlterer object.
* @throws NullPointerException if one of the given alterer is {@code null}.
*/
static <T extends Gene<?, T>, C extends Comparable<? super C>>
CompositeAlterer<T, C> join(
final Alterer<T, C> a1,
final Alterer<T, C> a2
) {
return CompositeAlterer.of(a1, a2);
}
}