001    package org.jaga.reproduction.proteinLocation;
002    
003    import org.jaga.reproduction.Mutation;
004    import org.jaga.individualRepresentation.proteinLocation.*;
005    import java.util.ArrayList;
006    import org.jaga.definitions.*;
007    
008    /**
009     * TODO: Complete these comments.
010     *
011     * <p><u>Project:</u> JAGA - Java API for Genetic Algorithms.</p>
012     *
013     * <p><u>Company:</u> University College London and JAGA.Org
014     *    (<a href="http://www.jaga.org" target="_blank">http://www.jaga.org</a>).
015     * </p>
016     *
017     * <p><u>Copyright:</u> (c) 2004 by G. Paperin.<br/>
018     *    This program is free software; you can redistribute it and/or modify
019     *    it under the terms of the GNU General Public License as published by
020     *    the Free Software Foundation, ONLY if you include a note of the original
021     *    author(s) in any redistributed/modified copy.<br/>
022     *    This program is distributed in the hope that it will be useful,
023     *    but WITHOUT ANY WARRANTY; without even the implied warranty of
024     *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
025     *    GNU General Public License for more details.<br/>
026     *    You should have received a copy of the GNU General Public License
027     *    along with this program; if not, write to the Free Software
028     *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
029     *    or see http://www.gnu.org/licenses/gpl.html</p>
030     *
031     * @author Greg Paperin (greg@jaga.org)
032     *
033     * @version JAGA public release 1.0 beta
034     */
035    
036    public class PolypeptidePatternMutation extends Mutation {
037    
038            private SubstitutionScoringMatrix scoringMatrix = new Blosum62();
039    
040            private int aminoAcid_deleteChance = 2;
041            private int aminoAcid_cloneChance = 2;
042            private int aminoAcid_mutateChance = 5;
043            private int aminoAcid_generaliseToPropertyChance = 3;
044            private int aminoAcid_generaliseToGroupChance = 2;
045    
046            private int group_substractChance = 5;
047            private int group_addChance = 5;
048            private int group_swapChance = 9;
049            private int group_deleteChance = 2;
050            private int group_cloneChance = 2;
051            private int group_onEmptyDeleteChance = 1;
052            private int group_onEmptyReplaceChance = 1;
053            private double group_onSingleReplaceProb = 0.75;
054            private double group_onPropertyTriggerPercent = 0.7;
055            private double group_onPropertyReplaceProb = 0.5;
056            private int group_onLargeTriggerLength = 12;
057            private int group_onLargeSplitChance = 2;
058            private int group_onLargeReplaceChance = 3;
059            private int group_onLargeDontActChance = 5;
060    
061            private int property_deleteChance = 2;

062            private int property_cloneChance = 5;
063            private int property_mutateChance = 5;
064            private int property_expandChance = 5;//3
065            private int property_expandGroupSize = 6;
066            private int property_expandSamePropCount = 5;
067    
068            private int singleGap_deleteChance = 3;
069            private int singleGap_cloneChance = 5;
070            private int singleGap_mutateChance = 5;
071            private int singleGap_expandChance = 2;
072            private int singleGap_expandGroupSize = 20;
073    
074    
075            public PolypeptidePatternMutation() {
076                    super();
077            }
078    
079            public PolypeptidePatternMutation(double mutProb) {
080                    super(mutProb);
081            }
082    
083            public Class getApplicableClass() {
084                    return ProteinLocationClassifier.class;
085            }
086    
087            private PolypeptidePatternItem [] mutateItem(AminoAcid aAcid, GAParameterSet params) {
088                    int sum = aminoAcid_cloneChance + aminoAcid_deleteChance + aminoAcid_mutateChance
089                                            + aminoAcid_generaliseToPropertyChance + aminoAcid_generaliseToGroupChance;
090                    int dice = params.getRandomGenerator().nextInt(0, sum);
091    
092                    // clone:
093                    if (0 <= dice && dice < aminoAcid_cloneChance) {
094                            return new PolypeptidePatternItem [] {aAcid, aAcid};
095    
096                    // delete:
097                    } else if (aminoAcid_cloneChance <= dice && dice < aminoAcid_cloneChance + aminoAcid_deleteChance) {
098                            return new PolypeptidePatternItem[0];
099    
100                    // mutate:
101                    } else if (aminoAcid_cloneChance + aminoAcid_deleteChance <= dice
102                                       && dice < aminoAcid_cloneChance + aminoAcid_deleteChance + aminoAcid_mutateChance) {
103                            /*
104                            AminoAcid substitute = scoringMatrix.chooseProbabalisticMutation(aAcid, params);
105                            if (null == substitute)
106                                    return new PolypeptidePatternItem[] {SingleGap.getInstance()};
107                            else
108                                    return new PolypeptidePatternItem[] {substitute};
109                            */
110                            return new PolypeptidePatternItem[] {AminoAcidFactory.getRandomResidue(params)};
111    
112                    // generalise to a property group:
113                    } else if (aminoAcid_cloneChance + aminoAcid_deleteChance + aminoAcid_mutateChance <= dice
114                                       && dice < aminoAcid_cloneChance + aminoAcid_deleteChance
115                                                                                                       + aminoAcid_mutateChance
116                                                                                                       + aminoAcid_generaliseToPropertyChance) {
117                            ArrayList props = new ArrayList();
118                            if (aAcid.isSmall())        props.add(AminoAcidPropertyFactory.Small);
119                            if (aAcid.isHydrophobic())  props.add(AminoAcidPropertyFactory.Hydrophobic);
120                            if (aAcid.isPolar())        props.add(AminoAcidPropertyFactory.Polar);
121                            if (aAcid.isPositive())     props.add(AminoAcidPropertyFactory.Positive);
122                            if (aAcid.isNegative())     props.add(AminoAcidPropertyFactory.Negative);
123                            if (aAcid.isTiny())         props.add(AminoAcidPropertyFactory.Tiny);
124                            if (aAcid.isAliphatic())    props.add(AminoAcidPropertyFactory.Aliphatic);
125                            if (aAcid.isAromatic())     props.add(AminoAcidPropertyFactory.Aromatic);
126                            Object p = props.get(params.getRandomGenerator().nextInt(0, props.size()));
127                            return new PolypeptidePatternItem [] {(AminoAcidProperty) p};
128    
129                    // must be generalise to list group:
130                    } else {
131                            AminoAcidGroup group = new AminoAcidGroup();
132                            group.addResidue(aAcid);
133                            return new PolypeptidePatternItem [] {group};
134    
135                    }
136            }
137    
138            private PolypeptidePatternItem [] mutateItem(AminoAcidGroup group, GAParameterSet params) {
139                    /*
140                       - delete an item from the group
141                       - add an item to the group
142                       - swap an item in the group
143                       - delete the whole group
144                       - clone the group
145                       then check in this order:
146                       - if group becomes empty, it wont be able to match anything, so:
147                               - delete it or
148                               - replace by a gap
149                       - if group has only one residue - consider replacing group by that acid
150                       - if more then X percent in group have same property - consider replacing by property group
151                       - if group becomes too large, consider:
152                               - splitting in two groups
153                               - replacing by a gap
154                     */
155                    RandomGenerator rnd = params.getRandomGenerator();
156                    int sum = group_substractChance + group_addChance + group_swapChance
157                                      + group_deleteChance + group_cloneChance;
158                    int dice = rnd.nextInt(0, sum);
159    
160                    // clone:
161                    if (0 <= dice && dice < group_cloneChance) {
162                            return new PolypeptidePatternItem[] {group, group};
163    
164                    // delete:
165                    } else if (group_cloneChance <= dice && dice < group_cloneChance + group_deleteChance) {
166                            return new PolypeptidePatternItem[0];
167    
168                    // substract a residue:
169                    } else if (group_cloneChance + group_deleteChance <= dice
170                                       && dice < group_cloneChance + group_deleteChance + group_substractChance) {
171                            int ind = rnd.nextInt(0, group.size());
172                            group.removeResidue(ind);
173    
174                    // add a residue:
175                    } else if (group_cloneChance + group_deleteChance + group_substractChance <= dice
176                                       && dice < group_cloneChance + group_deleteChance + group_substractChance + group_addChance) {
177                            group.addResidue(AminoAcidFactory.getRandomResidue(params));
178    
179                    // must be swap a residue:
180                    } else {
181                            int ind = rnd.nextInt(0, group.size());
182                            group.swapResidue(ind, AminoAcidFactory.getRandomResidue(params));
183    
184                    }
185    
186                    // Now the checks:
187    
188                    if (group.size() == 0) {
189                            dice = rnd.nextInt(0, group_onEmptyDeleteChance + group_onEmptyReplaceChance);
190                            if (dice < group_onEmptyDeleteChance)
191                                    return new PolypeptidePatternItem[0];
192                            else
193                                    return new PolypeptidePatternItem [] {SingleGap.getInstance()};
194                    }
195                    if (group.size() == 1) {
196                            if (rnd.nextDouble() < group_onSingleReplaceProb)
197                                    return new PolypeptidePatternItem [] {group.getResidue(0)};
198                    }
199                    int frequentProp = group.getMaxRepresentedProperty();
200                    if (0 != frequentProp) {
201                            if (group.getPropertyProportion(frequentProp) >= group_onPropertyTriggerPercent)
202                                    if (rnd.nextDouble() < group_onPropertyReplaceProb)
203                                            return new PolypeptidePatternItem [] {AminoAcidPropertyFactory.getPropertyByCode(frequentProp)};
204                    }
205                    if (group.size() >= group_onLargeTriggerLength) {
206                            dice = rnd.nextInt(0, group_onLargeSplitChance
207                                                                    + group_onLargeReplaceChance + group_onLargeDontActChance);
208                            if (dice < group_onLargeSplitChance) {
209                                    AminoAcidGroup group2 = new AminoAcidGroup();
210                                    int half = group.size() / 2;
211                                    for (int i = 0; i < half; i++) {
212                                            int ind = rnd.nextInt(0, group.size());
213                                            AminoAcid aa = group.removeResidue(ind);
214                                            group2.addResidue(aa);
215                                    }
216                                    return new PolypeptidePatternItem [] {group, group2};
217    
218                            } else if (dice < group_onLargeSplitChance + group_onLargeReplaceChance) {
219                                    return new PolypeptidePatternItem [] {SingleGap.getInstance()};
220    
221                            } else ; // Don't act = do nothing.
222                    }
223    
224                    return new PolypeptidePatternItem [] {group};
225            }
226    
227            private PolypeptidePatternItem [] mutateItem(AminoAcidProperty property, GAParameterSet params) {
228                    /*
229                    - delete the hole group
230                    - duplicate the group
231                    - mutate to some other property
232                    - mutate to aa group consisting of at least X% of acids with this property
233                    */
234                    int sum = property_deleteChance + property_cloneChance
235                                                               + property_mutateChance + property_expandChance;
236                    int dice = params.getRandomGenerator().nextInt(0, sum);
237    
238                    // clone:
239                    if (0 <= dice && dice < property_cloneChance) {
240                            return new PolypeptidePatternItem [] {property, property};
241    
242                    // delete:
243                    } else if (property_cloneChance <= dice && dice < property_cloneChance + property_deleteChance) {
244                            return new PolypeptidePatternItem[0];
245    
246                    // mutate:
247                    } else if (property_cloneChance + property_deleteChance <= dice
248                                       && dice < property_cloneChance + property_deleteChance + property_mutateChance) {
249                            return new PolypeptidePatternItem[] {AminoAcidPropertyFactory.getRandomProperty(params)};
250    
251                    // must be expand:
252                    } else {
253                            AminoAcidGroup group = new AminoAcidGroup();
254                            for (int i = 0; i < property_expandGroupSize; i++) {
255                                    AminoAcid aa;
256                                    if (i < property_expandSamePropCount)
257                                            aa = AminoAcidFactory.getRandomResidueByProperty(property.getProperty(), params);
258                                    else
259                                            aa = AminoAcidFactory.getRandomResidue(params);
260                                    group.addResidue(aa);
261                            }
262                            return new PolypeptidePatternItem [] {group};
263    
264                    }
265            }
266    
267            private PolypeptidePatternItem [] mutateItem(SingleGap gap, GAParameterSet params) {
268                    int sum = singleGap_cloneChance + singleGap_deleteChance
269                                      + singleGap_mutateChance + singleGap_expandChance;
270                    int dice = params.getRandomGenerator().nextInt(0, sum);
271    
272                    // clone:
273                    if (0 <= dice && dice < singleGap_cloneChance) {
274                            return new PolypeptidePatternItem [] {gap, gap};
275    
276                    // delete:
277                    } else if (singleGap_cloneChance <= dice && dice < singleGap_cloneChance + singleGap_deleteChance) {
278                            return new PolypeptidePatternItem[0];
279    
280                    // mutate:
281                    } else if (singleGap_cloneChance + singleGap_deleteChance <= dice
282                                       && dice < singleGap_cloneChance + singleGap_deleteChance + singleGap_mutateChance) {
283                            AminoAcid substitute = scoringMatrix.chooseProbabalisticMutation((AminoAcid) null, params);
284                            if (null == substitute)
285                                    return new PolypeptidePatternItem[] {SingleGap.getInstance()};
286                            else
287                                    return new PolypeptidePatternItem[] {substitute};
288    
289                    // must be expand:
290                    } else {
291                            AminoAcidGroup group = new AminoAcidGroup();
292                            for (int i = 0; i < singleGap_expandGroupSize; i++) {
293                                    AminoAcid aa = AminoAcidFactory.getRandomResidue(params);
294                                    group.addResidue(aa);
295                            }
296                            return new PolypeptidePatternItem [] {group};
297    
298                    }
299            }
300    
301            private PolypeptidePatternItem [] mutatePatternItem(PolypeptidePatternItem item, GAParameterSet params) {
302    
303                    if (item instanceof AminoAcid)
304                            return mutateItem((AminoAcid) item, params);
305                    if (item instanceof AminoAcidGroup)
306                            return mutateItem((AminoAcidGroup) item, params);
307                    if (item instanceof AminoAcidProperty)
308                            return mutateItem((AminoAcidProperty) item, params);
309                    if (item instanceof SingleGap)
310                            return mutateItem((SingleGap) item, params);
311                    throw new IllegalArgumentException("Cannot mutate a PolypeptidePatternItem"
312                                                                                       + " of an unexpected type ("
313                                                                                       + item.getClass().getName() + ")");
314            }
315    
316            public Individual reproduce(Individual parent, GAParameterSet params) {
317                    ProteinLocationClassifierFactory factory = (ProteinLocationClassifierFactory) params.getIndividualsFactory();
318                    ProteinLocationClassifier kid = (ProteinLocationClassifier)
319                                                                                    factory.createSpecificIndividual(parent, params);
320                    PolypeptidePattern pattern = kid.getPattern();
321                    RandomGenerator rnd = params.getRandomGenerator();
322                    double mutProb = getMutationProbability();
323                    int i = 0;
324                    while(i < pattern.getLength()) {
325                            if (rnd.nextDouble() > mutProb) {
326                                    i++;
327                                    continue;
328                            }
329                            PolypeptidePatternItem item = kid.getPattern().getItem(i);
330                            PolypeptidePatternItem [] res = mutatePatternItem(item, params);
331                            if (0 == res.length) {
332                                    pattern.removeItem(i);
333                                    i++;
334                            } else if (1 == res.length) {
335    
336                                    //if (null == res[0]) System.out.println("\n**********" + item.getClass().getName());
337    
338                                    pattern.replaceItem(i, res[0]);
339                                    i++;
340                            } else { /* must be 1 < res.length */
341                                    pattern.replaceItem(i, res[0]);
342                                    i++;
343                                    for (int j = 1; j < res.length; i++, j++) {
344                                            if (pattern.getLength() >= factory.getMaxPatternLength())
345                                                    break;
346                                            pattern.insertItem(i, res[j]);
347                                    }
348                            }
349                    }
350                    return kid;
351            }
352    
353            public Individual[] reproduce(Individual[] parents, GAParameterSet params) {
354                    Individual [] kids = new Individual[parents.length];
355                    for (int i = 0; i < parents.length; i++) {
356                            kids[i] = reproduce(parents[i], params);
357                    }
358                    return kids;
359            }
360    
361            public int getAminoAcid_cloneChance() {
362                    return aminoAcid_cloneChance;
363            }
364    
365            public void setAminoAcid_cloneChance(int aminoAcid_cloneChance) {
366                    this.aminoAcid_cloneChance = aminoAcid_cloneChance;
367            }
368    
369            public int getAminoAcid_deleteChance() {
370                    return aminoAcid_deleteChance;
371            }
372    
373            public void setAminoAcid_deleteChance(int aminoAcid_deleteChance) {
374                    this.aminoAcid_deleteChance = aminoAcid_deleteChance;
375            }
376    
377            public int getAminoAcid_generaliseToGroupChance() {
378                    return aminoAcid_generaliseToGroupChance;
379            }
380    
381            public void setAminoAcid_generaliseToGroupChance(int
382                      aminoAcid_generaliseToGroupChance) {
383                    this.aminoAcid_generaliseToGroupChance =
384                              aminoAcid_generaliseToGroupChance;
385            }
386    
387            public int getAminoAcid_generaliseToPropertyChance() {
388                    return aminoAcid_generaliseToPropertyChance;
389            }
390    
391            public void setAminoAcid_generaliseToPropertyChance(int
392                      aminoAcid_generaliseToPropertyChance) {
393                    this.aminoAcid_generaliseToPropertyChance =
394                              aminoAcid_generaliseToPropertyChance;
395            }
396    
397            public int getAminoAcid_mutateChance() {
398                    return aminoAcid_mutateChance;
399            }
400    
401            public void setAminoAcid_mutateChance(int aminoAcid_mutateChance) {
402                    this.aminoAcid_mutateChance = aminoAcid_mutateChance;
403            }
404    
405            public int getGroup_addChance() {
406                    return group_addChance;
407            }
408    
409            public void setGroup_addChance(int group_addChance) {
410                    this.group_addChance = group_addChance;
411            }
412    
413            public int getGroup_cloneChance() {
414                    return group_cloneChance;
415            }
416    
417            public void setGroup_cloneChance(int group_cloneChance) {
418                    this.group_cloneChance = group_cloneChance;
419            }
420    
421            public int getGroup_deleteChance() {
422                    return group_deleteChance;
423            }
424    
425            public void setGroup_deleteChance(int group_deleteChance) {
426                    this.group_deleteChance = group_deleteChance;
427            }
428    
429            public int getGroup_onEmptyDeleteChance() {
430                    return group_onEmptyDeleteChance;
431            }
432    
433            public void setGroup_onEmptyDeleteChance(int group_onEmptyDeleteChance) {
434                    this.group_onEmptyDeleteChance = group_onEmptyDeleteChance;
435            }
436    
437            public int getGroup_onEmptyReplaceChance() {
438                    return group_onEmptyReplaceChance;
439            }
440    
441            public void setGroup_onEmptyReplaceChance(int group_onEmptyReplaceChance) {
442                    this.group_onEmptyReplaceChance = group_onEmptyReplaceChance;
443            }
444    
445            public int getGroup_onLargeDontActChance() {
446                    return group_onLargeDontActChance;
447            }
448    
449            public void setGroup_onLargeDontActChance(int group_onLargeDontActChance) {
450                    this.group_onLargeDontActChance = group_onLargeDontActChance;
451            }
452    
453            public int getGroup_onLargeReplaceChance() {
454                    return group_onLargeReplaceChance;
455            }
456    
457            public void setGroup_onLargeReplaceChance(int group_onLargeReplaceChance) {
458                    this.group_onLargeReplaceChance = group_onLargeReplaceChance;
459            }
460    
461            public int getGroup_onLargeSplitChance() {
462                    return group_onLargeSplitChance;
463            }
464    
465            public void setGroup_onLargeSplitChance(int group_onLargeSplitChance) {
466                    this.group_onLargeSplitChance = group_onLargeSplitChance;
467            }
468    
469            public int getGroup_onLargeTriggerLength() {
470                    return group_onLargeTriggerLength;
471            }
472    
473            public void setGroup_onLargeTriggerLength(int group_onLargeTriggerLength) {
474                    this.group_onLargeTriggerLength = group_onLargeTriggerLength;
475            }
476    
477            public double getGroup_onPropertyReplaceProb() {
478                    return group_onPropertyReplaceProb;
479            }
480    
481            public void setGroup_onPropertyReplaceProb(double
482                                                                                               group_onPropertyReplaceProb) {
483                    this.group_onPropertyReplaceProb = group_onPropertyReplaceProb;
484            }
485    
486            public double getGroup_onPropertyTriggerPercent() {
487                    return group_onPropertyTriggerPercent;
488            }
489    
490            public void setGroup_onPropertyTriggerPercent(double
491                      group_onPropertyTriggerPercent) {
492                    this.group_onPropertyTriggerPercent = group_onPropertyTriggerPercent;
493            }
494    
495            public double getGroup_onSingleReplaceProb() {
496                    return group_onSingleReplaceProb;
497            }
498    
499            public void setGroup_onSingleReplaceProb(double group_onSingleReplaceProb) {
500                    this.group_onSingleReplaceProb = group_onSingleReplaceProb;
501            }
502    
503            public int getGroup_substractChance() {
504                    return group_substractChance;
505            }
506    
507            public void setGroup_substractChance(int group_substractChance) {
508                    this.group_substractChance = group_substractChance;
509            }
510    
511            public int getGroup_swapChance() {
512                    return group_swapChance;
513            }
514    
515            public void setGroup_swapChance(int group_swapChance) {
516                    this.group_swapChance = group_swapChance;
517            }
518    
519            public int getProperty_cloneChance() {
520                    return property_cloneChance;
521            }
522    
523            public void setProperty_cloneChance(int property_cloneChance) {
524                    this.property_cloneChance = property_cloneChance;
525            }
526    
527            public int getProperty_deleteChance() {
528                    return property_deleteChance;
529            }
530    
531            public void setProperty_deleteChance(int property_deleteChance) {
532                    this.property_deleteChance = property_deleteChance;
533            }
534    
535            public int getProperty_expandChance() {
536                    return property_expandChance;
537            }
538    
539            public void setProperty_expandChance(int property_expandChance) {
540                    this.property_expandChance = property_expandChance;
541            }
542    
543            public int getProperty_expandGroupSize() {
544                    return property_expandGroupSize;
545            }
546    
547            public void setProperty_expandGroupSize(int property_expandGroupSize) {
548                    this.property_expandGroupSize = property_expandGroupSize;
549            }
550    
551            public int getProperty_expandSamePropCount() {
552                    return property_expandSamePropCount;
553            }
554    
555            public void setProperty_expandSamePropCount(int
556                                                                                                    property_expandSamePropCount) {
557                    this.property_expandSamePropCount = property_expandSamePropCount;
558            }
559    
560            public int getProperty_mutateChance() {
561                    return property_mutateChance;
562            }
563    
564            public void setProperty_mutateChance(int property_mutateChance) {
565                    this.property_mutateChance = property_mutateChance;
566            }
567    
568            public SubstitutionScoringMatrix getScoringMatrix() {
569                    return scoringMatrix;
570            }
571    
572            public void setScoringMatrix(SubstitutionScoringMatrix scoringMatrix) {
573                    this.scoringMatrix = scoringMatrix;
574            }
575    
576            public int getSingleGap_cloneChance() {
577                    return singleGap_cloneChance;
578            }
579    
580            public void setSingleGap_cloneChance(int singleGap_cloneChance) {
581                    this.singleGap_cloneChance = singleGap_cloneChance;
582            }
583    
584            public int getSingleGap_deleteChance() {
585                    return singleGap_deleteChance;
586            }
587    
588            public void setSingleGap_deleteChance(int singleGap_deleteChance) {
589                    this.singleGap_deleteChance = singleGap_deleteChance;
590            }
591    
592            public int getSingleGap_expandChance() {
593                    return singleGap_expandChance;
594            }
595    
596            public void setSingleGap_expandChance(int singleGap_expandChance) {
597                    this.singleGap_expandChance = singleGap_expandChance;
598            }
599    
600            public int getSingleGap_expandGroupSize() {
601                    return singleGap_expandGroupSize;
602            }
603    
604            public void setSingleGap_expandGroupSize(int singleGap_expandGroupSize) {
605                    this.singleGap_expandGroupSize = singleGap_expandGroupSize;
606            }
607    
608            public int getSingleGap_mutateChance() {
609                    return singleGap_mutateChance;
610            }
611    
612            public void setSingleGap_mutateChance(int singleGap_mutateChance) {
613                    this.singleGap_mutateChance = singleGap_mutateChance;
614            }
615    
616    }