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