1 package net.bmahe.genetics4j.core.chromosomes;
2
3 import java.util.Arrays;
4 import java.util.Objects;
5
6 import org.apache.commons.lang3.Validate;
7
8 /**
9 * A chromosome implementation that represents genetic information as an array of double-precision floating-point
10 * values.
11 *
12 * <p>DoubleChromosome is ideal for continuous optimization problems where solutions can be encoded as real-valued
13 * vectors. This chromosome type provides high precision for numerical optimization tasks and is commonly used in
14 * function optimization, neural network weight evolution, and parameter tuning.
15 *
16 * <p>This chromosome type is particularly suitable for:
17 * <ul>
18 * <li><strong>Continuous optimization</strong>: Function minimization/maximization with real-valued parameters</li>
19 * <li><strong>Neural network evolution</strong>: Evolving connection weights and biases</li>
20 * <li><strong>Engineering optimization</strong>: Design parameters with continuous constraints</li>
21 * <li><strong>Scientific computing</strong>: Model parameter estimation and calibration</li>
22 * <li><strong>Financial modeling</strong>: Portfolio optimization and risk parameter tuning</li>
23 * <li><strong>Machine learning</strong>: Hyperparameter optimization for continuous parameters</li>
24 * </ul>
25 *
26 * <p>Key characteristics:
27 * <ul>
28 * <li><strong>High precision</strong>: 64-bit floating-point representation for accurate computations</li>
29 * <li><strong>Bounded values</strong>: All doubles are constrained to [minValue, maxValue]</li>
30 * <li><strong>Fixed length</strong>: Chromosome size is determined at creation time</li>
31 * <li><strong>Immutable</strong>: Values cannot be changed after construction</li>
32 * <li><strong>IEEE 754 compliant</strong>: Standard floating-point arithmetic and comparisons</li>
33 * </ul>
34 *
35 * <p>The chromosome maintains bounds information which is used by genetic operators such as:
36 * <ul>
37 * <li><strong>Arithmetic crossover</strong>: Weighted averaging of parent values</li>
38 * <li><strong>Gaussian mutation</strong>: Adding normally distributed noise</li>
39 * <li><strong>Uniform mutation</strong>: Random replacement within bounds</li>
40 * <li><strong>Creep mutation</strong>: Small incremental changes</li>
41 * </ul>
42 *
43 * <p>Special considerations for floating-point chromosomes:
44 * <ul>
45 * <li><strong>Precision handling</strong>: Be aware of floating-point precision limits</li>
46 * <li><strong>Boundary conditions</strong>: Handle edge cases at min/max values</li>
47 * <li><strong>Convergence</strong>: May require epsilon-based convergence criteria</li>
48 * <li><strong>Scaling</strong>: Consider normalizing parameters for better performance</li>
49 * </ul>
50 *
51 * @see Chromosome
52 * @see net.bmahe.genetics4j.core.spec.chromosome.DoubleChromosomeSpec
53 * @see net.bmahe.genetics4j.core.chromosomes.factory.DoubleChromosomeFactory
54 * @see FloatChromosome
55 */
56 public class DoubleChromosome implements Chromosome {
57
58 private final int size;
59 private final double minValue;
60 private final double maxValue;
61 private final double[] values;
62
63 /**
64 * Creates a new double chromosome with the specified parameters and values.
65 *
66 * @param _size the number of double values in this chromosome
67 * @param _minValue the minimum allowed value for any double in this chromosome
68 * @param _maxValue the maximum allowed value for any double in this chromosome
69 * @param _values the array of double values for this chromosome
70 * @throws IllegalArgumentException if size is not positive, if minValue > maxValue, if values array is null, or if
71 * the array length doesn't match the specified size
72 */
73 public DoubleChromosome(final int _size, final double _minValue, final double _maxValue, final double[] _values) {
74 Validate.isTrue(_size > 0);
75 Validate.isTrue(_minValue <= _maxValue);
76 Validate.notNull(_values);
77 Validate.isTrue(_size == _values.length, "Provided size does not match the size of the content");
78
79 this.size = _size;
80 this.minValue = _minValue;
81 this.maxValue = _maxValue;
82 this.values = Arrays.copyOf(_values, _size);
83 }
84
85 @Override
86 public int getNumAlleles() {
87 return size;
88 }
89
90 /**
91 * Returns the double value at the specified index.
92 *
93 * @param index the index of the allele to retrieve (0-based)
94 * @return the double value at the specified position
95 * @throws IllegalArgumentException if index is negative or greater than or equal to the chromosome size
96 */
97 public double getAllele(final int index) {
98 Validate.inclusiveBetween(0, size - 1, index);
99
100 return values[index];
101 }
102
103 /**
104 * Returns the number of double values in this chromosome.
105 *
106 * @return the chromosome size
107 */
108 public int getSize() {
109 return size;
110 }
111
112 /**
113 * Returns the minimum allowed value for doubles in this chromosome.
114 *
115 * @return the minimum value constraint
116 */
117 public double getMinValue() {
118 return minValue;
119 }
120
121 /**
122 * Returns the maximum allowed value for doubles in this chromosome.
123 *
124 * @return the maximum value constraint
125 */
126 public double getMaxValue() {
127 return maxValue;
128 }
129
130 /**
131 * Returns a copy of the double values in this chromosome.
132 *
133 * <p>The returned array is a defensive copy; modifications to it will not affect this chromosome.
134 *
135 * @return a copy of the double values array
136 */
137 public double[] getValues() {
138 return values;
139 }
140
141 @Override
142 public int hashCode() {
143 final int prime = 31;
144 int result = 1;
145 result = prime * result + Arrays.hashCode(values);
146 result = prime * result + Objects.hash(maxValue, minValue, size);
147 return result;
148 }
149
150 @Override
151 public boolean equals(Object obj) {
152 if (this == obj)
153 return true;
154 if (obj == null)
155 return false;
156 if (getClass() != obj.getClass())
157 return false;
158 DoubleChromosome other = (DoubleChromosome) obj;
159 return Double.doubleToLongBits(maxValue) == Double.doubleToLongBits(other.maxValue)
160 && Double.doubleToLongBits(minValue) == Double.doubleToLongBits(other.minValue) && size == other.size
161 && Arrays.equals(values, other.values);
162 }
163
164 @Override
165 public String toString() {
166 return "DoubleChromosome [size=" + size + ", minValue=" + minValue + ", maxValue=" + maxValue + ", values="
167 + Arrays.toString(values) + "]";
168 }
169 }