001 /*
002 * Java Genetic Algorithm Library (jenetics-3.7.0).
003 * Copyright (c) 2007-2016 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
019 */
020 package org.jenetics.tool.trial;
021
022 import static java.io.File.createTempFile;
023 import static java.lang.String.format;
024 import static java.nio.file.Files.deleteIfExists;
025 import static java.nio.file.Files.move;
026 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
027 import static java.util.Objects.requireNonNull;
028 import static org.jenetics.internal.util.jaxb.marshal;
029
030 import java.io.File;
031 import java.io.FileInputStream;
032 import java.io.FileOutputStream;
033 import java.io.IOException;
034 import java.io.InputStream;
035 import java.io.OutputStream;
036 import java.io.UncheckedIOException;
037 import java.nio.file.Path;
038 import java.util.Optional;
039 import java.util.function.Function;
040
041 import javax.xml.bind.Marshaller;
042 import javax.xml.bind.Unmarshaller;
043 import javax.xml.bind.annotation.XmlAccessType;
044 import javax.xml.bind.annotation.XmlAccessorType;
045 import javax.xml.bind.annotation.XmlAttribute;
046 import javax.xml.bind.annotation.XmlElement;
047 import javax.xml.bind.annotation.XmlRootElement;
048 import javax.xml.bind.annotation.XmlType;
049 import javax.xml.bind.annotation.adapters.XmlAdapter;
050 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
051
052 /**
053 * Represents an function testing measurement environment.
054 *
055 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
056 * @version 3.4
057 * @since 3.4
058 */
059 @XmlJavaTypeAdapter(TrialMeter.Model.Adapter.class)
060 public final class TrialMeter<T> {
061
062 private final String _name;
063 private final String _description;
064 private final Env _env;
065
066 private final Params<T> _params;
067 private final DataSet _dataSet;
068
069 private TrialMeter(
070 final String name,
071 final String description,
072 final Env env,
073 final Params<T> params,
074 final DataSet dataSet
075 ) {
076 _name = requireNonNull(name);
077 _description = description;
078 _env = requireNonNull(env);
079 _params = requireNonNull(params);
080 _dataSet = requireNonNull(dataSet);
081 }
082
083 public String getName() {
084 return _name;
085 }
086
087 /**
088 * Return the optional description string.
089 *
090 * @return the optional description string
091 */
092 public Optional<String> getDescription() {
093 return Optional.ofNullable(_description);
094 }
095
096 /**
097 * The trial meter environment information.
098 *
099 * @return the trial meter environment information
100 */
101 public Env getEnv() {
102 return _env;
103 }
104
105 /**
106 * Return the testing parameters.
107 *
108 * @return the testing parameters
109 */
110 public Params<T> getParams() {
111 return _params;
112 }
113
114 /**
115 * Return the current trail {@link DataSet}.
116 *
117 * @return the current trail data set
118 */
119 public DataSet getDataSet() {
120 return _dataSet;
121 }
122
123 /**
124 * Return the test data with the given name
125 *
126 * @param name the data name
127 * @return the test {@link Data} with the given name
128 * @throws NullPointerException if the given {@code name} is {@code null}
129 */
130 public Data getData(final String name) {
131 return _dataSet.get(name);
132 }
133
134 /**
135 * Return the number of test data results.
136 *
137 * @return the number of test data results.
138 */
139 public int dataSize() {
140 return _dataSet.dataSize();
141 }
142
143 /**
144 * Calculates the test values for all parameters. The length of the
145 * resulting {@code double[]} array must be {@link #dataSize()}.
146 *
147 * @param function the test function
148 */
149 public void sample(final Function<T, double[]> function) {
150 _params.values()
151 .subSeq(_dataSet.nextParamIndex())
152 .forEach(p -> _dataSet.add(function.apply(p)));
153 }
154
155 @Override
156 public String toString() {
157 return format(
158 "TrialMeter[sample=%d, param=%d]",
159 dataSize(), _dataSet.nextParamIndex()
160 );
161 }
162
163 /**
164 * Writes the current {@code TrialMeter} object (the calculated samples +
165 * the parameters) to the given output stream.
166 *
167 * @param out the output stream where to write the trial meter
168 * @throws UncheckedIOException if the marshalling fails
169 */
170 public void write(final OutputStream out) {
171 try {
172 final Marshaller marshaller = jaxb.context().createMarshaller();
173 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
174 marshaller.marshal(marshal(this), out);
175 } catch (Exception e) {
176 throw new UncheckedIOException(new IOException(e));
177 }
178 }
179
180 /**
181 * Writes the current {@code TrialMeter} object (the calculated samples +
182 * the parameters) to the given path.
183 *
184 * @param path the output path
185 * @throws UncheckedIOException if the marshalling fails
186 */
187 public void write(final Path path) {
188 try {
189 final File tempFile = createTempFile("__trial_meter__", ".xml");
190 try {
191 try (OutputStream out = new FileOutputStream(tempFile)) {
192 write(out);
193 }
194
195 move(tempFile.toPath(), path, REPLACE_EXISTING);
196 } finally {
197 deleteIfExists(tempFile.toPath());
198 }
199 } catch (IOException e) {
200 throw new UncheckedIOException(e);
201 }
202 }
203
204 /**
205 * Return a new trial measure environment.
206 *
207 * @param name the trial meter name
208 * @param description the trial meter description, maybe {@code null}
209 * @param params the parameters which are tested by this trial meter
210 * @param dataSetNames the names of the calculated data sets
211 * @param <T> the parameter type
212 * @return a new trial measure environment
213 */
214 public static <T> TrialMeter<T> of(
215 final String name,
216 final String description,
217 final Params<T> params,
218 final String... dataSetNames
219 ) {
220 return new TrialMeter<T>(
221 name,
222 description,
223 Env.of(),
224 params,
225 DataSet.of(params.size(), dataSetNames)
226 );
227 }
228
229 /**
230 * Return a new trial measure environment.
231 *
232 * @param name the trial meter name
233 * @param description the trial meter description, maybe {@code null}
234 * @param env the environment information
235 * @param params the parameters which are tested by this trial meter
236 * @param dataSetNames the names of the calculated data sets
237 * @param <T> the parameter type
238 * @return a new trial measure environment
239 */
240 public static <T> TrialMeter<T> of(
241 final String name,
242 final String description,
243 final Env env,
244 final Params<T> params,
245 final String... dataSetNames
246 ) {
247 return new TrialMeter<T>(
248 name,
249 description,
250 env,
251 params,
252 DataSet.of(params.size(), dataSetNames)
253 );
254 }
255
256 /**
257 * Read existing {@code TrialMeter} (intermediate) results from the given
258 * input stream.
259 *
260 * @param in the {@link InputStream} to read from
261 * @param <T> the parameter type
262 * @throws UncheckedIOException if reading the {@code TrialMeter} fails
263 * @return the {@code TrialMeter} object read from the input stream
264 */
265 @SuppressWarnings("unchecked")
266 public static <T> TrialMeter<T> read(final InputStream in) {
267 try {
268 final Unmarshaller unmarshaller = jaxb.context().createUnmarshaller();
269 return (TrialMeter<T>)Model.ADAPTER
270 .unmarshal((Model)unmarshaller.unmarshal(in));
271 } catch (Exception e) {
272 throw new UncheckedIOException(new IOException(e));
273 }
274 }
275
276 /**
277 * Read existing {@code TrialMeter} (intermediate) results from the given
278 * path.
279 *
280 * @param path the path the {@code TrialMeter} is read
281 * @param <T> the parameter type
282 * @throws UncheckedIOException if reading the {@code TrialMeter} fails
283 * @return the {@code TrialMeter} object read from the input stream
284 */
285 public static <T> TrialMeter<T> read(final Path path) {
286 try (InputStream in = new FileInputStream(path.toFile())) {
287 return read(in);
288 } catch (IOException e) {
289 throw new UncheckedIOException(e);
290 }
291 }
292
293
294 /* *************************************************************************
295 * JAXB object serialization
296 * ************************************************************************/
297
298 @XmlRootElement(name = "measurement")
299 @XmlType(name = "org.jenetics.tool.trial.TrialMeter")
300 @XmlAccessorType(XmlAccessType.FIELD)
301 @SuppressWarnings({"unchecked", "rawtypes"})
302 static final class Model {
303
304 @XmlAttribute
305 public String name;
306
307 @XmlAttribute
308 public String description;
309
310 @XmlElement(name = "environment", required = true, nillable = false)
311 public Env env;
312
313 @XmlElement(name = "params", required = true, nillable = false)
314 public Params params;
315
316 @XmlElement(name = "data-set", required = true, nillable = false)
317 public DataSet dataSet;
318
319 public static final class Adapter
320 extends XmlAdapter<Model, TrialMeter>
321 {
322 @Override
323 public Model marshal(final TrialMeter data) {
324 final Model model = new Model();
325 model.name = data._name;
326 model.description = data._description;
327 model.env = data._env;
328 model.params = data.getParams();
329 model.dataSet = data._dataSet;
330 return model;
331 }
332
333 @Override
334 public TrialMeter unmarshal(final Model model) {
335 return new TrialMeter(
336 model.name,
337 model.description,
338 model.env,
339 model.params,
340 model.dataSet
341 );
342 }
343 }
344
345 static final Adapter ADAPTER = new Adapter();
346 }
347
348 }
|