1 10 package org.jgap.gp.impl; 11 12 import java.util.*; 13 import org.jgap.*; 14 import org.jgap.util.*; 15 import org.jgap.gp.terminal.*; 16 import org.jgap.gp.*; 17 18 24 public class ProgramChromosome 25 extends BaseGPChromosome implements IGPChromosome, Comparable , Cloneable { 26 27 private final static String CVS_REVISION = "$Revision: 1.16 $"; 28 29 32 private transient CommandGene[] m_functionSet; 33 34 37 private int[] m_depth; 38 39 42 private Class [] argTypes; 43 44 private transient int m_index; 45 46 private transient int m_maxDepth; 47 48 51 private CommandGene[] m_genes; 52 53 60 private Object m_applicationData; 61 62 69 private boolean m_compareAppData; 70 71 public ProgramChromosome(GPConfiguration a_configuration, int a_size, 72 IGPProgram a_ind) 73 throws InvalidConfigurationException { 74 super(a_configuration, a_ind); 75 if (a_size <= 0) { 76 throw new IllegalArgumentException ( 77 "Chromosome size must be greater than zero"); 78 } 79 init(a_size); 80 } 81 82 public ProgramChromosome(GPConfiguration a_configuration, int a_size, 83 CommandGene[] a_functionSet, 84 Class [] a_argTypes, 85 IGPProgram a_ind) 86 throws InvalidConfigurationException { 87 super(a_configuration, a_ind); 88 if (a_size <= 0) { 89 throw new IllegalArgumentException ( 90 "Chromosome size must be greater than zero"); 91 } 92 m_functionSet = a_functionSet; 93 argTypes = a_argTypes; 94 init(a_size); 95 } 96 97 public ProgramChromosome(GPConfiguration a_configuration, 98 CommandGene[] a_initialGenes) 99 throws InvalidConfigurationException { 100 super(a_configuration); 101 int i = 0; 102 while (i < a_initialGenes.length && a_initialGenes[i] != null) { 103 i++; 104 } 105 CommandGene[] genes = new CommandGene[i]; 106 for (int k = 0; k < i; k++) { 107 genes[k] = a_initialGenes[k]; 108 } 109 init(a_initialGenes.length); 110 } 111 112 public ProgramChromosome(final GPConfiguration a_conf) 113 throws InvalidConfigurationException { 114 super(a_conf); 115 init(); 116 } 117 118 126 public ProgramChromosome() 127 throws InvalidConfigurationException { 128 this(GPGenotype.getStaticGPConfiguration()); 129 } 130 131 private void init() 132 throws InvalidConfigurationException { 133 init(getGPConfiguration().getPopulationSize()); 134 } 135 136 private void init(final int a_size) 137 throws InvalidConfigurationException { 138 m_depth = new int[a_size]; 139 m_genes = new CommandGene[a_size]; 140 141 } 142 143 public void setArgTypes(Class [] a_argTypes) { 144 argTypes = a_argTypes; 145 } 146 147 public synchronized Object clone() { 148 try { 149 ProgramChromosome chrom = new ProgramChromosome( (GPConfiguration) 150 getGPConfiguration(), (CommandGene[]) m_genes.clone()); 151 chrom.argTypes = (Class []) argTypes.clone(); 152 chrom.setFunctionSet( (CommandGene[]) getFunctionSet().clone()); 153 chrom.setFunctions( (CommandGene[]) getFunctions().clone()); 154 chrom.m_depth = (int[]) m_depth.clone(); 155 return chrom; 156 } catch (Exception cex) { 157 throw new IllegalStateException (cex.getMessage()); 160 } 161 } 162 163 169 public void cleanup() { 170 int len = m_genes.length; 171 for (int i = 0; i < len; i++) { 172 if (m_genes[i] == null) { 173 break; 174 } 175 m_genes[i].cleanup(); 176 } 177 } 178 179 192 public void growOrFull(final int a_num, final int a_depth, final Class a_type, 193 final Class [] a_argTypes, 194 final CommandGene[] a_functionSet, 195 boolean a_grow) { 196 try { 197 argTypes = a_argTypes; 198 setFunctionSet(new CommandGene[a_functionSet.length + a_argTypes.length]); 199 System.arraycopy(a_functionSet, 0, getFunctionSet(), 0, 200 a_functionSet.length); 201 for (int i = 0; i < a_argTypes.length; i++) { 202 m_functionSet[a_functionSet.length + i] 203 = new Argument(getGPConfiguration(), i, a_argTypes[i]); 204 } 205 206 CommandGene n = null; 209 int localDepth = a_depth; 228 m_index = 0; 229 m_maxDepth = localDepth; 230 growOrFullNode(a_num, localDepth, a_type, 0, m_functionSet, n, 0, a_grow, 231 -1, true); 232 redepth(); 233 } catch (InvalidConfigurationException iex) { 234 throw new IllegalStateException (iex.getMessage()); 235 } 236 } 237 238 246 public String toString(final int a_startNode) { 247 if (a_startNode < 0) { 248 return ""; 249 } 250 String funcName = m_genes[a_startNode].toString(); 254 int j = 1; 255 do { 256 String placeHolder = "&" + j; 257 int foundIndex = funcName.indexOf(placeHolder); 258 if (foundIndex < 0) { 259 break; 260 } 261 funcName = funcName.replaceFirst(placeHolder, ""); 262 j++; 263 } while (true); 264 if (j > 0) { 267 funcName = funcName.trim(); 268 } 269 IGPProgram ind = getIndividual(); 270 if (getFunctions()[a_startNode].getArity(ind) == 0) { 271 return funcName + " "; 272 } 273 String str = ""; 274 str += funcName + " ( "; 275 int arity = m_genes[a_startNode].getArity(ind); 276 for (int i = 0; i < arity; i++) { 277 str += toString(getChild(a_startNode, i)); 278 } 279 if (a_startNode == 0) { 280 str += ")"; 281 } 282 else { 283 str += ") "; 284 } 285 return str; 286 } 287 288 296 public String toStringNorm(final int a_startNode) { 297 if (a_startNode < 0) { 298 return ""; 299 } 300 IGPProgram ind = getIndividual(); 301 if (m_genes[a_startNode].getArity(ind) == 0) { 302 return getFunctions()[a_startNode].toString(); 303 } 304 String str = ""; 305 boolean paramOutput = false; 306 if (m_genes[a_startNode].getArity(ind) > 0) { 307 if (m_genes[a_startNode].toString().indexOf("&1") >= 0) { 308 paramOutput = true; 309 } 310 } 311 if (m_genes[a_startNode].getArity(ind) == 1 || paramOutput) { 312 str += getFunctions()[a_startNode].toString(); 313 } 314 if (a_startNode > 0) { 315 str = "(" + str; 316 } 317 for (int i = 0; i < m_genes[a_startNode].getArity(ind); i++) { 318 String childString = toStringNorm(getChild(a_startNode, i)); 319 String placeHolder = "&" + (i + 1); 320 int placeholderIndex = str.indexOf(placeHolder); 321 if (placeholderIndex >= 0) { 322 str = str.replaceFirst(placeHolder, childString); 323 } 324 else { 325 str += childString; 326 } 327 if (i == 0 && m_genes[a_startNode].getArity(ind) != 1 328 && !paramOutput) { 329 str += " " + m_genes[a_startNode].toString() + " "; 330 } 331 } 332 if (a_startNode > 0) { 333 str += ")"; 334 } 335 return str; 336 } 337 338 353 public boolean isPossible(Class a_returnType, int a_subReturnType, 354 CommandGene[] a_nodeSet, 355 boolean a_function, boolean a_growing) { 356 IGPProgram ind = getIndividual(); 357 for (int i = 0; i < a_nodeSet.length; i++) { 358 if (a_nodeSet[i].getReturnType() == a_returnType 359 && (a_subReturnType == 0 360 || a_subReturnType == a_nodeSet[i].getSubReturnType())) { 361 if (a_nodeSet[i].getArity(ind) == 0 && (!a_function || a_growing)) { 362 return true; 363 } 364 if (a_nodeSet[i].getArity(ind) != 0 && a_function) { 365 return true; 366 } 367 } 368 } 369 return false; 370 } 371 372 386 protected CommandGene selectNode(int a_chromIndex, Class a_returnType, 387 int a_subReturnType, 388 CommandGene[] a_functionSet, 389 boolean a_function, boolean a_growing) { 390 if (!isPossible(a_returnType, a_subReturnType, a_functionSet, a_function, 391 a_growing)) { 392 if (a_growing && a_returnType == CommandGene.VoidClass) { 393 try { 396 return new NOP(getGPConfiguration(), a_subReturnType); 397 } catch (InvalidConfigurationException iex) { 398 iex.printStackTrace(); 401 } 402 } 403 final String errormsg = "Chromosome (index " + a_chromIndex 404 + ") requires a " + 405 (a_function ? 406 ("function" + (a_growing ? " or terminal" : "")) 407 : "terminal") + " of return type " + 408 a_returnType 409 + " (sub return type " + a_subReturnType + ")" 410 + " but there is no such node available"; 411 if (!getGPConfiguration().isStrictProgramCreation()) { 412 throw new IllegalStateException (errormsg); 413 } 414 else { 415 throw new RuntimeException (errormsg); 416 } 417 } 418 CommandGene n = null; 419 int lindex; 420 IGPProgram ind = getIndividual(); 423 UniqueRandomGenerator randGen = new UniqueRandomGenerator(a_functionSet. 424 length, getGPConfiguration().getRandomGenerator()); 425 do { 426 lindex = randGen.nextInt(); 427 if (a_functionSet[lindex].getReturnType() == a_returnType 430 && (a_subReturnType == 0 431 || a_functionSet[lindex].getSubReturnType() == a_subReturnType)) { 432 if (a_functionSet[lindex].getArity(ind) == 0 && 433 (!a_function || a_growing)) { 434 n = a_functionSet[lindex]; 435 } 436 if (a_functionSet[lindex].getArity(ind) != 0 && a_function) { 437 n = a_functionSet[lindex]; 438 } 439 } 440 } while (n == null); 441 return n; 442 } 443 444 462 protected void growOrFullNode(int a_num, int a_depth, 463 Class a_returnType, 464 int a_subReturnType, 465 CommandGene[] a_functionSet, 466 CommandGene a_rootNode, int a_recurseLevel, 467 boolean a_grow, 468 int a_childNum, boolean a_validateNode) { 469 if (a_rootNode == null || a_validateNode) { 473 int tries = 0; 474 CommandGene[] localFunctionSet = (CommandGene[])a_functionSet.clone(); 475 do { 476 CommandGene node = selectNode(a_num, a_returnType, a_subReturnType, 477 localFunctionSet, a_depth >= 1, a_grow); 478 if (!getGPConfiguration().validateNode(this, node, a_rootNode, tries++, 479 a_num, a_recurseLevel, a_returnType, localFunctionSet, a_depth, 480 a_grow, a_childNum)) { 481 localFunctionSet = remove(localFunctionSet, node); 484 if (localFunctionSet.length == 0) { 485 throw new IllegalStateException ("No appropriate function found" 486 +" during program creation!"); 487 } 488 continue; 489 } 490 a_rootNode = node; 491 break; 492 } while (true); 493 } 494 m_depth[m_index] = m_maxDepth - a_depth; 497 if (a_rootNode instanceof ICloneable) { 498 m_genes[m_index++] = (CommandGene) ( (ICloneable) a_rootNode).clone(); 499 } 500 else { 501 m_genes[m_index++] = a_rootNode; 502 } 503 if (a_depth >= 1) { 504 IGPProgram ind = getIndividual(); 505 for (int i = 0; i < a_rootNode.getArity(ind); i++) { 506 507 if (m_index < m_depth.length) { 508 growOrFullNode(a_num, a_depth - 1, 509 a_rootNode.getChildType(getIndividual(), i), 510 a_rootNode.getSubChildType(i), 511 a_functionSet, a_rootNode, a_recurseLevel + 1, a_grow,i, true); 512 } 513 else { 514 throw new IllegalStateException ("Randomly created program violates" 517 + " configuration constraints (symptom 1). It may be that you" 518 + " specified a too small number of maxNodes to use!"); 519 } 520 } 521 } 522 else { 523 if (a_rootNode.getArity(getIndividual()) > 0) { 524 throw new IllegalStateException ("Randomly created program violates" 527 + " configuration constraints" 528 + " (symptom 2)"); 529 } 530 } 531 } 532 533 539 public void redepth() { 540 m_depth[0] = 0; 541 redepth(0); 542 } 543 544 559 protected int redepth(int a_index) { 560 int num = a_index + 1; 561 CommandGene command = getNode(a_index); 562 if (command == null) { 563 throw new IllegalStateException ("ProgramChromosome invalid at index " 564 + a_index); 565 } 566 IGPProgram ind = getIndividual(); 567 int arity = command.getArity(ind); 568 for (int i = 0; i < arity; i++) { 569 if (num < m_depth.length) { m_depth[num] = m_depth[a_index] + 1; 571 num = redepth(num); 573 if (num < 0) { 574 break; 575 } 576 } 577 else { 578 return -1; } 580 } 581 return num; 582 } 583 584 596 public int getChild(int a_index, int a_child) { 597 598 int len = getFunctions().length; 599 for (int i = a_index + 1; i < len; i++) { 600 if (m_depth[i] <= m_depth[a_index]) { 601 return -1; 602 } 603 if (m_depth[i] == m_depth[a_index] + 1) { 604 if (--a_child < 0) { 605 return i; 606 } 607 } 608 } 609 throw new RuntimeException ("Bad child " 610 + a_child 611 + " of node with index = " 612 + a_index); 613 } 614 615 public CommandGene[] getFunctionSet() { 616 return m_functionSet; 617 } 618 619 public void setFunctionSet(CommandGene[] a_functionSet) { 620 m_functionSet = a_functionSet; 621 } 622 623 public CommandGene[] getFunctions() { 624 return m_genes; 625 } 626 627 public void setFunctions(CommandGene[] a_functions) 628 throws InvalidConfigurationException { 629 m_genes = a_functions; 630 } 631 632 641 public int getSize(int a_index) { 642 int i; 643 for (i = a_index + 1; i < m_genes.length && m_genes[i] != null; 645 i++) { 646 if (m_depth[i] <= m_depth[a_index]) { 647 break; 648 } 649 } 650 return i - a_index; 651 } 652 653 662 public int getDepth(int a_index) { 663 int i, maxdepth = m_depth[a_index]; 664 for (i = a_index + 1; i < m_genes.length && m_genes[i] != null; 665 i++) { 666 if (m_depth[i] <= m_depth[a_index]) { 667 break; 668 } 669 if (m_depth[i] > maxdepth) { 670 maxdepth = m_depth[i]; 671 } 672 } 673 return maxdepth - m_depth[a_index]; 674 } 675 676 687 public int getParentNode(int a_child) { 688 if (a_child >= m_genes.length || m_genes[a_child] == null) { 689 return -1; 690 } 691 for (int i = a_child - 1; i >= 0; i--) { 692 if (m_depth[i] == m_depth[a_child] - 1) { 693 return i; 694 } 695 } 696 return -1; 697 } 698 699 710 public boolean execute_boolean(Object [] args) { 711 boolean rtn = m_genes[0].execute_boolean(this, 0, args); 712 cleanup(); 713 return rtn; 714 } 715 716 729 public boolean execute_boolean(int n, int child, Object [] args) { 730 if (child == 0) { 731 return m_genes[n + 1].execute_boolean(this, n + 1, args); 732 } 733 int other = getChild(n, child); 734 return m_genes[other].execute_boolean(this, other, args); 735 } 736 737 746 public void execute_void(Object [] args) { 747 m_genes[0].execute_void(this, 0, args); 748 cleanup(); 749 } 750 751 public void execute_void(int n, int child, Object [] args) { 752 if (child == 0) { 753 m_genes[n + 1].execute_void(this, n + 1, args); 754 } 755 else { 756 int other = getChild(n, child); 757 m_genes[other].execute_void(this, other, args); 758 } 759 } 760 761 772 public int execute_int(Object [] args) { 773 int rtn = m_genes[0].execute_int(this, 0, args); 774 cleanup(); 775 return rtn; 776 } 777 778 public int execute_int(int n, int child, Object [] args) { 779 if (child == 0) { 780 return m_genes[n + 1].execute_int(this, n + 1, args); 781 } 782 else { 783 int other = getChild(n, child); 784 return m_genes[other].execute_int(this, other, args); 785 } 786 } 787 788 798 public long execute_long(Object [] args) { 799 long rtn = m_genes[0].execute_long(this, 0, args); 800 cleanup(); 801 return rtn; 802 } 803 804 public long execute_long(int n, int child, Object [] args) { 805 if (child == 0) { 806 return m_genes[n + 1].execute_long(this, n + 1, args); 807 } 808 int other = getChild(n, child); 809 return m_genes[other].execute_long(this, other, args); 810 } 811 812 822 public float execute_float(Object [] args) { 823 float rtn = m_genes[0].execute_float(this, 0, args); 824 cleanup(); 825 return rtn; 826 } 827 828 public float execute_float(int n, int child, Object [] args) { 829 if (child == 0) { 830 return m_genes[n + 1].execute_float(this, n + 1, args); 831 } 832 int other = getChild(n, child); 833 return m_genes[other].execute_float(this, other, args); 834 } 835 836 846 public double execute_double(Object [] args) { 847 double rtn = m_genes[0].execute_double(this, 0, args); 848 cleanup(); 849 return rtn; 850 } 851 852 public double execute_double(int n, int child, Object [] args) { 853 if (child == 0) { 854 return m_genes[n + 1].execute_double(this, n + 1, args); 855 } 856 int other = getChild(n, child); 857 return m_genes[other].execute_double(this, other, args); 858 } 859 860 871 public Object execute_object(Object [] args) { 872 Object rtn = m_genes[0].execute_object(this, 0, args); 873 cleanup(); 874 return rtn; 875 } 876 877 public Object execute_object(int n, int child, Object [] args) { 878 if (child == 0) { 879 return m_genes[n + 1].execute_object(this, n + 1, args); 880 } 881 int other = getChild(n, child); 882 return m_genes[other].execute_object(this, other, args); 883 } 884 885 895 public Object execute(Object [] args) { 896 return m_genes[0].execute_object(this, 0, args); 897 } 898 899 public Object execute(int n, int child, Object [] args) { 900 return execute_object(n, child, args); 901 } 902 903 public void setGene(int index, CommandGene a_gene) { 904 if (a_gene == null) { 905 throw new IllegalArgumentException ("Gene may not be null!"); 906 } 907 m_genes[index] = a_gene; 908 } 909 910 public Class [] getArgTypes() { 911 return argTypes; 912 } 913 914 public int getArity() { 915 return argTypes.length; 916 } 917 918 924 public int size() { 925 int i = 0; 926 while (i < m_genes.length && m_genes[i] != null) { 927 i++; 928 } 929 return i; 930 } 931 932 946 public int compareTo(Object a_other) { 947 if (a_other == null) { 951 return 1; 952 } 953 int size = size(); 954 ProgramChromosome otherChromosome = (ProgramChromosome) a_other; 955 CommandGene[] otherGenes = otherChromosome.m_genes; 956 if (otherChromosome.size() != size) { 960 return size() - otherChromosome.size(); 961 } 962 for (int i = 0; i < size; i++) { 967 int comparison = m_genes[i].compareTo(otherGenes[i]); 968 if (comparison != 0) { 969 return comparison; 970 } 971 } 972 973 if (isCompareApplicationData()) { 974 if (getApplicationData() == null) { 977 if (otherChromosome.getApplicationData() != null) { 978 return -1; 979 } 980 } 981 else if (otherChromosome.getApplicationData() == null) { 982 return 1; 983 } 984 else { 985 if (getApplicationData() instanceof Comparable ) { 986 try { 987 return ( (Comparable ) getApplicationData()).compareTo( 988 otherChromosome.getApplicationData()); 989 } catch (ClassCastException cex) { 990 return -1; 991 } 992 } 993 else { 994 return getApplicationData().getClass().getName().compareTo( 995 otherChromosome.getApplicationData().getClass().getName()); 996 } 997 } 998 } 999 return 0; 1002 } 1003 1004 1013 public boolean equals(Object a_other) { 1014 try { 1015 return compareTo(a_other) == 0; 1016 } catch (ClassCastException cex) { 1017 return false; 1018 } 1019 } 1020 1021 1031 public void setCompareApplicationData(boolean a_doCompare) { 1032 m_compareAppData = a_doCompare; 1033 } 1034 1035 1041 public boolean isCompareApplicationData() { 1042 return m_compareAppData; 1043 } 1044 1045 1057 public Object getApplicationData() { 1058 return m_applicationData; 1059 } 1060 1061 1072 public synchronized CommandGene getGene(int a_locus) { 1073 return m_genes[a_locus]; 1074 } 1075 1076 private CommandGene[] remove(CommandGene[] a_functionSet, CommandGene node) { 1077 int size = a_functionSet.length; 1078 for (int i = 0; i < size; i++) { 1079 if (a_functionSet[i] == node) { 1080 CommandGene[] result = new CommandGene[size-1]; 1082 if (i>0) { 1083 System.arraycopy(a_functionSet, 0, result, 0, i); 1084 } 1085 if (size - i > 1) { 1086 System.arraycopy(a_functionSet, i + 1, result, i, size - i-1); 1087 } 1088 return result; 1089 } 1090 } 1091 return a_functionSet; 1092 } 1093} 1094 | Popular Tags |