001/* 002 * Java Genetic Algorithm Library (jenetics-7.2.0). 003 * Copyright (c) 2007-2023 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.ext; 021 022import static java.util.Objects.requireNonNull; 023import static io.jenetics.internal.util.Hashes.hash; 024import static io.jenetics.util.RandomRegistry.random; 025 026import java.io.Serial; 027import java.io.Serializable; 028import java.math.BigInteger; 029import java.util.Objects; 030 031import io.jenetics.NumericGene; 032import io.jenetics.internal.util.Requires; 033import io.jenetics.util.ISeq; 034import io.jenetics.util.MSeq; 035import io.jenetics.util.Mean; 036import io.jenetics.util.RandomRegistry; 037 038import io.jenetics.ext.internal.util.Randoms; 039 040/** 041 * Numeric chromosome implementation which holds an arbitrary sized integer 042 * number. 043 * 044 * <p>This is a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html"> 045 * value-based</a> class; use of identity-sensitive operations (including 046 * reference equality ({@code ==}), identity hash code, or synchronization) on 047 * instances of {@code IntegerGene} may have unpredictable results and should 048 * be avoided. 049 * 050 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 051 * @since 3.5 052 * @version 6.0 053 */ 054public final class BigIntegerGene 055 implements 056 NumericGene<BigInteger, BigIntegerGene>, 057 Mean<BigIntegerGene>, 058 Serializable 059{ 060 @Serial 061 private static final long serialVersionUID = 1L; 062 063 private static final BigInteger TWO = BigInteger.valueOf(2); 064 065 private final BigInteger _value; 066 private final BigInteger _min; 067 private final BigInteger _max; 068 069 private BigIntegerGene( 070 final BigInteger value, 071 final BigInteger min, 072 final BigInteger max 073 ) { 074 _value = requireNonNull(value); 075 _min = requireNonNull(min); 076 _max = requireNonNull(max); 077 } 078 079 @Override 080 public BigInteger allele() { 081 return _value; 082 } 083 084 @Override 085 public BigInteger min() { 086 return _min; 087 } 088 089 @Override 090 public BigInteger max() { 091 return _max; 092 } 093 094 @Override 095 public BigIntegerGene mean(final BigIntegerGene that) { 096 final BigInteger value = _value.add(that._value).divide(TWO); 097 return of(value, _min, _max); 098 } 099 100 @Override 101 public BigIntegerGene newInstance(final Number number) { 102 return of(BigInteger.valueOf(number.longValue()), _min, _max); 103 } 104 105 @Override 106 public BigIntegerGene newInstance(final BigInteger value) { 107 return of(value, _min, _max); 108 } 109 110 @Override 111 public BigIntegerGene newInstance() { 112 return of(_min, _max); 113 } 114 115 @Override 116 public int hashCode() { 117 return hash(_value, hash(_min, hash(_max, hash(getClass())))); 118 } 119 120 @Override 121 public boolean equals(final Object obj) { 122 return obj == this || 123 obj instanceof BigIntegerGene other && 124 Objects.equals(other._value, _value) && 125 Objects.equals(other._min, _min) && 126 Objects.equals(other._max, _max); 127 } 128 129 @Override 130 public String toString() { 131 return String.format("[%s]", _value); 132 } 133 134 /* ************************************************************************* 135 * Static factory methods. 136 **************************************************************************/ 137 138 static ISeq<BigIntegerGene> seq( 139 final BigInteger minimum, 140 final BigInteger maximum, 141 final int length 142 ) { 143 Requires.positive(length); 144 145 final var r = random(); 146 147 return MSeq.<BigIntegerGene>ofLength(length) 148 .fill(() -> new BigIntegerGene( 149 Randoms.nextBigInteger(minimum, maximum, r), minimum, maximum)) 150 .toISeq(); 151 } 152 153 /** 154 * Create a new random {@code BigIntegerGene} with the given value and the 155 * given range. If the {@code value} isn't within the interval [min, max), 156 * no exception is thrown. In this case the method 157 * {@link BigIntegerGene#isValid()} returns {@code false}. 158 * 159 * @param value the value of the gene. 160 * @param min the minimal valid value of this gene (inclusively). 161 * @param max the maximal valid value of this gene (exclusively). 162 * @return a new random {@code BigIntegerGene} 163 * @throws NullPointerException if one of the arguments is {@code null} 164 */ 165 public static BigIntegerGene of( 166 final BigInteger value, 167 final BigInteger min, 168 final BigInteger max 169 ) { 170 return new BigIntegerGene(value, min, max); 171 } 172 173 /** 174 * Create a new random {@code BigIntegerGene}. It is guaranteed that the 175 * value of the {@code BigIntegerGene} lies in the interval [min, max). 176 * 177 * @param min the minimal valid value of this gene (inclusively). 178 * @param max the maximal valid value of this gene (exclusively). 179 * @return a new random {@code BigIntegerGene} 180 * @throws NullPointerException if one of the arguments is {@code null} 181 */ 182 public static BigIntegerGene of(final BigInteger min, final BigInteger max) { 183 return of( 184 Randoms.nextBigInteger(min, max, RandomRegistry.random()), 185 min, 186 max 187 ); 188 } 189 190}