001/* 002 * Java Genetic Algorithm Library (jenetics-8.1.0). 003 * Copyright (c) 2007-2024 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 */ 020package io.jenetics.prog.regression; 021 022import java.util.List; 023 024import io.jenetics.ext.util.CsvSupport; 025 026/** 027 * Represents a sample point used for the symbolic regression task. It consists 028 * of an argument array and a result value. The sample point is comparable 029 * according its {@link #result()} value. 030 * 031 * @implSpec 032 * The dimensionality of the sample point must be at least one, which means 033 * {@code arity() >= 1}. 034 * 035 * @param <T> the sample type 036 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 037 * @version 5.0 038 * @since 5.0 039 */ 040public interface Sample<T> { 041 042 /** 043 * Return the dimensionality of the sample point arguments. 044 * 045 * @return the arity of the sample point 046 */ 047 int arity(); 048 049 /** 050 * Return the argument value with the given {@code index}. 051 * 052 * @see #arity() 053 * 054 * @param index the argument index 055 * @return the argument value with the given {@code index} 056 * @throws ArrayIndexOutOfBoundsException if the given {@code index} is not 057 * within the given range {@code [0, arity)} 058 */ 059 T argAt(final int index); 060 061 /** 062 * Return the result of the sample point. 063 * 064 * @return the result of the sample point 065 */ 066 T result(); 067 068 069 /* ************************************************************************* 070 * Static factory methods. 071 * ************************************************************************/ 072 073 /** 074 * Create a new sample point from the given argument and sample result. It 075 * represents the function arguments with the function value: 076 * {@code f: sample[0:sample.length-1] -> sample[sample.length-1]}. The last 077 * array element contains the result, and the first n-1 elements are function 078 * arguments. 079 * 080 * @param <T> the sample type 081 * @param sample the sample point result 082 * @return a new sample point 083 * @throws IllegalArgumentException if the argument array is empty 084 * @throws NullPointerException if the argument array is {@code null} 085 */ 086 static <T> Sample<T> of(final T[] sample) { 087 return new ObjectSample<>(sample.clone()); 088 } 089 090 /** 091 * Create a new sample point from the given argument and sample result. It 092 * represents the function arguments with the function value: 093 * {@code f: x -> y} 094 * 095 * @param x the argument 096 * @param y the sample point result 097 * @return a new sample point 098 */ 099 static Sample<Double> ofDouble(final double x, final double y) { 100 return new DoubleSample(x, y); 101 } 102 103 /** 104 * Create a new sample point from the given argument and sample result. It 105 * represents the function arguments with the function value: 106 * {@code f: (x1, x2) -> y} 107 * 108 * @param x1 the first argument 109 * @param x2 the second argument 110 * @param y the sample point result 111 * @return a new sample point 112 */ 113 static Sample<Double> ofDouble( 114 final double x1, 115 final double x2, 116 final double y 117 ) { 118 return new DoubleSample(x1, x2, y); 119 } 120 121 /** 122 * Create a new sample point from the given argument and sample result. It 123 * represents the function arguments with the function value: 124 * {@code f: (x1, x2, x3) -> y} 125 * 126 * @param x1 the first argument 127 * @param x2 the second argument 128 * @param x3 the second argument 129 * @param y the sample point result 130 * @return a new sample point 131 */ 132 static Sample<Double> ofDouble( 133 final double x1, 134 final double x2, 135 final double x3, 136 final double y 137 ) { 138 return new DoubleSample(x1, x2, x3, y); 139 } 140 141 /** 142 * Create a new sample point from the given argument and sample result. It 143 * represents the function arguments with the function value: 144 * {@code f: (x1, x2, x3, xn-1) -> y} 145 * 146 * @since 8.1 147 * 148 * @param values the sample data 149 * @return a new sample point 150 */ 151 static Sample<Double> ofDouble(final double... values) { 152 return new DoubleSample(values); 153 } 154 155 /** 156 * Parses the given CSV string into a list of double sample points. The 157 * following example shows how to create a list of sample points from a CSV 158 * string. 159 * {@snippet lang=java: 160 * static final List<Sample<Double>> SAMPLES = Sample.parseDoubles(""" 161 * 1.0, -8.0000 162 * 0.9, -6.2460 163 * 0.8, -4.7680 164 * 0.7, -3.5420 165 * 0.6, -2.5440 166 * 0.5, -1.7500 167 * 0.4, -1.1360 168 * 0.3, -0.6780 169 * 0.2, -0.3520 170 * 0.1, -0.1340 171 * 0.0, 0.0000 172 * 0.1, 0.0740 173 * 0.2, 0.1120 174 * 0.3, 0.1380 175 * 0.4, 0.1760 176 * 0.5, 0.2500 177 * 0.6, 0.3840 178 * 0.7, 0.6020 179 * 0.8, 0.9280 180 * 0.9, 1.3860 181 * 1.0, 2.0000 182 * """ 183 * ); 184 * } 185 * 186 * @since 8.1 187 * 188 * @param csv the CSV string to parse 189 * @return the parsed double samples 190 */ 191 static List<Sample<Double>> parseDoubles(final CharSequence csv) { 192 return CsvSupport.parseDoubles(csv).stream() 193 .map(Sample::ofDouble) 194 .toList(); 195 } 196 197}