1 package net.bmahe.genetics4j.core.chromosomes;
2
3 import java.util.BitSet;
4 import java.util.Objects;
5
6 import org.apache.commons.lang3.Validate;
7
8 /**
9 * A chromosome implementation that represents genetic information as a sequence of bits.
10 *
11 * <p>BitChromosome is commonly used for binary optimization problems, feature selection, and any application where the
12 * solution can be encoded as a bit string. Each bit (allele) can be either 0 or 1, representing boolean choices or
13 * binary features.
14 *
15 * <p>This implementation is immutable and uses a {@link BitSet} for efficient storage and manipulation of the bit
16 * sequence.
17 *
18 * <p>Common use cases include:
19 * <ul>
20 * <li>Binary optimization problems (knapsack, subset selection)</li>
21 * <li>Feature selection in machine learning</li>
22 * <li>Boolean satisfiability problems</li>
23 * <li>Circuit design and logic optimization</li>
24 * </ul>
25 *
26 * @see Chromosome
27 * @see java.util.BitSet
28 */
29 public class BitChromosome implements Chromosome {
30
31 private final int numBits;
32 private final BitSet bitSet;
33
34 /**
35 * Creates a new bit chromosome with the specified number of bits and initial values.
36 *
37 * @param _numBits the number of bits in this chromosome, must be positive
38 * @param _bitSet the initial bit values for this chromosome
39 * @throws IllegalArgumentException if numBits is zero or negative, if bitSet is null, or if numBits exceeds the
40 * bitSet size
41 */
42 public BitChromosome(final int _numBits, final BitSet _bitSet) {
43 Validate.isTrue(_numBits > 0, "numBits can't be zero or negative");
44 Objects.requireNonNull(_bitSet);
45 Validate.isTrue(_numBits <= _bitSet.size());
46
47 this.numBits = _numBits;
48 this.bitSet = new BitSet(numBits);
49 this.bitSet.or(_bitSet);
50 }
51
52 @Override
53 public int getNumAlleles() {
54 return numBits;
55 }
56
57 /**
58 * Returns the bit value at the specified index.
59 *
60 * @param index the index of the bit to retrieve (0-based)
61 * @return {@code true} if the bit is set (1), {@code false} if clear (0)
62 * @throws IllegalArgumentException if index is negative or greater than or equal to numBits
63 */
64 public boolean getBit(final int index) {
65 Validate.isTrue(index >= 0);
66 Validate.isTrue(index < numBits);
67
68 return bitSet.get(index);
69 }
70
71 /**
72 * Returns the underlying BitSet containing all bit values.
73 *
74 * <p>The returned BitSet is a copy and modifications to it will not affect this chromosome.
75 *
76 * @return a BitSet containing the bit values of this chromosome
77 */
78 public BitSet getBitSet() {
79 return bitSet;
80 }
81
82 /**
83 * Returns the number of bits set to 1 in this chromosome.
84 *
85 * <p>This method counts all bits that are set to true (1) in the chromosome's bit sequence.
86 *
87 * @return the count of bits set to 1, ranging from 0 to numBits
88 */
89 public int countOnes() {
90 return bitSet.cardinality();
91 }
92
93 /**
94 * Returns the number of bits set to 0 in this chromosome.
95 *
96 * <p>This method counts all bits that are set to false (0) in the chromosome's bit sequence. This is the complement
97 * of {@link #countOnes()}.
98 *
99 * @return the count of bits set to 0, ranging from 0 to numBits
100 * @see #countOnes()
101 */
102 public int countZeros() {
103 return numBits - countOnes();
104 }
105
106 @Override
107 public int hashCode() {
108 final int prime = 31;
109 int result = 1;
110 result = prime * result + (bitSet == null ? 0 : bitSet.hashCode());
111 return prime * result + numBits;
112 }
113
114 @Override
115 public boolean equals(Object obj) {
116 if (this == obj) {
117 return true;
118 }
119 if (obj == null) {
120 return false;
121 }
122 if (getClass() != obj.getClass()) {
123 return false;
124 }
125 BitChromosome other = (BitChromosome) obj;
126 if (bitSet == null) {
127 if (other.bitSet != null) {
128 return false;
129 }
130 } else if (!bitSet.equals(other.bitSet)) {
131 return false;
132 }
133 return !(numBits != other.numBits);
134 }
135
136 @Override
137 public String toString() {
138 return "BitChromosome [numBits=" + numBits + ", bitSet=" + bitSet + "]";
139 }
140 }