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