рдЖрдиреБрд╡рдВрд╢рд┐рдХ рдПрд▓реНрдЧреЛрд░рд┐рдердоред рд╕рд┐рджреНрдзрд╛рдВрдд рд╕реЗ рдЕрднреНрдпрд╛рд╕ рддрдХ

рд╢реБрдн рджреЛрдкрд╣рд░ рд╣рд╛рд▓ рд╣реА рдореЗрдВ, рдореИрдВрдиреЗ рдЖрддреНрдо-рд╢рд┐рдХреНрд╖рд╛ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред рдпрд╣ рдЖрдиреБрд╡рдВрд╢рд┐рдХ рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред

рдЬреАрдП рдХреЗ рдЙрд▓реНрд▓реЗрдЦрдиреАрдп рдЧреБрдгреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдпрд╣ рд╣реИ рдХрд┐ рдЪрдпрди, рдХреНрд░реЙрд╕рд┐рдВрдЧ рдФрд░ рдореНрдпреВрдЯреЗрд╢рди рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХрд╛ рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рдореЗрдВ рдЬрдирд░реЗрд╢рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреЛрдИ рдкрддрд╛ рдирд╣реАрдВ рд╣реИ - рдЙрдирдХреЗ рд▓рд┐рдП рдпрд╣ рдХреЗрд╡рд▓ 0 рдФрд░ 1. рдПрдХрдорд╛рддреНрд░ рдлрд╝рдВрдХреНрд╢рди рд╣реИ рдЬреЛ рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ рдпреЗ 0 рдФрд░ 1 рд╣реИрдВ - рдпрд╣ рдПрдХ рдлрд┐рдЯрдиреЗрд╕ рдлрдВрдХреНрд╢рди рд╣реИред

рдЗрд╕рд▓рд┐рдП, рдореИрдВрдиреЗ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ рдХрд┐ рдХрд┐рд╕реА рднреА GA рдХреЗ рд▓рд┐рдП рд╡рд╛рдпрд░рдлреНрд░реЗрдо рдХреНрд▓рд╛рд╕ рд▓рд┐рдЦрдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ред рдпрд╣ рдЗрд╕ рд▓реЗрдЦ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛ рд╣реЛрдЧрд╛ред рдпрд╣ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЖрдиреБрд╡рдВрд╢рд┐рдХ рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХреА рдореВрд▓ рдмрд╛рддреЗрдВ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реИрдВред

рдпрд╣ рдХрд┐рд╕рдХреЗ рд▓рд┐рдП рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ, рдореИрдВ рдмрд┐рд▓реНрд▓реА рдХреЗ рдиреАрдЪреЗ рдкреВрдЫрддрд╛ рд╣реВрдВред


рдХреЛрдб рдЬрд╛рд╡рд╛ рдореЗрдВ рд▓рд┐рдЦрд╛ рдЬрд╛рдПрдЧрд╛ред

рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд╡рдЬреВрдж рдХрд┐ рд╣рдо рд╡рд╛рдпрд░рдлреНрд░реЗрдо рд▓рд┐рдЦ рд░рд╣реЗ рд╣реИрдВ, рд╣рдореЗрдВ рдЗрд╕рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдХреНрд▓рд╛рд╕рд┐рдХ рдПрдирдкреА-рдкреВрд░реНрдг рд╕рдорд╕реНрдпрд╛ - рдпрд╛рддреНрд░рд╛ рд╡рд┐рдХреНрд░реЗрддрд╛ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд▓рд┐рдпрд╛ред

рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдереЛрдбрд╝рд╛ рд╕рд╛:

рдЬреАрдиреЛрдо (рд╡реНрдпрдХреНрддрд┐рдЧрдд) рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдо рд▓рдВрдмреЗ [] рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ, рдпрд╣ рд╡рд┐рдХрд▓реНрдк рдореБрдЭреЗ рдмреВрд▓рд┐рдпрди [] рд╕реЗ рдмреЗрд╣рддрд░ рд▓рдЧ рд░рд╣рд╛ рдерд╛ред

рд╣рдореЗрдВ рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рднреА рдЪрд╛рд╣рд┐рдП:

public interface FitnessFunction { int getArity(); //-    long run(long[] genom); //    . } 


рд╣рдо рдЬрд┐рд╕ рд╡рд░реНрдЧ рдХрд╛ рд╡рд┐рдХрд╛рд╕ рдХрд░ рд░рд╣реЗ рд╣реИрдВ:
 public class GeneticEngine{ public GeneticEngine(FitnessFunction fitnessFunction) {...} // public long[] run() {...} //  private void generateFirstGeneration() {...} //   private void selection(){...} //  private void crossing() {...} //  private void mutation() {...} //  } 


рдЪреВрдВрдХрд┐ рд╣рдо рдПрдХ "рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ" рд╡рд░реНрдЧ рд▓рд┐рдЦ рд░рд╣реЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдХрд┐ рдпрд╣ рдХреНрд░реЙрд╕рдмреНрд░реИрдбрд┐рдВрдЧ рдФрд░ рдЪрдпрди рдХреЗ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП 2 рдПрдирдо рдЬреЛрдбрд╝реЗ рдЧрдП (Enum):
 public enum SelectionType { TOURNEY, ROULETTE_WHEEL } public enum CrossingType { ONE_POINT_RECOMBINATION, TWO_POINT_RECOMBINATION, ELEMENTWISE_RECOMBINATION, ONE_ELEMENT_EXCHANGE } 


... рдФрд░ рдХреБрдЫ рдирд┐рдЬреА рдХреНрд╖реЗрддреНрд░:
 private int genomLength; //    private long generationCount; //-  private int individualCount; //- (,)   private SelectionType selectionType; //  private CrossingType crossingType; //  private boolean useMutation; //  private double mutationPercent; //    

рдЙрдирдХреЗ рд▓рд┐рдП рд╕реЗрдЯрд░ рдФрд░ рдЧреЗрдЯрд░реНрд╕ рд╣реИрдВред

рдФрд░ рдЕрдм, рдкрд╣рд▓реА рдЪреАрдЬреЗрдВ рдкрд╣рд▓реЗ ...

рдкрд╣рд▓реА рдкреАрдврд╝реА рдХреА рдкреАрдврд╝реАред


рд╕рдм рдХреБрдЫ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ: рд╣рдо рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рджреНрд╡рд╛рд░рд╛ рд▓реЛрдВрдЧ рдЙрддреНрдкрдиреНрди рдХрд░рддреЗ рд╣реИрдВ, рд╣рдо рд▓реЛрдВрдЧреЛ рд╕реЗ рдЬреАрдиреЛрдо рдХреА рд░рдЪрдирд╛ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдПрдХ рд╕рд░рдгреА рдореЗрдВ рд░рдЦрддреЗ рд╣реИрдВред рдореИрдВ рдХреЛрдб рдирд╣реАрдВ рджреВрдВрдЧрд╛ред

рдЪрдпрдиред

рдореБрдЭреЗ 2 рдкреНрд░рдХрд╛рд░ рдХреЗ рдЪрдпрди рдорд┐рд▓реЗ:

рдЪрдпрди рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдЬреАрдиреЛрдо рдХреА рдПрдХ рдирдИ рд╕рд░рдгреА рдмрдирд╛рддреА рд╣реИред

 private void selection(){ switch (selectionType) { case ROULETTE_WHEEL:{ float[] wheel = new float[this.individualCount]; wheel[0] = //   1-  for (int i=1;i<this.individualCount;i++){ wheel[i] = wheel[i-1] + //   i-  } float all = wheel[this.individualCount-1]; for (int i=0;i<this.individualCount;i++){ float index = Math.abs(this.random.nextFloat())*all; int l = 0; int r = individualCount-1; int c = 0; while (l < r){ c = (l+r) >> 1; if (index <= while[c]){ r = c; }else{ l = c + 1; } } this.genomListOffsprings[i] = this.genomListParents[l].clone(); } break; } case TOURNEY:{ for (int i=0;i<this.individualCount;i++){ int index1 = random.nextInt(individualCount); int index2 = random.nextInt(individualCount); long fr1 = //   index1  long fr2 = //   index2  this.genomListOffsprings[i] = fr1 > fr2 ? this.genomListParents[index1].clone() : this.genomListParents[index2].clone(); } break; } } 


рдХреБрдЫ рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ "рдЕрдкрдиреЗ рджрдо рдкрд░":



рдЕрдВрддрд░ рдкреНрд░рдЬрдирдиред


рдХреНрд░реЙрд╕рд┐рдВрдЧ рд╣реЛрддрд╛ рд╣реИ:


рдХреБрдЫ рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ "рдЕрдкрдиреЗ рджрдо рдкрд░":



* рдХреНрд░реЙрд╕рд┐рдВрдЧ рдФрд░ рдореНрдпреВрдЯреЗрд╢рди рдХреЗ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдмрд╛рдЗрдирд░реА рдСрдкрд░реЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред рдЗрд╕рд▓рд┐рдП, рд╣рдореЗрдВ рдХрдИ рд╕реНрдерд┐рд░ рдЪрд░ рдШреЛрд╖рд┐рдд рдХрд░рдиреЗ рдкрдбрд╝реЗред

 public static final int OCTET_LENGTH = 64; // -    public static final int MASK_FOR_MOD = OCTET_LENGTH - 1; //  "x%64"   "x & MASK_FOR_MOD" public static final int SHIFT_FOR_DIVISION; //  "x/64" - "x >> SHIFT_FOR_DIVISION" 


рджреЛ рдЬреАрдиреЛрдо рдХреЛ рдкрд╛рд░ рдХрд░рдиреЗ рдХрд╛ рдХрд╛рд░реНрдп:
(рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рдХреЛрдб рдХреЗрд╡рд▓ рдмрд┐рдЯрд╡рд╛рдЗрдЬрд╝ рдХреНрд░реЙрд╕рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рд╣реИ)
 private void cross(long[] genom1, long[] genom2) { switch (crossingType) { ... case ELEMENTWISE_RECOMBINATION:{ for (int outerOffset = 0; outerOffset < this.sizeOfArray; outerOffset++) { long mask = this.random.nextLong(); //   ,    (1- , 0-) long swapMask = (genom1[outerOffset] ^ genom2[outerOffset]) & mask; genom1[outerOffset] ^= swapMask; genom2[outerOffset] ^= swapMask; } break; } } 


рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг:
рдПрдХ рджреВрд╕рд░реЗ рдХреЗ рд╕рд╛рде рд╕рдВрдЦреНрдпрд╛рдУрдВ рдФрд░ рдмреА рдХрд╛ рдЖрджрд╛рди-рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдпрд╣ рдХрд░рдирд╛ рд╣реЛрдЧрд╛:
swapMask = рдПрдХ xor b;
a = a xor swapMask;
b = b xor рд╕реНрд╡реИрдкрдореИрдк;

рдФрд░ рдЕрдЧрд░ рд╣рдо рд╕реНрд╡реИрдкрдореИрдк рдкрд░ рдорд╛рд╕реНрдХ (рдФрд░) рд▓рдЧрд╛рддреЗ рд╣реИрдВ, рддреЛ a рдФрд░ b рдХреЗрд╡рд▓ рдЙрди рдмрд┐рдЯреНрд╕ рдХреЛ рдмрджрд▓реЗрдВрдЧреЗ рдЬреЛ рдорд╛рд╕реНрдХ рдирдВрдмрд░ рдореЗрдВ == 1 рд╣реИрдВред

swapMask = (a xor b) рдФрд░ рдорд╛рд╕реНрдХ;
a = a xor swapMask;
b = b xor рд╕реНрд╡реИрдкрдореИрдк;

рдЙрддреНрдкрд░рд┐рд╡рд░реНрддрдиред

 private void mutation() { for (long[] genom : this.genomListOffsprings) { if (random.nextDouble() <= mutationPercent) { mutate(genom); } } } private void mutate(long[] genom) { int index = this.random.nextInt(this.genomLength); int outerOffset = index >> SHIFT_FOR_DIVISION; int innerOffset = (index & MASK_FOR_MOD); long mask = 1L << innerOffset; genom[outerOffset] ^= mask; } 


рдереЛрдбрд╝рд╛ рдЙрд▓реНрдЯрд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЪрд╛рд╣рд┐рдП:
bit = bit xor 1;
рдЗрд╕рд▓рд┐рдП, рдХрд┐рд╕реА рднреА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдХрд┐рд╕реА рднреА рдмрд┐рдЯ рдХреЛ рдкрд▓рдЯрдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрдХрд╛рдИ рдХреЛ рд╡рд╛рдВрдЫрд┐рдд рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред

"рд╢рд░реАрд░ред"

рдФрд░ рдореБрдЦреНрдп рдХрд╛рд░реНрдп рдЬреЛ рдкрд┐рдЫрд▓реЗ рд╕рднреА рдХреЛ рдЬреЛрдбрд╝рддрд╛ рд╣реИ:

 public long[] run() { generateFirstGeneration(); while (currentGeneration < generationCount) { selection(); this.crossing(); if (useMutation) { mutation(); } currentGeneration++; } return . } 


рдЖрд╡реЗрджрдиред

рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИ:
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рдЖрдкрдХреЛ рдлрд┐рдЯрдиреЗрд╕рдлрдВрдХреНрд╢рди рдХреНрд▓рд╛рд╕ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
рдФрд░ рдлрд┐рд░ ...
 MyFitnessFunction ff = new MyFitnessFunction(); GeneticEngine ge = new GeneticEngine(ff); ge.setIndividualCount(1000); // -    ge.setGenerationCount(10000); // -  ge.setSelectionType(SelectionType.TOURNEY); //  ge.setCrossingType(CrossingType.ELEMENTWISE_RECOMBINATION); //  ge.setUseMutation(true); //    ge.setMutationPercent(0.02d); //    long[] better = ge.run(); // 


рдпрд╛рддреНрд░рд╛ рд╡рд┐рдХреНрд░реЗрддрд╛ рд╕рдорд╕реНрдпрд╛ рдкрд░ рд╡рд╛рдкрд╕ рдЖрддреЗ рд╣реИрдВред

рдЪреВрдВрдХрд┐ рд╢рд╣рд░реЛрдВ рдХреЗ рдмреАрдЪ рдХреА рджреВрд░реА random.nextInt (256) рд╕реЗ рднрд░реА рд╣реБрдИ рдереАред рдореИрдВрдиреЗ рдпрд╣ рд╕реБрдЭрд╛рд╡ рджреЗрдиреЗ рдХрд╛ рд╕рд╛рд╣рд╕ рдХрд┐рдпрд╛ рдХрд┐ 2 рд╢рд╣рд░реЛрдВ рдХреЗ рдмреАрдЪ рдХреА рдФрд╕рдд рджреВрд░реА = 128. => рд╕рднреА рд╢рд╣рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдорд╛рд░реНрдЧ рдХреА рдФрд╕рдд рд▓рдВрдмрд╛рдИ = 128 * 256 = 32768ред (! рдореИрдВ рдЧрд▓рдд рд╣реЛ рд╕рдХрддрд╛ рд╣реИ)ред

рдкрд░
 IndividualCount = 100; GenerationCount = 10000; SelectionType = SelectionType; CrossingType = ELEMENTWISE_RECOMBINATION; UseMutation = true; MutationPercent = 0.02d; 

GA 6-7 рд╕реЗрдХрдВрдб рдХреЗ рд▓рд┐рдП рдкрде = 10000-12000 рдкрд╛рддрд╛ рд╣реИред рдЬреЛ рдФрд╕рдд рд╕реЗ 3 рдЧреБрдирд╛ рдмреЗрд╣рддрд░ рд╣реИред

рдкрд░
 IndividualCount = 1000; GenerationCount = 10000; 

5500-7000 рдкреНрд░рддрд┐ рдорд┐рдирдЯред

рдкрд░
 IndividualCount = 10000; GenerationCount = 100000; 

рдХреЛрдб рд▓рдЧрднрдЧ 15 рдШрдВрдЯреЗ рддрдХ рдЪрд▓рддрд╛ рд╣реИред рдФрд░ рдорд╛рд░реНрдЧ = 3500-4000 рдкрд╛рддрд╛ рд╣реИред

рдЖрдЧреЗ рдХрд╣рд╛рдВ рдмрдврд╝реЗрдВрдЧреЗред



GitHub рд╕реЗ рд▓рд┐рдВрдХ рдХрд░реЗрдВред рдореБрдЭреЗ рдЦреБрд╢реА рд╣реЛрдЧреА рдЕрдЧрд░ рдХреЛрдИ рдХрд╛рдо рдЖрдПрдЧрд╛ред

UPD: рдХреЛрдб рдЬрд╛рд╡рд╛ рдореЗрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рдЗрд╕реЗ java.util рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдмрд┐рдирд╛ рд▓рд┐рдЦрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА, рдФрд░ рдЗрд╕рд▓рд┐рдП рдпрд╣ C рдХреА рддрд░рд╣ рд▓рдЧ рд░рд╣рд╛ рдерд╛ред
рдЗрд╕ рдкрд╣рд▓реВ рдХрд╛ рдХрд╛рд░рдг рдХреНрдпрд╛ рд╣реИ:

(рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ, рдХреЛрдб рдПрд╕-рд╢рдиреА рдХреЗ рд╕рд╛рде рднреНрд░рдорд┐рдд рдерд╛, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЗрд╕ рдХрд╛рд░реНрдп рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рддрд╛ рд╣реВрдВ)

UPD2: рд▓рд┐рдпреЛрдХрд╛рд░реНрдб рдХреЛ рд░реВрд▓реЗ (рдмрд╛рдЗрдирд░реА рдЦреЛрдЬ рдореЗрдВ) рдореЗрдВ рдПрдХ рддреНрд░реБрдЯрд┐ рдорд┐рд▓реАред рдлрд┐рдХреНрд╕реНрдбред

Source: https://habr.com/ru/post/In138091/


All Articles