1 46 package org.jgap; 47 48 import java.lang.reflect.*; 49 import java.util.*; 50 import java.io.*; 51 import java.net.*; 52 53 67 public class Chromosome 68 extends BaseChromosome implements IPersistentRepresentation { 69 70 private final static String CVS_REVISION = "$Revision: 1.91 $"; 71 78 private Object m_applicationData; 79 80 87 private List m_multiObjective; 88 89 92 private Gene[] m_genes; 93 94 98 private boolean m_isSelectedForNextGeneration; 99 100 108 protected double m_fitnessValue = FitnessFunction.NO_FITNESS_VALUE; 109 110 117 private boolean m_compareAppData; 118 119 126 private IGeneConstraintChecker m_geneAlleleChecker; 127 128 132 public final static String GENE_DELIMITER = "#"; 133 134 138 public final static String GENE_DELIMITER_HEADING = "<"; 139 140 144 public final static String GENE_DELIMITER_CLOSING = ">"; 145 146 149 public final static String CHROM_DELIMITER = "#"; 150 151 161 public Chromosome() 162 throws InvalidConfigurationException { 163 super(Genotype.getStaticConfiguration()); 164 } 165 166 175 public Chromosome(final Configuration a_configuration) 176 throws InvalidConfigurationException { 177 super(a_configuration); 178 } 179 180 192 public Chromosome(final Configuration a_configuration, 193 String a_persistentRepresentatuion) 194 throws InvalidConfigurationException, UnsupportedRepresentationException { 195 super(a_configuration); 196 setValueFromPersistentRepresentation(a_persistentRepresentatuion); 197 } 198 199 209 public Chromosome(final Configuration a_configuration, 210 final int a_desiredSize) 211 throws InvalidConfigurationException { 212 super(a_configuration); 213 if (a_desiredSize <= 0) { 214 throw new IllegalArgumentException ( 215 "Chromosome size must be greater than zero"); 216 } 217 m_genes = new Gene[a_desiredSize]; 218 } 219 220 238 public Chromosome(final Configuration a_configuration, 239 final Gene a_sampleGene, final int a_desiredSize) 240 throws InvalidConfigurationException { 241 this(a_configuration, a_desiredSize); 242 initFromGene(a_sampleGene); 243 } 244 245 public Chromosome(final Configuration a_configuration, Gene a_sampleGene, 246 int a_desiredSize, 247 IGeneConstraintChecker a_constraintChecker) 248 throws InvalidConfigurationException { 249 this(a_configuration, a_desiredSize); 250 initFromGene(a_sampleGene); 251 setConstraintChecker(a_constraintChecker); 252 } 253 254 protected void initFromGene(Gene a_sampleGene) { 255 if (a_sampleGene == null) { 259 throw new IllegalArgumentException ( 260 "Sample Gene cannot be null."); 261 } 262 for (int i = 0; i < m_genes.length; i++) { 266 m_genes[i] = a_sampleGene.newGene(); 267 } 268 } 269 270 282 public Chromosome(final Configuration a_configuration, Gene[] a_initialGenes) 283 throws InvalidConfigurationException { 284 this(a_configuration, a_initialGenes == null ? 0 : a_initialGenes.length); 285 checkGenes(a_initialGenes); 286 m_genes = a_initialGenes; 287 } 288 289 305 public Chromosome(final Configuration a_configuration, Gene[] a_initialGenes, 306 IGeneConstraintChecker a_constraintChecker) 307 throws InvalidConfigurationException { 308 this(a_configuration, a_initialGenes.length); 309 checkGenes(a_initialGenes); 310 m_genes = a_initialGenes; 311 setConstraintChecker(a_constraintChecker); 312 } 313 314 322 protected void checkGenes(Gene[] a_initialGenes) { 323 for (int i = 0; i < a_initialGenes.length; i++) { 328 if (a_initialGenes[i] == null) { 329 throw new IllegalArgumentException ( 330 "The gene at index " + i + " in the given array of " + 331 "genes was found to be null. No gene in the array " + 332 "may be null."); 333 } 334 } 335 } 336 337 352 public synchronized Object clone() { 353 if (getConfiguration() == null) { 358 throw new IllegalStateException ( 359 "The active Configuration object must be set on this " + 360 "Chromosome prior to invocation of the clone() method."); 361 } 362 IChromosome copy = null; 363 IChromosomePool pool = getConfiguration().getChromosomePool(); 367 if (pool != null) { 368 copy = pool.acquireChromosome(); 369 if (copy != null) { 370 Gene[] genes = copy.getGenes(); 371 for (int i = 0; i < size(); i++) { 372 genes[i].setAllele(m_genes[i].getAllele()); 373 } 374 } 375 } 376 try { 377 if (copy == null) { 378 int size = size(); 384 if (size > 0) { 385 Gene[] copyOfGenes = new Gene[size]; 386 for (int i = 0; i < copyOfGenes.length; i++) { 387 copyOfGenes[i] = m_genes[i].newGene(); 388 copyOfGenes[i].setAllele(m_genes[i].getAllele()); 389 } 390 394 copy = new Chromosome(getConfiguration(), copyOfGenes); 395 } 396 else { 397 copy = new Chromosome(getConfiguration()); 398 } 399 } 400 copy.setConstraintChecker(getConstraintChecker()); 403 } 404 catch (InvalidConfigurationException iex) { 405 throw new IllegalStateException (iex.getMessage()); 406 } 407 try { 410 copy.setApplicationData(cloneObject(getApplicationData())); 411 } 412 catch (Exception ex) { 413 throw new IllegalStateException (ex.getMessage()); 414 } 415 return copy; 416 } 417 418 429 protected Object cloneObject(Object a_object) 430 throws Exception { 431 if (a_object == null) { 432 return null; 433 } 434 ICloneHandler cloner = getConfiguration().getJGAPFactory(). 437 getCloneHandlerFor(a_object, a_object.getClass()); 438 if (cloner != null) { 439 return cloner.perform(a_object, null, this); 440 } 441 else { 442 return a_object; 445 } 446 } 447 448 459 public synchronized Gene getGene(int a_desiredLocus) { 460 return m_genes[a_desiredLocus]; 461 } 462 463 473 public synchronized Gene[] getGenes() { 474 return m_genes; 475 } 476 477 488 public int size() { 489 if (m_genes == null) { 490 return 0; 492 } 493 else { 494 return m_genes.length; 495 } 496 } 497 498 514 public double getFitnessValue() { 515 if (m_fitnessValue >= 0.000d) { 516 return m_fitnessValue; 517 } 518 else { 519 return calcFitnessValue(); 520 } 521 } 522 523 529 public double getFitnessValueDirectly() { 530 return m_fitnessValue; 531 } 532 533 540 protected double calcFitnessValue() { 541 if (getConfiguration() != null) { 542 FitnessFunction normalFitnessFunction = getConfiguration(). 543 getFitnessFunction(); 544 if (normalFitnessFunction != null) { 545 m_fitnessValue = normalFitnessFunction.getFitnessValue(this); 549 } 550 } 551 return m_fitnessValue; 552 } 553 554 565 public void setFitnessValue(double a_newFitnessValue) { 566 if (a_newFitnessValue >= 0 && 567 Math.abs(m_fitnessValue - a_newFitnessValue) > 0.0000001) { 568 m_fitnessValue = a_newFitnessValue; 569 } 570 } 571 572 573 583 public void setFitnessValueDirectly(double a_newFitnessValue) { 584 m_fitnessValue = a_newFitnessValue; 585 } 586 587 595 public String toString() { 596 StringBuffer representation = new StringBuffer (); 597 representation.append(S_SIZE + ":" + size()); 598 representation.append(", " + S_FITNESS_VALUE + ":" + m_fitnessValue); 602 representation.append(", " + S_ALLELES + ":"); 603 representation.append("["); 604 for (int i = 0; i < m_genes.length; i++) { 607 if (i > 0) { 608 representation.append(", "); 609 } 610 if (m_genes[i] == null) { 611 representation.append("null"); 612 } 613 else { 614 representation.append(m_genes[i].toString()); 615 } 616 } 617 representation.append("]"); 618 String appData; 619 if (getApplicationData() != null) { 620 appData = getApplicationData().toString(); 621 } 622 else { 623 appData = "null"; 624 } 625 representation.append(", " + S_APPLICATION_DATA + ":" + appData); 626 return representation.toString(); 627 } 628 629 641 public String getPersistentRepresentation() { 642 StringBuffer b = new StringBuffer (); 643 b.append(m_fitnessValue); 646 b.append(CHROM_DELIMITER); 647 b.append(m_genes.length); 649 b.append(CHROM_DELIMITER); 650 Gene gene; 651 for (int i = 0; i < m_genes.length; i++) { 652 gene = m_genes[i]; 653 b.append(GENE_DELIMITER_HEADING); 654 try { 655 b.append(URLEncoder.encode(gene.getClass().getName() 656 + GENE_DELIMITER 657 + gene.getPersistentRepresentation() 658 , "UTF-8")); 659 } 660 catch (UnsupportedEncodingException uex) { 661 throw new RuntimeException ("UTF-8 should always be supported!", uex); 662 } 663 b.append(GENE_DELIMITER_CLOSING); 664 } 665 return b.toString(); 666 } 667 668 679 public void setValueFromPersistentRepresentation(String a_representation) 680 throws UnsupportedRepresentationException { 681 if (a_representation != null) { 682 try { 683 List r = split(a_representation); 684 String g; 685 g = URLDecoder.decode( (String ) r.get(0), "UTF-8"); 688 setFitnessValue(Double.parseDouble(g)); 689 r.remove(0); 690 g = URLDecoder.decode( (String ) r.get(0), "UTF-8"); 693 int count = Integer.parseInt(g); 694 m_genes = new Gene[count]; 695 r.remove(0); 696 Iterator iter = r.iterator(); 699 StringTokenizer st; 700 String clas; 701 String representation; 702 Gene gene; 703 int index = 0; 704 while (iter.hasNext()) { 705 g = URLDecoder.decode( (String ) iter.next(), "UTF-8"); 706 st = new StringTokenizer(g, GENE_DELIMITER); 707 if (st.countTokens() != 2) 708 throw new UnsupportedRepresentationException("In " + g + ", " + 709 "expecting two tokens, separated by " + GENE_DELIMITER); 710 clas = st.nextToken(); 711 representation = st.nextToken(); 712 gene = createGene(clas, representation); 713 m_genes[index++] = gene; 714 } 715 } 716 catch (Exception ex) { 717 throw new UnsupportedRepresentationException(ex.toString()); 718 } 719 } 720 } 721 722 736 protected Gene createGene(String a_geneClassName, 737 String a_persistentRepresentation) 738 throws Exception { 739 Class geneClass = Class.forName(a_geneClassName); 740 Constructor constr = geneClass.getConstructor(new Class [] {Configuration.class}); 741 Gene gene = (Gene) constr.newInstance(new Object [] {getConfiguration()}); 742 gene.setValueFromPersistentRepresentation(a_persistentRepresentation); 743 return gene; 744 } 745 746 758 protected static final List split(String a_string) 759 throws UnsupportedRepresentationException { 760 List a = Collections.synchronizedList(new ArrayList()); 761 int index = 0; 764 StringTokenizer st0 = new StringTokenizer 765 (a_string, CHROM_DELIMITER, false); 766 if (!st0.hasMoreTokens()) { 767 throw new UnsupportedRepresentationException("Fitness value expected!"); 768 } 769 String fitnessS = st0.nextToken(); 770 a.add(fitnessS); 771 index += fitnessS.length(); 772 if (!st0.hasMoreTokens()) { 773 throw new UnsupportedRepresentationException("Number of genes expected!"); 774 } 775 String numGenes = st0.nextToken(); 776 a.add(numGenes); 777 index += numGenes.length(); 778 779 index += 2; 781 if (!st0.hasMoreTokens()) { 782 throw new UnsupportedRepresentationException("Gene data missing!"); 783 } 784 785 a_string = a_string.substring(index); 788 789 StringTokenizer st = new StringTokenizer 792 (a_string, GENE_DELIMITER_HEADING + GENE_DELIMITER_CLOSING, true); 793 while (st.hasMoreTokens()) { 794 if (!st.nextToken().equals(GENE_DELIMITER_HEADING)) { 795 throw new UnsupportedRepresentationException(a_string + " no open tag"); 796 } 797 String n = st.nextToken(); 798 if (n.equals(GENE_DELIMITER_CLOSING)) { 799 a.add(""); 800 } 801 else { 802 a.add(n); 803 if (!st.nextToken().equals(GENE_DELIMITER_CLOSING)) { 804 throw new UnsupportedRepresentationException 805 (a_string + " no close tag"); 806 } 807 } 808 } 809 return a; 810 } 811 812 831 public static IChromosome randomInitialChromosome( 832 Configuration a_configuration) 833 throws InvalidConfigurationException { 834 if (a_configuration == null) { 837 throw new IllegalArgumentException ( 838 "Configuration instance must not be null"); 839 } 840 a_configuration.lockSettings(); 844 IChromosomePool pool = a_configuration.getChromosomePool(); 849 if (pool != null) { 850 IChromosome randomChromosome = pool.acquireChromosome(); 851 if (randomChromosome != null) { 852 Gene[] genes = randomChromosome.getGenes(); 853 RandomGenerator generator = a_configuration.getRandomGenerator(); 854 for (int i = 0; i < genes.length; i++) { 855 genes[i].setToRandomValue(generator); 856 857 } 858 randomChromosome.setFitnessValueDirectly(FitnessFunction. 859 NO_FITNESS_VALUE); 860 return randomChromosome; 861 } 862 } 863 IChromosome sampleChromosome = 867 a_configuration.getSampleChromosome(); 868 sampleChromosome.setFitnessValue(FitnessFunction.NO_FITNESS_VALUE); 869 Gene[] sampleGenes = sampleChromosome.getGenes(); 870 Gene[] newGenes = new Gene[sampleGenes.length]; 871 RandomGenerator generator = a_configuration.getRandomGenerator(); 872 for (int i = 0; i < newGenes.length; i++) { 873 newGenes[i] = sampleGenes[i].newGene(); 880 newGenes[i].setToRandomValue(generator); 883 884 } 885 return new Chromosome(a_configuration, newGenes); 889 } 890 891 903 public boolean equals(Object other) { 904 915 try { 916 return compareTo(other) == 0; 917 } 918 catch (ClassCastException cex) { 919 return false; 920 } 921 } 922 923 933 public int hashCode() { 934 int geneHashcode; 937 int hashCode = 1; 938 if (m_genes != null) { 939 for (int i = 0; i < m_genes.length; i++) { 940 geneHashcode = m_genes[i].hashCode(); 941 hashCode = 31 * hashCode + geneHashcode; 942 } 943 } 944 return hashCode; 945 } 946 947 962 public int compareTo(Object other) { 963 if (other == null) { 967 return 1; 968 } 969 int size = size(); 970 IChromosome otherChromosome = (IChromosome) other; 971 Gene[] otherGenes = otherChromosome.getGenes(); 972 if (otherChromosome.size() != size) { 976 return size() - otherChromosome.size(); 977 } 978 for (int i = 0; i < size; i++) { 983 int comparison = m_genes[i].compareTo(otherGenes[i]); 984 if (comparison != 0) { 985 return comparison; 986 } 987 } 988 if (m_fitnessValue != otherChromosome.getFitnessValueDirectly()) { 991 FitnessEvaluator eval = getConfiguration().getFitnessEvaluator(); 992 if (eval != null) { 993 if (eval.isFitter(m_fitnessValue, 994 otherChromosome.getFitnessValueDirectly())) { 995 return 1; 996 } 997 else { 998 return -1; 999 } 1000 } 1001 else { 1002 return -1; 1005 } 1006 } 1007 if (m_compareAppData) { 1008 if (getApplicationData() == null) { 1011 if (otherChromosome.getApplicationData() != null) { 1012 return -1; 1013 } 1014 } 1015 else if (otherChromosome.getApplicationData() == null) { 1016 return 1; 1017 } 1018 else { 1019 if (getApplicationData() instanceof Comparable ) { 1020 try { 1021 return ( (Comparable ) getApplicationData()).compareTo( 1022 otherChromosome.getApplicationData()); 1023 } 1024 catch (ClassCastException cex) { 1025 1026 return -1; 1027 } 1028 } 1029 else { 1030 return getApplicationData().getClass().getName().compareTo( 1031 otherChromosome.getApplicationData().getClass().getName()); 1032 } 1033 } 1034 } 1035 return 0; 1038 } 1039 1040 1050 public void setIsSelectedForNextGeneration(boolean a_isSelected) { 1051 m_isSelectedForNextGeneration = a_isSelected; 1052 } 1053 1054 1063 public boolean isSelectedForNextGeneration() { 1064 return m_isSelectedForNextGeneration; 1065 } 1066 1067 1075 public void cleanup() { 1076 if (getConfiguration() == null) { 1077 throw new IllegalStateException ( 1078 "The active Configuration object must be set on this " + 1079 "Chromosome prior to invocation of the cleanup() method."); 1080 } 1081 m_fitnessValue = getConfiguration().getFitnessFunction(). 1084 NO_FITNESS_VALUE; 1085 m_isSelectedForNextGeneration = false; 1086 IChromosomePool pool = getConfiguration().getChromosomePool(); 1094 if (pool != null) { 1095 pool.releaseChromosome(this); 1099 } 1100 else { 1101 for (int i = 0; i < size(); i++) { 1106 m_genes[i].cleanup(); 1107 } 1108 } 1109 } 1110 1111 1124 public void setApplicationData(Object a_newData) { 1125 m_applicationData = a_newData; 1126 } 1127 1128 1140 public Object getApplicationData() { 1141 return m_applicationData; 1142 } 1143 1144 1153 public void setGenes(Gene[] a_genes) 1154 throws InvalidConfigurationException { 1155 m_genes = a_genes; 1161 verify(getConstraintChecker()); 1162 } 1163 1164 1174 public void setCompareApplicationData(boolean a_doCompare) { 1175 m_compareAppData = a_doCompare; 1176 } 1177 1178 1184 public boolean isCompareApplicationData() { 1185 return m_compareAppData; 1186 } 1187 1188 1198 public void setConstraintChecker(IGeneConstraintChecker a_constraintChecker) 1199 throws InvalidConfigurationException { 1200 verify(a_constraintChecker); 1201 m_geneAlleleChecker = a_constraintChecker; 1202 } 1203 1204 1211 public IGeneConstraintChecker getConstraintChecker() { 1212 return m_geneAlleleChecker; 1213 } 1214 1215 1225 protected void verify(IGeneConstraintChecker a_constraintChecker) 1226 throws InvalidConfigurationException { 1227 if (a_constraintChecker != null && getGenes() != null) { 1228 int len = getGenes().length; 1229 for (int i = 0; i < len; i++) { 1230 Gene gene = getGene(i); 1231 if (!a_constraintChecker.verify(gene, null, this, i)) { 1232 throw new InvalidConfigurationException( 1233 "The gene type " 1234 + gene.getClass().getName() 1235 + " is not allowed to be used in the chromosome due to the" 1236 + " constraint checker used."); 1237 } 1238 } 1239 } 1240 } 1241 1242 1246 1247 public boolean isHandlerFor(Object a_obj, Class a_class) { 1248 if (a_class == Chromosome.class) { 1249 return true; 1250 } 1251 else { 1252 return false; 1253 } 1254 } 1255 1256 1257 public Object perform(Object a_obj, Class a_class, Object a_params) 1258 throws Exception { 1259 return randomInitialChromosome(getConfiguration()); 1260 } 1261 1262 public void setMultiObjectives(List a_values) { 1266 if (m_multiObjective == null) { 1267 m_multiObjective = new Vector(); 1268 } 1269 m_multiObjective.clear(); 1270 m_multiObjective.addAll(a_values); 1271 } 1272 1273 public List getMultiObjectives() { 1274 return m_multiObjective; 1275 } 1276} 1277 | Popular Tags |