001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021 022 023package org.biojava.bio.dp.twohead; 024 025import java.io.File; 026import java.io.FileNotFoundException; 027import java.io.FileOutputStream; 028import java.io.IOException; 029import java.io.OutputStream; 030import java.io.PrintStream; 031import java.lang.reflect.Constructor; 032import java.lang.reflect.InvocationTargetException; 033import java.util.HashMap; 034import java.util.Iterator; 035import java.util.Map; 036 037import org.biojava.bio.BioError; 038import org.biojava.bio.BioException; 039import org.biojava.bio.dist.Distribution; 040import org.biojava.bio.dp.BackPointer; 041import org.biojava.bio.dp.DP; 042import org.biojava.bio.dp.EmissionState; 043import org.biojava.bio.dp.IllegalTransitionException; 044import org.biojava.bio.dp.MagicalState; 045import org.biojava.bio.dp.MarkovModel; 046import org.biojava.bio.dp.ScoreType; 047import org.biojava.bio.dp.State; 048import org.biojava.bio.symbol.AlphabetIndex; 049import org.biojava.bio.symbol.AlphabetManager; 050import org.biojava.bio.symbol.FiniteAlphabet; 051import org.biojava.bio.symbol.IllegalAlphabetException; 052import org.biojava.bio.symbol.IllegalSymbolException; 053import org.biojava.bio.symbol.Symbol; 054import org.biojava.utils.ClassTools; 055import org.biojava.utils.bytecode.ByteCode; 056import org.biojava.utils.bytecode.CodeClass; 057import org.biojava.utils.bytecode.CodeException; 058import org.biojava.utils.bytecode.CodeField; 059import org.biojava.utils.bytecode.CodeGenerator; 060import org.biojava.utils.bytecode.CodeMethod; 061import org.biojava.utils.bytecode.CodeUtils; 062import org.biojava.utils.bytecode.GeneratedClassLoader; 063import org.biojava.utils.bytecode.GeneratedCodeClass; 064import org.biojava.utils.bytecode.GeneratedCodeMethod; 065import org.biojava.utils.bytecode.IfExpression; 066import org.biojava.utils.bytecode.InstructionVector; 067import org.biojava.utils.bytecode.IntrospectedCodeClass; 068import org.biojava.utils.bytecode.LocalVariable; 069 070/** 071 * This is an implementation of CellCalculatorFactoryMaker that compiles the 072 * HMM object down to Java byte-code that is equivalent in behaviour to the 073 * interpreter. 074 * 075 * @author Matthew Pocock 076 * @author Greg Cox 077 * @since 1.1 078 */ 079 080public class DPCompiler implements CellCalculatorFactoryMaker { 081 //private final boolean debug = false; 082 private final boolean debug = true; 083 084 private final boolean dumpToDisk; 085 086 private final GeneratedClassLoader classLoader; 087 088 public DPCompiler(boolean dumpToDisk) { 089 this.dumpToDisk = dumpToDisk; 090 classLoader = new GeneratedClassLoader(ClassTools.getClassLoader(this)); 091 } 092 093 public CellCalculatorFactory make(DP dp) { 094 Class forwardC = generateForardClass(dp); 095 Class backwardC = generateBackwardClass(dp); 096 Class viterbiC = generateViterbiClass(dp); 097 098 try { 099 Constructor forward = forwardC.getConstructor(new Class[] { 100 DP.class, 101 ScoreType.class 102 }); 103 Constructor backward = backwardC.getConstructor(new Class[] { 104 DP.class, 105 ScoreType.class 106 }); 107 Constructor viterbi = viterbiC.getConstructor(new Class[] { 108 DP.class, 109 ScoreType.class, 110 BackPointer.class 111 }); 112 return new Factory(dp, forward, backward, viterbi); 113 } catch (NoSuchMethodException nsme) { 114 throw new BioError("Couldn't find constructor on generated class", nsme); 115 } 116 } 117 118 public static String makeName(String prefix, MarkovModel model) { 119 StringBuffer nameBuffer = new StringBuffer(prefix); 120 121 for(Iterator i = model.stateAlphabet().iterator(); i.hasNext(); ) { 122 nameBuffer.append("_"); 123 try { 124 nameBuffer.append(model.transitionsFrom((State) i.next()).size()); 125 } catch (IllegalSymbolException ise) { 126 throw new BioError( 127 "Assertion Failure: State dissapeared from model", ise 128 ); 129 } 130 } 131 132 return nameBuffer.substring(0); 133 } 134 135 public Class generateForardClass(DP dp) { 136 // forward recursion is: 137 // 138 // score[state_i] = 139 // emission * sum_j(prev_score[state_j] * transition[state_j, state_i]) 140 // 141 // where prev_score is found as score[advance_i[0][advance_i[1]] 142 // however, in log space (as we use), this becomes: 143 // 144 // score[state_i] = 145 // emission + log( sum_j ( 146 // exp(prev_score[state_j] + transition[state_i, state_j]) 147 // )) 148 // 149 // In practice, for sequences of any length, the sum terms are too 150 // near to zero for numerical instablilty not to play a huge part. So, we 151 // take out a factor of max_j( prev_score[state_j] ) from the sum and add 152 // it to the total. 153 // 154 // score[state_i] = 155 // emission + log( sum_j ( 156 // exp(transition[state_i, state_j] + (prev_score[state_j]- factor) ) 157 // )) + factor 158 159 160 try { 161 MarkovModel model = dp.getModel(); 162 163 String name = makeName("org.biojava.bio.dp.twohead.Forward", model); 164 if(!classLoader.hasGeneratedClass(name)) { 165 CodeClass _Object = IntrospectedCodeClass.forClass(Object.class); 166 CodeClass _DP = IntrospectedCodeClass.forClass(DP.class); 167 CodeClass _ScoreType = IntrospectedCodeClass.forClass(ScoreType.class); 168 CodeClass _State_A = IntrospectedCodeClass.forClass(State [].class); 169 CodeClass _Cell_A_A = IntrospectedCodeClass.forClass(Cell [][].class); 170 CodeClass _CellCalculator = IntrospectedCodeClass.forClass(CellCalculator.class); 171 172 GeneratedCodeClass clazz = new GeneratedCodeClass( 173 name, 174 _Object, 175 new CodeClass[] {_CellCalculator}, 176 CodeUtils.ACC_PUBLIC | CodeUtils.ACC_STRICT 177 ); 178 179 State[] states = dp.getStates(); 180 AlphabetIndex stateIndexer = AlphabetManager.getAlphabetIndex(states); 181 182 CodeField stateF = clazz.createField( 183 "states", 184 _State_A, 185 CodeUtils.ACC_PROTECTED 186 ); 187 188 // The fields that contain transition scores as double []. 189 // This is built so that if two states shair the same transition 190 // distribution, they refer to the same transition field. This gives 191 // good optimizers a fighting chance to do some hard-core optimizations. 192 CodeField[] transitionFields = new CodeField[states.length]; 193 AlphabetIndex[] transitionIndexers = new AlphabetIndex[states.length]; 194 195 // The constructor must load in the transition probabilities. 196 // It uses the indexToFieldIndex to ensure that parameters are loaded 197 // just once. 198 GeneratedCodeMethod __init = clazz.createMethod( 199 "<init>", 200 CodeUtils.TYPE_VOID, 201 new CodeClass[] {_DP, _ScoreType }, 202 new String[] { "dp", "scoreType" }, 203 CodeUtils.ACC_PUBLIC 204 ); 205 206 clazz.setCodeGenerator(__init, createInit( 207 model, states, 208 clazz, __init, 209 transitionIndexers, transitionFields, 210 stateF, null 211 )); 212 213 GeneratedCodeMethod initialize = clazz.createMethod( 214 "initialize", 215 CodeUtils.TYPE_VOID, 216 new CodeClass[] {_Cell_A_A}, 217 new String[] { "cells" }, 218 CodeUtils.ACC_PUBLIC 219 ); 220 clazz.setCodeGenerator( 221 initialize, 222 createFRecursion( 223 true, 224 model, states, stateIndexer, 225 stateF, transitionFields, transitionIndexers, 226 initialize 227 ) 228 ); 229 230 GeneratedCodeMethod calcCell = clazz.createMethod( 231 "calcCell", 232 CodeUtils.TYPE_VOID, 233 new CodeClass[] {_Cell_A_A }, 234 new String[] { "cells" }, 235 CodeUtils.ACC_PUBLIC 236 ); 237 clazz.setCodeGenerator( 238 calcCell, 239 createFRecursion( 240 false, 241 model, states, stateIndexer, 242 stateF, transitionFields, transitionIndexers, 243 calcCell 244 ) 245 ); 246 247 if(dumpToDisk == true) { 248 try { 249 StringBuffer fName = new StringBuffer(name); 250 for(int i = 0; i < fName.length(); i++) { 251 if(fName.charAt(i) == '.') { 252 fName.setCharAt(i, '/'); 253 } 254 } 255 fName.append(".class"); 256 257 File dumpFile = new File(fName.substring(0)); 258 System.out.println("Dumping file: " + fName); 259 dumpFile.getParentFile().mkdirs(); 260 261 OutputStream out = new FileOutputStream(dumpFile); 262 clazz.createCode(out); 263 out.close(); 264 } catch (FileNotFoundException fnfe) { 265 throw new BioError("Couldn't dump dp class", fnfe); 266 } catch (IOException ioe) { 267 throw new BioError("Couldn't dump dp class", ioe); 268 } 269 } 270 271 classLoader.defineClass(clazz); 272 } 273 try { 274 return classLoader.loadClass(name); 275 } catch (Exception e) { 276 throw new BioError("Can't find previously generated class for " + name, e); 277 } 278 } catch (CodeException ce) { 279 throw new BioError("Couldn't generate class", ce); 280 } catch (NoSuchMethodException nsme) { 281 throw new BioError( "Couldn't find method", nsme); 282 } catch (NoSuchFieldException nsfe) { 283 throw new BioError("Couldn't find field", nsfe); 284 } catch (IllegalSymbolException ise) { 285 throw new BioError("Couldn't find symbol", ise); 286 } catch (BioException be) { 287 throw new BioError("Couldn't create indexer", be); 288 } 289 } 290 291 public Class generateBackwardClass(DP dp) { 292 // backward recursion is: 293 // score[state_i] = 294 // sum_j(prev_score[state_j] * transition[state_i, state_j] * emission[j]) 295 // where prev_score is found as score[advance_j[0][advance_j[1]] 296 // however, in log space (as we use), this becomes: 297 // score[state_i] = 298 // emission + log( sum_j ( 299 // exp(prev_score[state_j] + transition[state_j, state_i) 300 // )) 301 // 302 // In practice, for sequences of any length, the sum terms are too 303 // near to zero for numerical instablilty not to play a huge part. So, we 304 // take out a factor of max_j( prev_score[state_j] ) from the sum and add 305 // it to the total. 306 307 try { 308 MarkovModel model = dp.getModel(); 309 310 String name = makeName("org.biojava.bio.dp.twohead.Backward", model); 311 if(!classLoader.hasGeneratedClass(name)) { 312 CodeClass _Object = IntrospectedCodeClass.forClass(Object.class); 313 CodeClass _DP = IntrospectedCodeClass.forClass(DP.class); 314 CodeClass _ScoreType = IntrospectedCodeClass.forClass(ScoreType.class); 315 CodeClass _State_A = IntrospectedCodeClass.forClass(State [].class); 316 CodeClass _Cell_A_A = IntrospectedCodeClass.forClass(Cell [][].class); 317 CodeClass _CellCalculator = IntrospectedCodeClass.forClass(CellCalculator.class); 318 319 GeneratedCodeClass clazz = new GeneratedCodeClass( 320 name, 321 _Object, 322 new CodeClass[] {_CellCalculator}, 323 CodeUtils.ACC_PUBLIC | CodeUtils.ACC_STRICT 324 ); 325 326 State[] states = dp.getStates(); 327 AlphabetIndex stateIndexer = AlphabetManager.getAlphabetIndex(states); 328 329 CodeField stateF = clazz.createField( 330 "states", 331 _State_A, 332 CodeUtils.ACC_PROTECTED 333 ); 334 335 // The fields that contain transition scores as double []. 336 // This is built so that if two states shair the same transition 337 // distribution, they refer to the same transition field. This gives 338 // good optimizers a fighting chance to do some hard-core optimizations. 339 CodeField[] transitionFields = new CodeField[states.length]; 340 AlphabetIndex[] transitionIndexers = new AlphabetIndex[states.length]; 341 342 // The constructor must load in the transition probabilities. 343 // It uses the indexToFieldIndex to ensure that parameters are loaded 344 // just once. 345 GeneratedCodeMethod __init = clazz.createMethod( 346 "<init>", 347 CodeUtils.TYPE_VOID, 348 new CodeClass[] {_DP, _ScoreType }, 349 new String[] { "dp", "scoreType" }, 350 CodeUtils.ACC_PUBLIC 351 ); 352 353 clazz.setCodeGenerator(__init, createInit( 354 model, states, 355 clazz, __init, 356 transitionIndexers, transitionFields, 357 stateF, null 358 )); 359 360 GeneratedCodeMethod initialize = clazz.createMethod( 361 "initialize", 362 CodeUtils.TYPE_VOID, 363 new CodeClass[] {_Cell_A_A}, 364 new String[] { "cells" }, 365 CodeUtils.ACC_PUBLIC 366 ); 367 clazz.setCodeGenerator( 368 initialize, 369 createBRecursion( 370 true, 371 model, states, stateIndexer, 372 stateF, transitionFields, transitionIndexers, 373 initialize 374 ) 375 ); 376 377 GeneratedCodeMethod calcCell = clazz.createMethod( 378 "calcCell", 379 CodeUtils.TYPE_VOID, 380 new CodeClass[] {_Cell_A_A }, 381 new String[] { "cells" }, 382 CodeUtils.ACC_PUBLIC 383 ); 384 clazz.setCodeGenerator( 385 calcCell, 386 createBRecursion( 387 false, 388 model, states, stateIndexer, 389 stateF, transitionFields, transitionIndexers, 390 calcCell 391 ) 392 ); 393 394 if(dumpToDisk == true) { 395 try { 396 StringBuffer fName = new StringBuffer(name); 397 for(int i = 0; i < fName.length(); i++) { 398 if(fName.charAt(i) == '.') { 399 fName.setCharAt(i, '/'); 400 } 401 } 402 fName.append(".class"); 403 404 File dumpFile = new File(fName.substring(0)); 405 System.out.println("Dumping file: " + fName); 406 dumpFile.getParentFile().mkdirs(); 407 408 OutputStream out = new FileOutputStream(dumpFile); 409 clazz.createCode(out); 410 out.close(); 411 } catch (FileNotFoundException fnfe) { 412 throw new BioError( "Couldn't dump dp class", fnfe); 413 } catch (IOException ioe) { 414 throw new BioError( "Couldn't dump dp class", ioe); 415 } 416 } 417 418 classLoader.defineClass(clazz); 419 } 420 try { 421 return classLoader.loadClass(name); 422 } catch (Exception e) { 423 throw new BioError("Can't find previously generated class for " + name, e); 424 } 425 } catch (CodeException ce) { 426 throw new BioError("Couldn't generate class", ce); 427 } catch (NoSuchMethodException nsme) { 428 throw new BioError( "Couldn't find method", nsme); 429 } catch (NoSuchFieldException nsfe) { 430 throw new BioError( "Couldn't find field", nsfe); 431 } catch (IllegalSymbolException ise) { 432 throw new BioError( "Couldn't find symbol", ise); 433 } catch (BioException be) { 434 throw new BioError( "Couldn't create indexer", be); 435 } 436 } 437 438 public Class generateViterbiClass(DP dp) { 439 // viterbi recursion is: 440 // score[state_i] = 441 // emission * max_j(prev_score[state_j] * transition[state_j, state_i]) 442 // however, in log space (as we use), this becomes: 443 // score[state_i] = 444 // emission + max_j( 445 // prev_score[state_j] + transition[state_j, state_i] 446 // )) 447 448 try { 449 MarkovModel model = dp.getModel(); 450 451 String name = makeName("org.biojava.bio.dp.twohead.Viterbi", model); 452 if(!classLoader.hasGeneratedClass(name)) { 453 454 CodeClass _Object = IntrospectedCodeClass.forClass(Object.class); 455 CodeClass _DP = IntrospectedCodeClass.forClass(DP.class); 456 CodeClass _BackPointer = IntrospectedCodeClass.forClass(BackPointer.class); 457 CodeClass _ScoreType = IntrospectedCodeClass.forClass(ScoreType.class); 458 CodeClass _State_A = IntrospectedCodeClass.forClass(State [].class); 459 CodeClass _Cell_A_A = IntrospectedCodeClass.forClass(Cell [][].class); 460 CodeClass _CellCalculator = IntrospectedCodeClass.forClass(CellCalculator.class); 461 462 GeneratedCodeClass clazz = new GeneratedCodeClass( 463 name, 464 _Object, 465 new CodeClass[] {_CellCalculator}, 466 CodeUtils.ACC_PUBLIC | CodeUtils.ACC_STRICT 467 ); 468 469 State[] states = dp.getStates(); 470 AlphabetIndex stateIndexer = AlphabetManager.getAlphabetIndex(states); 471 472 CodeField terminalBP = clazz.createField( 473 "terminalBP", 474 _BackPointer, 475 CodeUtils.ACC_PROTECTED 476 ); 477 478 CodeField stateF = clazz.createField( 479 "states", 480 _State_A, 481 CodeUtils.ACC_PROTECTED 482 ); 483 484 // The fields that contain transition scores as double []. 485 // This is built so that if two states shair the same transition 486 // distribution, they refer to the same transition field. This gives 487 // good optimizers a fighting chance to do some hard-core optimizations. 488 CodeField[] transitionFields = new CodeField[states.length]; 489 AlphabetIndex[] transitionIndexers = new AlphabetIndex[states.length]; 490 491 // The constructor must load in the transition probabilities. 492 // It uses the indexToFieldIndex to ensure that parameters are loaded 493 // just once. 494 GeneratedCodeMethod __init = clazz.createMethod( 495 "<init>", 496 CodeUtils.TYPE_VOID, 497 new CodeClass[] {_DP, _ScoreType, _BackPointer }, 498 new String[] { "dp", "scoreType", "backPointer" }, 499 CodeUtils.ACC_PUBLIC 500 ); 501 502 clazz.setCodeGenerator(__init, createInit( 503 model, states, 504 clazz, __init, 505 transitionIndexers, transitionFields, 506 stateF, terminalBP 507 )); 508 509 GeneratedCodeMethod initialize = clazz.createMethod( 510 "initialize", 511 CodeUtils.TYPE_VOID, 512 new CodeClass[] {_Cell_A_A}, 513 new String[] { "cells" }, 514 CodeUtils.ACC_PUBLIC 515 ); 516 clazz.setCodeGenerator( 517 initialize, 518 createVRecursion( 519 true, 520 model, states, stateIndexer, 521 stateF, transitionFields, transitionIndexers, 522 terminalBP, 523 initialize 524 ) 525 ); 526 527 GeneratedCodeMethod calcCell = clazz.createMethod( 528 "calcCell", 529 CodeUtils.TYPE_VOID, 530 new CodeClass[] {_Cell_A_A }, 531 new String[] { "cells" }, 532 CodeUtils.ACC_PUBLIC 533 ); 534 clazz.setCodeGenerator( 535 calcCell, 536 createVRecursion( 537 false, 538 model, states, stateIndexer, 539 stateF, transitionFields, transitionIndexers, 540 terminalBP, 541 calcCell 542 ) 543 ); 544 545 if(dumpToDisk == true) { 546 try { 547 StringBuffer fName = new StringBuffer(name); 548 for(int i = 0; i < fName.length(); i++) { 549 if(fName.charAt(i) == '.') { 550 fName.setCharAt(i, '/'); 551 } 552 } 553 fName.append(".class"); 554 555 File dumpFile = new File(fName.substring(0)); 556 System.out.println("Dumping file: " + fName); 557 dumpFile.getParentFile().mkdirs(); 558 559 OutputStream out = new FileOutputStream(dumpFile); 560 clazz.createCode(out); 561 out.close(); 562 } catch (FileNotFoundException fnfe) { 563 throw new BioError( "Couldn't dump dp class", fnfe); 564 } catch (IOException ioe) { 565 throw new BioError( "Couldn't dump dp class", ioe); 566 } 567 } 568 569 classLoader.defineClass(clazz); 570 } 571 try { 572 return classLoader.loadClass(name); 573 } catch (Exception e) { 574 throw new BioError( "Can't find previously generated class for " + name, e); 575 } 576 } catch (CodeException ce) { 577 throw new BioError( "Couldn't generate class", ce); 578 } catch (NoSuchMethodException nsme) { 579 throw new BioError( "Couldn't find method", nsme); 580 } catch (NoSuchFieldException nsfe) { 581 throw new BioError( "Couldn't find field", nsfe); 582 } catch (IllegalSymbolException ise) { 583 throw new BioError( "Couldn't find symbol", ise); 584 } catch (BioException be) { 585 throw new BioError( "Couldn't create indexer", be); 586 } 587 } 588 589 CodeGenerator createVRecursion( 590 boolean isInit, 591 MarkovModel model, 592 State[] states, 593 AlphabetIndex stateIndex, 594 CodeField stateF, 595 CodeField [] transitionFields, 596 AlphabetIndex[] transitionIndexers, 597 CodeField terminalBP, 598 GeneratedCodeMethod method 599 ) throws 600 NoSuchMethodException, 601 NoSuchFieldException, 602 IllegalSymbolException, 603 CodeException 604 { 605 CodeClass _Cell = IntrospectedCodeClass.forClass(Cell.class); 606 CodeField _Cell_score = _Cell.getFieldByName("scores"); 607 CodeField _Cell_backpointer = _Cell.getFieldByName("backPointers"); 608 CodeField _Cell_emissions = _Cell.getFieldByName("emissions"); 609 CodeClass _State = IntrospectedCodeClass.forClass(State.class); 610 CodeClass _BackPointer = IntrospectedCodeClass.forClass(BackPointer.class); 611 CodeClass _BackPointer_A = IntrospectedCodeClass.forClass(BackPointer [].class); 612 CodeMethod _BackPointer_init = _BackPointer.getConstructor(new CodeClass [] {_State, _BackPointer, CodeUtils.TYPE_DOUBLE}); 613 CodeClass _double_A = IntrospectedCodeClass.forClass(double [].class); 614 615 InstructionVector ccV = new InstructionVector(); 616 617 // if(isInit && state instanceof emission) { 618 // cell[0][0] = (state == Magical) ? 0.0 : NaN; 619 // } else { 620 // cell[0][0].score[i] = cell[0][0].emissions[i] + 621 // max_j(cell[adv_i_0][adv_i_1] + t_j[i]) 622 // } 623 624 // cell_00 = cell[0][0]; 625 // cell_01 = cell[0][1]; 626 // cell_10 = cell[1][0]; 627 // cell_11 = cell[1][1]; 628 LocalVariable[][] cell = new LocalVariable[2][2]; 629 cell[0][0] = new LocalVariable(_Cell, "cell_00"); 630 cell[0][1] = new LocalVariable(_Cell, "cell_01"); 631 cell[1][0] = new LocalVariable(_Cell, "cell_10"); 632 cell[1][1] = new LocalVariable(_Cell, "cell_11"); 633 634 ccV.add( ByteCode.make_aload (method.getVariable("cells"))); 635 ccV.add( ByteCode.make_dup ()); 636 ccV.add( ByteCode.make_iconst (0)); 637 ccV.add( ByteCode.make_aaload ()); 638 ccV.add( ByteCode.make_dup ()); 639 ccV.add( ByteCode.make_iconst (0)); 640 ccV.add( ByteCode.make_aaload ()); 641 ccV.add( ByteCode.make_astore (cell[0][0])); 642 ccV.add( ByteCode.make_iconst (1)); 643 ccV.add( ByteCode.make_aaload ()); 644 ccV.add( ByteCode.make_astore (cell[0][1])); 645 ccV.add( ByteCode.make_iconst (1)); 646 ccV.add( ByteCode.make_aaload ()); 647 ccV.add( ByteCode.make_dup ()); 648 ccV.add( ByteCode.make_iconst (0)); 649 ccV.add( ByteCode.make_aaload ()); 650 ccV.add( ByteCode.make_astore (cell[1][0])); 651 ccV.add( ByteCode.make_iconst (1)); 652 ccV.add( ByteCode.make_aaload ()); 653 ccV.add( ByteCode.make_astore (cell[1][1])); 654 655 // score_00 = cell[0][0].score; 656 // score_01 = cell[0][1].score; 657 // score_10 = cell[1][0].score; 658 // score_11 = cell[1][1].score; 659 660 LocalVariable[][] score = new LocalVariable[2][2]; 661 score[0][0] = new LocalVariable(_double_A, "score_00"); 662 score[0][1] = new LocalVariable(_double_A, "score_01"); 663 score[1][0] = new LocalVariable(_double_A, "score_10"); 664 score[1][1] = new LocalVariable(_double_A, "score_11"); 665 ccV.add( ByteCode.make_aload (cell[0][0])); 666 ccV.add( ByteCode.make_getfield ( _Cell_score)); 667 ccV.add( ByteCode.make_astore (score[0][0])); 668 ccV.add( ByteCode.make_aload (cell[0][1])); 669 ccV.add( ByteCode.make_getfield ( _Cell_score)); 670 ccV.add( ByteCode.make_astore (score[0][1])); 671 ccV.add( ByteCode.make_aload (cell[1][0])); 672 ccV.add( ByteCode.make_getfield ( _Cell_score)); 673 ccV.add( ByteCode.make_astore (score[1][0])); 674 ccV.add( ByteCode.make_aload (cell[1][1])); 675 ccV.add( ByteCode.make_getfield ( _Cell_score)); 676 ccV.add( ByteCode.make_astore (score[1][1])); 677 678 // backpointer_00 = cell[0][0].backpointer; 679 // backpointer_01 = cell[0][1].backpointer; 680 // backpointer_10 = cell[1][0].backpointer; 681 // backpointer_11 = cell[1][1].backpointer; 682 683 LocalVariable[][] backpointer = new LocalVariable[2][2]; 684 backpointer[0][0] = new LocalVariable(_BackPointer_A, "backpointer_00"); 685 backpointer[0][1] = new LocalVariable(_BackPointer_A, "backpointer_01"); 686 backpointer[1][0] = new LocalVariable(_BackPointer_A, "backpointer_10"); 687 backpointer[1][1] = new LocalVariable(_BackPointer_A, "backpointer_11"); 688 ccV.add( ByteCode.make_aload (cell[0][0])); 689 ccV.add( ByteCode.make_getfield ( _Cell_backpointer)); 690 ccV.add( ByteCode.make_astore (backpointer[0][0])); 691 ccV.add( ByteCode.make_aload (cell[0][1])); 692 ccV.add( ByteCode.make_getfield ( _Cell_backpointer)); 693 ccV.add( ByteCode.make_astore (backpointer[0][1])); 694 ccV.add( ByteCode.make_aload (cell[1][0])); 695 ccV.add( ByteCode.make_getfield ( _Cell_backpointer)); 696 ccV.add( ByteCode.make_astore (backpointer[1][0])); 697 ccV.add( ByteCode.make_aload (cell[1][1])); 698 ccV.add( ByteCode.make_getfield ( _Cell_backpointer)); 699 ccV.add( ByteCode.make_astore (backpointer[1][1])); 700 701 LocalVariable emissions = new LocalVariable(_double_A, "emissions"); 702 ccV.add( ByteCode.make_aload (cell[0][0] )); 703 ccV.add( ByteCode.make_getfield (_Cell_emissions)); 704 ccV.add( ByteCode.make_astore (emissions)); 705 706 LocalVariable max = new LocalVariable(CodeUtils.TYPE_DOUBLE, "max"); 707 LocalVariable max_j = new LocalVariable(CodeUtils.TYPE_INT, "max_j"); 708 for(int i = 0; i < states.length; i++) { 709 State state = states[i]; 710 InstructionVector stateV = new InstructionVector(); 711 if(isInit && state instanceof EmissionState) { 712 stateV.add( ByteCode.make_aload (score[0][0])); 713 stateV.add( ByteCode.make_iconst (i)); 714 if(state instanceof MagicalState) { 715 stateV.add( ByteCode.make_dconst (0.0)); 716 stateV.add( ByteCode.make_aload (backpointer[0][0])); 717 stateV.add( ByteCode.make_iconst (i)); 718 stateV.add( ByteCode.make_aload (method.getThis())); 719 stateV.add( ByteCode.make_getfield (terminalBP)); 720 stateV.add( ByteCode.make_aastore ()); 721 } else { 722 stateV.add( ByteCode.make_dconst (Double.NaN)); 723 } 724 stateV.add( ByteCode.make_dastore ()); 725 } else { 726 int[] advance = getAdvance(state); 727 FiniteAlphabet trans = model.transitionsFrom(state); 728 729 // find max/argmax of t_j[i] + v[j] 730 // make a max pipeline 731 Iterator each_j = trans.iterator(); 732 State state_j; 733 int state_jIndx; 734 735 // first state primes the pump 736 stateV.add( ByteCode.make_dconst (Double.NEGATIVE_INFINITY)); 737 stateV.add( ByteCode.make_dstore (max)); 738 stateV.add( ByteCode.make_iconst (-1)); 739 stateV.add( ByteCode.make_istore (max_j)); 740 741 // then process each state 742 while(each_j.hasNext()) { 743 state_j = (State) each_j.next(); 744 state_jIndx = stateIndex.indexForSymbol(state_j); 745 stateV.add( createTransitionLastSum( 746 method, 747 transitionIndexers[state_jIndx].indexForSymbol(state), 748 state_jIndx, 749 transitionFields, 750 getAdvanced(score, advance) 751 )); 752 stateV.add( ByteCode.make_dup2 ()); 753 stateV.add( ByteCode.make_dload (max)); 754 stateV.add( ByteCode.make_dcmpl ()); 755 756 // if dcmpl is 1, we need to store the new max & imax. If either 757 // is NaN, keep the current max. 758 InstructionVector saveNewMax = new InstructionVector(); 759 saveNewMax.add( ByteCode.make_dstore (max)); 760 saveNewMax.add( ByteCode.make_iconst (state_jIndx)); 761 saveNewMax.add( ByteCode.make_istore (max_j)); 762 763 // if they are equal or max is greater or either is NaN 764 // dump current value 765 InstructionVector useOldMax = new InstructionVector(); 766 useOldMax.add( ByteCode.make_pop2()); 767 768 stateV.add( new IfExpression( 769 ByteCode.op_ifge, // branch if int on stack is >= 0 770 saveNewMax, 771 useOldMax 772 )); 773 } 774 775 // if (max_j == -1) 776 // score[i] = NaN 777 // bp[i] = null 778 // else 779 // sum = emissions[i] + max 780 // score[i] = sum 781 // bp[i] = new BackPointer(state[i], bp[adv_0][adv_1], sum) 782 // endif 783 784 // (max == max) && (max_j != -1) 785 stateV.add( ByteCode.make_iload (max_j)); 786 787 InstructionVector ifNoIn = new InstructionVector(); 788 InstructionVector ifGotIn = new InstructionVector(); 789 790 ifNoIn.add( ByteCode.make_aload (score[0][0])); 791 ifNoIn.add( ByteCode.make_iconst (i)); 792 ifNoIn.add( ByteCode.make_dconst (Double.NaN)); 793 ifNoIn.add( ByteCode.make_dastore ()); 794 ifNoIn.add( ByteCode.make_aload (backpointer[0][0])); 795 ifNoIn.add( ByteCode.make_iconst (i)); 796 ifNoIn.add( ByteCode.make_aconst_null ()); 797 ifNoIn.add( ByteCode.make_aastore ()); 798 799 // score[i] = emissions[i] + max if emitting state, else score[i] = max 800 ifGotIn.add( ByteCode.make_aload (score[0][0])); 801 ifGotIn.add( ByteCode.make_iconst (i)); 802 ifGotIn.add( ByteCode.make_dload (max)); 803 if(state instanceof EmissionState) { 804 ifGotIn.add( ByteCode.make_aload (emissions)); 805 ifGotIn.add( ByteCode.make_iconst (i)); 806 ifGotIn.add( ByteCode.make_daload ()); 807 ifGotIn.add( ByteCode.make_dadd ()); 808 } 809 ifGotIn.add( ByteCode.make_dastore ()); 810 811 // backpointer[i] = new BackPointer( 812 // state[i], 813 // backPointer[adv_0][adv_1], 814 // score 815 // ); 816 817 // backpointer[i] = 818 ifGotIn.add( ByteCode.make_aload (backpointer[0][0])); 819 ifGotIn.add( ByteCode.make_iconst (i)); 820 821 // new BackPointer - dup for <init> invoke 822 ifGotIn.add( ByteCode.make_new (_BackPointer)); 823 ifGotIn.add( ByteCode.make_dup ()); 824 825 // state[i] 826 ifGotIn.add( ByteCode.make_aload (method.getThis())); 827 ifGotIn.add( ByteCode.make_getfield (stateF)); 828 ifGotIn.add( ByteCode.make_iconst (i)); 829 ifGotIn.add( ByteCode.make_aaload ()); 830 831 // backpointer[adv_0][adv_1] [max_j] 832 ifGotIn.add( ByteCode.make_aload (getAdvanced(backpointer, advance))); 833 ifGotIn.add( ByteCode.make_iload (max_j)); 834 ifGotIn.add( ByteCode.make_aaload ()); 835 836 // score[i] 837 ifGotIn.add( ByteCode.make_aload (score[0][0])); 838 ifGotIn.add( ByteCode.make_iconst (i)); 839 ifGotIn.add( ByteCode.make_daload ()); 840 841 // backpointer.<init> 842 ifGotIn.add( ByteCode.make_invokespecial( _BackPointer_init)); 843 844 // store backpointer 845 ifGotIn.add( ByteCode.make_aastore ()); 846 847 stateV.add( new IfExpression( 848 ByteCode.op_ifge, // ifge means max_j >= 0 849 ifGotIn, 850 ifNoIn 851 )); 852 } 853 ccV.add(stateV); 854 } 855 856 // dump out scores & backpointers 857 /*LocalVariable sc = new LocalVariable(CodeUtils.TYPE_DOUBLE, "score_i"); 858 LocalVariable bp = new LocalVariable(_BackPointer, "bp_i"); 859 for(int i = 0; i < states.length; i++) { 860 ccV.add( ByteCode.make_aload (score[0][0])); 861 ccV.add( ByteCode.make_iconst (i)); 862 ccV.add( ByteCode.make_daload ()); 863 ccV.add( ByteCode.make_dstore (sc)); 864 865 ccV.add( ByteCode.make_aload (backpointer[0][0])); 866 ccV.add( ByteCode.make_iconst (i)); 867 ccV.add( ByteCode.make_aaload ()); 868 ccV.add( ByteCode.make_astore (bp)); 869 } 870 */ 871 ccV.add( ByteCode.make_return ()); 872 873 return ccV; 874 } 875 876 private CodeGenerator createFRecursion( 877 boolean isInit, 878 MarkovModel model, 879 State[] states, 880 AlphabetIndex stateIndex, 881 CodeField stateF, 882 CodeField [] transitionFields, 883 AlphabetIndex[] transitionIndexers, 884 GeneratedCodeMethod method 885 ) throws 886 NoSuchMethodException, 887 NoSuchFieldException, 888 IllegalSymbolException, 889 CodeException 890 { 891 CodeClass _Cell = IntrospectedCodeClass.forClass(Cell.class); 892 CodeField _Cell_score = _Cell.getFieldByName("scores"); 893 CodeField _Cell_emissions = _Cell.getFieldByName("emissions"); 894 CodeClass _double_A = IntrospectedCodeClass.forClass(double [].class); 895 CodeClass _Math = IntrospectedCodeClass.forClass(Math.class); 896 CodeMethod _Math_exp = _Math.getMethod("exp", new CodeClass[] { CodeUtils.TYPE_DOUBLE }); 897 CodeMethod _Math_log = _Math.getMethod("log", new CodeClass[] { CodeUtils.TYPE_DOUBLE }); 898 899 InstructionVector ccV = new InstructionVector(); 900 901 ccV.add( debug(message("Retrieving local variables"))); 902 903 // if(isInit && state instanceof emission) { 904 // cell[0][0] = (state == Magical) ? 0.0 : NaN; 905 // } else { 906 // cell[0][0].score[i] = cell[0][0].emissions[i] + 907 // sum_j(cell[adv_i_0][adv_i_1] + t_j[i]) 908 // } 909 910 // cell_00 = cell[0][0]; 911 // cell_01 = cell[0][1]; 912 // cell_10 = cell[1][0]; 913 // cell_11 = cell[1][1]; 914 LocalVariable[][] cell = new LocalVariable[2][2]; 915 cell[0][0] = new LocalVariable(_Cell, "cell_00"); 916 cell[0][1] = new LocalVariable(_Cell, "cell_01"); 917 cell[1][0] = new LocalVariable(_Cell, "cell_10"); 918 cell[1][1] = new LocalVariable(_Cell, "cell_11"); 919 920 ccV.add( ByteCode.make_aload (method.getVariable("cells"))); 921 ccV.add( ByteCode.make_dup ()); 922 ccV.add( ByteCode.make_iconst (0)); 923 ccV.add( ByteCode.make_aaload ()); 924 ccV.add( ByteCode.make_dup ()); 925 ccV.add( ByteCode.make_iconst (0)); 926 ccV.add( ByteCode.make_aaload ()); 927 ccV.add( ByteCode.make_astore (cell[0][0])); 928 ccV.add( ByteCode.make_iconst (1)); 929 ccV.add( ByteCode.make_aaload ()); 930 ccV.add( ByteCode.make_astore (cell[0][1])); 931 ccV.add( ByteCode.make_iconst (1)); 932 ccV.add( ByteCode.make_aaload ()); 933 ccV.add( ByteCode.make_dup ()); 934 ccV.add( ByteCode.make_iconst (0)); 935 ccV.add( ByteCode.make_aaload ()); 936 ccV.add( ByteCode.make_astore (cell[1][0])); 937 ccV.add( ByteCode.make_iconst (1)); 938 ccV.add( ByteCode.make_aaload ()); 939 ccV.add( ByteCode.make_astore (cell[1][1])); 940 941 // score_00 = cell[0][0].score; 942 // score_01 = cell[0][1].score; 943 // score_10 = cell[1][0].score; 944 // score_11 = cell[1][1].score; 945 946 LocalVariable[][] score = new LocalVariable[2][2]; 947 score[0][0] = new LocalVariable(_double_A, "score_00"); 948 score[0][1] = new LocalVariable(_double_A, "score_01"); 949 score[1][0] = new LocalVariable(_double_A, "score_10"); 950 score[1][1] = new LocalVariable(_double_A, "score_11"); 951 ccV.add( ByteCode.make_aload (cell[0][0])); 952 ccV.add( ByteCode.make_getfield ( _Cell_score)); 953 ccV.add( ByteCode.make_astore (score[0][0])); 954 ccV.add( ByteCode.make_aload (cell[0][1])); 955 ccV.add( ByteCode.make_getfield ( _Cell_score)); 956 ccV.add( ByteCode.make_astore (score[0][1])); 957 ccV.add( ByteCode.make_aload (cell[1][0])); 958 ccV.add( ByteCode.make_getfield ( _Cell_score)); 959 ccV.add( ByteCode.make_astore (score[1][0])); 960 ccV.add( ByteCode.make_aload (cell[1][1])); 961 ccV.add( ByteCode.make_getfield ( _Cell_score)); 962 ccV.add( ByteCode.make_astore (score[1][1])); 963 964 LocalVariable emissions = new LocalVariable(_double_A, "emissions"); 965 ccV.add( ByteCode.make_aload (cell[0][0] )); 966 ccV.add( ByteCode.make_getfield (_Cell_emissions)); 967 ccV.add( ByteCode.make_astore (emissions)); 968 969 LocalVariable max = new LocalVariable(CodeUtils.TYPE_DOUBLE, "max"); 970 for(int i = 0; i < states.length; i++) { 971 State state = states[i]; 972 InstructionVector stateV = new InstructionVector(); 973 // we need to push score & i onto the stack so that after finding the sum 974 // we can just push it back into the array 975 stateV.add( ByteCode.make_aload (score[0][0])); 976 stateV.add( ByteCode.make_iconst (i)); 977 if(isInit && state instanceof EmissionState) { 978 if(state instanceof MagicalState) { 979 stateV.add( ByteCode.make_dconst (0.0)); 980 } else { 981 stateV.add( ByteCode.make_dconst (Double.NaN)); 982 } 983 } else { 984 int[] advance = getAdvance(state); 985 FiniteAlphabet trans = model.transitionsFrom(state); 986 987 LocalVariable j_scores = getAdvanced(score, advance); 988 989 if(trans.size() == 1) { 990 State state_j = (State) trans.iterator().next(); 991 int state_jIndx = stateIndex.indexForSymbol(state_j); 992 993 // only one source. F[i] = trans_j[i] + F[j] + e[i] 994 stateV.add( ByteCode.make_aload (method.getThis())); 995 stateV.add( ByteCode.make_getfield (transitionFields[state_jIndx])); 996 stateV.add( ByteCode.make_iconst (transitionIndexers[state_jIndx].indexForSymbol(state))); 997 stateV.add( ByteCode.make_daload ()); 998 stateV.add( ByteCode.make_aload (j_scores)); 999 stateV.add( ByteCode.make_iconst (state_jIndx)); 1000 stateV.add( ByteCode.make_daload ()); 1001 stateV.add( ByteCode.make_dadd ()); 1002 if(state instanceof EmissionState) { 1003 stateV.add( ByteCode.make_aload (emissions)); 1004 stateV.add( ByteCode.make_iconst (i)); 1005 stateV.add( ByteCode.make_daload ()); 1006 stateV.add( ByteCode.make_dadd ()); 1007 } 1008 } else { 1009 // f[i] = emission[i] + log( sum_j [ 1010 // exp( (j_scores[j] - max_j_score) + t_j[i] + e) 1011 // ]) + max_j_score 1012 1013 // find max j_scores 1014 stateV.add( ByteCode.make_dconst (Double.NEGATIVE_INFINITY)); 1015 stateV.add( ByteCode.make_dstore (max)); 1016 1017 Iterator each_j = trans.iterator(); 1018 while(each_j.hasNext()) { 1019 State state_j = (State) each_j.next(); 1020 int state_jIndx = stateIndex.indexForSymbol(state_j); 1021 stateV.add( ByteCode.make_aload (j_scores)); 1022 stateV.add( ByteCode.make_iconst (state_jIndx)); 1023 stateV.add( ByteCode.make_daload ()); 1024 stateV.add( ByteCode.make_dup2 ()); 1025 stateV.add( ByteCode.make_dload (max)); 1026 stateV.add( ByteCode.make_dcmpl ()); // puts -1 if max > this one 1027 1028 InstructionVector ifLargerThanMax = new InstructionVector(); 1029 ifLargerThanMax.add( ByteCode.make_dstore (max)); 1030 1031 InstructionVector ifSmallerThanMax = new InstructionVector(); 1032 ifSmallerThanMax.add( ByteCode.make_pop2()); 1033 1034 stateV.add( new IfExpression( 1035 ByteCode.op_ifge, // branch if int on stack >= 0 1036 ifLargerThanMax, 1037 ifSmallerThanMax 1038 )); 1039 } 1040 1041 LocalVariable maxDB = new LocalVariable(CodeUtils.TYPE_DOUBLE, "max"); 1042 InstructionVector dbi = new InstructionVector(); 1043 dbi.add( ByteCode.make_dload (max)); 1044 dbi.add( ByteCode.make_dstore (maxDB)); 1045 dbi.add( message("Max " + i + " = ", maxDB)); 1046 stateV.add( debug(dbi)); 1047 1048 // log sum of exponents - prime the sum with zero 1049 stateV.add( ByteCode.make_dconst (0.0)); 1050 1051 each_j = trans.iterator(); 1052 while(each_j.hasNext()) { 1053 State state_j = (State) each_j.next(); 1054 int state_jIndx = stateIndex.indexForSymbol(state_j); 1055 1056 // score 1057 stateV.add( ByteCode.make_aload (j_scores)); 1058 stateV.add( ByteCode.make_iconst (state_jIndx)); 1059 stateV.add( ByteCode.make_daload ()); 1060 1061 // is score NaN? 1062 stateV.add( ByteCode.make_dup2()); 1063 stateV.add( ByteCode.make_dup2()); 1064 stateV.add( ByteCode.make_dcmpl()); 1065 1066 InstructionVector scoreNotNaN = new InstructionVector(); 1067 // load max & subtract it from score 1068 // (j_score - max) 1069 scoreNotNaN.add( ByteCode.make_dload (max)); 1070 scoreNotNaN.add( ByteCode.make_dsub ()); 1071 1072 // exp( (j_score - max) + transition) 1073 scoreNotNaN.add( ByteCode.make_aload (method.getThis())); 1074 scoreNotNaN.add( ByteCode.make_getfield (transitionFields[state_jIndx])); 1075 scoreNotNaN.add( ByteCode.make_iconst (transitionIndexers[state_jIndx].indexForSymbol(state))); 1076 scoreNotNaN.add( ByteCode.make_daload ()); 1077 scoreNotNaN.add( ByteCode.make_dadd ()); 1078 scoreNotNaN.add( ByteCode.make_invokestatic (_Math_exp)); 1079 1080 // sum this and current sum 1081 scoreNotNaN.add( ByteCode.make_dadd()); 1082 1083 InstructionVector scoreIsNaN = new InstructionVector(); 1084 scoreIsNaN.add( ByteCode.make_pop2()); 1085 1086 stateV.add( new IfExpression( 1087 ByteCode.op_ifge, 1088 scoreNotNaN, 1089 scoreIsNaN 1090 )); 1091 } 1092 1093 // log sum 1094 stateV.add( ByteCode.make_invokestatic (_Math_log)); 1095 1096 if(state instanceof EmissionState) { 1097 // emissions[i] 1098 stateV.add( ByteCode.make_aload (emissions)); 1099 stateV.add( ByteCode.make_iconst (i)); 1100 stateV.add( ByteCode.make_daload ()); 1101 1102 // sum emission with j sum 1103 stateV.add( ByteCode.make_dadd ()); 1104 } 1105 1106 // lastly add on a factor of max - added here for maximum numerical stability 1107 stateV.add( ByteCode.make_dload (max)); 1108 stateV.add( ByteCode.make_dadd ()); 1109 } 1110 } 1111 // store score on stack into scores array 1112 stateV.add( ByteCode.make_dastore ()); 1113 ccV.add( stateV ); 1114 } 1115 1116 // dump out state scores 1117 LocalVariable sc = new LocalVariable(CodeUtils.TYPE_DOUBLE, "score_i"); 1118 InstructionVector dbi = new InstructionVector(); 1119 for(int i = 0; i < states.length; i++) { 1120 dbi.add( ByteCode.make_aload (score[0][0])); 1121 dbi.add( ByteCode.make_iconst (i)); 1122 dbi.add( ByteCode.make_daload ()); 1123 dbi.add( ByteCode.make_dstore (sc)); 1124 dbi.add( message("Score " + i + " = ", sc)); 1125 } 1126 ccV.add( debug(dbi)); 1127 1128 ccV.add( ByteCode.make_return ()); 1129 1130 return ccV; 1131 } 1132 1133 private CodeGenerator createBRecursion( 1134 boolean isInit, 1135 MarkovModel model, 1136 State[] states, 1137 AlphabetIndex stateIndex, 1138 CodeField stateF, 1139 CodeField [] transitionFields, 1140 AlphabetIndex[] transitionIndexers, 1141 GeneratedCodeMethod method 1142 ) throws 1143 NoSuchMethodException, 1144 NoSuchFieldException, 1145 IllegalSymbolException, 1146 CodeException 1147 { 1148 CodeClass _Cell = IntrospectedCodeClass.forClass(Cell.class); 1149 CodeField _Cell_score = _Cell.getFieldByName("scores"); 1150 CodeField _Cell_emissions = _Cell.getFieldByName("emissions"); 1151 CodeClass _double_A = IntrospectedCodeClass.forClass(double [].class); 1152 CodeClass _Math = IntrospectedCodeClass.forClass(Math.class); 1153 CodeMethod _Math_exp = _Math.getMethod("exp", new CodeClass[] { CodeUtils.TYPE_DOUBLE }); 1154 CodeMethod _Math_log = _Math.getMethod("log", new CodeClass[] { CodeUtils.TYPE_DOUBLE }); 1155 1156 InstructionVector ccV = new InstructionVector(); 1157 1158 ccV.add( debug(message("Retrieving local variables"))); 1159 1160 // if(isInit && state instanceof emission) { 1161 // cell[0][0] = (state == Magical) ? 0.0 : NaN; 1162 // } else { 1163 // cell[0][0].score[i] = cell[0][0].emissions[i] + 1164 // sum_j(cell[adv_i_0][adv_i_1] + t_j[i]) 1165 // } 1166 1167 // cell_00 = cell[0][0]; 1168 // cell_01 = cell[0][1]; 1169 // cell_10 = cell[1][0]; 1170 // cell_11 = cell[1][1]; 1171 LocalVariable[][] cell = new LocalVariable[2][2]; 1172 cell[0][0] = new LocalVariable(_Cell, "cell_00"); 1173 cell[0][1] = new LocalVariable(_Cell, "cell_01"); 1174 cell[1][0] = new LocalVariable(_Cell, "cell_10"); 1175 cell[1][1] = new LocalVariable(_Cell, "cell_11"); 1176 1177 ccV.add( ByteCode.make_aload (method.getVariable("cells"))); 1178 ccV.add( ByteCode.make_dup ()); 1179 ccV.add( ByteCode.make_iconst (0)); 1180 ccV.add( ByteCode.make_aaload ()); 1181 ccV.add( ByteCode.make_dup ()); 1182 ccV.add( ByteCode.make_iconst (0)); 1183 ccV.add( ByteCode.make_aaload ()); 1184 ccV.add( ByteCode.make_astore (cell[0][0])); 1185 ccV.add( ByteCode.make_iconst (1)); 1186 ccV.add( ByteCode.make_aaload ()); 1187 ccV.add( ByteCode.make_astore (cell[0][1])); 1188 ccV.add( ByteCode.make_iconst (1)); 1189 ccV.add( ByteCode.make_aaload ()); 1190 ccV.add( ByteCode.make_dup ()); 1191 ccV.add( ByteCode.make_iconst (0)); 1192 ccV.add( ByteCode.make_aaload ()); 1193 ccV.add( ByteCode.make_astore (cell[1][0])); 1194 ccV.add( ByteCode.make_iconst (1)); 1195 ccV.add( ByteCode.make_aaload ()); 1196 ccV.add( ByteCode.make_astore (cell[1][1])); 1197 1198 // score_00 = cell[0][0].score; 1199 // score_01 = cell[0][1].score; 1200 // score_10 = cell[1][0].score; 1201 // score_11 = cell[1][1].score; 1202 1203 LocalVariable[][] score = new LocalVariable[2][2]; 1204 score[0][0] = new LocalVariable(_double_A, "score_00"); 1205 score[0][1] = new LocalVariable(_double_A, "score_01"); 1206 score[1][0] = new LocalVariable(_double_A, "score_10"); 1207 score[1][1] = new LocalVariable(_double_A, "score_11"); 1208 ccV.add( ByteCode.make_aload (cell[0][0])); 1209 ccV.add( ByteCode.make_getfield ( _Cell_score)); 1210 ccV.add( ByteCode.make_astore (score[0][0])); 1211 ccV.add( ByteCode.make_aload (cell[0][1])); 1212 ccV.add( ByteCode.make_getfield ( _Cell_score)); 1213 ccV.add( ByteCode.make_astore (score[0][1])); 1214 ccV.add( ByteCode.make_aload (cell[1][0])); 1215 ccV.add( ByteCode.make_getfield ( _Cell_score)); 1216 ccV.add( ByteCode.make_astore (score[1][0])); 1217 ccV.add( ByteCode.make_aload (cell[1][1])); 1218 ccV.add( ByteCode.make_getfield ( _Cell_score)); 1219 ccV.add( ByteCode.make_astore (score[1][1])); 1220 1221 LocalVariable[][] emission = new LocalVariable[2][2]; 1222 emission[0][1] = new LocalVariable(_double_A, "emission_01"); 1223 emission[1][0] = new LocalVariable(_double_A, "emission_10"); 1224 emission[1][1] = new LocalVariable(_double_A, "emission_11"); 1225 ccV.add( ByteCode.make_aload (cell[0][1] )); 1226 ccV.add( ByteCode.make_getfield (_Cell_emissions)); 1227 ccV.add( ByteCode.make_astore (emission[0][1])); 1228 ccV.add( ByteCode.make_aload (cell[1][0] )); 1229 ccV.add( ByteCode.make_getfield (_Cell_emissions)); 1230 ccV.add( ByteCode.make_astore (emission[1][0])); 1231 ccV.add( ByteCode.make_aload (cell[1][1] )); 1232 ccV.add( ByteCode.make_getfield (_Cell_emissions)); 1233 ccV.add( ByteCode.make_astore (emission[1][1])); 1234 1235 LocalVariable max = new LocalVariable(CodeUtils.TYPE_DOUBLE, "max"); 1236 for(int i = states.length-1; i >= 0 ; i--) { 1237 State state = states[i]; 1238 ccV.add( debug(message("Calculating for state " + i + " " + state.getName()))); 1239 InstructionVector stateV = new InstructionVector(); 1240 // we need to push score & i onto the stack so that after finding the sum 1241 // we can just push it back into the array 1242 stateV.add( ByteCode.make_aload (score[0][0])); 1243 stateV.add( ByteCode.make_iconst (i)); 1244 if(isInit && state instanceof EmissionState) { 1245 stateV.add( debug(message("initalizing"))); 1246 if(state instanceof MagicalState) { 1247 stateV.add( debug(message("magical"))); 1248 stateV.add( ByteCode.make_dconst (0.0)); 1249 } else { 1250 stateV.add( debug(message("mundane"))); 1251 stateV.add( ByteCode.make_dconst (Double.NaN)); 1252 } 1253 } else { 1254 FiniteAlphabet trans = model.transitionsFrom(state); 1255 1256 if(trans.size() == 1) { 1257 stateV.add( debug(message("single-source optimization"))); 1258 1259 State state_j = (State) trans.iterator().next(); 1260 int state_jIndx = stateIndex.indexForSymbol(state_j); 1261 1262 // work out advance 1263 // only one source. B[i] = trans_j[i] + B[j] + e[j] 1264 // only add e[j] if emitting state 1265 int [] advance = getAdvance(state_j); 1266 1267 stateV.add( ByteCode.make_aload (method.getThis())); 1268 stateV.add( ByteCode.make_getfield (transitionFields[i])); 1269 stateV.add( ByteCode.make_iconst (transitionIndexers[i].indexForSymbol(state_j))); 1270 stateV.add( ByteCode.make_daload ()); 1271 stateV.add( ByteCode.make_aload (getAdvanced(score, advance))); 1272 stateV.add( ByteCode.make_iconst (state_jIndx)); 1273 stateV.add( ByteCode.make_daload ()); 1274 stateV.add( ByteCode.make_dadd ()); 1275 if(state_j instanceof EmissionState) { 1276 stateV.add( ByteCode.make_aload (getAdvanced(emission, advance))); 1277 stateV.add( ByteCode.make_iconst (i)); 1278 stateV.add( ByteCode.make_daload ()); 1279 stateV.add( ByteCode.make_dadd ()); 1280 } 1281 1282 LocalVariable tmp = new LocalVariable(CodeUtils.TYPE_DOUBLE, "tmp"); 1283 InstructionVector dbi = new InstructionVector(); 1284 dbi.add( ByteCode.make_dup2()); 1285 dbi.add( ByteCode.make_dstore(tmp)); 1286 dbi.add( message("got sum of ", tmp)); 1287 stateV.add( debug(dbi)); 1288 1289 } else { 1290 // B[i] = log( sum_j [ 1291 // exp( (j_scores[j] - max_j_score) + t_j[i] + e[j]) 1292 // ]) + max_j_score 1293 1294 stateV.add( debug(message("full recursion"))); 1295 1296 // find max j_scores 1297 stateV.add( ByteCode.make_dconst (Double.NEGATIVE_INFINITY)); 1298 stateV.add( ByteCode.make_dstore (max)); 1299 1300 Iterator each_j = trans.iterator(); 1301 while(each_j.hasNext()) { 1302 State state_j = (State) each_j.next(); 1303 int state_jIndx = stateIndex.indexForSymbol(state_j); 1304 int[] advance = getAdvance(state_j); 1305 1306 stateV.add( ByteCode.make_aload (getAdvanced(score, advance))); 1307 stateV.add( ByteCode.make_iconst (state_jIndx)); 1308 stateV.add( ByteCode.make_daload ()); 1309 stateV.add( ByteCode.make_dup2 ()); 1310 stateV.add( ByteCode.make_dload (max)); 1311 stateV.add( ByteCode.make_dcmpl ()); // puts -1 if max > this one 1312 1313 InstructionVector ifLargerThanMax = new InstructionVector(); 1314 ifLargerThanMax.add( debug(message("Larger"))); 1315 ifLargerThanMax.add( debug(message(" max: ", max))); 1316 ifLargerThanMax.add( ByteCode.make_dstore (max)); 1317 1318 InstructionVector ifSmallerThanMax = new InstructionVector(); 1319 ifSmallerThanMax.add( debug(message("Smaller"))); 1320 ifSmallerThanMax.add( debug(message(" max: ", max))); 1321 ifSmallerThanMax.add( ByteCode.make_pop2 ()); 1322 1323 stateV.add( new IfExpression( 1324 ByteCode.op_ifge, // branch if int on stack >= 0 1325 ifLargerThanMax, 1326 ifSmallerThanMax 1327 )); 1328 } 1329 1330 stateV.add( debug(message("Taking out factor ", max))); 1331 1332 // sum logs of exponents - prime sum with zero 1333 stateV.add( ByteCode.make_dconst (0.0)); 1334 1335 each_j = trans.iterator(); 1336 while(each_j.hasNext()) { 1337 State state_j = (State) each_j.next(); 1338 int state_jIndx = stateIndex.indexForSymbol(state_j); 1339 int[] advance = getAdvance(state_j); 1340 // score 1341 stateV.add( ByteCode.make_aload (getAdvanced(score, advance))); 1342 stateV.add( ByteCode.make_iconst (state_jIndx)); 1343 stateV.add( ByteCode.make_daload ()); 1344 1345 // is score NaN? 1346 stateV.add( ByteCode.make_dup2()); 1347 stateV.add( ByteCode.make_dup2()); 1348 stateV.add( ByteCode.make_dcmpl()); 1349 // stack now looks like sum, score_j, score_j isNaN 1350 // - boolean popped off during conditional branch leaving 1351 // sum, score_j 1352 1353 InstructionVector scoreNotNaN = new InstructionVector(); 1354 // load max & subtract it from score 1355 scoreNotNaN.add( ByteCode.make_dload (max)); 1356 scoreNotNaN.add( ByteCode.make_dsub ()); 1357 // sum, score_j - max 1358 1359 // (j_score - max) + transition + emission[j]) // only add emission if emiting state 1360 scoreNotNaN.add( ByteCode.make_aload (method.getThis())); 1361 scoreNotNaN.add( ByteCode.make_getfield (transitionFields[i])); 1362 scoreNotNaN.add( ByteCode.make_iconst (transitionIndexers[i].indexForSymbol(state_j))); 1363 scoreNotNaN.add( ByteCode.make_daload ()); 1364 scoreNotNaN.add( ByteCode.make_dadd ()); 1365 if(state_j instanceof EmissionState) { 1366 scoreNotNaN.add( ByteCode.make_aload (getAdvanced(score, advance))); 1367 scoreNotNaN.add( ByteCode.make_iconst (state_jIndx)); 1368 scoreNotNaN.add( ByteCode.make_daload ()); 1369 scoreNotNaN.add( ByteCode.make_dadd ()); 1370 } 1371 scoreNotNaN.add( ByteCode.make_invokestatic (_Math_exp)); 1372 1373 // sum this and current sum 1374 scoreNotNaN.add( ByteCode.make_dadd()); 1375 1376 InstructionVector scoreIsNaN = new InstructionVector(); 1377 scoreIsNaN.add( ByteCode.make_pop2()); 1378 1379 stateV.add( new IfExpression( 1380 ByteCode.op_ifge, 1381 scoreNotNaN, 1382 scoreIsNaN 1383 )); 1384 } 1385 1386 // log sum 1387 stateV.add( ByteCode.make_invokestatic (_Math_log)); 1388 1389 // lastly add on a factor of max - added here for maximum numerical stability 1390 stateV.add( ByteCode.make_dload (max)); 1391 stateV.add( ByteCode.make_dadd ()); 1392 } 1393 } 1394 // store score on stack into scores array 1395 stateV.add( ByteCode.make_dastore ()); 1396 ccV.add( stateV ); 1397 } 1398 1399 // dump out state scores 1400 LocalVariable sc = new LocalVariable(CodeUtils.TYPE_DOUBLE, "score_i"); 1401 InstructionVector dbi = new InstructionVector(); 1402 for(int i = 0; i < states.length; i++) { 1403 dbi.add( ByteCode.make_aload (score[0][0])); 1404 dbi.add( ByteCode.make_iconst (i)); 1405 dbi.add( ByteCode.make_daload ()); 1406 dbi.add( ByteCode.make_dstore (sc)); 1407 dbi.add( message("Score " + i + " = ", sc)); 1408 } 1409 ccV.add( debug(dbi)); 1410 1411 ccV.add( ByteCode.make_return ()); 1412 1413 return ccV; 1414 } 1415 1416 private CodeGenerator createInit( 1417 MarkovModel model, State[] states, 1418 GeneratedCodeClass clazz, 1419 GeneratedCodeMethod __init, 1420 AlphabetIndex[] transitionIndexers, 1421 CodeField[] transitionFields, 1422 CodeField stateF, 1423 CodeField terminalBP 1424 ) throws 1425 NoSuchFieldException, NoSuchMethodException, CodeException, 1426 IllegalSymbolException, BioException 1427 { 1428 CodeClass _Object = IntrospectedCodeClass.forClass(Object.class); 1429 CodeMethod _Object_init = _Object.getConstructor(CodeUtils.EMPTY_LIST); 1430 CodeClass _Symbol = IntrospectedCodeClass.forClass(Symbol.class); 1431 CodeClass _State = IntrospectedCodeClass.forClass(State.class); 1432 CodeClass _State_A = IntrospectedCodeClass.forClass(State [].class); 1433 CodeClass _double_A = IntrospectedCodeClass.forClass(double [].class); 1434 CodeClass _DP = IntrospectedCodeClass.forClass(DP.class); 1435 CodeMethod _DP_getStates = _DP.getMethod("getStates", CodeUtils.EMPTY_LIST); 1436 CodeMethod _DP_getModel = _DP.getMethod("getModel", CodeUtils.EMPTY_LIST); 1437 CodeClass _Distribution = IntrospectedCodeClass.forClass(Distribution.class); 1438 CodeMethod _Distribution_getAlphabet = _Distribution.getMethod("getAlphabet", CodeUtils.EMPTY_LIST); 1439 CodeClass _ScoreType = IntrospectedCodeClass.forClass(ScoreType.class); 1440 CodeMethod _ScoreType_calculateScore = _ScoreType.getMethod("calculateScore", new CodeClass[] {_Distribution, _Symbol}); 1441 CodeClass _MarkovModel = IntrospectedCodeClass.forClass(MarkovModel.class); 1442 CodeMethod _MarkovModel_getWeights = _MarkovModel.getMethod("getWeights", new CodeClass[] {_State}); 1443 CodeClass _FiniteAlphabet = IntrospectedCodeClass.forClass(FiniteAlphabet.class); 1444 CodeMethod _FiniteAlphabet_size = _FiniteAlphabet.getMethod("size", CodeUtils.EMPTY_LIST); 1445 CodeClass _Math = IntrospectedCodeClass.forClass(Math.class); 1446 CodeMethod _Math_log = _Math.getMethod("log", new CodeClass[] { CodeUtils.TYPE_DOUBLE }); 1447 1448 int[] indexToFieldIndex = new int[states.length]; 1449 Map distToIndx = new HashMap(); 1450 for(int i = 0; i < states.length; i++) { 1451 State s = states[i]; 1452 Distribution dist = model.getWeights(s); 1453 Integer indxI = (Integer) distToIndx.get(dist); 1454 if(indxI == null) { 1455 indxI = new Integer(i); 1456 distToIndx.put(dist, indxI); 1457 transitionFields[i] = clazz.createField( 1458 "t_" + i, 1459 _double_A, 1460 CodeUtils.ACC_PROTECTED 1461 ); 1462 indexToFieldIndex[i] = i; 1463 } else { 1464 int indx = indxI.intValue(); 1465 transitionFields[i] = transitionFields[indx]; 1466 indexToFieldIndex[i] = indexToFieldIndex[indx]; 1467 } 1468 } 1469 1470 InstructionVector initG = new InstructionVector(); 1471 // invoke super() 1472 initG.add( ByteCode.make_aload (__init.getThis())); 1473 initG.add( ByteCode.make_invokespecial (_Object_init)); 1474 1475 // load up the dp object. 1476 // Store the states array, and HMM 1477 LocalVariable statesLV = new LocalVariable(_State_A, "states"); 1478 LocalVariable modelLV = new LocalVariable(_MarkovModel, "model"); 1479 initG.add( ByteCode.make_aload (__init.getVariable("dp"))); 1480 initG.add( ByteCode.make_dup ()); 1481 initG.add( ByteCode.make_invokevirtual (_DP_getStates)); 1482 initG.add( ByteCode.make_astore (statesLV)); 1483 initG.add( ByteCode.make_invokevirtual (_DP_getModel)); 1484 initG.add( ByteCode.make_astore (modelLV)); 1485 initG.add( ByteCode.make_aload (__init.getThis())); 1486 initG.add( ByteCode.make_aload (statesLV)); 1487 initG.add( ByteCode.make_putfield (stateF)); 1488 1489 // store the backPointer thing in terminalBP 1490 if(terminalBP != null) { 1491 initG.add( ByteCode.make_aload (__init.getThis())); 1492 initG.add( ByteCode.make_aload (__init.getVariable("backPointer"))); 1493 initG.add( ByteCode.make_putfield (terminalBP)); 1494 } 1495 1496 LocalVariable distLV = new LocalVariable(_Distribution, "dist"); 1497 1498 // load in the transition probabilities to the transition fields 1499 for(int i = 0; i < transitionFields.length; i++) { 1500 // if this field reference is the first one for this distribution 1501 if(indexToFieldIndex[i] == i) { 1502 // Distribution dist = model.getWeights(states[i]); 1503 Distribution dist = model.getWeights(states[i]); 1504 1505 initG.add( ByteCode.make_aload (modelLV)); 1506 initG.add( ByteCode.make_aload (statesLV)); 1507 initG.add( ByteCode.make_iconst (i)); 1508 initG.add( ByteCode.make_aaload ()); 1509 initG.add( ByteCode.make_invokeinterface (_MarkovModel_getWeights)); 1510 initG.add( ByteCode.make_astore (distLV)); 1511 1512 int size = ((FiniteAlphabet) dist.getAlphabet()).size(); 1513 Symbol[] transitionSymbols = new Symbol[size]; 1514 1515 initG.add( ByteCode.make_aload (distLV)); 1516 initG.add( ByteCode.make_invokeinterface (_Distribution_getAlphabet)); 1517 initG.add( ByteCode.make_invokeinterface (_FiniteAlphabet_size)); 1518 1519 // t_i = new double[size]; // leave t_i on stack 1520 initG.add( ByteCode.make_iconst (size)); 1521 initG.add( ByteCode.make_newarray (CodeUtils.TYPE_DOUBLE)); 1522 initG.add( ByteCode.make_dup ()); 1523 initG.add( ByteCode.make_aload (__init.getThis())); 1524 initG.add( ByteCode.make_swap ()); 1525 initG.add( ByteCode.make_putfield (transitionFields[i])); 1526 1527 // t_i[j] = scoreType.calculateScore( 1528 // dist, states[ jj ] 1529 // ); 1530 // for each jj in dist - j is index from 0 in t_i in same order as jj 1531 int j = 0; 1532 for(int jj = 0; jj < states.length; jj++) { 1533 State state = states[jj]; 1534 if(dist.getAlphabet().contains(state)) { 1535 transitionSymbols[j] = state; 1536 initG.add( ByteCode.make_dup ()); 1537 initG.add( ByteCode.make_iconst (j)); 1538 initG.add( ByteCode.make_aload (__init.getVariable("scoreType"))); 1539 initG.add( ByteCode.make_aload (distLV)); 1540 initG.add( ByteCode.make_aload (statesLV)); 1541 initG.add( ByteCode.make_iconst (jj)); 1542 initG.add( ByteCode.make_aaload ()); 1543 initG.add( ByteCode.make_invokeinterface (_ScoreType_calculateScore)); 1544 initG.add( ByteCode.make_invokestatic (_Math_log)); 1545 initG.add( ByteCode.make_dastore ()); 1546 j++; 1547 } 1548 } 1549 1550 transitionIndexers[i] = AlphabetManager.getAlphabetIndex(transitionSymbols); 1551 initG.add( ByteCode.make_pop ()); 1552 } 1553 } 1554 1555 // return nothing 1556 initG.add( ByteCode.make_return ()); 1557 1558 return initG; 1559 } 1560 1561 private InstructionVector createTransitionLastSum( 1562 GeneratedCodeMethod method, 1563 int i, int j, 1564 CodeField transition[], LocalVariable lastScore 1565 ) throws CodeException { 1566 InstructionVector sumV = new InstructionVector(); 1567 1568 // transition_j[i]; 1569 sumV.add( ByteCode.make_aload (method.getThis())); 1570 sumV.add( ByteCode.make_getfield (transition[j])); 1571 sumV.add( ByteCode.make_iconst (i)); 1572 sumV.add( ByteCode.make_daload ()); 1573 1574 // lastScore[j] 1575 sumV.add( ByteCode.make_aload (lastScore)); 1576 sumV.add( ByteCode.make_iconst (j)); 1577 sumV.add( ByteCode.make_daload ()); 1578 1579 // add 1580 sumV.add( ByteCode.make_dadd ()); 1581 1582 return sumV; 1583 } 1584 1585 private CodeGenerator message(String message) { 1586 try { 1587 CodeClass _String = IntrospectedCodeClass.forClass(String.class); 1588 CodeClass _System = IntrospectedCodeClass.forClass(System.class); 1589 CodeField _System_out = _System.getFieldByName("out"); 1590 CodeClass _PrintStream = IntrospectedCodeClass.forClass(PrintStream.class); 1591 CodeMethod _PrintStream_println = _PrintStream.getMethod("println", new CodeClass[] { _String }); 1592 1593 InstructionVector iv = new InstructionVector(); 1594 1595 iv.add( ByteCode.make_getstatic (_System_out)); 1596 iv.add( ByteCode.make_sconst (message)); 1597 iv.add( ByteCode.make_invokevirtual (_PrintStream_println)); 1598 1599 return iv; 1600 } catch (NoSuchFieldException nsfe) { 1601 throw new BioError( "Can't make message statements", nsfe); 1602 } catch (NoSuchMethodException nsme) { 1603 throw new BioError( "Can't make message statements", nsme); 1604 } 1605 } 1606 1607 private CodeGenerator message(String message, LocalVariable var) { 1608 try { 1609 CodeClass _Object = IntrospectedCodeClass.forClass(Object.class); 1610 CodeClass _String = IntrospectedCodeClass.forClass(String.class); 1611 CodeClass _System = IntrospectedCodeClass.forClass(System.class); 1612 CodeField _System_out = _System.getFieldByName("out"); 1613 CodeClass _PrintStream = IntrospectedCodeClass.forClass(PrintStream.class); 1614 CodeMethod _PrintStream_print = _PrintStream.getMethod("print", new CodeClass[] { _String }); 1615 1616 InstructionVector iv = new InstructionVector(); 1617 1618 iv.add( ByteCode.make_getstatic (_System_out)); 1619 iv.add( ByteCode.make_sconst (message)); 1620 iv.add( ByteCode.make_invokevirtual (_PrintStream_print)); 1621 1622 iv.add( ByteCode.make_getstatic (_System_out)); 1623 1624 CodeMethod _PrintStream_printXln; 1625 if(var.getType().isPrimitive()) { 1626 _PrintStream_printXln = _PrintStream.getMethod("println", new CodeClass[] { var.getType() }); 1627 if(var.getType() == CodeUtils.TYPE_INT) { 1628 iv.add( ByteCode.make_iload(var)); 1629 } else if(var.getType() == CodeUtils.TYPE_DOUBLE) { 1630 iv.add( ByteCode.make_dload(var)); 1631 } else { 1632 throw new BioError("Unsupported primative " + var.getType()); 1633 } 1634 } else { 1635 iv.add( ByteCode.make_aload(var)); 1636 _PrintStream_printXln = _PrintStream.getMethod("println", new CodeClass [] { _Object }); 1637 } 1638 iv.add( ByteCode.make_invokevirtual (_PrintStream_printXln)); 1639 1640 return iv; 1641 } catch (NoSuchFieldException nsfe) { 1642 throw new BioError( "Can't make message statements", nsfe); 1643 } catch (NoSuchMethodException nsme) { 1644 throw new BioError( "Can't make message statements", nsme); 1645 } catch (CodeException ce) { 1646 throw new BioError( "Can't make message statements", ce); 1647 } 1648 } 1649 1650 private CodeGenerator debug(CodeGenerator child) { 1651 if(debug) { 1652 return child; 1653 } else { 1654 return CodeUtils.DO_NOTHING; 1655 } 1656 } 1657 1658 private int[] getAdvance(State s) { 1659 if(s instanceof EmissionState) { 1660 return ((EmissionState) s).getAdvance(); 1661 } else { 1662 return new int[] {0, 0}; 1663 } 1664 } 1665 1666 private LocalVariable getAdvanced(LocalVariable[][] what, int[] advance) { 1667 return what[advance[0]][advance[1]]; 1668 } 1669 1670 private static class Factory implements CellCalculatorFactory { 1671 private final DP dp; 1672 private final Constructor forwards; 1673 private final Constructor backwards; 1674 private final Constructor viterbi; 1675 1676 public Factory( 1677 DP dp, 1678 Constructor forwards, 1679 Constructor backwards, 1680 Constructor viterbi 1681 ) { 1682 this.dp = dp; 1683 this.viterbi = viterbi; 1684 this.forwards = forwards; 1685 this.backwards = backwards; 1686 } 1687 1688 public CellCalculator forwards(ScoreType scoreType) 1689 throws 1690 IllegalSymbolException, 1691 IllegalAlphabetException, 1692 IllegalTransitionException 1693 { 1694 try { 1695 return (CellCalculator) forwards.newInstance(new Object[] { dp, scoreType }); 1696 } catch (InstantiationException ie) { 1697 throw new BioError("Counld not instantiate auto-generated class"); 1698 } catch (IllegalAccessException ie) { 1699 throw new BioError("Counld not instantiate auto-generated class"); 1700 } catch (InvocationTargetException ie) { 1701 throw new BioError("Counld not instantiate auto-generated class"); 1702 } 1703 } 1704 1705 public CellCalculator backwards(ScoreType scoreType) 1706 throws 1707 IllegalSymbolException, 1708 IllegalAlphabetException, 1709 IllegalTransitionException 1710 { 1711 try { 1712 return (CellCalculator) backwards.newInstance(new Object[] { dp, scoreType }); 1713 } catch (InstantiationException ie) { 1714 throw new BioError("Counld not instantiate auto-generated class"); 1715 } catch (IllegalAccessException ie) { 1716 throw new BioError("Counld not instantiate auto-generated class"); 1717 } catch (InvocationTargetException ie) { 1718 throw new BioError("Counld not instantiate auto-generated class"); 1719 } 1720 } 1721 1722 public CellCalculator viterbi(ScoreType scoreType, BackPointer terminal) 1723 throws 1724 IllegalSymbolException, 1725 IllegalAlphabetException, 1726 IllegalTransitionException 1727 { 1728 try { 1729 return (CellCalculator) viterbi.newInstance(new Object[] { dp, scoreType, terminal }); 1730 } catch (InstantiationException ie) { 1731 throw new BioError( "Counld not instantiate auto-generated class", ie); 1732 } catch (IllegalAccessException ie) { 1733 throw new BioError( "Counld not instantiate auto-generated class-", ie); 1734 } catch (InvocationTargetException ie) { 1735 throw new BioError("Counld not instantiate auto-generated class using " + viterbi + " with " + dp + ", " + scoreType + ", " + terminal, ie); 1736 } 1737 } 1738 } 1739}