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