So I Created a class Term. This class represents a term of a polynomial such as 2x4 where 2 is coefficient and 4 is exponent of the
term.
Data members:-
int coefficient
int exponent
public class Term2 {
private int coefficient;
private int exponent;
public Term2() {
coefficient = 0;
exponent = 0;
}
public Term2(int coefficient, int exponent) {
this.coefficient = coefficient;
this.exponent = exponent;
}
public int getCoefficient() {
return coefficient;
}
public void setCoefficient(int coefficient) {
this.coefficient = coefficient;
}
public int getExponent() {
return exponent;
}
public void setExponent(int exponent) {
this.exponent = exponent;
}
}
then I Created another class called Polynomial. The internal representation of a polynomial is an array of Terms. The size of this array should be fixed. I
Provided a constructor for this class that will set all terms of a polynomial object as zero (where coefficient is 0 and exponent is 0).
then I created a funtion called
setTerm(int, int)
which Setting a term of a polynomial object. Each successive call of
this function should set next term of the polynomial object.
package javaapplication2;
import java.util.Scanner;
public class Polynomials {
private Term2 terms[];
private int valueLength = 0;
public Polynomials(int termSize) {
terms = new Term2[termSize];
for (int i = 0; i < terms.length; i++) {
terms[i] = new Term2(0, 0);
}
}
public void setTerm(int c, int e) {
if (valueLength >= terms.length) {
System.out.println("big");
return;
}
terms[valueLength++] = new Term2(c, e);
if (e > 0) {
for (int i = 0; i < terms.length; i++) {
terms[i] = new Term2(c, e);
}
}
}
public static void main(String[] args) {
int n;
System.out.println("Enter the number of terms : ");
Scanner in = new Scanner(System.in);
n = in.nextInt();
Polynomials p = new Polynomials(n);
p.setTerm(2, 3);
Term2 t = new Term2();
}
}
STUCKED
is the code structure is correct as I am not able to get the expected output in addtion i also want to achieve the two below funtionality
1.sort() ñ to arrange the terms in ascending order of exponents.
Provide a function to print a polynomial object
please suggest me the best solution
OUTPUT
run:
Enter the number of terms :
2
BUILD SUCCESSFUL (total time: 3 seconds)
The arrray is a too complicated data structure here. (Besides if (e > 0) { ... } messes things up.)
Either a Map from exponent to Term2 or to the coefficient.
public class Polynomials {
private SortedMap<Integer, Term2> termsByExponent = new TreeMap<>();
public Polynomials() {
}
public void setTerm(int c, int e) {
termsByExponent.put(e, new Term2(c, e));
}
/**
* #param exp the exponent (not the index).
*/
public Term2 getTerm(int exp) {
return termsByExponent.computeIfAbsent(exp, e -> new Term2(0, e));
}
public Term2 getTermByIndex(int i) {
return termsByExponent.values().get(i);
}
public int size() {
return map.size();
}
#Override
public String toString() {
return termsByExponent.values().stream()
.map(t -> String.format("%s%d.x^%d",
t.getCoefficient() >= 0 ? "+" : "", // Minus already there.
t.getCoefficient(),
t.getExponent()))
.collect(Collectors.join(""))
.replaceFirst("\\.x\\^0\\b", "")
.replaceFirst("\\^1\\b", "");
}
}
Related
I have a Result class in which I keep all values/results.
All my code:
public class Main {
public static void main(String[] args) {
Main main = new Main();
Result result = new Result();
Divider divider = new Divider();
String[] myTestArray = new String[]{"1234", "12"};
if (myTestArray.length != 2) {
System.out.printf("You can not use %d arguments. " +
"To perform division, you need to use 2 arguments `", myTestArray.length);`
System.exit(1);
}
int dividend = Integer.parseInt(myTestArray[0]);
int divisor = Integer.parseInt(myTestArray[1]);
divider.divide(dividend, divisor);
Formatter formatter = new Formatter();
formatter.format(result);
}
}
public class Divider {
Result result;
public Divider() {
this.result = new Result();
}
/**
* divide method performs division of two numbers
*/
public void divide(int dividend, int divisor) {
result.setDividend(Math.abs(dividend));
result.setDivisor(Math.abs(divisor));
result.setQuotient(divideTwoNumbers(result.getDividend(),
result.getDivisor()));
}
/**
*
*/
public int calculateProduct(int partialDividend) {
int multiplicand = divideTwoNumbers(partialDividend, `result.getDivisor());`
result.setProduct(multipleTwoNumbers(result.getDivisor(), `multiplicand));`
result.setRemainder(partialDividend - result.getProduct());
return result.getProduct();
}
/**
* Method divideTwoNumbers is used instead of operands "/"
*/
public int divideTwoNumbers(int dividend, int divisor) {
int result = 0;
for (int i = 0; dividend >= divisor; i++) {
dividend = dividend - divisor;
result++;
}
return result;
}
/**
* Method multipleTwoNumbers is used instead of operands "*"
*/
public int multipleTwoNumbers(int multiplicand, int multiplier) {
int product = 0;
for (int i = 0; i < multiplicand; i++) {
product = product + multiplier;
}
return product;
}
}
I think, my problem is around here somewhere
public class Formatter {
Result result;
Divider divider;
private int firstIndexPartialDividend = 0; // find the beginning of the number
private int countSpace = 0; // space counter
public Formatter() {
this.result = new Result();
this.divider = new Divider();
}
public void format() {
// print the first row
printFirstRow();
String dividendText = Integer.toString(result.getDividend());
for (int i = 1; i <= dividendText.length(); i++) {
result.setFirstPartialDividend(Integer.parseInt
(dividendText.substring(firstIndexPartialDividend, i)));
// print the second row
if (result.getFirstPartialDividend() >= result.getDivisor() &&
firstIndexPartialDividend == 0) {
countSpace = dividendText.length() - i;
printSecondRow(result.getFirstPartialDividend());
firstIndexPartialDividend = i;
// To align the space in the next row.
if (Integer.toString(result.getProduct()).length()
> Integer.toString(result.getRemainder()).length() &&
result.getRemainder() > 0) {
countSpace = Integer.toString(result.getProduct()).length()
- Integer.toString(result.getRemainder()).length();
} else {
countSpace = 0;
}
}
}
}
/**
* printFirstRow method - print the first row of an application
*/
public void printFirstRow() {
System.out.printf("%d|%d\n", result.getDividend(), `enter code here`result.getDivisor());
}
/**
* printSecondRow method - print the second row of an application
*/
public void printSecondRow(int firstPartialDividend) {
divider.calculateProduct(firstPartialDividend);
System.out.println(result.getProduct() + getSpace(countSpace) + `enter code here`"|" + (result.getQuotient()));
}
/**
* getSpace method to get the number of spaces you want
*/
public String getSpace(int count) {
String space = "";
for (int i = 0; i < count; i++)
space += " ";
return space;
}
}
public class Result {
private int quotient; // keep the result of division
private int dividend;
private int divisor;
private int firstPartialDividend; //keep the result of division the `enter code here`first partial dividend
private int product;
private int remainder;
`enter code here`public Result() {
this.dividend = dividend;
this.divisor = divisor;
}
public int getQuotient() {
return quotient;
}
public void setQuotient(int quotient) {
this.quotient = quotient;
}
public int getDividend() {
return dividend;
}
public void setDividend(int dividend) {
this.dividend = dividend;
}
public int getDivisor() {
return divisor;
}
public void setDivisor(int divisor) {
this.divisor = divisor;
}
public int getFirstPartialDividend() {
return firstPartialDividend;
}
public void setFirstPartialDividend(int firstPartialDividend) {
this.firstPartialDividend = firstPartialDividend;
}
public int getProduct() {
return product;
}
public void setProduct(int product) {
this.product = product;
}
public int getRemainder() {
return remainder;
}
public void setRemainder(int remainder) {
this.remainder = remainder;
}
}
values are still 0
My program should print long division result
Like this:
1234|12
12 |102
34
24
10
Of course this is not the whole program, I am still working on it.
The image shown has stopped before the assignment is complete. The parameter value is 1234, and the current value of this.dividend is zero. If you step the debugger forward, both will have the value of 1234
Your setters are working fine. You are just not calling the setters on the correct instances.
Regarding the "issue". You have a Result and Divider instance in main method that is not given to the Formatter. When you create a new Formatter() it has its own instances that are initialized with the default values of zero.
You probably should have a constructors that carry through the same instances. For example
Result result = new Result(); // this probably isn't even needed
Divider divider = new Divider(result); // param could be removed
divider.divide(x1, x2); // This method could create and store `new Result()` value on its own
Formatter formatter = new Formatter(divider, result); // again, result not needed since it would be internal to the divider
formatter.format();
(and your formatter should probably only "format the result" as the name implies instead of also doing calculations with the Divider instance)
You can also remove new Main() since that isn't doing anything
OneCricketeer - thanks a lot!!!
I has changed constructor Divider and Formatter.
Result result = new Result();
Divider divider = new Divider(result);
divider.divide(dividend, divisor);
Formatter formatter = new Formatter(result);
formatter.format();
public Divider(Result result) {
this.result = result;
}
public Formatter(Result result) {
this.result = result;
this.divider = new Divider(result);
}
Now my output is
1234|12
12 |102
public enum Operator {
PLUS("+"),
MINUS("-");
private final String operator;
Operator(String operator) {
this.operator = operator;
}
public String getOperator() {
return operator;
}
public static Operator getByValue(String operator) {
for (Operator operatorEnum : Operator.values()) {
if (operatorEnum.getOperator().equals(operator)) {
return operatorEnum;
}
}
throw new IllegalArgumentException("Invalid value");
}
}
//////////
public enum MetricConvertor {
m(1000),
cm(10),
mm(1),
km(1000000),
dm(100);
private int scale;
MetricConvertor(int scale) {
this.scale = scale;
}
public int getScale() {
return scale;
}
}
/////////
public class Application {
public static void main(String[] args) {
int scale = MetricConvertor.valueOf("m").getScale();
}
I wan to create a calculator that is capable of computing a metric distance value from an expression that contains different scales and systems.
Output should be specified by the user.
Only Addition and subtraction is allowed.
Output is in lowest unit.
Expression: 10 cm + 1 m - 10 mm
Result: 1090 mm
I am stuck at this point, how can I add or substract the values for a list and convert them at the lowest scale sistem( eg above mm, but it can be dm if are added for example dm + m + km)
Here is solution
split each string by add/minus and add it to appropriate list
split number and metric in each list(can use matcher) and sum it
result = sumAdd - sumMinus(mm).
Please optimize it, because i don't have time to optimize this code, I need to go to bed :D
Result is in mm, so you have to get lowest metric and recaculate it(leave it to you).
private static int caculator(String exp) {
List<String> addList = new ArrayList<>();
List<String> minusList = new ArrayList<>();
int checkPoint = 0;
boolean op = true;//default first value is plus
// Split string with add/minus
for (int i = 1; i < exp.length(); i++) {
String s = exp.substring(i, i + 1);
if (Operator.PLUS.getOperator().equals(s)) {
checkOperator(addList, minusList, op, exp.substring(checkPoint, i).trim());
checkPoint = i + 1;
op = true;
continue;
}
if (Operator.MINUS.getOperator().equals(s)) {
checkOperator(addList, minusList, op, exp.substring(checkPoint, i).trim());
checkPoint = i + 1;
op = false;
continue;
}
}
// Add last string
checkOperator(addList, minusList, op, exp.substring(checkPoint).trim());
// Get sum each list
int sumAdd = sumList(addList);
int sumMinus = sumList(minusList);
return sumAdd - sumMinus;
}
//sum a list
private static int sumList(List<String> addList) {
int sum = 0;
for (String s: addList) {
String[] arr = s.split(" ");
int value = Integer.parseInt(arr[0]);
int scale = MetricConvertor.valueOf(arr[1]).getScale();
sum += value * scale;
}
return sum;
}
// check operator to put into approriate list
private static void checkOperator(List<String> addList, List<String> minusList, boolean op, String substring) {
if (op) {
addList.add(substring);
} else {
minusList.add(substring);
}
}
I have written a polynomial class and a tester class. The polynomial class can evaluate and return the sum of the polynomial when the degree, coefficients and the value of x are provided. Basically I need to edit my toString method so it actually prints out the polynomial
import java.util.Arrays;
import java.util.Scanner;
public class Polynomial {
private int degree;
private int [] coefficient;
private double evaluation;
private double sum;
private double value;
Scanner key = new Scanner(System.in);
public Polynomial(int degree)
{
this.degree = degree;
coefficient = new int [degree+1];
}
public void setCoefficient(int coefficient)
{
this.coefficient[this.degree] = coefficient;
}
public int getCoefficient(int degree)
{
return coefficient[degree];
}
public double Evaluate(double value)
{
this.value =value;
for (int i=0; i<=degree; i++)
{
System.out.println("Enter coefficent for position " + i);
this.coefficient[i] = key.nextInt();
evaluation = Math.pow(value, i)*this.coefficient[0] ;
this.sum += evaluation;
}
return sum;
}
/** Standard toString method */
//needed something better than this below...needed an actual polynomial printed out
public String toString()
{
return "The degree of the polynomial is " + degree + " and the value for which it has been evaluated is" + value;
}
}
This should be along the lines you should be proceeding. I included the main function in your Polynomial class for simplicity, so you will have to modify that if you want to keep it in your tester class. Notice that degree has been made into an integer array of size degree +1(allocated in the constructor):
import java.util.Scanner;
public class Polynomial {
private int degree;
private int [] coefficient;
private double evaluation;
private double sum;
Scanner key = new Scanner(System.in);
public Polynomial(int degree)
{
this.degree = degree;
coefficient = new int [degree+1];
}
public void setCoefficient(int coefficient, int degree)
{
this.coefficient[degree] = coefficient;
}
public int getCoefficient(int degree)
{
return coefficient[degree];
}
public void Evaluate(double value)
{
for (int i=0; i<=degree; i++)
{
System.out.println("Enter coefficent for position " + i);
this.coefficient[i] = key.nextInt();
evaluation = Math.pow(value, i)*this.coefficient[0] ;
this.sum += evaluation;
}
}
public double getSum(){
return sum;
}
public String toString()
{
String s = "";
for (int i=0; i <= degree; i++)
{
s += coefficient[i];
switch (i) {
case 0:
s += " + ";
break;
case 1:
s += "x + ";
break;
default:
s += "x^" + i + ((i==degree)?"":" + ");
}
}
return s;
}
public static void main(String[] args) {
int degree;
double sum;
int coefficient;
Scanner key = new Scanner(System.in);
System.out.println("Enter the degree of the polynomial");
degree=key.nextInt();
Polynomial fun = new Polynomial(degree);
fun.Evaluate(3.0);
System.out.println(" The sum of the polynomial is " + fun.getSum());
System.out.println(fun);
}
}
The usual way of making the objects of a class printable is to supply a toString method in the class, which specifies how to express objects of that class as a String. Methods such as println and other ways of outputting a value will call a class's toString method if they need to print an object of that class.
You should adopt the same pattern with your Polynomial class - write a toString method with all the output logic. Then in your PolynomialTester class, all you need to write is System.out.println(fun); and the rest will just happen. You'll find this far more versatile than writing a method that actually does the printing. For example, you'll be able to write something like
System.out.println("My polynomial is " + fun + " and " + fun + " is my polynomial.");
if that's your idea of fun.
A few other things concern me about your class.
You seem to be only storing one coefficient and one exponent. I'd expect a polynomial to have a whole array of coefficients.
You have fields for evaluation and sum - but these only really make sense while a polynomial is being evaluated. They're not long-term properties of the polynomial. So don't store them in fields. Have them as local variables of the evaluate method, and return the result of the evaluation.
I'd expect a class like this to be immutable. That is, you should provide all the coefficients when the object is created, and just never change them thereafter. If you do it that way, there's no need to write setter methods.
So I've written my own version of your class, that fixes those issues listed above, and implements a toString method that you can use for printing it. A second version of toString lets you specify which letter you want to use for x. I've used "varargs" in the constructor, so you can construct your polynomial with a line such as
Polynomial fun = new Polynomial (7, 2, 5, 0, 1);
specifying the coefficients from the constant term through in order to the coefficient of the term with the highest exponent. Or you can just pass an array.
See that I've changed the logic a wee bit - my version prints the polynomial in the conventional order, from highest to lowest exponent. It leaves off the decimals if the coefficient is an integer. It doesn't print a 1 in front of an x. And it deals cleanly with - signs.
import java.util.Arrays;
public class Polynomial {
private double[] coefficients;
public Polynomial(double... coefficients) {
this.coefficients = Arrays.copyOf(coefficients, coefficients.length);
}
public int getDegree() {
int biggestExponent = coefficients.length - 1;
while(biggestExponent > 0 && coefficients[biggestExponent] == 0.0) {
biggestExponent--;
}
return biggestExponent;
}
public double getCoefficient(int exponent) {
if (exponent < 0 || exponent > getDegree()) {
return 0.0;
} else {
return coefficients[exponent];
}
}
public double evaluateAt(double x) {
double toReturn = 0.0;
for (int term = 0; term < coefficients.length; term++) {
toReturn += coefficients[term] * Math.pow(x, term);
}
return toReturn;
}
#Override
public String toString() {
return toString('x');
}
public String toString(char variable) {
boolean anythingAppendedYet = false;
StringBuilder toReturn = new StringBuilder();
for (int exponent = coefficients.length - 1; exponent >= 0; exponent--) {
if (coefficients[exponent] != 0.0) {
appendSign(toReturn, exponent, anythingAppendedYet);
appendNumberPart(toReturn, exponent);
appendLetterAndExponent(toReturn, exponent, variable);
anythingAppendedYet = true;
}
}
if (anythingAppendedYet) {
return toReturn.toString();
} else {
return "0";
}
}
private void appendSign(StringBuilder toAppendTo, int exponent, boolean anythingAppendedYet) {
if (coefficients[exponent] < 0) {
toAppendTo.append(" - ");
} else if (anythingAppendedYet) {
toAppendTo.append(" + ");
}
}
private void appendNumberPart(StringBuilder toAppendTo, int exponent) {
double numberPart = Math.abs(coefficients[exponent]);
if (numberPart != 1.0 || exponent == 0) {
//Don't print 1 in front of the letter, but do print 1 if it's the constant term.
if (numberPart == Math.rint(numberPart)) {
// Coefficient is an integer, so don't show decimals
toAppendTo.append((long) numberPart);
} else {
toAppendTo.append(numberPart);
}
}
}
private void appendLetterAndExponent(StringBuilder toAppendTo, int exponent, char variable) {
if (exponent > 0) {
toAppendTo.append(variable);
}
if (exponent > 1) {
toAppendTo.append("^");
toAppendTo.append(exponent);
}
}
}
So I tested it with this class
public class PolynomialTester {
public static void main(String[] args) {
Polynomial fun = new Polynomial (7, 2, 5, 0, 1);
System.out.println(fun.getDegree());
System.out.println(fun.evaluateAt(3));
System.out.println(fun);
}
}
and the output was
4
139.0
x^4 + 5x^2 + 2x + 7
then I realised that you wanted to be able to input the coefficients in a loop. So I changed PolynomialTester to this. See how I build the array and then create the object.
import java.util.Scanner;
public class PolynomialTester {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter the degree:");
int degree = input.nextInt();
double[] coefficients = new double[degree + 1];
for( int exponent = 0; exponent <= degree; exponent++) {
System.out.println("Enter the coefficient of x^" + exponent);
coefficients[exponent] = input.nextDouble();
}
Polynomial fun = new Polynomial (coefficients);
System.out.println(fun.evaluateAt(3));
System.out.println(fun);
input.close();
}
}
Note that if you really want your polynomial to be printed in "reverse" order, with the constant term first, you could change the loop in the toString method to this.
for (int exponent = 0; exponent < coefficients.length; exponent++) {
You may add a class member String poly, then modify the following method.
public void Evaluate(double value)
{
for (int i=0; i<=degree; i++)
{
System.out.println("Enter coefficent for position " + i);
this.coefficient= key.nextInt();
evaluation = Math.pow(value, i)*coefficient ;
this.sum += evaluation;
this.poly = "";
if(coefficient != 0)
{
if(i > 0)
{
this.poly += " + " + Integer.toString(coefficient) + "x^" + Integer.toString(i); // you may replace x with the actual value if you want
}
else
{
this.poly = Integer.toString(coefficient)
}
}
}
}
I have written a simple genetic algorithm program in java. What it is does is maximize the decimal value represented by the bits in the chromosome. Somehow mutation is not working as expected, e.g. causing two genes to mutate when just one is to change. The print statements I have included there show which to mutate, but in addition to that some more chromosomes get mutated. I can't figure out what the problem is :-(
Here are my java classes.
Gene.java
public class Gene {
private int value;
public Gene() {
value = Math.random() < 0.5 ? 0 : 1;
}
public Gene(int value) {
if (value != 0 && value != 1) {
throw new IllegalArgumentException("value must be either 0 or 1");
}
else {
this.value = value;
}
}
public void mutate() {
value = 1 - value;
}
public int value() {
return value;
}
#Override
public String toString() {
return String.valueOf(value);
}
}
Chromosome.java
import java.util.ArrayList;
import java.util.List;
public class Chromosome implements Comparable {
private ArrayList<Gene> genes;
private final int chromosomeLength;
public Chromosome(int length) {
this.genes = new ArrayList<>();
this.chromosomeLength = length > 0 ? length : 16;
for (int i = 0; i < chromosomeLength; i++) {
this.genes.add(i, new Gene());
}
}
public List<Gene> getAllele(int fromIndex, int toIndex) {
return new ArrayList<>(genes.subList(fromIndex, toIndex));
}
public void setAllele(int fromIndex, List<Gene> allele) {
int lastIndex = fromIndex + allele.size();
if (lastIndex > chromosomeLength) {
throw new IndexOutOfBoundsException("the allele exceeds beyond the size of the chromosome");
}
for (int i = fromIndex, j = 0; i < lastIndex; i++, j++) {
genes.set(i, allele.get(j));
}
}
public int getChromosomeLength() {
return chromosomeLength;
}
public void setGeneAt(int index, Gene gene) {
genes.set(index, gene);
}
public Gene getGeneAt(int index) {
return genes.get(index);
}
public int value() {
return Integer.parseInt(this.toString(), 2);
}
#Override
public String toString() {
StringBuilder chromosome = new StringBuilder("");
genes.stream().forEach((Gene g) -> chromosome.append(g));
return chromosome.toString();
}
#Override
public int compareTo(Object anotherChromosome) {
Chromosome c = (Chromosome) anotherChromosome;
return this.value() - c.value();
}
}
GenePool.java
import java.util.ArrayList;
import java.util.Arrays;
public class GenePool {
private final ArrayList<Chromosome> genePool;
private final int genePoolSize;
private final int chromosomeLength;
private final double crossOverRate;
private final double mutationRate;
private int[] crossPoints;
public GenePool(int numOfChromosome, int chromosomeLength, double crossOverRate, double mutationRate) {
this.genePoolSize = numOfChromosome;
this.chromosomeLength = chromosomeLength > 0 ? chromosomeLength : 16;
this.crossOverRate = crossOverRate;
this.mutationRate = mutationRate;
crossPoints = new int[1];
crossPoints[0] = this.chromosomeLength / 2;
genePool = new ArrayList<>();
for (int i = 0; i < numOfChromosome; i++) {
genePool.add(new Chromosome(chromosomeLength));
}
}
public int getGenePoolSize() {
return genePoolSize;
}
public Chromosome getChromosomeAt(int index) {
return genePool.get(index);
}
public void setChromosomeAt(int index, Chromosome c) {
genePool.set(index, c);
}
public int getChromosomeLength() {
return chromosomeLength;
}
public Chromosome[] crossOver(Chromosome c1, Chromosome c2) {
Chromosome[] offsprings = new Chromosome[2];
offsprings[0] = new Chromosome(c1.getChromosomeLength());
offsprings[1] = new Chromosome(c1.getChromosomeLength());
Chromosome[] parentChromosomes = {c1, c2};
int selector = 0;
for (int i = 0, start = 0; i <= crossPoints.length; i++) {
int crossPoint = i == crossPoints.length ? c1.getChromosomeLength() : crossPoints[i];
offsprings[0].setAllele(start, parentChromosomes[selector].getAllele(start, crossPoint));
offsprings[1].setAllele(start, parentChromosomes[1 - selector].getAllele(start, crossPoint));
selector = 1 - selector;
start = crossPoint;
}
return offsprings;
}
public void mutateGenePool() {
int totalGeneCount = genePoolSize * chromosomeLength;
System.out.println("Mutating genes:");
for (int i = 0; i < totalGeneCount; i++) {
double prob = Math.random();
if (prob < mutationRate) {
System.out.printf("Chromosome#: %d\tGene#: %d\n", i / chromosomeLength, i % chromosomeLength);
genePool.get(i / chromosomeLength).getGeneAt(i % chromosomeLength).mutate();
}
}
System.out.println("");
}
public int getLeastFitIndex() {
int index = 0;
int min = genePool.get(index).value();
int currentValue;
for (int i = 1; i < genePoolSize; i++) {
currentValue = genePool.get(i).value();
if (currentValue < min) {
index = i;
min = currentValue;
}
}
return index;
}
public void saveFittest(ArrayList<Chromosome> offsprings) {
// sort in ascending order
offsprings.sort(null);
offsprings.stream().forEach((offspring) -> {
int leastFitIndex = getLeastFitIndex();
if (offspring.value() > genePool.get(leastFitIndex).value()) {
genePool.set(leastFitIndex, offspring);
}
});
}
public void evolve(int noOfGeneration) {
for (int generation = 1; generation <= noOfGeneration; generation++) {
System.out.println("Generation :" + generation);
ArrayList<Integer> selection = new ArrayList<>();
for (int i = 0; i < genePoolSize; i++) {
if (Math.random() <= crossOverRate) {
selection.add(i);
}
}
if (selection.size() % 2 == 1) {
selection.remove(selection.size() - 1);
}
ArrayList<Chromosome> offsprings = new ArrayList<>();
for (int i = 0; i < selection.size(); i += 2) {
int index1 = selection.get(i);
int index2 = selection.get(i + 1);
offsprings.addAll(Arrays.asList(crossOver(genePool.get(index1), genePool.get(index2))));
}
System.out.println("Before saving the offsprings");
displayChromosomes(genePool, "GenePool");
displayChromosomes(offsprings, "Offsprings");
saveFittest(offsprings);
System.out.println("Before mutation:");
displayChromosomes(genePool, "GenePool");
mutateGenePool();
System.out.println("After mutation:");
displayChromosomes(genePool, "GenePool");
System.out.println("\n\n");
}
}
public void displayChromosomes(ArrayList<Chromosome> geneList, String name) {
System.out.println(name);
if (geneList.isEmpty()) {
System.out.println("Empty list");
}
geneList.stream().forEach((c) -> {
System.out.println(c + " -> " + c.value());
});
System.out.println("");
}
}
GADemo.java
public class GADemo {
public static void main(String[] args) {
GenePool gp = new GenePool(6, 8, 0.25, 0.01);
gp.evolve(10);
}
}
After evolving for a number of generations, the chromosomes all tend to become exactly the same, or very similar. And the problem is that that value is not the maximum for that many bits, and sometimes even a small value. For example, for 8 bits the values should (tend to) approach 255, but this doesn't do so in my code. Someone please provide a hint where/how to look for and solve the problem.
Focus on these lines and imagine the references. These are from setAllele()
for (int i = fromIndex, j = 0; i < lastIndex; i++, j++) {
genes.set(i, allele.get(j));
}
You are basically copying the reference from one onto the other. They are the same Gene so whatever mutation you do on those genes, will also affect even other Chromosomes.
You must produce a deep copy here.
Initially each chromosome has an own list of genes. But when you do the crossover operation you set gene objects from one chromosome into the gene list of other chromosome.
When you evolve the system, the number of shared genes will rise and therefore ultimately all chromosomes will share the same genes. No matter how you mutate a gene the chromosomes are not affected.
EDIT:
As Incognito also answered the setAllele method seems to be the culprit where gene sharing starts. You may want to introduce a method in the gene class where you can set its value given another gene.
I made this code to calculate numbers:
import java.util.Random;
public class Sorting {
private double[] player;
private int k=5;
private int j=5;
public void sort(){
player = new double[k];
for(int i=1;i<k;i++){
double tempp ;
for(i=1;i<j;i++){
tempp = Math.random() * i;
player[i]=tempp;
System.out.println("Result "+i+"="+player[i]);
}
}
}
public static void main(String []args){
Sorting k=new Sorting();
k.sort();
}}
and the result is:
Result 1=0.4529689730194949
Result 2=0.09643822768644617
Result 3=1.841047494651026
Result 4=2.1807153629323777
Now, I want to add a label from the biggest to the smallest result number labeled EXCELLENT, VERY GOOD, GOOD and BAD like this:
Result 1=0.4529689730194949 labeled GOOD
Result 2=0.09643822768644617 labeled BAD
Result 3=1.841047494651026 labeled VERY GOOD
Result 4=2.1807153629323777 labeled EXCELLENT
public class Sorting
{
private double[] player;
private int k=5;
private int j=5;
String[] rating = {"BAD", "GOOD", "VERY GOOD", "EXCELENT"};
public void sort()
{
player = new double[k];
for(int i=1; i<k; i++)
{
double tempp;
for(i=1; i<j; i++) // i should probably be zero since your array starts on value 0, not 1.
{
tempp = Math.random() * i;
player[i]=tempp;
System.out.println("Result " + i + " = " + player[i] + " Rating is " + rating[(int)player[i]]);
}
}
}
public static void main(String[] args)
{
Sorting k = new Sorting();
k.sort();
}
}
your code seems a little odd but i fixed the problem you were asking about.
TreeSet already sort the numbers ascending by default.
Here my version:
Sample output:
Result: 0.12754837127918317 => BAD
Result: 0.7956890627771006 => EXCELLENT
Result: 0.3123868511945034 => GOOD
Result: 0.6332109887264882 => VERY_GOOD
public class FourRandomNumbersEvaluator {
private TreeSet<Double> numbers;
private Map<Double,Evaluation> numbersWithEvaluations = new HashMap<Double,Evaluation>();
private enum Evaluation {BAD, GOOD, VERY_GOOD, EXCELLENT}
private static final int NUMBER_OF_GENERATED_NUMBERS = 4;
public FourRandomNumbersEvaluator(TreeSet<Double> numbers) {
if(numbers == null || numbers.size() != 4){
throw new IllegalArgumentException("your have to provide exactly 4 numbers");
}
this.numbers = numbers;
}
public static void main(String[] args) {
FourRandomNumbersEvaluator evaluator = new FourRandomNumbersEvaluator(generateNumbers());
evaluator.evaluate();
evaluator.printNumbersWithEvaluations();
}
private static TreeSet<Double> generateNumbers() {
TreeSet<Double> numbers = new TreeSet<Double>();
while(numbers.size() < NUMBER_OF_GENERATED_NUMBERS){
double number = Math.random();
if(numberNotAlreadyExisting(numbers, number)){
numbers.add(number);
}
}
return numbers;
}
private static boolean numberNotAlreadyExisting(TreeSet<Double> numbers, double number) {
return !numbers.contains(number);
}
public void evaluate() {
int i = 0;
for(Double number : numbers){
numbersWithEvaluations.put(number, Evaluation.values()[i++]);
}
}
private void printNumbersWithEvaluations(){
for(Map.Entry<Double,Evaluation> numberWithEvaluation : numbersWithEvaluations.entrySet())
System.out.println("Result: "+ numberWithEvaluation.getKey() + " => " + numberWithEvaluation.getValue());
}
}