c2c2d890747a1755751c22e1990692d8bd9f897c
[jalview.git] / forester / java / src / org / forester / evoinference / TestPhylogenyReconstruction.java
1 // $Id:
2 // $
3 //
4 // FORESTER -- software libraries and applications
5 // for evolutionary biology research and applications.
6 //
7 // Copyright (C) 2008-2009 Christian M. Zmasek
8 // Copyright (C) 2008-2009 Burnham Institute for Medical Research
9 // All rights reserved
10 //
11 // This library is free software; you can redistribute it and/or
12 // modify it under the terms of the GNU Lesser General Public
13 // License as published by the Free Software Foundation; either
14 // version 2.1 of the License, or (at your option) any later version.
15 //
16 // This library is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 // Lesser General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public
22 // License along with this library; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 //
25 // Contact: phylosoft @ gmail . com
26 // WWW: https://sites.google.com/site/cmzmasek/home/software/forester
27
28 package org.forester.evoinference;
29
30 import java.io.File;
31 import java.io.FileInputStream;
32 import java.io.StringWriter;
33 import java.util.Date;
34 import java.util.List;
35
36 import org.forester.evoinference.distance.NeighborJoining;
37 import org.forester.evoinference.distance.PairwiseDistanceCalculator;
38 import org.forester.evoinference.matrix.character.BasicCharacterStateMatrix;
39 import org.forester.evoinference.matrix.character.CharacterStateMatrix;
40 import org.forester.evoinference.matrix.character.CharacterStateMatrix.BinaryStates;
41 import org.forester.evoinference.matrix.character.CharacterStateMatrix.GainLossStates;
42 import org.forester.evoinference.matrix.distance.BasicSymmetricalDistanceMatrix;
43 import org.forester.evoinference.matrix.distance.DistanceMatrix;
44 import org.forester.evoinference.parsimony.DolloParsimony;
45 import org.forester.evoinference.parsimony.FitchParsimony;
46 import org.forester.io.parsers.GeneralMsaParser;
47 import org.forester.io.parsers.SymmetricalDistanceMatrixParser;
48 import org.forester.io.parsers.nhx.NHXParser;
49 import org.forester.msa.Msa;
50 import org.forester.phylogeny.Phylogeny;
51 import org.forester.phylogeny.factories.ParserBasedPhylogenyFactory;
52 import org.forester.phylogeny.factories.PhylogenyFactory;
53 import org.forester.util.ForesterUtil;
54
55 public class TestPhylogenyReconstruction {
56
57     private final static double ZERO_DIFF = 1.0E-9;
58
59     public static boolean isEqual( final double a, final double b ) {
60         return ( ( Math.abs( a - b ) ) < ZERO_DIFF );
61     }
62
63     public static boolean isUnequal( final double a, final double b ) {
64         return !isEqual( a, b );
65     }
66
67     public static void main( final String[] args ) {
68         if ( testNeighborJoining() ) {
69             System.out.println( "OK." );
70         }
71         else {
72             System.out.println( "failed." );
73         }
74         //timeNeighborJoining();
75     }
76
77     public static boolean test( final File test_dir ) {
78         System.out.print( "  Basic symmetrical distance matrix: " );
79         if ( !testBasicSymmetricalDistanceMatrix() ) {
80             System.out.println( "failed." );
81             return false;
82         }
83         System.out.println( "OK." );
84         System.out.print( "  Basic character state matrix: " );
85         if ( !testBasicCharacterStateMatrix() ) {
86             System.out.println( "failed." );
87             return false;
88         }
89         System.out.println( "OK." );
90         System.out.print( "  Symmetrical distance matrix parser: " );
91         if ( !testSymmetricalDistanceMatrixParser() ) {
92             System.out.println( "failed." );
93             return false;
94         }
95         System.out.println( "OK." );
96         System.out.print( "  Distance Calculation: " );
97         if ( !testDistanceCalculationMethods( test_dir ) ) {
98             System.out.println( "failed." );
99             return false;
100         }
101         System.out.println( "OK." );
102         System.out.print( "  Neighbor Joining: " );
103         if ( !testNeighborJoining() ) {
104             System.out.println( "failed." );
105             return false;
106         }
107         System.out.println( "OK." );
108         System.out.print( "  Dollo Parsimony: " );
109         if ( !testDolloParsimony() ) {
110             System.out.println( "failed." );
111             return false;
112         }
113         System.out.println( "OK." );
114         System.out.print( "  Dollo Parsimony on non binary trees: " );
115         if ( !testDolloParsimonyOnNonBinaryTree() ) {
116             System.out.println( "failed." );
117             return false;
118         }
119         System.out.println( "OK." );
120         System.out.print( "  Fitch Parsimony: " );
121         if ( !testFitchParsimony() ) {
122             System.out.println( "failed." );
123             return false;
124         }
125         System.out.println( "OK." );
126         return true;
127     }
128
129     private static boolean testDistanceCalculationMethods( final File test_dir ) {
130         try {
131             final Msa msa0 = GeneralMsaParser.parse( new FileInputStream( test_dir + ForesterUtil.FILE_SEPARATOR
132                     + "bcl.aln" ) );
133             final BasicSymmetricalDistanceMatrix pwd0 = PairwiseDistanceCalculator.calcKimuraDistances( msa0 );
134             if ( pwd0.getSize() != 120 ) {
135                 return false;
136             }
137             for( int i = 0; i < pwd0.getSize(); ++i ) {
138                 if ( !isEqual( pwd0.getValue( i, i ), 0.0 ) ) {
139                     return false;
140                 }
141             }
142         }
143         catch ( final Exception e ) {
144             e.printStackTrace( System.out );
145             return false;
146         }
147         return true;
148     }
149
150     private static boolean testBasicCharacterStateMatrix() {
151         try {
152             final CharacterStateMatrix<String> matrix_0 = new BasicCharacterStateMatrix<String>( 4, 8 );
153             final CharacterStateMatrix<String> matrix_00 = new BasicCharacterStateMatrix<String>( 4, 8 );
154             matrix_0.setIdentifier( 0, "A" );
155             matrix_0.setIdentifier( 1, "B" );
156             matrix_0.setIdentifier( 2, "C" );
157             matrix_0.setIdentifier( 3, "D" );
158             matrix_0.setCharacter( 0, "0" );
159             matrix_0.setCharacter( 1, "1" );
160             matrix_0.setCharacter( 2, "2" );
161             matrix_0.setCharacter( 3, "3" );
162             matrix_0.setCharacter( 4, "4" );
163             matrix_0.setCharacter( 5, "5" );
164             matrix_0.setCharacter( 6, "6" );
165             matrix_0.setCharacter( 7, "7" );
166             matrix_00.setIdentifier( 0, "A" );
167             matrix_00.setIdentifier( 1, "B" );
168             matrix_00.setIdentifier( 2, "C" );
169             matrix_00.setIdentifier( 3, "D" );
170             matrix_00.setCharacter( 3, "3" );
171             matrix_00.setCharacter( 4, "4" );
172             if ( !matrix_0.getCharacter( 1 ).equals( "1" ) ) {
173                 return false;
174             }
175             if ( !matrix_0.getIdentifier( 0 ).equals( "A" ) ) {
176                 return false;
177             }
178             matrix_0.setState( 0, 0, "00" );
179             matrix_00.setState( 0, 0, "00" );
180             if ( !matrix_0.getState( 0, 0 ).equals( "00" ) ) {
181                 return false;
182             }
183             matrix_0.setState( 0, 1, "01" );
184             matrix_00.setState( 0, 1, "01" );
185             if ( !matrix_0.getState( 0, 1 ).equals( "01" ) ) {
186                 return false;
187             }
188             matrix_0.setState( 1, 1, "11" );
189             matrix_00.setState( 1, 1, "11" );
190             if ( !matrix_0.getState( 1, 1 ).equals( "11" ) ) {
191                 return false;
192             }
193             matrix_0.setState( 1, 0, "10" );
194             matrix_00.setState( 1, 0, "10" );
195             if ( !matrix_0.getState( 1, 0 ).equals( "10" ) ) {
196                 return false;
197             }
198             matrix_0.setState( 1, 2, "12" );
199             matrix_00.setState( 1, 2, "12" );
200             if ( !matrix_0.getState( 1, 2 ).equals( "12" ) ) {
201                 return false;
202             }
203             matrix_0.setState( 3, 7, "37" );
204             matrix_00.setState( 3, 7, "37" );
205             if ( !matrix_0.getState( 3, 7 ).equals( "37" ) ) {
206                 return false;
207             }
208             matrix_0.setState( 2, 6, "26" );
209             matrix_00.setState( 2, 6, "26" );
210             if ( !matrix_0.getState( 2, 6 ).equals( "26" ) ) {
211                 return false;
212             }
213             matrix_0.setState( "D", "3", "33" );
214             matrix_00.setState( "D", "3", "33" );
215             if ( !matrix_0.getState( 3, 3 ).equals( "33" ) ) {
216                 return false;
217             }
218             if ( !matrix_0.getState( "D", "3" ).equals( "33" ) ) {
219                 return false;
220             }
221             matrix_0.setState( "C", "4", "24" );
222             matrix_00.setState( "C", "4", "24" );
223             if ( !matrix_0.getState( 2, 4 ).equals( "24" ) ) {
224                 return false;
225             }
226             if ( !matrix_0.getState( "C", "4" ).equals( "24" ) ) {
227                 return false;
228             }
229             if ( matrix_0.isEmpty() ) {
230                 return false;
231             }
232             if ( matrix_0.getNumberOfIdentifiers() != 4 ) {
233                 return false;
234             }
235             if ( matrix_0.getNumberOfCharacters() != 8 ) {
236                 return false;
237             }
238             if ( !matrix_0.equals( matrix_0 ) ) {
239                 return false;
240             }
241             if ( !matrix_0.equals( matrix_00 ) ) {
242                 return false;
243             }
244             matrix_00.setState( "C", "4", "123" );
245             if ( matrix_0.equals( matrix_00 ) ) {
246                 return false;
247             }
248             final Integer[][] ints = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
249             final CharacterStateMatrix<Integer> matrix_000 = new BasicCharacterStateMatrix<Integer>( ints );
250             matrix_000.toString();
251             if ( matrix_000.getNumberOfCharacters() != 4 ) {
252                 return false;
253             }
254             if ( matrix_000.getNumberOfIdentifiers() != 3 ) {
255                 return false;
256             }
257             if ( matrix_000.getState( 0, 1 ) != 2 ) {
258                 return false;
259             }
260             if ( matrix_000.getState( 2, 3 ) != 12 ) {
261                 return false;
262             }
263             final Integer[][] ints0 = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
264             final CharacterStateMatrix<Integer> matrix_0000 = new BasicCharacterStateMatrix<Integer>( ints0 );
265             if ( !matrix_000.equals( matrix_0000 ) ) {
266                 return false;
267             }
268             final Integer[][] ints00 = { { 1, 2, 3, -4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
269             final CharacterStateMatrix<Integer> matrix_00000 = new BasicCharacterStateMatrix<Integer>( ints00 );
270             if ( matrix_000.equals( matrix_00000 ) ) {
271                 return false;
272             }
273             final CharacterStateMatrix<String> clone0 = matrix_0.copy();
274             final CharacterStateMatrix<String> clone00 = matrix_00.copy();
275             if ( !clone0.equals( matrix_0 ) ) {
276                 return false;
277             }
278             if ( !clone00.equals( matrix_00 ) ) {
279                 return false;
280             }
281             if ( clone00.equals( clone0 ) ) {
282                 return false;
283             }
284             final CharacterStateMatrix<String> pivot0 = matrix_0.pivot();
285             final CharacterStateMatrix<String> pivot00 = matrix_00.pivot();
286             if ( !pivot0.getState( 1, 0 ).equals( "01" ) ) {
287                 return false;
288             }
289             if ( !pivot0.getState( 6, 2 ).equals( "26" ) ) {
290                 return false;
291             }
292             if ( !matrix_0.getState( 2, 6 ).equals( "26" ) ) {
293                 return false;
294             }
295             final CharacterStateMatrix<String> pivotpivot00 = pivot00.pivot();
296             if ( !pivotpivot00.equals( matrix_00 ) ) {
297                 return false;
298             }
299             final CharacterStateMatrix<BinaryStates> nex = new BasicCharacterStateMatrix<BinaryStates>( 4, 3 );
300             nex.setIdentifier( 0, "amphioxus" );
301             nex.setIdentifier( 1, "sponge" );
302             nex.setIdentifier( 2, "sea_anemone" );
303             nex.setIdentifier( 3, "cobra" );
304             nex.setCharacter( 0, "notch" );
305             nex.setCharacter( 1, "homeobox" );
306             nex.setCharacter( 2, "wnt" );
307             nex.setState( 0, 0, BinaryStates.ABSENT );
308             nex.setState( 0, 1, BinaryStates.ABSENT );
309             nex.setState( 0, 2, BinaryStates.ABSENT );
310             nex.setState( 1, 0, BinaryStates.PRESENT );
311             nex.setState( 1, 1, BinaryStates.PRESENT );
312             nex.setState( 1, 2, BinaryStates.ABSENT );
313             nex.setState( 2, 0, BinaryStates.PRESENT );
314             nex.setState( 2, 1, BinaryStates.PRESENT );
315             nex.setState( 2, 2, BinaryStates.PRESENT );
316             nex.setState( 3, 0, BinaryStates.PRESENT );
317             nex.setState( 3, 1, BinaryStates.ABSENT );
318             nex.setState( 3, 2, BinaryStates.ABSENT );
319             StringWriter w = new StringWriter();
320             nex.toWriter( w, CharacterStateMatrix.Format.NEXUS_BINARY );
321             //System.out.println( w.getBuffer().toString() );
322             w = new StringWriter();
323             nex.pivot().toWriter( w, CharacterStateMatrix.Format.NEXUS_BINARY );
324             //System.out.println( w.getBuffer().toString() );
325         }
326         catch ( final Exception e ) {
327             e.printStackTrace( System.out );
328             return false;
329         }
330         return true;
331     }
332
333     private static boolean testBasicSymmetricalDistanceMatrix() {
334         try {
335             final DistanceMatrix matrix_0 = new BasicSymmetricalDistanceMatrix( 4 );
336             matrix_0.setIdentifier( 0, "A" );
337             matrix_0.setIdentifier( 1, "B" );
338             matrix_0.setIdentifier( 2, "C" );
339             matrix_0.setIdentifier( 3, "0123456789012" );
340             matrix_0.setValue( 1, 0, 0.00001 );
341             matrix_0.setValue( 0, 2, 0.0000009 );
342             matrix_0.setValue( 3, 0, 3.0 );
343             matrix_0.setValue( 1, 2, 4.0 );
344             matrix_0.setValue( 3, 1, 5.0 );
345             matrix_0.setValue( 2, 3, 6.0 );
346             if ( !matrix_0.getIdentifier( 0 ).equals( "A" ) ) {
347                 return false;
348             }
349             if ( !matrix_0.getIdentifier( 1 ).equals( "B" ) ) {
350                 return false;
351             }
352             if ( !matrix_0.getIdentifier( 2 ).equals( "C" ) ) {
353                 return false;
354             }
355             if ( !matrix_0.getIdentifier( 3 ).equals( "0123456789012" ) ) {
356                 return false;
357             }
358             if ( matrix_0.getSize() != 4 ) {
359                 return false;
360             }
361             if ( !isEqual( matrix_0.getValue( 0, 0 ), 0.0 ) ) {
362                 return false;
363             }
364             if ( !isEqual( matrix_0.getValue( 3, 3 ), 0.0 ) ) {
365                 return false;
366             }
367             if ( !isEqual( matrix_0.getValue( 0, 1 ), 0.00001 ) ) {
368                 return false;
369             }
370             if ( !isEqual( matrix_0.getValue( 0, 2 ), 0.0000009 ) ) {
371                 return false;
372             }
373             if ( !isEqual( matrix_0.getValue( 0, 3 ), 3 ) ) {
374                 return false;
375             }
376             if ( !isEqual( matrix_0.getValue( 1, 0 ), 0.00001 ) ) {
377                 return false;
378             }
379             if ( !isEqual( matrix_0.getValue( 1, 2 ), 4 ) ) {
380                 return false;
381             }
382             if ( !isEqual( matrix_0.getValue( 1, 3 ), 5 ) ) {
383                 return false;
384             }
385             if ( !isEqual( matrix_0.getValue( 2, 0 ), 0.0000009 ) ) {
386                 return false;
387             }
388             if ( !isEqual( matrix_0.getValue( 2, 1 ), 4 ) ) {
389                 return false;
390             }
391             if ( !isEqual( matrix_0.getValue( 2, 3 ), 6 ) ) {
392                 return false;
393             }
394             if ( !isEqual( matrix_0.getValue( 3, 0 ), 3 ) ) {
395                 return false;
396             }
397             if ( !isEqual( matrix_0.getValue( 3, 1 ), 5 ) ) {
398                 return false;
399             }
400             if ( !isEqual( matrix_0.getValue( 3, 2 ), 6 ) ) {
401                 return false;
402             }
403             final StringBuffer matrix_0_phylip = new StringBuffer();
404             matrix_0_phylip.append( "    4" );
405             matrix_0_phylip.append( ForesterUtil.LINE_SEPARATOR );
406             matrix_0_phylip.append( "A           0.000000  0.000010  0.000001  3.000000" );
407             matrix_0_phylip.append( ForesterUtil.LINE_SEPARATOR );
408             matrix_0_phylip.append( "B           0.000010  0.000000  4.000000  5.000000" );
409             matrix_0_phylip.append( ForesterUtil.LINE_SEPARATOR );
410             matrix_0_phylip.append( "C           0.000001  4.000000  0.000000  6.000000" );
411             matrix_0_phylip.append( ForesterUtil.LINE_SEPARATOR );
412             matrix_0_phylip.append( "0123456789  3.000000  5.000000  6.000000  0.000000" );
413             if ( !matrix_0_phylip.toString()
414                     .equals( matrix_0.toStringBuffer( DistanceMatrix.Format.PHYLIP ).toString() ) ) {
415                 return false;
416             }
417         }
418         catch ( final Exception e ) {
419             e.printStackTrace( System.out );
420             return false;
421         }
422         return true;
423     }
424
425     private static boolean testDolloParsimony() {
426         try {
427             final BinaryStates PRESENT = BinaryStates.PRESENT;
428             final BinaryStates ABSENT = BinaryStates.ABSENT;
429             final GainLossStates UNCHANGED_PRESENT = GainLossStates.UNCHANGED_PRESENT;
430             final DolloParsimony dollo1 = DolloParsimony.createInstance();
431             final PhylogenyFactory factory1 = ParserBasedPhylogenyFactory.getInstance();
432             final String p1_str = "((((((a,b)ab,c)ac,d)ad,(e,f)ef)af,(g,h)gh)ah,i)r";
433             final Phylogeny p1 = factory1.create( p1_str, new NHXParser() )[ 0 ];
434             CharacterStateMatrix<CharacterStateMatrix.BinaryStates> m1 = new BasicCharacterStateMatrix<CharacterStateMatrix.BinaryStates>( 9,
435                                                                                                                                            1 );
436             m1.setIdentifier( 0, "a" );
437             m1.setIdentifier( 1, "b" );
438             m1.setIdentifier( 2, "c" );
439             m1.setIdentifier( 3, "d" );
440             m1.setIdentifier( 4, "e" );
441             m1.setIdentifier( 5, "f" );
442             m1.setIdentifier( 6, "g" );
443             m1.setIdentifier( 7, "h" );
444             m1.setIdentifier( 8, "i" );
445             m1.setCharacter( 0, "0" );
446             m1.setState( "a", "0", PRESENT );
447             m1.setState( "b", "0", ABSENT );
448             m1.setState( "c", "0", PRESENT );
449             m1.setState( "d", "0", ABSENT );
450             m1.setState( "e", "0", ABSENT );
451             m1.setState( "f", "0", ABSENT );
452             m1.setState( "g", "0", ABSENT );
453             m1.setState( "h", "0", ABSENT );
454             m1.setState( "i", "0", ABSENT );
455             dollo1.execute( p1, m1 );
456             if ( dollo1.getTotalGains() != 1 ) {
457                 return false;
458             }
459             if ( dollo1.getTotalLosses() != 1 ) {
460                 return false;
461             }
462             if ( dollo1.getTotalUnchanged() != 15 ) {
463                 return false;
464             }
465             m1.setState( "b", "0", PRESENT );
466             dollo1.execute( p1, m1 );
467             if ( dollo1.getTotalGains() != 1 ) {
468                 return false;
469             }
470             if ( dollo1.getTotalLosses() != 0 ) {
471                 return false;
472             }
473             if ( dollo1.getTotalUnchanged() != 16 ) {
474                 return false;
475             }
476             m1.setState( "b", "0", ABSENT );
477             m1.setState( "e", "0", PRESENT );
478             dollo1.execute( p1, m1 );
479             if ( dollo1.getTotalGains() != 1 ) {
480                 return false;
481             }
482             if ( dollo1.getTotalLosses() != 3 ) {
483                 return false;
484             }
485             if ( dollo1.getTotalUnchanged() != 13 ) {
486                 return false;
487             }
488             m1.setState( "a", "0", ABSENT );
489             m1.setState( "c", "0", ABSENT );
490             m1.setState( "g", "0", PRESENT );
491             dollo1.setReturnInternalStates( true );
492             dollo1.setReturnGainLossMatrix( true );
493             dollo1.execute( p1, m1 );
494             if ( dollo1.getTotalGains() != 1 ) {
495                 return false;
496             }
497             if ( dollo1.getTotalLosses() != 3 ) {
498                 return false;
499             }
500             if ( dollo1.getTotalUnchanged() != 13 ) {
501                 return false;
502             }
503             final DolloParsimony dollo2 = DolloParsimony.createInstance();
504             final PhylogenyFactory factory2 = ParserBasedPhylogenyFactory.getInstance();
505             final String p2_str = "((((((a,b)ab,c)ac,d)ad,(e,f)ef)af,(g,h,i)gi)ai,((j,k,l)jl,(m,n,o)mo,(p,q,r)pr)jr)root";
506             final Phylogeny p2 = factory2.create( p2_str, new NHXParser() )[ 0 ];
507             final CharacterStateMatrix<CharacterStateMatrix.BinaryStates> m2 = new BasicCharacterStateMatrix<CharacterStateMatrix.BinaryStates>( 18,
508                                                                                                                                                  4 );
509             m2.setIdentifier( 0, "a" );
510             m2.setIdentifier( 1, "b" );
511             m2.setIdentifier( 2, "c" );
512             m2.setIdentifier( 3, "d" );
513             m2.setIdentifier( 4, "e" );
514             m2.setIdentifier( 5, "f" );
515             m2.setIdentifier( 6, "g" );
516             m2.setIdentifier( 7, "h" );
517             m2.setIdentifier( 8, "i" );
518             m2.setIdentifier( 9, "j" );
519             m2.setIdentifier( 10, "k" );
520             m2.setIdentifier( 11, "l" );
521             m2.setIdentifier( 12, "m" );
522             m2.setIdentifier( 13, "n" );
523             m2.setIdentifier( 14, "o" );
524             m2.setIdentifier( 15, "p" );
525             m2.setIdentifier( 16, "q" );
526             m2.setIdentifier( 17, "r" );
527             m2.setCharacter( 0, "0" );
528             m2.setCharacter( 1, "1" );
529             m2.setCharacter( 2, "2" );
530             m2.setCharacter( 3, "3" );
531             m2.setState( "a", "0", PRESENT );
532             m2.setState( "b", "0", ABSENT );
533             m2.setState( "c", "0", PRESENT );
534             m2.setState( "d", "0", ABSENT );
535             m2.setState( "e", "0", ABSENT );
536             m2.setState( "f", "0", ABSENT );
537             m2.setState( "g", "0", ABSENT );
538             m2.setState( "h", "0", ABSENT );
539             m2.setState( "i", "0", ABSENT );
540             m2.setState( "j", "0", ABSENT );
541             m2.setState( "k", "0", ABSENT );
542             m2.setState( "l", "0", ABSENT );
543             m2.setState( "m", "0", ABSENT );
544             m2.setState( "n", "0", ABSENT );
545             m2.setState( "o", "0", ABSENT );
546             m2.setState( "p", "0", ABSENT );
547             m2.setState( "q", "0", ABSENT );
548             m2.setState( "r", "0", ABSENT );
549             m2.setState( "a", "1", PRESENT );
550             m2.setState( "b", "1", ABSENT );
551             m2.setState( "c", "1", PRESENT );
552             m2.setState( "d", "1", ABSENT );
553             m2.setState( "e", "1", ABSENT );
554             m2.setState( "f", "1", ABSENT );
555             m2.setState( "g", "1", PRESENT );
556             m2.setState( "h", "1", ABSENT );
557             m2.setState( "i", "1", ABSENT );
558             m2.setState( "j", "1", PRESENT );
559             m2.setState( "k", "1", ABSENT );
560             m2.setState( "l", "1", ABSENT );
561             m2.setState( "m", "1", PRESENT );
562             m2.setState( "n", "1", ABSENT );
563             m2.setState( "o", "1", ABSENT );
564             m2.setState( "p", "1", ABSENT );
565             m2.setState( "q", "1", ABSENT );
566             m2.setState( "r", "1", ABSENT );
567             m2.setState( "a", "2", ABSENT );
568             m2.setState( "b", "2", ABSENT );
569             m2.setState( "c", "2", ABSENT );
570             m2.setState( "d", "2", ABSENT );
571             m2.setState( "e", "2", ABSENT );
572             m2.setState( "f", "2", ABSENT );
573             m2.setState( "g", "2", ABSENT );
574             m2.setState( "h", "2", ABSENT );
575             m2.setState( "i", "2", ABSENT );
576             m2.setState( "j", "2", PRESENT );
577             m2.setState( "k", "2", ABSENT );
578             m2.setState( "l", "2", ABSENT );
579             m2.setState( "m", "2", PRESENT );
580             m2.setState( "n", "2", ABSENT );
581             m2.setState( "o", "2", ABSENT );
582             m2.setState( "p", "2", PRESENT );
583             m2.setState( "q", "2", ABSENT );
584             m2.setState( "r", "2", ABSENT );
585             m2.setState( "a", "3", ABSENT );
586             m2.setState( "b", "3", ABSENT );
587             m2.setState( "c", "3", PRESENT );
588             m2.setState( "d", "3", ABSENT );
589             m2.setState( "e", "3", ABSENT );
590             m2.setState( "f", "3", ABSENT );
591             m2.setState( "g", "3", PRESENT );
592             m2.setState( "h", "3", ABSENT );
593             m2.setState( "i", "3", ABSENT );
594             m2.setState( "j", "3", ABSENT );
595             m2.setState( "k", "3", ABSENT );
596             m2.setState( "l", "3", ABSENT );
597             m2.setState( "m", "3", ABSENT );
598             m2.setState( "n", "3", ABSENT );
599             m2.setState( "o", "3", ABSENT );
600             m2.setState( "p", "3", ABSENT );
601             m2.setState( "q", "3", ABSENT );
602             m2.setState( "r", "3", ABSENT );
603             dollo2.setReturnInternalStates( true );
604             dollo2.setReturnGainLossMatrix( true );
605             dollo2.execute( p2, m2 );
606             final CharacterStateMatrix<BinaryStates> i_m = dollo2.getInternalStatesMatrix();
607             final CharacterStateMatrix<GainLossStates> gl_m = dollo2.getGainLossMatrix();
608             if ( dollo2.getTotalGains() != 3 ) {
609                 return false;
610             }
611             if ( dollo2.getTotalLosses() != 22 ) {
612                 return false;
613             }
614             if ( dollo2.getTotalUnchanged() != 95 ) {
615                 return false;
616             }
617             if ( i_m.getState( "ab", "0" ) != PRESENT ) {
618                 return false;
619             }
620             if ( i_m.getState( "ac", "0" ) != PRESENT ) {
621                 return false;
622             }
623             if ( i_m.getState( "ad", "0" ) != ABSENT ) {
624                 return false;
625             }
626             if ( i_m.getState( "af", "0" ) != ABSENT ) {
627                 return false;
628             }
629             if ( i_m.getState( "ef", "0" ) != ABSENT ) {
630                 return false;
631             }
632             if ( i_m.getState( "ai", "0" ) != ABSENT ) {
633                 return false;
634             }
635             if ( i_m.getState( "gi", "0" ) != ABSENT ) {
636                 return false;
637             }
638             if ( i_m.getState( "jl", "0" ) != ABSENT ) {
639                 return false;
640             }
641             if ( i_m.getState( "mo", "0" ) != ABSENT ) {
642                 return false;
643             }
644             if ( i_m.getState( "pr", "0" ) != ABSENT ) {
645                 return false;
646             }
647             if ( i_m.getState( "jr", "0" ) != ABSENT ) {
648                 return false;
649             }
650             if ( i_m.getState( "root", "0" ) != ABSENT ) {
651                 return false;
652             }
653             if ( i_m.getState( "ab", "1" ) != PRESENT ) {
654                 return false;
655             }
656             if ( i_m.getState( "ac", "1" ) != PRESENT ) {
657                 return false;
658             }
659             if ( i_m.getState( "ad", "1" ) != PRESENT ) {
660                 return false;
661             }
662             if ( i_m.getState( "af", "1" ) != PRESENT ) {
663                 return false;
664             }
665             if ( i_m.getState( "ef", "1" ) != ABSENT ) {
666                 return false;
667             }
668             if ( i_m.getState( "ai", "1" ) != PRESENT ) {
669                 return false;
670             }
671             if ( i_m.getState( "gi", "1" ) != PRESENT ) {
672                 return false;
673             }
674             if ( i_m.getState( "jl", "1" ) != PRESENT ) {
675                 return false;
676             }
677             if ( i_m.getState( "mo", "1" ) != PRESENT ) {
678                 return false;
679             }
680             if ( i_m.getState( "pr", "1" ) != ABSENT ) {
681                 return false;
682             }
683             if ( i_m.getState( "jr", "1" ) != PRESENT ) {
684                 return false;
685             }
686             if ( i_m.getState( "root", "1" ) != PRESENT ) {
687                 return false;
688             }
689             if ( i_m.getState( "ab", "2" ) != ABSENT ) {
690                 return false;
691             }
692             if ( i_m.getState( "ac", "2" ) != ABSENT ) {
693                 return false;
694             }
695             if ( i_m.getState( "ad", "2" ) != ABSENT ) {
696                 return false;
697             }
698             if ( i_m.getState( "af", "2" ) != ABSENT ) {
699                 return false;
700             }
701             if ( i_m.getState( "ef", "2" ) != ABSENT ) {
702                 return false;
703             }
704             if ( i_m.getState( "ai", "2" ) != ABSENT ) {
705                 return false;
706             }
707             if ( i_m.getState( "gi", "2" ) != ABSENT ) {
708                 return false;
709             }
710             if ( i_m.getState( "jl", "2" ) != PRESENT ) {
711                 return false;
712             }
713             if ( i_m.getState( "mo", "2" ) != PRESENT ) {
714                 return false;
715             }
716             if ( i_m.getState( "pr", "2" ) != PRESENT ) {
717                 return false;
718             }
719             if ( i_m.getState( "jr", "2" ) != PRESENT ) {
720                 return false;
721             }
722             if ( i_m.getState( "root", "2" ) != ABSENT ) {
723                 return false;
724             }
725             if ( i_m.getState( "ab", "3" ) != ABSENT ) {
726                 return false;
727             }
728             if ( i_m.getState( "ac", "3" ) != PRESENT ) {
729                 return false;
730             }
731             if ( i_m.getState( "ad", "3" ) != PRESENT ) {
732                 return false;
733             }
734             if ( i_m.getState( "af", "3" ) != PRESENT ) {
735                 return false;
736             }
737             if ( i_m.getState( "ef", "3" ) != ABSENT ) {
738                 return false;
739             }
740             if ( i_m.getState( "ai", "3" ) != PRESENT ) {
741                 return false;
742             }
743             if ( i_m.getState( "gi", "3" ) != PRESENT ) {
744                 return false;
745             }
746             if ( i_m.getState( "jl", "3" ) != ABSENT ) {
747                 return false;
748             }
749             if ( i_m.getState( "mo", "3" ) != ABSENT ) {
750                 return false;
751             }
752             if ( i_m.getState( "pr", "3" ) != ABSENT ) {
753                 return false;
754             }
755             if ( i_m.getState( "jr", "3" ) != ABSENT ) {
756                 return false;
757             }
758             if ( i_m.getState( "root", "3" ) != ABSENT ) {
759                 return false;
760             }
761             if ( gl_m.getState( "a", "0" ) != UNCHANGED_PRESENT ) {
762                 return false;
763             }
764             final DolloParsimony dollo9 = DolloParsimony.createInstance();
765             final PhylogenyFactory factory9 = ParserBasedPhylogenyFactory.getInstance();
766             final String p9_str = "((((((a,b)ab,c)ac,d)ad,(e,f)ef)af,(g,h)gh)ah,i)r";
767             final Phylogeny p9 = factory9.create( p9_str, new NHXParser() )[ 0 ];
768             m1 = new BasicCharacterStateMatrix<CharacterStateMatrix.BinaryStates>( 9, 3 );
769             m1.setIdentifier( 0, "a" );
770             m1.setIdentifier( 1, "b" );
771             m1.setIdentifier( 2, "c" );
772             m1.setIdentifier( 3, "d" );
773             m1.setIdentifier( 4, "e" );
774             m1.setIdentifier( 5, "f" );
775             m1.setIdentifier( 6, "g" );
776             m1.setIdentifier( 7, "h" );
777             m1.setIdentifier( 8, "i" );
778             m1.setState( 0, 0, PRESENT );
779             m1.setState( 1, 0, ABSENT );
780             m1.setState( 2, 0, PRESENT );
781             m1.setState( 3, 0, ABSENT );
782             m1.setState( 4, 0, ABSENT );
783             m1.setState( 5, 0, ABSENT );
784             m1.setState( 6, 0, ABSENT );
785             m1.setState( 7, 0, ABSENT );
786             m1.setState( 8, 0, ABSENT );
787             m1.setState( 0, 1, PRESENT );
788             m1.setState( 1, 1, PRESENT );
789             m1.setState( 2, 1, PRESENT );
790             m1.setState( 3, 1, PRESENT );
791             m1.setState( 4, 1, ABSENT );
792             m1.setState( 5, 1, ABSENT );
793             m1.setState( 6, 1, ABSENT );
794             m1.setState( 7, 1, ABSENT );
795             m1.setState( 8, 1, ABSENT );
796             m1.setState( 0, 2, PRESENT );
797             m1.setState( 1, 2, ABSENT );
798             m1.setState( 2, 2, ABSENT );
799             m1.setState( 3, 2, ABSENT );
800             m1.setState( 4, 2, ABSENT );
801             m1.setState( 5, 2, ABSENT );
802             m1.setState( 6, 2, ABSENT );
803             m1.setState( 7, 2, PRESENT );
804             m1.setState( 8, 2, ABSENT );
805             dollo9.execute( p9, m1 );
806             if ( dollo9.getTotalGains() != 3 ) {
807                 return false;
808             }
809             if ( dollo9.getTotalLosses() != 6 ) {
810                 return false;
811             }
812             final DolloParsimony dollo10 = DolloParsimony.createInstance();
813             final PhylogenyFactory factory10 = ParserBasedPhylogenyFactory.getInstance();
814             final String p10_str = "((((((a,b)ab,c)ac,d)ad,(e,f)ef)af,(g,h)gh)ah,i)r";
815             final Phylogeny p10 = factory10.create( p10_str, new NHXParser() )[ 0 ];
816             final CharacterStateMatrix<CharacterStateMatrix.BinaryStates> m10 = new BasicCharacterStateMatrix<CharacterStateMatrix.BinaryStates>( 9,
817                                                                                                                                                   1 );
818             m10.setIdentifier( 0, "a" );
819             m10.setIdentifier( 1, "b" );
820             m10.setIdentifier( 2, "c" );
821             m10.setIdentifier( 3, "d" );
822             m10.setIdentifier( 4, "e" );
823             m10.setIdentifier( 5, "f" );
824             m10.setIdentifier( 6, "g" );
825             m10.setIdentifier( 7, "h" );
826             m10.setIdentifier( 8, "i" );
827             m10.setState( 0, 0, PRESENT );
828             m10.setState( 1, 0, ABSENT );
829             m10.setState( 2, 0, PRESENT );
830             m10.setState( 3, 0, ABSENT );
831             m10.setState( 4, 0, ABSENT );
832             m10.setState( 5, 0, ABSENT );
833             m10.setState( 6, 0, ABSENT );
834             m10.setState( 7, 0, ABSENT );
835             m10.setState( 8, 0, ABSENT );
836             dollo10.execute( p10, m10 );
837             if ( dollo10.getTotalGains() != 1 ) {
838                 return false;
839             }
840             if ( dollo10.getTotalLosses() != 1 ) {
841                 return false;
842             }
843         }
844         catch ( final Exception e ) {
845             e.printStackTrace( System.out );
846             return false;
847         }
848         return true;
849     }
850
851     private static boolean testDolloParsimonyOnNonBinaryTree() {
852         try {
853             final BinaryStates PRESENT = BinaryStates.PRESENT;
854             final BinaryStates ABSENT = BinaryStates.ABSENT;
855             final DolloParsimony dollo1 = DolloParsimony.createInstance();
856             final PhylogenyFactory factory1 = ParserBasedPhylogenyFactory.getInstance();
857             final String p1_str = "((((((a,b,y)aby,c)ac,d)ad,(e,f)ef)af,(g,h)gh)ah,i)r";
858             final Phylogeny p1 = factory1.create( p1_str, new NHXParser() )[ 0 ];
859             final CharacterStateMatrix<CharacterStateMatrix.BinaryStates> m1 = new BasicCharacterStateMatrix<CharacterStateMatrix.BinaryStates>( 10,
860                                                                                                                                                  1 );
861             m1.setIdentifier( 0, "a" );
862             m1.setIdentifier( 1, "b" );
863             m1.setIdentifier( 2, "y" );
864             m1.setIdentifier( 3, "c" );
865             m1.setIdentifier( 4, "d" );
866             m1.setIdentifier( 5, "e" );
867             m1.setIdentifier( 6, "f" );
868             m1.setIdentifier( 7, "g" );
869             m1.setIdentifier( 8, "h" );
870             m1.setIdentifier( 9, "i" );
871             m1.setCharacter( 0, "0" );
872             m1.setState( "a", "0", PRESENT );
873             m1.setState( "b", "0", ABSENT );
874             m1.setState( "y", "0", PRESENT );
875             m1.setState( "c", "0", PRESENT );
876             m1.setState( "d", "0", ABSENT );
877             m1.setState( "e", "0", ABSENT );
878             m1.setState( "f", "0", ABSENT );
879             m1.setState( "g", "0", ABSENT );
880             m1.setState( "h", "0", ABSENT );
881             m1.setState( "i", "0", ABSENT );
882             dollo1.execute( p1, m1 );
883             if ( dollo1.getTotalGains() != 1 ) {
884                 return false;
885             }
886             if ( dollo1.getTotalLosses() != 1 ) {
887                 return false;
888             }
889             if ( dollo1.getTotalUnchanged() != 16 ) {
890                 return false;
891             }
892             m1.setState( "b", "0", PRESENT );
893             dollo1.execute( p1, m1 );
894             if ( dollo1.getTotalGains() != 1 ) {
895                 return false;
896             }
897             if ( dollo1.getTotalLosses() != 0 ) {
898                 return false;
899             }
900             if ( dollo1.getTotalUnchanged() != 17 ) {
901                 return false;
902             }
903             m1.setState( "a", "0", ABSENT );
904             m1.setState( "b", "0", ABSENT );
905             dollo1.execute( p1, m1 );
906             if ( dollo1.getTotalGains() != 1 ) {
907                 return false;
908             }
909             if ( dollo1.getTotalLosses() != 2 ) {
910                 return false;
911             }
912             if ( dollo1.getTotalUnchanged() != 15 ) {
913                 return false;
914             }
915             m1.setState( "y", "0", ABSENT );
916             dollo1.execute( p1, m1 );
917             if ( dollo1.getTotalGains() != 1 ) {
918                 return false;
919             }
920             if ( dollo1.getTotalLosses() != 0 ) {
921                 return false;
922             }
923             if ( dollo1.getTotalUnchanged() != 17 ) {
924                 return false;
925             }
926             final DolloParsimony dollo2 = DolloParsimony.createInstance();
927             final PhylogenyFactory factory2 = ParserBasedPhylogenyFactory.getInstance();
928             final String p2_str = "((((((a,b,y)aby,c,d)cad,e,f)af,(g,h)gh)ah,i))r";
929             final Phylogeny p2 = factory2.create( p2_str, new NHXParser() )[ 0 ];
930             final CharacterStateMatrix<CharacterStateMatrix.BinaryStates> m2 = new BasicCharacterStateMatrix<CharacterStateMatrix.BinaryStates>( 10,
931                                                                                                                                                  1 );
932             m2.setIdentifier( 0, "a" );
933             m2.setIdentifier( 1, "b" );
934             m2.setIdentifier( 2, "y" );
935             m2.setIdentifier( 3, "c" );
936             m2.setIdentifier( 4, "d" );
937             m2.setIdentifier( 5, "e" );
938             m2.setIdentifier( 6, "f" );
939             m2.setIdentifier( 7, "g" );
940             m2.setIdentifier( 8, "h" );
941             m2.setIdentifier( 9, "i" );
942             m2.setCharacter( 0, "0" );
943             m2.setState( "a", "0", PRESENT );
944             m2.setState( "b", "0", ABSENT );
945             m2.setState( "y", "0", PRESENT );
946             m2.setState( "c", "0", PRESENT );
947             m2.setState( "d", "0", ABSENT );
948             m2.setState( "e", "0", ABSENT );
949             m2.setState( "f", "0", ABSENT );
950             m2.setState( "g", "0", ABSENT );
951             m2.setState( "h", "0", ABSENT );
952             m2.setState( "i", "0", ABSENT );
953             dollo2.setReturnInternalStates( true );
954             dollo2.execute( p2, m2 );
955             CharacterStateMatrix<BinaryStates> i_m2 = dollo2.getInternalStatesMatrix();
956             if ( i_m2.getState( "aby", "0" ) != PRESENT ) {
957                 return false;
958             }
959             if ( i_m2.getState( "cad", "0" ) != PRESENT ) {
960                 return false;
961             }
962             if ( i_m2.getState( "af", "0" ) != ABSENT ) {
963                 return false;
964             }
965             if ( i_m2.getState( "gh", "0" ) != ABSENT ) {
966                 return false;
967             }
968             if ( i_m2.getState( "ah", "0" ) != ABSENT ) {
969                 return false;
970             }
971             if ( i_m2.getState( "r", "0" ) != ABSENT ) {
972                 return false;
973             }
974             if ( dollo2.getTotalGains() != 1 ) {
975                 return false;
976             }
977             if ( dollo2.getTotalLosses() != 2 ) {
978                 return false;
979             }
980             if ( dollo2.getTotalUnchanged() != 14 ) {
981                 return false;
982             }
983             m2.setState( "b", "0", PRESENT );
984             dollo2.execute( p2, m2 );
985             if ( dollo2.getTotalGains() != 1 ) {
986                 return false;
987             }
988             if ( dollo2.getTotalLosses() != 1 ) {
989                 return false;
990             }
991             if ( dollo2.getTotalUnchanged() != 15 ) {
992                 return false;
993             }
994             m2.setState( "a", "0", ABSENT );
995             m2.setState( "b", "0", ABSENT );
996             dollo2.execute( p2, m2 );
997             if ( dollo2.getTotalGains() != 1 ) {
998                 return false;
999             }
1000             if ( dollo2.getTotalLosses() != 3 ) {
1001                 return false;
1002             }
1003             if ( dollo2.getTotalUnchanged() != 13 ) {
1004                 return false;
1005             }
1006             m2.setState( "y", "0", ABSENT );
1007             dollo2.execute( p2, m2 );
1008             if ( dollo2.getTotalGains() != 1 ) {
1009                 return false;
1010             }
1011             if ( dollo2.getTotalLosses() != 0 ) {
1012                 return false;
1013             }
1014             if ( dollo2.getTotalUnchanged() != 16 ) {
1015                 return false;
1016             }
1017             m2.setState( "c", "0", ABSENT );
1018             dollo2.execute( p2, m2 );
1019             if ( dollo2.getTotalGains() != 0 ) {
1020                 return false;
1021             }
1022             if ( dollo2.getTotalLosses() != 0 ) {
1023                 return false;
1024             }
1025             if ( dollo2.getTotalUnchanged() != 17 ) {
1026                 return false;
1027             }
1028             m2.setState( "y", "0", PRESENT );
1029             m2.setState( "e", "0", PRESENT );
1030             dollo2.execute( p2, m2 );
1031             if ( dollo2.getTotalGains() != 1 ) {
1032                 return false;
1033             }
1034             if ( dollo2.getTotalLosses() != 5 ) {
1035                 return false;
1036             }
1037             if ( dollo2.getTotalUnchanged() != 11 ) {
1038                 return false;
1039             }
1040             i_m2 = dollo2.getInternalStatesMatrix();
1041             if ( i_m2.getState( "aby", "0" ) != PRESENT ) {
1042                 return false;
1043             }
1044             if ( i_m2.getState( "cad", "0" ) != PRESENT ) {
1045                 return false;
1046             }
1047             if ( i_m2.getState( "af", "0" ) != PRESENT ) {
1048                 return false;
1049             }
1050             if ( i_m2.getState( "gh", "0" ) != ABSENT ) {
1051                 return false;
1052             }
1053             if ( i_m2.getState( "ah", "0" ) != ABSENT ) {
1054                 return false;
1055             }
1056             if ( i_m2.getState( "r", "0" ) != ABSENT ) {
1057                 return false;
1058             }
1059         }
1060         catch ( final Exception e ) {
1061             e.printStackTrace( System.out );
1062             return false;
1063         }
1064         return true;
1065     }
1066
1067     private static boolean testFitchParsimony() {
1068         try {
1069             final BinaryStates PRESENT = BinaryStates.PRESENT;
1070             final BinaryStates ABSENT = BinaryStates.ABSENT;
1071             final GainLossStates GAIN = GainLossStates.GAIN;
1072             final GainLossStates LOSS = GainLossStates.LOSS;
1073             final GainLossStates UNCHANGED_PRESENT = GainLossStates.UNCHANGED_PRESENT;
1074             final GainLossStates UNCHANGED_ABSENT = GainLossStates.UNCHANGED_ABSENT;
1075             final FitchParsimony<String> fitch1 = new FitchParsimony<String>();
1076             final PhylogenyFactory factory1 = ParserBasedPhylogenyFactory.getInstance();
1077             final String p1_str = "((((((a,b)ab,c)ac,d)ad,(e,f)ef)af,(g,h,i)gi)ai,((j,k,l)jl,(m,n,o)mo,(p,q,r)pr)jr)root";
1078             final Phylogeny p1 = factory1.create( p1_str, new NHXParser() )[ 0 ];
1079             final CharacterStateMatrix<String> m1 = new BasicCharacterStateMatrix<String>( 18, 1 );
1080             m1.setIdentifier( 0, "a" );
1081             m1.setIdentifier( 1, "b" );
1082             m1.setIdentifier( 2, "c" );
1083             m1.setIdentifier( 3, "d" );
1084             m1.setIdentifier( 4, "e" );
1085             m1.setIdentifier( 5, "f" );
1086             m1.setIdentifier( 6, "g" );
1087             m1.setIdentifier( 7, "h" );
1088             m1.setIdentifier( 8, "i" );
1089             m1.setIdentifier( 9, "j" );
1090             m1.setIdentifier( 10, "k" );
1091             m1.setIdentifier( 11, "l" );
1092             m1.setIdentifier( 12, "m" );
1093             m1.setIdentifier( 13, "n" );
1094             m1.setIdentifier( 14, "o" );
1095             m1.setIdentifier( 15, "p" );
1096             m1.setIdentifier( 16, "q" );
1097             m1.setIdentifier( 17, "r" );
1098             m1.setCharacter( 0, "0" );
1099             m1.setState( "a", "0", "A" );
1100             m1.setState( "b", "0", "A" );
1101             m1.setState( "c", "0", "B" );
1102             m1.setState( "d", "0", "C" );
1103             m1.setState( "e", "0", "D" );
1104             m1.setState( "f", "0", "A" );
1105             m1.setState( "g", "0", "A" );
1106             m1.setState( "h", "0", "B" );
1107             m1.setState( "i", "0", "C" );
1108             m1.setState( "j", "0", "A" );
1109             m1.setState( "k", "0", "B" );
1110             m1.setState( "l", "0", "C" );
1111             m1.setState( "m", "0", "B" );
1112             m1.setState( "n", "0", "B" );
1113             m1.setState( "o", "0", "B" );
1114             m1.setState( "p", "0", "A" );
1115             m1.setState( "q", "0", "C" );
1116             m1.setState( "r", "0", "D" );
1117             fitch1.setReturnInternalStates( true );
1118             fitch1.setReturnGainLossMatrix( false );
1119             fitch1.setRandomize( false );
1120             fitch1.execute( p1, m1 );
1121             final CharacterStateMatrix<String> i_m = fitch1.getInternalStatesMatrix();
1122             final CharacterStateMatrix<List<String>> i_m_all = fitch1.getInternalStatesMatrixPriorToTraceback();
1123             if ( fitch1.getCost() != 10 ) {
1124                 return false;
1125             }
1126             if ( !i_m.getState( "ab", "0" ).equals( "A" ) ) {
1127                 return false;
1128             }
1129             if ( !i_m.getState( "ac", "0" ).equals( "A" ) ) {
1130                 return false;
1131             }
1132             if ( !i_m.getState( "ad", "0" ).equals( "A" ) ) {
1133                 return false;
1134             }
1135             if ( !i_m.getState( "ef", "0" ).equals( "A" ) ) {
1136                 return false;
1137             }
1138             if ( !i_m.getState( "ai", "0" ).equals( "A" ) ) {
1139                 return false;
1140             }
1141             if ( !i_m.getState( "gi", "0" ).equals( "A" ) ) {
1142                 return false;
1143             }
1144             if ( !i_m.getState( "jl", "0" ).equals( "A" ) ) {
1145                 return false;
1146             }
1147             if ( !i_m.getState( "mo", "0" ).equals( "B" ) ) {
1148                 return false;
1149             }
1150             if ( !i_m.getState( "pr", "0" ).equals( "A" ) ) {
1151                 return false;
1152             }
1153             if ( i_m_all.getState( "ab", "0" ).size() != 1 ) {
1154                 return false;
1155             }
1156             if ( !i_m_all.getState( "ab", "0" ).contains( "A" ) ) {
1157                 return false;
1158             }
1159             if ( i_m_all.getState( "ac", "0" ).size() != 2 ) {
1160                 return false;
1161             }
1162             if ( !i_m_all.getState( "ac", "0" ).contains( "A" ) ) {
1163                 return false;
1164             }
1165             if ( !i_m_all.getState( "ac", "0" ).contains( "B" ) ) {
1166                 return false;
1167             }
1168             if ( i_m_all.getState( "ad", "0" ).size() != 3 ) {
1169                 return false;
1170             }
1171             if ( !i_m_all.getState( "ad", "0" ).contains( "A" ) ) {
1172                 return false;
1173             }
1174             if ( !i_m_all.getState( "ad", "0" ).contains( "B" ) ) {
1175                 return false;
1176             }
1177             if ( !i_m_all.getState( "ad", "0" ).contains( "C" ) ) {
1178                 return false;
1179             }
1180             if ( i_m_all.getState( "af", "0" ).size() != 1 ) {
1181                 return false;
1182             }
1183             if ( !i_m_all.getState( "af", "0" ).contains( "A" ) ) {
1184                 return false;
1185             }
1186             if ( i_m_all.getState( "ef", "0" ).size() != 2 ) {
1187                 return false;
1188             }
1189             if ( !i_m_all.getState( "ef", "0" ).contains( "A" ) ) {
1190                 return false;
1191             }
1192             if ( !i_m_all.getState( "ef", "0" ).contains( "D" ) ) {
1193                 return false;
1194             }
1195             if ( i_m_all.getState( "gi", "0" ).size() != 3 ) {
1196                 return false;
1197             }
1198             if ( !i_m_all.getState( "gi", "0" ).contains( "A" ) ) {
1199                 return false;
1200             }
1201             if ( !i_m_all.getState( "gi", "0" ).contains( "B" ) ) {
1202                 return false;
1203             }
1204             if ( !i_m_all.getState( "gi", "0" ).contains( "C" ) ) {
1205                 return false;
1206             }
1207             if ( i_m_all.getState( "ai", "0" ).size() != 1 ) {
1208                 return false;
1209             }
1210             if ( !i_m_all.getState( "ai", "0" ).contains( "A" ) ) {
1211                 return false;
1212             }
1213             if ( i_m_all.getState( "jl", "0" ).size() != 3 ) {
1214                 return false;
1215             }
1216             if ( !i_m_all.getState( "jl", "0" ).contains( "A" ) ) {
1217                 return false;
1218             }
1219             if ( !i_m_all.getState( "jl", "0" ).contains( "B" ) ) {
1220                 return false;
1221             }
1222             if ( !i_m_all.getState( "jl", "0" ).contains( "C" ) ) {
1223                 return false;
1224             }
1225             if ( i_m_all.getState( "mo", "0" ).size() != 1 ) {
1226                 return false;
1227             }
1228             if ( !i_m_all.getState( "mo", "0" ).contains( "B" ) ) {
1229                 return false;
1230             }
1231             if ( i_m_all.getState( "pr", "0" ).size() != 3 ) {
1232                 return false;
1233             }
1234             if ( !i_m_all.getState( "pr", "0" ).contains( "A" ) ) {
1235                 return false;
1236             }
1237             if ( !i_m_all.getState( "pr", "0" ).contains( "C" ) ) {
1238                 return false;
1239             }
1240             if ( !i_m_all.getState( "pr", "0" ).contains( "D" ) ) {
1241                 return false;
1242             }
1243             if ( i_m_all.getState( "jr", "0" ).size() != 4 ) {
1244                 return false;
1245             }
1246             if ( !i_m_all.getState( "jr", "0" ).contains( "A" ) ) {
1247                 return false;
1248             }
1249             if ( !i_m_all.getState( "jr", "0" ).contains( "B" ) ) {
1250                 return false;
1251             }
1252             if ( !i_m_all.getState( "jr", "0" ).contains( "C" ) ) {
1253                 return false;
1254             }
1255             if ( !i_m_all.getState( "jr", "0" ).contains( "D" ) ) {
1256                 return false;
1257             }
1258             final FitchParsimony<String> fitch2 = new FitchParsimony<String>();
1259             final PhylogenyFactory factory2 = ParserBasedPhylogenyFactory.getInstance();
1260             final String p2_str = "((a,b)ab,(c,(d,e)de)cde)r";
1261             final Phylogeny p2 = factory2.create( p2_str, new NHXParser() )[ 0 ];
1262             final CharacterStateMatrix<String> m2 = new BasicCharacterStateMatrix<String>( 5, 1 );
1263             m2.setIdentifier( 0, "a" );
1264             m2.setIdentifier( 1, "b" );
1265             m2.setIdentifier( 2, "c" );
1266             m2.setIdentifier( 3, "d" );
1267             m2.setIdentifier( 4, "e" );
1268             m2.setCharacter( 0, "0" );
1269             m2.setState( "a", "0", "C" );
1270             m2.setState( "b", "0", "A" );
1271             m2.setState( "c", "0", "C" );
1272             m2.setState( "d", "0", "A" );
1273             m2.setState( "e", "0", "G" );
1274             fitch2.setReturnInternalStates( true );
1275             fitch2.setReturnGainLossMatrix( false );
1276             fitch2.execute( p2, m2 );
1277             final CharacterStateMatrix<String> i_m2 = fitch2.getInternalStatesMatrix();
1278             final CharacterStateMatrix<List<String>> i_m_all2 = fitch2.getInternalStatesMatrixPriorToTraceback();
1279             if ( fitch2.getCost() != 3 ) {
1280                 return false;
1281             }
1282             if ( !i_m2.getState( "ab", "0" ).equals( "A" ) ) {
1283                 return false;
1284             }
1285             if ( !i_m2.getState( "de", "0" ).equals( "A" ) ) {
1286                 return false;
1287             }
1288             if ( !i_m2.getState( "cde", "0" ).equals( "A" ) ) {
1289                 return false;
1290             }
1291             if ( !i_m2.getState( "r", "0" ).equals( "A" ) ) {
1292                 return false;
1293             }
1294             if ( i_m_all2.getState( "cde", "0" ).size() != 3 ) {
1295                 return false;
1296             }
1297             if ( !i_m_all2.getState( "cde", "0" ).contains( "A" ) ) {
1298                 return false;
1299             }
1300             if ( !i_m_all2.getState( "cde", "0" ).contains( "C" ) ) {
1301                 return false;
1302             }
1303             if ( !i_m_all2.getState( "cde", "0" ).contains( "G" ) ) {
1304                 return false;
1305             }
1306             if ( i_m_all2.getState( "ab", "0" ).size() != 2 ) {
1307                 return false;
1308             }
1309             if ( !i_m_all2.getState( "ab", "0" ).contains( "A" ) ) {
1310                 return false;
1311             }
1312             if ( !i_m_all2.getState( "ab", "0" ).contains( "C" ) ) {
1313                 return false;
1314             }
1315             fitch2.setReturnInternalStates( true );
1316             fitch2.setReturnGainLossMatrix( false );
1317             fitch2.setUseLast( true );
1318             fitch2.execute( p2, m2 );
1319             final CharacterStateMatrix<String> i_m21 = fitch2.getInternalStatesMatrix();
1320             final CharacterStateMatrix<List<String>> i_m_all21 = fitch2.getInternalStatesMatrixPriorToTraceback();
1321             if ( fitch2.getCost() != 3 ) {
1322                 return false;
1323             }
1324             if ( !i_m21.getState( "ab", "0" ).equals( "C" ) ) {
1325                 return false;
1326             }
1327             if ( !i_m21.getState( "de", "0" ).equals( "G" ) ) {
1328                 return false;
1329             }
1330             if ( !i_m21.getState( "cde", "0" ).equals( "C" ) ) {
1331                 return false;
1332             }
1333             if ( !i_m21.getState( "r", "0" ).equals( "C" ) ) {
1334                 return false;
1335             }
1336             if ( i_m_all21.getState( "cde", "0" ).size() != 3 ) {
1337                 return false;
1338             }
1339             if ( !i_m_all21.getState( "cde", "0" ).contains( "A" ) ) {
1340                 return false;
1341             }
1342             if ( !i_m_all21.getState( "cde", "0" ).contains( "C" ) ) {
1343                 return false;
1344             }
1345             if ( !i_m_all21.getState( "cde", "0" ).contains( "G" ) ) {
1346                 return false;
1347             }
1348             final FitchParsimony<String> fitch3 = new FitchParsimony<String>();
1349             final PhylogenyFactory factory3 = ParserBasedPhylogenyFactory.getInstance();
1350             final String p3_str = "(((a,b)ab,((c,d)cd,e)cde)abcde,f)r";
1351             final Phylogeny p3 = factory3.create( p3_str, new NHXParser() )[ 0 ];
1352             final CharacterStateMatrix<String> m3 = new BasicCharacterStateMatrix<String>( 6, 1 );
1353             m3.setIdentifier( 0, "a" );
1354             m3.setIdentifier( 1, "b" );
1355             m3.setIdentifier( 2, "c" );
1356             m3.setIdentifier( 3, "d" );
1357             m3.setIdentifier( 4, "e" );
1358             m3.setIdentifier( 5, "f" );
1359             m3.setCharacter( 0, "0" );
1360             m3.setState( "a", "0", "C" );
1361             m3.setState( "b", "0", "U" );
1362             m3.setState( "c", "0", "G" );
1363             m3.setState( "d", "0", "U" );
1364             m3.setState( "e", "0", "A" );
1365             m3.setState( "f", "0", "A" );
1366             fitch3.setReturnInternalStates( true );
1367             fitch3.setReturnGainLossMatrix( false );
1368             fitch3.execute( p3, m3 );
1369             final CharacterStateMatrix<String> i_m3 = fitch3.getInternalStatesMatrix();
1370             final CharacterStateMatrix<List<String>> i_m_all3 = fitch3.getInternalStatesMatrixPriorToTraceback();
1371             if ( fitch3.getCost() != 4 ) {
1372                 return false;
1373             }
1374             if ( !i_m3.getState( "ab", "0" ).equals( "U" ) ) {
1375                 return false;
1376             }
1377             if ( !i_m3.getState( "cd", "0" ).equals( "U" ) ) {
1378                 return false;
1379             }
1380             if ( !i_m3.getState( "cde", "0" ).equals( "U" ) ) {
1381                 return false;
1382             }
1383             if ( !i_m3.getState( "abcde", "0" ).equals( "U" ) ) {
1384                 return false;
1385             }
1386             if ( !i_m3.getState( "r", "0" ).equals( "A" ) ) {
1387                 return false;
1388             }
1389             if ( i_m_all3.getState( "cde", "0" ).size() != 3 ) {
1390                 return false;
1391             }
1392             if ( !i_m_all3.getState( "cde", "0" ).contains( "A" ) ) {
1393                 return false;
1394             }
1395             if ( !i_m_all3.getState( "cde", "0" ).contains( "G" ) ) {
1396                 return false;
1397             }
1398             if ( !i_m_all3.getState( "cde", "0" ).contains( "U" ) ) {
1399                 return false;
1400             }
1401             if ( i_m_all3.getState( "ab", "0" ).size() != 2 ) {
1402                 return false;
1403             }
1404             if ( !i_m_all3.getState( "ab", "0" ).contains( "C" ) ) {
1405                 return false;
1406             }
1407             if ( !i_m_all3.getState( "ab", "0" ).contains( "U" ) ) {
1408                 return false;
1409             }
1410             if ( i_m_all3.getState( "cd", "0" ).size() != 2 ) {
1411                 return false;
1412             }
1413             if ( !i_m_all3.getState( "cd", "0" ).contains( "G" ) ) {
1414                 return false;
1415             }
1416             if ( !i_m_all3.getState( "cd", "0" ).contains( "U" ) ) {
1417                 return false;
1418             }
1419             if ( i_m_all3.getState( "abcde", "0" ).size() != 1 ) {
1420                 return false;
1421             }
1422             if ( !i_m_all3.getState( "abcde", "0" ).contains( "U" ) ) {
1423                 return false;
1424             }
1425             if ( i_m_all3.getState( "r", "0" ).size() != 2 ) {
1426                 return false;
1427             }
1428             if ( !i_m_all3.getState( "r", "0" ).contains( "A" ) ) {
1429                 return false;
1430             }
1431             if ( !i_m_all3.getState( "r", "0" ).contains( "U" ) ) {
1432                 return false;
1433             }
1434             final FitchParsimony<BinaryStates> fitch4 = new FitchParsimony<BinaryStates>();
1435             final PhylogenyFactory factory4 = ParserBasedPhylogenyFactory.getInstance();
1436             final String p4_str = "(((a,b)ab,((c,d)cd,e)cde)abcde,f)r";
1437             final Phylogeny p4 = factory4.create( p4_str, new NHXParser() )[ 0 ];
1438             final CharacterStateMatrix<BinaryStates> m4 = new BasicCharacterStateMatrix<BinaryStates>( 6, 1 );
1439             m4.setIdentifier( 0, "a" );
1440             m4.setIdentifier( 1, "b" );
1441             m4.setIdentifier( 2, "c" );
1442             m4.setIdentifier( 3, "d" );
1443             m4.setIdentifier( 4, "e" );
1444             m4.setIdentifier( 5, "f" );
1445             m4.setCharacter( 0, "0" );
1446             m4.setState( "a", "0", PRESENT );
1447             m4.setState( "b", "0", ABSENT );
1448             m4.setState( "c", "0", PRESENT );
1449             m4.setState( "d", "0", PRESENT );
1450             m4.setState( "e", "0", ABSENT );
1451             m4.setState( "f", "0", ABSENT );
1452             fitch4.setReturnInternalStates( true );
1453             fitch4.setReturnGainLossMatrix( true );
1454             fitch4.execute( p4, m4 );
1455             final CharacterStateMatrix<GainLossStates> gl_m_4 = fitch4.getGainLossMatrix();
1456             if ( fitch4.getCost() != 2 ) {
1457                 return false;
1458             }
1459             if ( fitch4.getTotalLosses() != 0 ) {
1460                 return false;
1461             }
1462             if ( fitch4.getTotalGains() != 2 ) {
1463                 return false;
1464             }
1465             if ( fitch4.getTotalUnchanged() != 9 ) {
1466                 return false;
1467             }
1468             if ( gl_m_4.getState( "a", "0" ) != GAIN ) {
1469                 return false;
1470             }
1471             if ( gl_m_4.getState( "b", "0" ) != UNCHANGED_ABSENT ) {
1472                 return false;
1473             }
1474             if ( gl_m_4.getState( "ab", "0" ) != UNCHANGED_ABSENT ) {
1475                 return false;
1476             }
1477             if ( gl_m_4.getState( "cd", "0" ) != GAIN ) {
1478                 return false;
1479             }
1480             if ( gl_m_4.getState( "r", "0" ) != UNCHANGED_ABSENT ) {
1481                 return false;
1482             }
1483             final FitchParsimony<BinaryStates> fitch5 = new FitchParsimony<BinaryStates>();
1484             final PhylogenyFactory factory5 = ParserBasedPhylogenyFactory.getInstance();
1485             final String p5_str = "(((a,b)ab,((c,d)cd,e)cde)abcde,f)r";
1486             final Phylogeny p5 = factory5.create( p5_str, new NHXParser() )[ 0 ];
1487             final CharacterStateMatrix<BinaryStates> m5 = new BasicCharacterStateMatrix<BinaryStates>( 6, 1 );
1488             m5.setIdentifier( 0, "a" );
1489             m5.setIdentifier( 1, "b" );
1490             m5.setIdentifier( 2, "c" );
1491             m5.setIdentifier( 3, "d" );
1492             m5.setIdentifier( 4, "e" );
1493             m5.setIdentifier( 5, "f" );
1494             m5.setCharacter( 0, "0" );
1495             m5.setState( "a", "0", PRESENT );
1496             m5.setState( "b", "0", ABSENT );
1497             m5.setState( "c", "0", PRESENT );
1498             m5.setState( "d", "0", ABSENT );
1499             m5.setState( "e", "0", PRESENT );
1500             m5.setState( "f", "0", ABSENT );
1501             fitch5.setReturnInternalStates( true );
1502             fitch5.setReturnGainLossMatrix( true );
1503             fitch5.execute( p5, m5 );
1504             final CharacterStateMatrix<GainLossStates> gl_m_5 = fitch5.getGainLossMatrix();
1505             if ( fitch5.getCost() != 3 ) {
1506                 return false;
1507             }
1508             if ( fitch5.getTotalLosses() != 2 ) {
1509                 return false;
1510             }
1511             if ( fitch5.getTotalGains() != 1 ) {
1512                 return false;
1513             }
1514             if ( fitch5.getTotalUnchanged() != 8 ) {
1515                 return false;
1516             }
1517             if ( gl_m_5.getState( "abcde", "0" ) != GAIN ) {
1518                 return false;
1519             }
1520             if ( gl_m_5.getState( "a", "0" ) != UNCHANGED_PRESENT ) {
1521                 return false;
1522             }
1523             if ( gl_m_5.getState( "b", "0" ) != LOSS ) {
1524                 return false;
1525             }
1526             if ( gl_m_5.getState( "d", "0" ) != LOSS ) {
1527                 return false;
1528             }
1529             if ( gl_m_5.getState( "r", "0" ) != UNCHANGED_ABSENT ) {
1530                 return false;
1531             }
1532             final FitchParsimony<BinaryStates> fitch6 = new FitchParsimony<BinaryStates>();
1533             final PhylogenyFactory factory6 = ParserBasedPhylogenyFactory.getInstance();
1534             final String p6_str = "(((a,b)ab,((c,d)cd,e)cde)abcde,f)r";
1535             final Phylogeny p6 = factory6.create( p6_str, new NHXParser() )[ 0 ];
1536             final CharacterStateMatrix<BinaryStates> m6 = new BasicCharacterStateMatrix<BinaryStates>( 6, 1 );
1537             m6.setIdentifier( 0, "a" );
1538             m6.setIdentifier( 1, "b" );
1539             m6.setIdentifier( 2, "c" );
1540             m6.setIdentifier( 3, "d" );
1541             m6.setIdentifier( 4, "e" );
1542             m6.setIdentifier( 5, "f" );
1543             m6.setCharacter( 0, "0" );
1544             m6.setState( "a", "0", PRESENT );
1545             m6.setState( "b", "0", ABSENT );
1546             m6.setState( "c", "0", PRESENT );
1547             m6.setState( "d", "0", PRESENT );
1548             m6.setState( "e", "0", ABSENT );
1549             m6.setState( "f", "0", PRESENT );
1550             fitch6.setReturnInternalStates( true );
1551             fitch6.setReturnGainLossMatrix( true );
1552             fitch6.execute( p6, m6 );
1553             final CharacterStateMatrix<GainLossStates> gl_m_6 = fitch6.getGainLossMatrix();
1554             if ( fitch6.getCost() != 2 ) {
1555                 return false;
1556             }
1557             if ( fitch6.getTotalLosses() != 2 ) {
1558                 return false;
1559             }
1560             if ( fitch6.getTotalGains() != 0 ) {
1561                 return false;
1562             }
1563             if ( fitch6.getTotalUnchanged() != 9 ) {
1564                 return false;
1565             }
1566             if ( gl_m_6.getState( "abcde", "0" ) != UNCHANGED_PRESENT ) {
1567                 return false;
1568             }
1569             if ( gl_m_6.getState( "r", "0" ) != UNCHANGED_PRESENT ) {
1570                 return false;
1571             }
1572             if ( gl_m_6.getState( "b", "0" ) != LOSS ) {
1573                 return false;
1574             }
1575             if ( gl_m_6.getState( "e", "0" ) != LOSS ) {
1576                 return false;
1577             }
1578             final FitchParsimony<BinaryStates> fitch7 = new FitchParsimony<BinaryStates>();
1579             final PhylogenyFactory factory7 = ParserBasedPhylogenyFactory.getInstance();
1580             final String p7_str = "(((a,b)ab,(c,d)cd)abcd,((e,f)ef,(g,h)gh)efgh)r";
1581             final Phylogeny p7 = factory7.create( p7_str, new NHXParser() )[ 0 ];
1582             final CharacterStateMatrix<BinaryStates> m7 = new BasicCharacterStateMatrix<BinaryStates>( 8, 1 );
1583             m7.setIdentifier( 0, "a" );
1584             m7.setIdentifier( 1, "b" );
1585             m7.setIdentifier( 2, "c" );
1586             m7.setIdentifier( 3, "d" );
1587             m7.setIdentifier( 4, "e" );
1588             m7.setIdentifier( 5, "f" );
1589             m7.setIdentifier( 6, "g" );
1590             m7.setIdentifier( 7, "h" );
1591             m7.setCharacter( 0, "0" );
1592             m7.setState( "a", "0", PRESENT );
1593             m7.setState( "b", "0", ABSENT );
1594             m7.setState( "c", "0", PRESENT );
1595             m7.setState( "d", "0", ABSENT );
1596             m7.setState( "e", "0", PRESENT );
1597             m7.setState( "f", "0", ABSENT );
1598             m7.setState( "g", "0", PRESENT );
1599             m7.setState( "h", "0", ABSENT );
1600             fitch7.setReturnInternalStates( true );
1601             fitch7.setReturnGainLossMatrix( true );
1602             fitch7.execute( p7, m7 );
1603             final CharacterStateMatrix<GainLossStates> gl_m_7 = fitch7.getGainLossMatrix();
1604             if ( fitch7.getCost() != 4 ) {
1605                 return false;
1606             }
1607             if ( fitch7.getTotalLosses() != 0 ) {
1608                 return false;
1609             }
1610             if ( fitch7.getTotalGains() != 4 ) {
1611                 return false;
1612             }
1613             if ( fitch7.getTotalUnchanged() != 11 ) {
1614                 return false;
1615             }
1616             if ( gl_m_7.getState( "a", "0" ) != GAIN ) {
1617                 return false;
1618             }
1619             if ( gl_m_7.getState( "c", "0" ) != GAIN ) {
1620                 return false;
1621             }
1622             if ( gl_m_7.getState( "e", "0" ) != GAIN ) {
1623                 return false;
1624             }
1625             if ( gl_m_7.getState( "g", "0" ) != GAIN ) {
1626                 return false;
1627             }
1628             if ( gl_m_7.getState( "r", "0" ) != UNCHANGED_ABSENT ) {
1629                 return false;
1630             }
1631             fitch7.setReturnInternalStates( true );
1632             fitch7.setReturnGainLossMatrix( true );
1633             fitch7.setUseLast( true );
1634             fitch7.execute( p7, m7 );
1635             final CharacterStateMatrix<GainLossStates> gl_m_71 = fitch7.getGainLossMatrix();
1636             if ( fitch7.getCost() != 4 ) {
1637                 return false;
1638             }
1639             if ( fitch7.getTotalLosses() != 4 ) {
1640                 return false;
1641             }
1642             if ( fitch7.getTotalGains() != 0 ) {
1643                 return false;
1644             }
1645             if ( fitch7.getTotalUnchanged() != 11 ) {
1646                 return false;
1647             }
1648             if ( gl_m_71.getState( "b", "0" ) != LOSS ) {
1649                 return false;
1650             }
1651             if ( gl_m_71.getState( "d", "0" ) != LOSS ) {
1652                 return false;
1653             }
1654             if ( gl_m_71.getState( "f", "0" ) != LOSS ) {
1655                 return false;
1656             }
1657             if ( gl_m_71.getState( "h", "0" ) != LOSS ) {
1658                 return false;
1659             }
1660             if ( gl_m_71.getState( "r", "0" ) != UNCHANGED_PRESENT ) {
1661                 return false;
1662             }
1663             final FitchParsimony<BinaryStates> fitch8 = new FitchParsimony<BinaryStates>();
1664             final PhylogenyFactory factory8 = ParserBasedPhylogenyFactory.getInstance();
1665             final String p8_str = "(((a,b)ab,(c,d)cd)abcd,((e,f)ef,(g,h)gh)efgh)r";
1666             final Phylogeny p8 = factory8.create( p8_str, new NHXParser() )[ 0 ];
1667             final CharacterStateMatrix<BinaryStates> m8 = new BasicCharacterStateMatrix<BinaryStates>( 8, 1 );
1668             m8.setIdentifier( 0, "a" );
1669             m8.setIdentifier( 1, "b" );
1670             m8.setIdentifier( 2, "c" );
1671             m8.setIdentifier( 3, "d" );
1672             m8.setIdentifier( 4, "e" );
1673             m8.setIdentifier( 5, "f" );
1674             m8.setIdentifier( 6, "g" );
1675             m8.setIdentifier( 7, "h" );
1676             m8.setCharacter( 0, "0" );
1677             m8.setState( "a", "0", PRESENT );
1678             m8.setState( "b", "0", PRESENT );
1679             m8.setState( "c", "0", PRESENT );
1680             m8.setState( "d", "0", ABSENT );
1681             m8.setState( "e", "0", ABSENT );
1682             m8.setState( "f", "0", ABSENT );
1683             m8.setState( "g", "0", ABSENT );
1684             m8.setState( "h", "0", ABSENT );
1685             fitch8.setReturnInternalStates( true );
1686             fitch8.setReturnGainLossMatrix( true );
1687             fitch8.execute( p8, m8 );
1688             final CharacterStateMatrix<GainLossStates> gl_m_8 = fitch8.getGainLossMatrix();
1689             if ( fitch8.getCost() != 2 ) {
1690                 return false;
1691             }
1692             if ( fitch8.getTotalLosses() != 1 ) {
1693                 return false;
1694             }
1695             if ( fitch8.getTotalGains() != 1 ) {
1696                 return false;
1697             }
1698             if ( fitch8.getTotalUnchanged() != 13 ) {
1699                 return false;
1700             }
1701             if ( gl_m_8.getState( "d", "0" ) != LOSS ) {
1702                 return false;
1703             }
1704             if ( gl_m_8.getState( "abcd", "0" ) != GAIN ) {
1705                 return false;
1706             }
1707             final FitchParsimony<BinaryStates> fitch9 = new FitchParsimony<BinaryStates>();
1708             final PhylogenyFactory factory9 = ParserBasedPhylogenyFactory.getInstance();
1709             final String p9_str = "(((a,b)ab,c)abc,d)abcd";
1710             final Phylogeny p9 = factory9.create( p9_str, new NHXParser() )[ 0 ];
1711             final CharacterStateMatrix<BinaryStates> m9 = new BasicCharacterStateMatrix<BinaryStates>( 4, 1 );
1712             m9.setIdentifier( 0, "a" );
1713             m9.setIdentifier( 1, "b" );
1714             m9.setIdentifier( 2, "c" );
1715             m9.setIdentifier( 3, "d" );
1716             m9.setCharacter( 0, "0" );
1717             m9.setState( "a", "0", PRESENT );
1718             m9.setState( "b", "0", ABSENT );
1719             m9.setState( "c", "0", PRESENT );
1720             m9.setState( "d", "0", ABSENT );
1721             fitch9.setReturnInternalStates( true );
1722             fitch9.setReturnGainLossMatrix( true );
1723             fitch9.setUseLast( false );
1724             fitch9.execute( p9, m9 );
1725             final CharacterStateMatrix<GainLossStates> gl_m_9a = fitch9.getGainLossMatrix();
1726             if ( fitch9.getCost() != 2 ) {
1727                 return false;
1728             }
1729             if ( fitch9.getTotalLosses() != 1 ) {
1730                 return false;
1731             }
1732             if ( fitch9.getTotalGains() != 1 ) {
1733                 return false;
1734             }
1735             if ( fitch9.getTotalUnchanged() != 5 ) {
1736                 return false;
1737             }
1738             if ( gl_m_9a.getState( "a", "0" ) != UNCHANGED_PRESENT ) {
1739                 return false;
1740             }
1741             if ( gl_m_9a.getState( "b", "0" ) != LOSS ) {
1742                 return false;
1743             }
1744             if ( gl_m_9a.getState( "c", "0" ) != UNCHANGED_PRESENT ) {
1745                 return false;
1746             }
1747             if ( gl_m_9a.getState( "d", "0" ) != UNCHANGED_ABSENT ) {
1748                 return false;
1749             }
1750             if ( gl_m_9a.getState( "ab", "0" ) != UNCHANGED_PRESENT ) {
1751                 return false;
1752             }
1753             if ( gl_m_9a.getState( "abc", "0" ) != GAIN ) {
1754                 return false;
1755             }
1756             if ( gl_m_9a.getState( "abcd", "0" ) != UNCHANGED_ABSENT ) {
1757                 return false;
1758             }
1759             fitch9.setUseLast( true );
1760             fitch9.execute( p9, m9 );
1761             final CharacterStateMatrix<GainLossStates> gl_m_9b = fitch9.getGainLossMatrix();
1762             if ( fitch9.getCost() != 2 ) {
1763                 return false;
1764             }
1765             if ( fitch9.getTotalLosses() != 2 ) {
1766                 return false;
1767             }
1768             if ( fitch9.getTotalGains() != 0 ) {
1769                 return false;
1770             }
1771             if ( fitch9.getTotalUnchanged() != 5 ) {
1772                 return false;
1773             }
1774             if ( gl_m_9b.getState( "a", "0" ) != UNCHANGED_PRESENT ) {
1775                 return false;
1776             }
1777             if ( gl_m_9b.getState( "b", "0" ) != LOSS ) {
1778                 return false;
1779             }
1780             if ( gl_m_9b.getState( "c", "0" ) != UNCHANGED_PRESENT ) {
1781                 return false;
1782             }
1783             if ( gl_m_9b.getState( "d", "0" ) != LOSS ) {
1784                 return false;
1785             }
1786             if ( gl_m_9b.getState( "ab", "0" ) != UNCHANGED_PRESENT ) {
1787                 return false;
1788             }
1789             if ( gl_m_9b.getState( "abc", "0" ) != UNCHANGED_PRESENT ) {
1790                 return false;
1791             }
1792             if ( gl_m_9b.getState( "abcd", "0" ) != UNCHANGED_PRESENT ) {
1793                 return false;
1794             }
1795             fitch9.setUseLast( false );
1796             fitch9.setRandomize( true );
1797             fitch9.setRandomNumberSeed( 8722445 );
1798             fitch9.execute( p9, m9 );
1799             fitch9.getGainLossMatrix();
1800             if ( fitch9.getCost() != 2 ) {
1801                 return false;
1802             }
1803             if ( fitch9.getTotalLosses() != 1 ) {
1804                 return false;
1805             }
1806             if ( fitch9.getTotalGains() != 1 ) {
1807                 return false;
1808             }
1809             if ( fitch9.getTotalUnchanged() != 5 ) {
1810                 return false;
1811             }
1812             final FitchParsimony<BinaryStates> fitch10 = new FitchParsimony<BinaryStates>();
1813             final PhylogenyFactory factory10 = ParserBasedPhylogenyFactory.getInstance();
1814             final String p10_str = "((((a,b)ab,c)abc,d)abcd,e)abcde";
1815             final Phylogeny p10 = factory10.create( p10_str, new NHXParser() )[ 0 ];
1816             final CharacterStateMatrix<BinaryStates> m10 = new BasicCharacterStateMatrix<BinaryStates>( 5, 1 );
1817             m10.setIdentifier( 0, "a" );
1818             m10.setIdentifier( 1, "b" );
1819             m10.setIdentifier( 2, "c" );
1820             m10.setIdentifier( 3, "d" );
1821             m10.setIdentifier( 4, "e" );
1822             m10.setCharacter( 0, "0" );
1823             m10.setState( "a", "0", PRESENT );
1824             m10.setState( "b", "0", ABSENT );
1825             m10.setState( "c", "0", ABSENT );
1826             m10.setState( "d", "0", PRESENT );
1827             m10.setState( "e", "0", ABSENT );
1828             fitch10.setReturnInternalStates( true );
1829             fitch10.setReturnGainLossMatrix( true );
1830             fitch10.setUseLast( false );
1831             fitch10.execute( p10, m10 );
1832             final CharacterStateMatrix<GainLossStates> gl_m_10a = fitch10.getGainLossMatrix();
1833             if ( fitch10.getCost() != 2 ) {
1834                 return false;
1835             }
1836             if ( fitch10.getTotalLosses() != 0 ) {
1837                 return false;
1838             }
1839             if ( fitch10.getTotalGains() != 2 ) {
1840                 return false;
1841             }
1842             if ( fitch10.getTotalUnchanged() != 7 ) {
1843                 return false;
1844             }
1845             if ( gl_m_10a.getState( "a", "0" ) != GAIN ) {
1846                 return false;
1847             }
1848             if ( gl_m_10a.getState( "b", "0" ) != UNCHANGED_ABSENT ) {
1849                 return false;
1850             }
1851             if ( gl_m_10a.getState( "c", "0" ) != UNCHANGED_ABSENT ) {
1852                 return false;
1853             }
1854             if ( gl_m_10a.getState( "d", "0" ) != GAIN ) {
1855                 return false;
1856             }
1857             if ( gl_m_10a.getState( "e", "0" ) != UNCHANGED_ABSENT ) {
1858                 return false;
1859             }
1860             if ( gl_m_10a.getState( "ab", "0" ) != UNCHANGED_ABSENT ) {
1861                 return false;
1862             }
1863             if ( gl_m_10a.getState( "abc", "0" ) != UNCHANGED_ABSENT ) {
1864                 return false;
1865             }
1866             if ( gl_m_10a.getState( "abcd", "0" ) != UNCHANGED_ABSENT ) {
1867                 return false;
1868             }
1869             if ( gl_m_10a.getState( "abcde", "0" ) != UNCHANGED_ABSENT ) {
1870                 return false;
1871             }
1872             fitch10.setUseLast( true );
1873             fitch10.execute( p10, m10 );
1874             final CharacterStateMatrix<GainLossStates> gl_m_10b = fitch10.getGainLossMatrix();
1875             if ( fitch10.getCost() != 2 ) {
1876                 return false;
1877             }
1878             if ( fitch10.getTotalLosses() != 0 ) {
1879                 return false;
1880             }
1881             if ( fitch10.getTotalGains() != 2 ) {
1882                 return false;
1883             }
1884             if ( fitch10.getTotalUnchanged() != 7 ) {
1885                 return false;
1886             }
1887             if ( gl_m_10b.getState( "a", "0" ) != GAIN ) {
1888                 return false;
1889             }
1890             if ( gl_m_10b.getState( "b", "0" ) != UNCHANGED_ABSENT ) {
1891                 return false;
1892             }
1893             if ( gl_m_10b.getState( "c", "0" ) != UNCHANGED_ABSENT ) {
1894                 return false;
1895             }
1896             if ( gl_m_10b.getState( "d", "0" ) != GAIN ) {
1897                 return false;
1898             }
1899             if ( gl_m_10b.getState( "e", "0" ) != UNCHANGED_ABSENT ) {
1900                 return false;
1901             }
1902             if ( gl_m_10b.getState( "ab", "0" ) != UNCHANGED_ABSENT ) {
1903                 return false;
1904             }
1905             if ( gl_m_10b.getState( "abc", "0" ) != UNCHANGED_ABSENT ) {
1906                 return false;
1907             }
1908             if ( gl_m_10b.getState( "abcd", "0" ) != UNCHANGED_ABSENT ) {
1909                 return false;
1910             }
1911             if ( gl_m_10b.getState( "abcde", "0" ) != UNCHANGED_ABSENT ) {
1912                 return false;
1913             }
1914         }
1915         catch ( final Exception e ) {
1916             e.printStackTrace( System.out );
1917             return false;
1918         }
1919         return true;
1920     }
1921
1922     private static boolean testNeighborJoining() {
1923         try {
1924             NeighborJoining nj = NeighborJoining.createInstance();
1925             final BasicSymmetricalDistanceMatrix m0 = new BasicSymmetricalDistanceMatrix( 4 );
1926             m0.setIdentifier( 0, "A" );
1927             m0.setIdentifier( 1, "B" );
1928             m0.setIdentifier( 2, "C" );
1929             m0.setIdentifier( 3, "D" );
1930             m0.setRow( "5 ", 1 );
1931             m0.setRow( "3 6 ", 2 );
1932             m0.setRow( "7.5 10.5 5.5", 3 );
1933             final Phylogeny p0 = nj.execute( m0 );
1934             p0.reRoot( p0.getNode( "D" ) );
1935             if ( isUnequal( p0.getNode( "A" ).getDistanceToParent(), 1 ) ) {
1936                 return false;
1937             }
1938             if ( isUnequal( p0.getNode( "B" ).getDistanceToParent(), 4 ) ) {
1939                 return false;
1940             }
1941             if ( isUnequal( p0.getNode( "C" ).getDistanceToParent(), 0.5 ) ) {
1942                 return false;
1943             }
1944             if ( isUnequal( p0.getNode( "D" ).getDistanceToParent(), 2.5 ) ) {
1945                 return false;
1946             }
1947             if ( isUnequal( p0.getNode( "A" ).getParent().getDistanceToParent(), 1.5 ) ) {
1948                 return false;
1949             }
1950             if ( isUnequal( p0.getNode( "A" ).getParent().getParent().getDistanceToParent(), 2.5 ) ) {
1951                 return false;
1952             }
1953             nj = NeighborJoining.createInstance();
1954             final BasicSymmetricalDistanceMatrix m00 = new BasicSymmetricalDistanceMatrix( 4 );
1955             m00.setIdentifier( 0, "A" );
1956             m00.setIdentifier( 1, "B" );
1957             m00.setIdentifier( 2, "C" );
1958             m00.setIdentifier( 3, "D" );
1959             m00.setRow( "2.01 ", 1 );
1960             m00.setRow( "3 3.01 ", 2 );
1961             m00.setRow( "3.01 3.02 1.01", 3 );
1962             final Phylogeny p00 = nj.execute( m00 );
1963             p00.reRoot( p00.getNode( "D" ) );
1964             if ( isUnequal( p00.getNode( "A" ).getDistanceToParent(), 1 ) ) {
1965                 return false;
1966             }
1967             if ( isUnequal( p00.getNode( "B" ).getDistanceToParent(), 1.01 ) ) {
1968                 return false;
1969             }
1970             if ( isUnequal( p00.getNode( "C" ).getDistanceToParent(), 0.5 ) ) {
1971                 return false;
1972             }
1973             if ( isUnequal( p00.getNode( "D" ).getDistanceToParent(), 0.255 ) ) {
1974                 return false;
1975             }
1976             if ( isUnequal( p00.getNode( "A" ).getParent().getDistanceToParent(), 1.5 ) ) {
1977                 return false;
1978             }
1979             if ( isUnequal( p00.getNode( "A" ).getParent().getParent().getDistanceToParent(), 0.255 ) ) {
1980                 return false;
1981             }
1982             BasicSymmetricalDistanceMatrix m = new BasicSymmetricalDistanceMatrix( 6 );
1983             m.setRow( "5", 1 );
1984             m.setRow( "4 7", 2 );
1985             m.setRow( "7 10 7", 3 );
1986             m.setRow( "6 9 6 5", 4 );
1987             m.setRow( "8 11 8 9 8", 5 );
1988             m.setIdentifier( 0, "A" );
1989             m.setIdentifier( 1, "B" );
1990             m.setIdentifier( 2, "C" );
1991             m.setIdentifier( 3, "D" );
1992             m.setIdentifier( 4, "E" );
1993             m.setIdentifier( 5, "F" );
1994             nj = NeighborJoining.createInstance();
1995             final Phylogeny p1 = nj.execute( m );
1996             p1.reRoot( p1.getNode( "F" ) );
1997             if ( isUnequal( p1.getNode( "A" ).getDistanceToParent(), 1 ) ) {
1998                 return false;
1999             }
2000             if ( isUnequal( p1.getNode( "B" ).getDistanceToParent(), 4 ) ) {
2001                 return false;
2002             }
2003             if ( isUnequal( p1.getNode( "C" ).getDistanceToParent(), 2 ) ) {
2004                 return false;
2005             }
2006             if ( isUnequal( p1.getNode( "D" ).getDistanceToParent(), 3 ) ) {
2007                 return false;
2008             }
2009             if ( isUnequal( p1.getNode( "E" ).getDistanceToParent(), 2 ) ) {
2010                 return false;
2011             }
2012             if ( isUnequal( p1.getNode( "F" ).getDistanceToParent(), 2.5 ) ) {
2013                 return false;
2014             }
2015             if ( isUnequal( p1.getNode( "A" ).getParent().getDistanceToParent(), 1 ) ) {
2016                 return false;
2017             }
2018             if ( isUnequal( p1.getNode( "A" ).getParent().getParent().getDistanceToParent(), 1 ) ) {
2019                 return false;
2020             }
2021             if ( isUnequal( p1.getNode( "A" ).getParent().getParent().getParent().getDistanceToParent(), 2.5 ) ) {
2022                 return false;
2023             }
2024             if ( isUnequal( p1.getNode( "B" ).getParent().getDistanceToParent(), 1 ) ) {
2025                 return false;
2026             }
2027             if ( isUnequal( p1.getNode( "D" ).getParent().getDistanceToParent(), 1 ) ) {
2028                 return false;
2029             }
2030             if ( isUnequal( p1.getNode( "E" ).getParent().getDistanceToParent(), 1 ) ) {
2031                 return false;
2032             }
2033             m = new BasicSymmetricalDistanceMatrix( 7 );
2034             m.setIdentifier( 0, "Bovine" );
2035             m.setIdentifier( 1, "Mouse" );
2036             m.setIdentifier( 2, "Gibbon" );
2037             m.setIdentifier( 3, "Orang" );
2038             m.setIdentifier( 4, "Gorilla" );
2039             m.setIdentifier( 5, "Chimp" );
2040             m.setIdentifier( 6, "Human" );
2041             m.setRow( "0.00000 1.68660 1.71980 1.66060 1.52430 1.60430 1.59050", 0 );
2042             m.setRow( "1.68660 0.00000 1.52320 1.48410 1.44650 1.43890 1.46290", 1 );
2043             m.setRow( "1.71980 1.52320 0.00000 0.71150 0.59580 0.61790 0.55830", 2 );
2044             m.setRow( "1.66060 1.48410 0.71150 0.00000 0.46310 0.50610 0.47100", 3 );
2045             m.setRow( "1.52430 1.44650 0.59580 0.46310 0.00000 0.34840 0.30830", 4 );
2046             m.setRow( "1.60430 1.43890 0.61790 0.50610 0.34840 0.00000 0.26920", 5 );
2047             m.setRow( "1.59050 1.46290 0.55830 0.47100 0.30830 0.26920 0.00000", 6 );
2048             nj = NeighborJoining.createInstance( false, 6 );
2049             final Phylogeny p2 = nj.execute( m );
2050             p2.reRoot( p2.getNode( "Bovine" ) );
2051             if ( isUnequal( p2.getNode( "Chimp" ).getDistanceToParent(), 0.151675 ) ) {
2052                 return false;
2053             }
2054             if ( isUnequal( p2.getNode( "Human" ).getDistanceToParent(), 0.117525 ) ) {
2055                 return false;
2056             }
2057             if ( isUnequal( p2.getNode( "Gorilla" ).getDistanceToParent(), 0.153932 ) ) {
2058                 return false;
2059             }
2060             if ( isUnequal( p2.getNode( "Orang" ).getDistanceToParent(), 0.284694 ) ) {
2061                 return false;
2062             }
2063             if ( isUnequal( p2.getNode( "Gibbon" ).getDistanceToParent(), 0.357931 ) ) {
2064                 return false;
2065             }
2066             if ( isUnequal( p2.getNode( "Mouse" ).getDistanceToParent(), 0.76891 ) ) {
2067                 return false;
2068             }
2069             if ( isUnequal( p2.getNode( "Bovine" ).getDistanceToParent(), 0.458845 ) ) {
2070                 return false;
2071             }
2072             if ( isUnequal( p2.getNode( "Chimp" ).getParent().getDistanceToParent(), 0.039819 ) ) {
2073                 return false;
2074             }
2075             if ( isUnequal( p2.getNode( "Human" ).getParent().getDistanceToParent(), 0.039819 ) ) {
2076                 return false;
2077             }
2078             if ( isUnequal( p2.getNode( "Chimp" ).getParent().getParent().getDistanceToParent(), 0.026956 ) ) {
2079                 return false;
2080             }
2081             if ( isUnequal( p2.getNode( "Chimp" ).getParent().getParent().getParent().getDistanceToParent(), 0.046481 ) ) {
2082                 return false;
2083             }
2084             if ( isUnequal( p2.getNode( "Chimp" ).getParent().getParent().getParent().getParent().getDistanceToParent(),
2085                             0.420269 ) ) {
2086                 return false;
2087             }
2088             if ( isUnequal( p2.getNode( "Chimp" ).getParent().getParent().getParent().getParent().getParent()
2089                     .getDistanceToParent(), 0.458845 ) ) {
2090                 return false;
2091             }
2092             m = new BasicSymmetricalDistanceMatrix( 4 );
2093             m.setIdentifier( 0, "A" );
2094             m.setIdentifier( 1, "B" );
2095             m.setIdentifier( 2, "C" );
2096             m.setIdentifier( 3, "D" );
2097             m.setRow( "0.00 0.95 0.17 0.98", 0 );
2098             m.setRow( "0.95 0.00 1.02 1.83", 1 );
2099             m.setRow( "0.17 1.02 0.00 1.01", 2 );
2100             m.setRow( "0.98 1.83 1.01 0.00", 3 );
2101             final Phylogeny p3 = nj.execute( m );
2102             p3.reRoot( p3.getNode( "C" ) );
2103             if ( isUnequal( p3.getNode( "A" ).getDistanceToParent(), 0.05 ) ) {
2104                 return false;
2105             }
2106             if ( isUnequal( p3.getNode( "B" ).getDistanceToParent(), 0.90 ) ) {
2107                 return false;
2108             }
2109             if ( !isEqual( p3.getNode( "C" ).getDistanceToParent(), 0.05 ) ) {
2110                 return false;
2111             }
2112             if ( !isEqual( p3.getNode( "D" ).getDistanceToParent(), 0.91 ) ) {
2113                 return false;
2114             }
2115             if ( isUnequal( p3.getNode( "A" ).getParent().getDistanceToParent(), 0.02 ) ) {
2116                 return false;
2117             }
2118             if ( isUnequal( p3.getNode( "A" ).getParent().getParent().getDistanceToParent(), 0.05 ) ) {
2119                 return false;
2120             }
2121             //if ( TIME ) {
2122             //    timeNeighborJoining();
2123             //}
2124         }
2125         catch ( final Exception e ) {
2126             e.printStackTrace( System.out );
2127             return false;
2128         }
2129         return true;
2130     }
2131
2132     private static boolean testSymmetricalDistanceMatrixParser() {
2133         try {
2134             final String l = ForesterUtil.getLineSeparator();
2135             StringBuffer source = new StringBuffer();
2136             source.append( " 4" + l );
2137             source.append( "A 0 0 0 0" + l );
2138             source.append( "B 1 0 0 0" + l );
2139             source.append( "C 2 4 0 0" + l );
2140             source.append( "D 3 5 6 0" + l );
2141             source.append( l );
2142             source.append( " 4" + l );
2143             source.append( "A 0   11  12  13" + l );
2144             source.append( "B 11  0   14  15" + l );
2145             source.append( "C 12  14  0   16" + l );
2146             source.append( "D 13  15  16  0" + l );
2147             source.append( l );
2148             source.append( l );
2149             source.append( "     " + l );
2150             source.append( " 4" + l );
2151             source.append( " A        0     " + l );
2152             source.append( " B            21 0" + l );
2153             source.append( " C            22 24    0  " + l );
2154             source.append( " # 2 222 2 2 " + l );
2155             source.append( " D            23 25 26 0" + l );
2156             source.append( l );
2157             source.append( l );
2158             source.append( "     " + l );
2159             final SymmetricalDistanceMatrixParser p0 = SymmetricalDistanceMatrixParser.createInstance();
2160             final DistanceMatrix[] ma0 = p0.parse( source.toString() );
2161             if ( ma0.length != 3 ) {
2162                 return false;
2163             }
2164             if ( !isEqual( ma0[ 0 ].getValue( 0, 0 ), 0 ) ) {
2165                 return false;
2166             }
2167             if ( !isEqual( ma0[ 0 ].getValue( 1, 0 ), 1 ) ) {
2168                 return false;
2169             }
2170             if ( !isEqual( ma0[ 0 ].getValue( 2, 0 ), 2 ) ) {
2171                 return false;
2172             }
2173             if ( !isEqual( ma0[ 0 ].getValue( 3, 0 ), 3 ) ) {
2174                 return false;
2175             }
2176             if ( !isEqual( ma0[ 0 ].getValue( 0, 1 ), 1 ) ) {
2177                 return false;
2178             }
2179             if ( !isEqual( ma0[ 0 ].getValue( 1, 1 ), 0 ) ) {
2180                 return false;
2181             }
2182             if ( !isEqual( ma0[ 0 ].getValue( 2, 1 ), 4 ) ) {
2183                 return false;
2184             }
2185             if ( !isEqual( ma0[ 0 ].getValue( 3, 1 ), 5 ) ) {
2186                 return false;
2187             }
2188             if ( !isEqual( ma0[ 1 ].getValue( 0, 0 ), 0 ) ) {
2189                 return false;
2190             }
2191             if ( !isEqual( ma0[ 1 ].getValue( 1, 0 ), 11 ) ) {
2192                 return false;
2193             }
2194             if ( !isEqual( ma0[ 1 ].getValue( 2, 0 ), 12 ) ) {
2195                 return false;
2196             }
2197             if ( !isEqual( ma0[ 1 ].getValue( 3, 0 ), 13 ) ) {
2198                 return false;
2199             }
2200             if ( !isEqual( ma0[ 1 ].getValue( 0, 1 ), 11 ) ) {
2201                 return false;
2202             }
2203             if ( !isEqual( ma0[ 1 ].getValue( 1, 1 ), 0 ) ) {
2204                 return false;
2205             }
2206             if ( !isEqual( ma0[ 1 ].getValue( 2, 1 ), 14 ) ) {
2207                 return false;
2208             }
2209             if ( !isEqual( ma0[ 1 ].getValue( 3, 1 ), 15 ) ) {
2210                 return false;
2211             }
2212             if ( !isEqual( ma0[ 2 ].getValue( 0, 0 ), 0 ) ) {
2213                 return false;
2214             }
2215             if ( !isEqual( ma0[ 2 ].getValue( 1, 0 ), 21 ) ) {
2216                 return false;
2217             }
2218             if ( !isEqual( ma0[ 2 ].getValue( 2, 0 ), 22 ) ) {
2219                 return false;
2220             }
2221             if ( !isEqual( ma0[ 2 ].getValue( 3, 0 ), 23 ) ) {
2222                 return false;
2223             }
2224             if ( !isEqual( ma0[ 2 ].getValue( 0, 1 ), 21 ) ) {
2225                 return false;
2226             }
2227             if ( !isEqual( ma0[ 2 ].getValue( 1, 1 ), 0 ) ) {
2228                 return false;
2229             }
2230             if ( !isEqual( ma0[ 2 ].getValue( 2, 1 ), 24 ) ) {
2231                 return false;
2232             }
2233             if ( !isEqual( ma0[ 2 ].getValue( 3, 1 ), 25 ) ) {
2234                 return false;
2235             }
2236             source = new StringBuffer();
2237             source.append( "A 0 0 0 0" + l );
2238             source.append( "B 1 0 0 0" + l );
2239             source.append( "C 2 4 0 0" + l );
2240             source.append( "D 3 5 6 0" + l );
2241             source.append( " " + l );
2242             source.append( "A 0   11  12  13" + l );
2243             source.append( "B 11  0   14  15" + l );
2244             source.append( "C 12  14  0   16" + l );
2245             source.append( "D 13  15  16  0" + l );
2246             source.append( l );
2247             source.append( " A        0     " + l );
2248             source.append( " B            21 0" + l );
2249             source.append( " C            22 24    0  " + l );
2250             source.append( " # 2 222 2 2 " + l );
2251             source.append( " D            23 25 26 0" + l );
2252             final DistanceMatrix[] ma1 = p0.parse( source.toString() );
2253             if ( ma1.length != 3 ) {
2254                 return false;
2255             }
2256             if ( !isEqual( ma1[ 0 ].getValue( 0, 0 ), 0 ) ) {
2257                 return false;
2258             }
2259             if ( !isEqual( ma1[ 0 ].getValue( 1, 0 ), 1 ) ) {
2260                 return false;
2261             }
2262             if ( !isEqual( ma1[ 0 ].getValue( 2, 0 ), 2 ) ) {
2263                 return false;
2264             }
2265             if ( !isEqual( ma1[ 0 ].getValue( 3, 0 ), 3 ) ) {
2266                 return false;
2267             }
2268             if ( !isEqual( ma1[ 0 ].getValue( 0, 1 ), 1 ) ) {
2269                 return false;
2270             }
2271             if ( !isEqual( ma1[ 0 ].getValue( 1, 1 ), 0 ) ) {
2272                 return false;
2273             }
2274             if ( !isEqual( ma1[ 0 ].getValue( 2, 1 ), 4 ) ) {
2275                 return false;
2276             }
2277             if ( !isEqual( ma1[ 0 ].getValue( 3, 1 ), 5 ) ) {
2278                 return false;
2279             }
2280             if ( !isEqual( ma1[ 1 ].getValue( 0, 0 ), 0 ) ) {
2281                 return false;
2282             }
2283             if ( !isEqual( ma1[ 1 ].getValue( 1, 0 ), 11 ) ) {
2284                 return false;
2285             }
2286             if ( !isEqual( ma1[ 1 ].getValue( 2, 0 ), 12 ) ) {
2287                 return false;
2288             }
2289             if ( !isEqual( ma1[ 1 ].getValue( 3, 0 ), 13 ) ) {
2290                 return false;
2291             }
2292             if ( !isEqual( ma1[ 1 ].getValue( 0, 1 ), 11 ) ) {
2293                 return false;
2294             }
2295             if ( !isEqual( ma1[ 1 ].getValue( 1, 1 ), 0 ) ) {
2296                 return false;
2297             }
2298             if ( !isEqual( ma1[ 1 ].getValue( 2, 1 ), 14 ) ) {
2299                 return false;
2300             }
2301             if ( !isEqual( ma1[ 1 ].getValue( 3, 1 ), 15 ) ) {
2302                 return false;
2303             }
2304             if ( !isEqual( ma1[ 2 ].getValue( 0, 0 ), 0 ) ) {
2305                 return false;
2306             }
2307             if ( !isEqual( ma1[ 2 ].getValue( 1, 0 ), 21 ) ) {
2308                 return false;
2309             }
2310             if ( !isEqual( ma1[ 2 ].getValue( 2, 0 ), 22 ) ) {
2311                 return false;
2312             }
2313             if ( !isEqual( ma1[ 2 ].getValue( 3, 0 ), 23 ) ) {
2314                 return false;
2315             }
2316             if ( !isEqual( ma1[ 2 ].getValue( 0, 1 ), 21 ) ) {
2317                 return false;
2318             }
2319             if ( !isEqual( ma1[ 2 ].getValue( 1, 1 ), 0 ) ) {
2320                 return false;
2321             }
2322             if ( !isEqual( ma1[ 2 ].getValue( 2, 1 ), 24 ) ) {
2323                 return false;
2324             }
2325             if ( !isEqual( ma1[ 2 ].getValue( 3, 1 ), 25 ) ) {
2326                 return false;
2327             }
2328             source = new StringBuffer();
2329             source.append( "A 0" + l );
2330             source.append( "B 10 0" + l );
2331             final DistanceMatrix[] ma2 = p0.parse( source.toString() );
2332             if ( ma2.length != 1 ) {
2333                 return false;
2334             }
2335             if ( !isEqual( ma2[ 0 ].getValue( 0, 1 ), 10 ) ) {
2336                 return false;
2337             }
2338             source = new StringBuffer();
2339             source.append( " " + l );
2340             source.append( "#" + l );
2341             final DistanceMatrix[] ma3 = p0.parse( source.toString() );
2342             if ( ma3.length != 0 ) {
2343                 return false;
2344             }
2345             source = new StringBuffer();
2346             source.append( " " + l );
2347             source.append( "A 0   11  12  13" + l );
2348             source.append( "B     0   14  15" + l );
2349             source.append( "C         0   16" + l );
2350             source.append( "D              0" + l );
2351             source.append( l );
2352             source.append( "A 0 21  22  23" + l );
2353             source.append( "B 0 24  25" + l );
2354             source.append( "C 0 26" + l );
2355             source.append( "D 0" + l );
2356             p0.setInputMatrixType( SymmetricalDistanceMatrixParser.InputMatrixType.UPPER_TRIANGLE );
2357             final DistanceMatrix[] ma4 = p0.parse( source );
2358             if ( ma4.length != 2 ) {
2359                 return false;
2360             }
2361             if ( !isEqual( ma4[ 0 ].getValue( 0, 0 ), 0 ) ) {
2362                 return false;
2363             }
2364             if ( !isEqual( ma4[ 0 ].getValue( 1, 0 ), 11 ) ) {
2365                 return false;
2366             }
2367             if ( !isEqual( ma4[ 0 ].getValue( 2, 0 ), 12 ) ) {
2368                 return false;
2369             }
2370             if ( !isEqual( ma4[ 0 ].getValue( 3, 0 ), 13 ) ) {
2371                 return false;
2372             }
2373             if ( !isEqual( ma4[ 0 ].getValue( 0, 1 ), 11 ) ) {
2374                 return false;
2375             }
2376             if ( !isEqual( ma4[ 0 ].getValue( 1, 1 ), 0 ) ) {
2377                 return false;
2378             }
2379             if ( !isEqual( ma4[ 0 ].getValue( 2, 1 ), 14 ) ) {
2380                 return false;
2381             }
2382             if ( !isEqual( ma4[ 0 ].getValue( 3, 1 ), 15 ) ) {
2383                 return false;
2384             }
2385             if ( !isEqual( ma4[ 0 ].getValue( 0, 2 ), 12 ) ) {
2386                 return false;
2387             }
2388             if ( !isEqual( ma4[ 0 ].getValue( 1, 2 ), 14 ) ) {
2389                 return false;
2390             }
2391             if ( !isEqual( ma4[ 0 ].getValue( 2, 2 ), 0 ) ) {
2392                 return false;
2393             }
2394             if ( !isEqual( ma4[ 0 ].getValue( 3, 2 ), 16 ) ) {
2395                 return false;
2396             }
2397             if ( !isEqual( ma4[ 0 ].getValue( 0, 3 ), 13 ) ) {
2398                 return false;
2399             }
2400             if ( !isEqual( ma4[ 0 ].getValue( 1, 3 ), 15 ) ) {
2401                 return false;
2402             }
2403             if ( !isEqual( ma4[ 0 ].getValue( 2, 3 ), 16 ) ) {
2404                 return false;
2405             }
2406             if ( !isEqual( ma4[ 0 ].getValue( 3, 3 ), 0 ) ) {
2407                 return false;
2408             }
2409             source = new StringBuffer();
2410             source.append( " 4 " + l );
2411             source.append( "A 0   11  12  13" + l );
2412             source.append( "B     0   14  15" + l );
2413             source.append( "C         0   16" + l );
2414             source.append( "D              0" + l );
2415             source.append( " 4" + l );
2416             source.append( "A 0 21  22  23" + l );
2417             source.append( "B 0 24  25" + l );
2418             source.append( "C 0 26" + l );
2419             source.append( "D 0" + l );
2420             source.append( "     " + l );
2421             source.append( " 4" + l );
2422             source.append( "A 0 21  22  23" + l );
2423             source.append( "B 0 24  25" + l );
2424             source.append( "C 0 26" + l );
2425             source.append( "D 0" + l );
2426             source.append( l );
2427             source.append( "A 0 21  22  23" + l );
2428             source.append( "B 0 24  25" + l );
2429             source.append( "C 0 26" + l );
2430             source.append( "D 0" + l );
2431             p0.setInputMatrixType( SymmetricalDistanceMatrixParser.InputMatrixType.UPPER_TRIANGLE );
2432             final DistanceMatrix[] ma5 = p0.parse( source );
2433             if ( ma5.length != 4 ) {
2434                 return false;
2435             }
2436             if ( !isEqual( ma5[ 0 ].getValue( 0, 0 ), 0 ) ) {
2437                 return false;
2438             }
2439             if ( !isEqual( ma5[ 0 ].getValue( 1, 0 ), 11 ) ) {
2440                 return false;
2441             }
2442             if ( !isEqual( ma5[ 0 ].getValue( 2, 0 ), 12 ) ) {
2443                 return false;
2444             }
2445             if ( !isEqual( ma5[ 0 ].getValue( 3, 0 ), 13 ) ) {
2446                 return false;
2447             }
2448             if ( !isEqual( ma5[ 0 ].getValue( 0, 1 ), 11 ) ) {
2449                 return false;
2450             }
2451             if ( !isEqual( ma5[ 0 ].getValue( 1, 1 ), 0 ) ) {
2452                 return false;
2453             }
2454             if ( !isEqual( ma5[ 0 ].getValue( 2, 1 ), 14 ) ) {
2455                 return false;
2456             }
2457             if ( !isEqual( ma5[ 0 ].getValue( 3, 1 ), 15 ) ) {
2458                 return false;
2459             }
2460             if ( !isEqual( ma5[ 0 ].getValue( 0, 2 ), 12 ) ) {
2461                 return false;
2462             }
2463             if ( !isEqual( ma5[ 0 ].getValue( 1, 2 ), 14 ) ) {
2464                 return false;
2465             }
2466             if ( !isEqual( ma5[ 0 ].getValue( 2, 2 ), 0 ) ) {
2467                 return false;
2468             }
2469             if ( !isEqual( ma5[ 0 ].getValue( 3, 2 ), 16 ) ) {
2470                 return false;
2471             }
2472             if ( !isEqual( ma5[ 0 ].getValue( 0, 3 ), 13 ) ) {
2473                 return false;
2474             }
2475             if ( !isEqual( ma5[ 0 ].getValue( 1, 3 ), 15 ) ) {
2476                 return false;
2477             }
2478             if ( !isEqual( ma5[ 0 ].getValue( 2, 3 ), 16 ) ) {
2479                 return false;
2480             }
2481             if ( !isEqual( ma5[ 0 ].getValue( 3, 3 ), 0 ) ) {
2482                 return false;
2483             }
2484         }
2485         catch ( final Exception e ) {
2486             e.printStackTrace( System.out );
2487             return false;
2488         }
2489         return true;
2490     }
2491
2492     private static void timeNeighborJoining() {
2493         final NeighborJoining nj = NeighborJoining.createInstance();
2494         for( int n = 3; n <= 10; ++n ) {
2495             final int x = ( int ) Math.pow( 2, n );
2496             final BasicSymmetricalDistanceMatrix mt = new BasicSymmetricalDistanceMatrix( x );
2497             mt.randomize( new Date().getTime() );
2498             //  for( int i = 0; i < mt.getSize(); i++ ) {
2499             //      mt.setIdentifier( i, i + "i" );
2500             //  }
2501             //  System.out.println( mt.toStringBuffer( Format.PHYLIP ) );
2502             final long start_time = new Date().getTime();
2503             nj.execute( mt );
2504             System.out.println( "Size: " + x + " -> " + ( new Date().getTime() - start_time ) + "ms" );
2505         }
2506     }
2507 }