001 /*
002 * Java Genetic Algorithm Library (jenetics-7.1.1).
003 * Copyright (c) 2007-2022 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@gmail.com)
019 */
020 package io.jenetics.prog.regression;
021
022 import static java.lang.String.format;
023 import static java.util.Objects.requireNonNull;
024
025 import java.io.Serial;
026 import java.io.Serializable;
027 import java.lang.reflect.Array;
028 import java.util.AbstractList;
029 import java.util.List;
030 import java.util.function.Function;
031 import java.util.stream.Stream;
032
033 import io.jenetics.ext.util.Tree;
034
035 import io.jenetics.prog.op.Op;
036 import io.jenetics.prog.op.Program;
037
038 /**
039 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
040 * @version 7.1
041 * @since 5.0
042 */
043 final class SampleList<T>
044 extends AbstractList<Sample<T>>
045 implements
046 Sampling<T>,
047 Serializable
048 {
049 @Serial
050 private static final long serialVersionUID = 1L;
051
052 private final List<? extends Sample<T>> _samples;
053
054 private final Class<T> _type;
055 private final T[][] _arguments;
056 private final T[] _results;
057
058 @SuppressWarnings("unchecked")
059 SampleList(final List<? extends Sample<T>> samples) {
060 if (samples.isEmpty()) {
061 throw new IllegalArgumentException("Sample list must not be empty.");
062 }
063
064 _type = (Class<T>)samples.get(0).argAt(0).getClass();
065
066 final int arity = samples.get(0).arity();
067 if (arity == 0) {
068 throw new IllegalArgumentException(
069 "The arity of the sample point must not be zero."
070 );
071 }
072
073 for (int i = 0; i < samples.size(); ++i) {
074 final var sample = samples.get(i);
075 if (arity != sample.arity()) {
076 throw new IllegalArgumentException(format(
077 "Expected arity %d, but got %d for sample index %d.",
078 arity, sample.arity(), i
079 ));
080 }
081 }
082
083 _samples = samples;
084
085 _arguments = samples.stream()
086 .map(s -> args(_type, s))
087 .toArray(size -> (T[][])Array.newInstance(_type, size, 0));
088
089 _results = _samples.stream()
090 .map(Sample::result)
091 .toArray(size -> (T[])Array.newInstance(_type, size));
092 }
093
094 private static <T> T[] args(final Class<T> type, final Sample<T> sample) {
095 @SuppressWarnings("unchecked")
096 final T[] args = (T[])Array
097 .newInstance(sample.argAt(0).getClass(), sample.arity());
098 for (int i = 0; i < args.length; ++i) {
099 args[i] = sample.argAt(i);
100 }
101
102 return args;
103 }
104
105 @Override
106 public Result<T> eval(final Tree<? extends Op<T>, ?> program) {
107 requireNonNull(program);
108 return eval(args -> Program.eval(program, args));
109 }
110
111 @Override
112 public Result<T> eval(final Function<? super T[], ? extends T> function) {
113 requireNonNull(function);
114 @SuppressWarnings("unchecked")
115 final T[] calculated = Stream.of(_arguments)
116 .map(function)
117 .toArray(size -> (T[])Array.newInstance(_type, size));
118
119 return new Result<>(calculated, _results);
120 }
121
122 @Override
123 public Sample<T> get(int index) {
124 return _samples.get(index);
125 }
126
127 @Override
128 public int size() {
129 return _samples.size();
130 }
131
132 }
|