SampleList.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-7.1.0).
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 }