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.lang.String.format;
023 import static java.util.Collections.singletonList;
024 import static java.util.Objects.requireNonNull;
025 import static org.jenetics.tool.trial.SampleSummary.toSampleSummary;
026
027 import java.io.Serializable;
028 import java.util.ArrayList;
029 import java.util.Arrays;
030 import java.util.List;
031 import java.util.stream.Collectors;
032
033 import javax.xml.bind.annotation.XmlAccessType;
034 import javax.xml.bind.annotation.XmlAccessorType;
035 import javax.xml.bind.annotation.XmlAttribute;
036 import javax.xml.bind.annotation.XmlElement;
037 import javax.xml.bind.annotation.XmlRootElement;
038 import javax.xml.bind.annotation.XmlType;
039 import javax.xml.bind.annotation.adapters.XmlAdapter;
040 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
041
042 /**
043 * This class collects a list of {@link Sample} result objects into on
044 * {@code Data} object.
045 *
046 * @see Sample
047 *
048 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
049 * @version 3.4
050 * @since 3.4
051 */
052 @XmlJavaTypeAdapter(Data.Model.Adapter.class)
053 public final class Data implements Serializable {
054
055 private static final long serialVersionUID = 1L;
056
057 private final String _name;
058 private final List<Sample> _samples = new ArrayList<>();
059
060 private Data(final String name, final List<Sample> samples) {
061 if (samples.isEmpty()) {
062 throw new IllegalArgumentException("Sample list must not be empty.");
063 }
064 if (!samples.stream().allMatch(s -> samples.get(0).size() == s.size())) {
065 throw new IllegalArgumentException(
066 "All sample object must have the same size."
067 );
068 }
069
070 _name = requireNonNull(name);
071 _samples.addAll(samples);
072 }
073
074 /**
075 * Return the name of the sample {@code Data} collections.
076 *
077 * @return the name of the sample {@code Data} collections
078 */
079 public String getName() {
080 return _name;
081 }
082
083 /**
084 * The number of {@link Sample} objects this {@code Data} class contains.
085 *
086 * @return the size of the data object
087 */
088 public int dataSize() {
089 return _samples.size();
090 }
091
092 /**
093 * The number of values of an {@link Sample} object.
094 *
095 * @see Sample#size()
096 *
097 * @return number of values of an {@link Sample} object
098 */
099 public int sampleSize() {
100 return _samples.get(0).size();
101 }
102
103 /**
104 * Return the current {@link Sample} object. A newly created object is
105 * returned on demand.
106 *
107 * @return the current {@link Sample} object
108 */
109 public Sample currentSample() {
110 Sample sample = _samples.get(_samples.size() - 1);
111 if (sample.isFull()) {
112 sample = sample.newSample();
113 _samples.add(sample);
114 }
115
116 return sample;
117 }
118
119 /**
120 * Return the index of the next parameter index to calculate.
121 *
122 * @return the index of the next parameter index to calculate
123 */
124 public int nextParamIndex() {
125 return currentSample().nextIndex();
126 }
127
128 /**
129 * Calculate the sample summary of this data object.
130 *
131 * @return the sample summary of this data object
132 */
133 public SampleSummary summary() {
134 return _samples.stream()
135 .filter(Sample::isFull)
136 .collect(toSampleSummary(sampleSize()));
137 }
138
139 @Override
140 public int hashCode() {
141 return (37*_name.hashCode() + 17)*_samples.hashCode()*37 + 17;
142 }
143
144 @Override
145 public boolean equals(final Object obj) {
146 return obj instanceof Data &&
147 _name.equals(((Data)obj)._name) &&
148 _samples.equals(((Data)obj)._samples);
149 }
150
151 @Override
152 public String toString() {
153 return format("Data[name=%s, size=%d]", _name, dataSize());
154 }
155
156 /**
157 * Create a new {@code Data} object with the given parameters.
158 *
159 * @param name the name of the data object
160 * @param samples the sample list of the data object
161 * @throws NullPointerException if one of the parameters is {@code null}
162 * @return a new {@code Data} object with the given parameters
163 */
164 public static Data of(final String name, final List<Sample> samples) {
165 return new Data(name, samples);
166 }
167
168 /**
169 * Return a new {@code Data} object with the given name and the given number
170 * of parameters.
171 *
172 * @param name the name of the data object
173 * @param parameterCount the parameter count of the created samples
174 * @throws NullPointerException if the data {@code name} is {@code null}
175 * @throws IllegalArgumentException if the given {@code parameterCount} is
176 * smaller then one
177 * @return a new {@code Data} object with the given parameters
178 */
179 public static Data of(final String name, final int parameterCount) {
180 return of(name, singletonList(Sample.of(parameterCount)));
181 }
182
183
184 /* *************************************************************************
185 * JAXB object serialization
186 * ************************************************************************/
187
188 @XmlRootElement(name = "data")
189 @XmlType(name = "org.jenetics.tool.trial.Data")
190 @XmlAccessorType(XmlAccessType.FIELD)
191 final static class Model {
192
193 @XmlAttribute
194 public String name;
195
196 @XmlElement(name = "sample")
197 public List<String> samples;
198
199 public static final class Adapter extends XmlAdapter<Model, Data> {
200 @Override
201 public Model marshal(final Data data) {
202 final Model model = new Model();
203 model.name = data._name;
204 model.samples = data._samples.stream()
205 .map(s -> s.stream().mapToObj(Double::toString)
206 .collect(Collectors.joining(" ")))
207 .collect(Collectors.toList());
208 return model;
209 }
210
211 @Override
212 public Data unmarshal(final Model model) {
213 return Data.of(
214 model.name,
215 model.samples.stream()
216 .map(s -> Arrays.stream(s.split("\\s"))
217 .mapToDouble(Double::parseDouble).toArray())
218 .map(Sample::of)
219 .collect(Collectors.toList())
220 );
221 }
222 }
223
224 }
225 }
|