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