1 /* FILE: sub_grph.cpp 2 * DATE MODIFIED: 31-Aug-07 3 * DESCRIPTION: Part of the SREC graph compiler project source files. 4 * 5 * Copyright 2007, 2008 Nuance Communciations, Inc. * 6 * * 7 * Licensed under the Apache License, Version 2.0 (the 'License'); * 8 * you may not use this file except in compliance with the License. * 9 * * 10 * You may obtain a copy of the License at * 11 * http://www.apache.org/licenses/LICENSE-2.0 * 12 * * 13 * Unless required by applicable law or agreed to in writing, software * 14 * distributed under the License is distributed on an 'AS IS' BASIS, * 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 16 * See the License for the specific language governing permissions and * 17 * limitations under the License. * 18 * * 19 *---------------------------------------------------------------------------*/ 20 21 #include <iostream> 22 #include <string> 23 #include <assert.h> 24 #include <cstdio> 25 26 #include "sub_grph.h" 27 28 29 static int checkEntry (int *itemList, int count, int item); 30 31 static int checkEntry (int *itemList, int count, int item) 32 { 33 for (int ii= 0; ii < count; ii++) 34 if (item == itemList[ii]) 35 return ii; 36 return -1; 37 } 38 39 bool IsSlot (std::string label) 40 { 41 int count= label.size(); 42 int fPos= label.find_first_of ("___"); 43 int lPos= label.find_last_of ("___") + 1; 44 // std::cout << label << " " << count << " " << fPos << " " << lPos << std::endl; 45 if (fPos >= 0 && lPos == count) 46 return true; 47 else 48 return false; 49 } 50 51 52 void SubGraph::pushScope () 53 { 54 opStack[popOp++]= lastScope; 55 opStack[popOp++]= startId; 56 opStack[popOp++]= endId; 57 opStack[popOp++]= lastId; 58 opStack[popOp++]= arg1; 59 opStack[popOp++]= arg2; 60 opStack[popOp++]= numArc; 61 return; 62 } 63 64 void SubGraph::popScope () 65 { 66 prevStartId= startId; 67 prevEndId= endId; 68 arcLoc= opStack[--popOp]; 69 arg2= opStack[--popOp]; 70 arg1= opStack[--popOp]; 71 lastId= opStack[--popOp]; 72 endId= opStack[--popOp]; 73 startId= opStack[--popOp]; 74 lastScope= opStack[--popOp]; 75 return; 76 } 77 78 void SubGraph::BeginScope (int scopeType, int newArg1, int newArg2) 79 // Begin a new scope 80 // Create nodes for item and /item but no transitions 81 { 82 pushScope(); 83 84 arg1= newArg1; 85 arg2= newArg2; 86 lastScope= scopeType; 87 arcLoc= numArc; 88 89 startId= NewVertexId(); 90 91 switch (scopeType) { 92 case SCOPE_ITEM: 93 case SCOPE_RULE: 94 case SCOPE_COUNT: 95 case SCOPE_REPEAT: 96 case SCOPE_OPT: 97 endId= -1; 98 lastId= startId; 99 break; 100 case SCOPE_ONEOF: 101 endId= NewVertexId(); 102 lastId= endId; 103 break; 104 default: 105 printf ("Shouldn't be getting here\n"); 106 } 107 return; 108 } 109 110 void SubGraph::EndScope () 111 // End the current scope 112 { 113 int closeId= CloseScope(); 114 lastId= ConnectLastScope (startId, closeId); 115 } 116 117 int SubGraph::ConnectLastScope (int beginScopeId, int endScopeId) 118 // Connect up the child network to the parent 119 { 120 int begLabel, endLabel, begOutLabel, endOutLabel; 121 122 if (endId == -1) 123 endId= lastId; 124 if (lastScope == SCOPE_RULE) { 125 begLabel= BEGINRULE_LABEL; 126 begOutLabel= BEGINRULE_LABEL; 127 endLabel= ENDRULE_LABEL; 128 endOutLabel= arg1; // For inserting into closing brace 129 } 130 else { 131 begLabel= BEGINSCOPE_LABEL; 132 begOutLabel= BEGINRULE_LABEL; 133 endLabel= ENDSCOPE_LABEL; 134 endOutLabel= ENDSCOPE_LABEL; 135 } 136 137 popScope(); 138 139 switch (lastScope) { 140 case SCOPE_ITEM: 141 case SCOPE_COUNT: 142 case SCOPE_REPEAT: 143 case SCOPE_OPT: 144 (void) CreateArc (begLabel, begOutLabel, lastId, beginScopeId); 145 lastId= NewVertexId(); 146 (void) CreateArc (endLabel, endOutLabel, endScopeId, lastId); 147 break; 148 case SCOPE_ONEOF: 149 (void) CreateArc (begLabel, begOutLabel, startId, beginScopeId); 150 (void) CreateArc (endLabel, endOutLabel, endScopeId, endId); 151 break; 152 case SCOPE_RULE: 153 (void) CreateArc (begLabel, begOutLabel, lastId, beginScopeId); 154 lastId= NewVertexId(); 155 (void) CreateArc (endLabel, ruleId, endScopeId, lastId); 156 break; 157 case SCOPE_ROOT: 158 (void) CreateArc (begLabel, begOutLabel, lastId, beginScopeId); 159 lastId= NewVertexId(); 160 (void) CreateArc (endLabel, endOutLabel, endScopeId, lastId); 161 break; 162 default: 163 printf ("Shouldn't be getting here\n"); 164 } 165 return lastId; 166 } 167 168 int SubGraph::CloseScope () 169 // Closes the transitions and returns to the previous scope 170 // Special case for count and repeats 171 { 172 int ii, finalId, endLoc, blockCount; 173 174 switch (lastScope) { 175 case SCOPE_ITEM: 176 case SCOPE_RULE: 177 case SCOPE_ONEOF: 178 break; 179 case SCOPE_OPT: 180 (void) CreateArc (NONE_LABEL, NONE_LABEL, startId, lastId); // start to end 181 break; 182 case SCOPE_COUNT: 183 endLoc= numArc; 184 blockCount= numVertex - startId - 1; 185 // Special case, min-count= 0 186 187 for (ii= 1; ii < arg1; ii++) 188 CopyFastArcs (this, arcLoc, endLoc, ii * blockCount, -1, -1, -1, -1); 189 finalId= lastId + (arg2 - 1) * blockCount; 190 for ( ; ii < arg2; ii++) { 191 CopyFastArcs (this, arcLoc, endLoc, ii * blockCount, -1, -1, -1, -1); 192 (void) CreateArc (NONE_LABEL, NONE_LABEL, lastId + (ii - 1) * blockCount, finalId); 193 } 194 if (arg1 <= 0) 195 (void) CreateArc (NONE_LABEL, NONE_LABEL, startId, finalId); // start to end 196 197 UpdateVertexCount (endLoc); 198 lastId= finalId; 199 break; 200 case SCOPE_REPEAT: 201 endLoc= numArc; 202 blockCount= numVertex - startId - 1; 203 #if 1 204 for (ii= 1; ii < arg1; ii++) 205 CopyFastArcs (this, arcLoc, endLoc, ii * blockCount, -1, -1, -1, -1); 206 finalId= lastId + (arg1 - 1) * blockCount; 207 208 // loop 209 CopyFastArcs (this, arcLoc, endLoc, blockCount, startId, finalId, lastId, finalId); 210 211 // start to end 212 if (arg1 == 0) 213 (void) CreateArc (NONE_LABEL, NONE_LABEL, startId, finalId); 214 #else 215 // loop 216 CopyFastArcs (this, arcLoc, endLoc, blockCount, startId, lastId, lastId, lastId); 217 UpdateVertexCount (endLoc); 218 219 // second part 220 blockCount= numVertex - startId; 221 CopyFastArcs (this, arcLoc, endLoc, blockCount, startId, lastId, lastId, -1); 222 UpdateVertexCount (endLoc); 223 224 // once 225 finalId= lastId + blockCount; 226 blockCount= numVertex - startId; 227 if (arg1 <= 1) 228 CopyFastArcs (this, arcLoc, endLoc, blockCount, startId, startId, lastId, finalId); 229 230 // start to end 231 if (arg1 == 0) 232 (void) CreateArc (NONE_LABEL, NONE_LABEL, startId, finalId); 233 #endif 234 235 UpdateVertexCount (endLoc); 236 lastId= finalId; 237 break; 238 default: 239 printf ("Shouldn't be getting here\n"); 240 } 241 return lastId; 242 } 243 244 int SubGraph::AddItem (int inputLabel, int tagLabel) 245 { 246 int newId; 247 248 switch (lastScope) { 249 case SCOPE_RULE: 250 arg1= tagLabel; 251 case SCOPE_ITEM: 252 case SCOPE_OPT: 253 case SCOPE_COUNT: 254 case SCOPE_REPEAT: 255 newId= NewVertexId(); 256 (void) CreateArc (inputLabel, tagLabel, lastId, newId); 257 lastId= newId; 258 break; 259 case SCOPE_ONEOF: 260 (void) CreateArc (inputLabel, tagLabel, startId, endId); 261 lastId= endId; 262 break; 263 default: ; 264 printf ("Shouldn't be getting here\n"); 265 } 266 return lastId; 267 } 268 269 int SubGraph::AddTag (int tagLabel) 270 { 271 int newId; 272 273 switch (lastScope) { 274 case SCOPE_RULE: 275 case SCOPE_ITEM: 276 case SCOPE_OPT: 277 case SCOPE_COUNT: 278 case SCOPE_REPEAT: 279 newId= NewVertexId(); 280 (void) CreateArc (TAG_LABEL, tagLabel, lastId, newId); 281 lastId= newId; 282 break; 283 case SCOPE_ONEOF: 284 (void) CreateArc (TAG_LABEL, tagLabel, startId, endId); 285 lastId= endId; 286 break; 287 default: 288 printf ("Shouldn't be getting here\n"); 289 } 290 return lastId; 291 } 292 293 void SubGraph::ExpandRules (SubGraph **subList, int *lookupList, int numSubs) 294 { 295 int initialId, finalId, ruleId, pos; 296 297 for (int ii= 0; ii < numArc; ii++) { 298 ruleId= arc[ii]->GetInput(); 299 if (ruleId < 0 && ruleId > NONE_LABEL) { 300 initialId= arc[ii]->GetFromId(); 301 finalId= arc[ii]->GetToId(); 302 ruleId= checkEntry (lookupList, numSubs, -ruleId); 303 assert (ruleId >= 0); 304 // printf ("Expanding rule (%d) %s\n", -ruleId, subList[ruleId]->title); 305 306 arc[ii]->AssignInput (DISCARD_LABEL); // Clear down the rule 307 // printf ("------------------------"); 308 // subList[ruleId]->SortLanguage(); 309 // subList[ruleId]->Print(); 310 // printf ("------------------------////"); 311 pos= numArc; 312 CopyFastArcs (subList[ruleId], 0, subList[ruleId]->numArc, numVertex, 313 subList[ruleId]->startId, initialId, subList[ruleId]->lastId, finalId); 314 UpdateVertexCount (pos); 315 } 316 } 317 UpdateVertexCount (0); 318 SortLanguage (); 319 return; 320 } 321 322 void SubGraph::UpdateVertexCount (int startLoc) 323 { 324 int vertId, maxVertId; 325 326 maxVertId= -1; 327 for (int ii= startLoc; ii < numArc; ii++) { 328 vertId= arc[ii]->GetFromId(); 329 if (maxVertId < vertId) 330 maxVertId= vertId; 331 vertId= arc[ii]->GetToId(); 332 if (maxVertId < vertId) 333 maxVertId= vertId; 334 } 335 maxVertId++; 336 if (startLoc <= 0) // i.e. a fresh start 337 numVertex= maxVertId; 338 else if (numVertex < maxVertId) 339 numVertex= maxVertId; 340 return; 341 } 342 343 void SubGraph::AddTerminalConnections () 344 { 345 // Add terminal transition 346 (void) CreateArc (TERMINAL_LABEL, NONE_LABEL, lastId, TERMINAL_LABEL); 347 return; 348 } 349 350 void SubGraph::RemoveRuleConnections () 351 { 352 AddTerminalConnections (); 353 RemoveTagConnections (-1, -1); 354 RemoveRuleStarts (-1, -1); 355 RemoveRuleEnds (-1, -1); 356 RemoveNulls (-1, -1); 357 ClearRuleIds (); 358 359 ClearDuplicateArcs (); 360 RemoveUnvisitedArcs (startId, lastId); 361 RemoveDiscardedArcs (); 362 RenumberNodes (); 363 UpdateVertexCount (0); 364 365 SortLanguage (); 366 return; 367 } 368 369 void SubGraph::RemoveRuleStarts (int startPoint, int endPoint) 370 { 371 if (startPoint == -1 && endPoint == -1) { 372 startPoint= startId; 373 endPoint= lastId; 374 } 375 376 int *nodeList= new int [numVertex]; 377 int *visitList= new int [numVertex]; 378 for (int ii= 0; ii < numVertex; ii++) 379 visitList[ii]= 0; 380 381 SortLanguage (); 382 ProcessBegins (startPoint, endPoint, BEGINRULE_LABEL, nodeList, 0, visitList, numVertex); 383 ClearLabelledConnections (BEGINRULE_LABEL); 384 385 delete [] nodeList; 386 delete [] visitList; 387 return; 388 } 389 390 void SubGraph::RemoveRuleEnds (int startPoint, int endPoint) 391 { 392 if (startPoint == -1 && endPoint == -1) { 393 startPoint= startId; 394 endPoint= lastId; 395 } 396 397 int *nodeList= new int [numVertex]; 398 int *visitList= new int [numVertex]; 399 for (int ii= 0; ii < numVertex; ii++) 400 visitList[ii]= 0; 401 402 SortLanguageReverse (); 403 ProcessEnds (endPoint, startPoint, ENDRULE_LABEL, nodeList, 0, visitList, numVertex); 404 ClearLabelledConnections (ENDRULE_LABEL); 405 406 delete [] nodeList; 407 delete [] visitList; 408 return; 409 } 410 411 void SubGraph::RemoveNulls (int startPoint, int endPoint) 412 { 413 if (startPoint == -1 && endPoint == -1) { 414 startPoint= startId; 415 endPoint= lastId; 416 } 417 418 int *nodeList= new int [numVertex]; 419 int *visitList= new int [numVertex]; 420 for (int ii= 0; ii < numVertex; ii++) 421 visitList[ii]= 0; 422 423 SortLanguage (); 424 ProcessBegins (startPoint, endPoint, NONE_LABEL, nodeList, 0, visitList, numVertex); 425 ClearLabelledConnections (NONE_LABEL); 426 427 delete [] nodeList; 428 delete [] visitList; 429 return; 430 } 431 432 void SubGraph::RemoveInternalConnections () 433 { 434 RemoveForwardConnections (-1, -1); 435 RemoveBackwardConnections (-1, -1); 436 ClearDuplicateArcs (); 437 RemoveUnvisitedArcs (startId, lastId); 438 RemoveDiscardedArcs (); 439 RenumberNodes (); 440 UpdateVertexCount (0); 441 442 SortLanguage (); 443 return; 444 } 445 446 void SubGraph::RemoveForwardConnections (int startPoint, int endPoint) 447 { 448 // Code to pull up nodes for forward connecting transitions 449 450 if (startPoint == -1 && endPoint == -1) { 451 startPoint= startId; 452 endPoint= lastId; 453 } 454 455 int *nodeList= new int [numVertex]; 456 int *visitList= new int [numVertex]; 457 for (int ii= 0; ii < numVertex; ii++) 458 visitList[ii]= 0; 459 460 SortLanguage (); 461 ProcessBegins (startPoint, endPoint, BEGINSCOPE_LABEL, nodeList, 0, visitList, numVertex); 462 ClearLabelledConnections (BEGINSCOPE_LABEL); 463 RemoveDiscardedArcs (); 464 465 delete [] nodeList; 466 delete [] visitList; 467 return; 468 } 469 470 void SubGraph::PullUpBegins (int currId, int baseId, int finalId, int procLabel, 471 int *nodeList, int currNum, int maxNum) 472 { 473 int rix; 474 475 nodeList[currNum]= currId; 476 rix= FindFromIndex (currId); 477 if (rix < 0) 478 return; 479 while (rix < sortNum && arc[forwardList[rix]]->GetFromId() == currId) { 480 if (arc[forwardList[rix]]->GetInput() == procLabel) { 481 PullUpBegins (arc[forwardList[rix]]->GetToId(), baseId, 482 finalId, procLabel, nodeList, currNum+1, maxNum); 483 } 484 else if (arc[forwardList[rix]]->GetInput() != DISCARD_LABEL) 485 InheritArc (arc[forwardList[rix]], baseId); 486 rix++; 487 } 488 return; 489 } 490 491 void SubGraph::ProcessBegins (int currId, int finalId, int procLabel, 492 int *nodeList, int currNum, int *visitMark, int maxNum) 493 { 494 int rix, nextId; 495 496 nodeList[currNum]= currId; 497 rix= FindFromIndex (currId); 498 if (rix < 0) { 499 visitMark[currId]= 1; 500 return; 501 } 502 while (rix < sortNum && arc[forwardList[rix]]->GetFromId() == currId) { 503 if (arc[forwardList[rix]]->GetInput() == procLabel) { 504 PullUpBegins (arc[forwardList[rix]]->GetToId(), currId, 505 finalId, procLabel, nodeList, currNum, maxNum); 506 } 507 508 nextId= arc[forwardList[rix]]->GetToId(); 509 if (nextId >= 0 && nextId != finalId && checkEntry (nodeList, currNum, nextId) < 0 510 && visitMark[nextId] == 0) 511 ProcessBegins (nextId, finalId, procLabel, nodeList, currNum+1, visitMark, maxNum); 512 rix++; 513 } 514 visitMark[currId]= 1; 515 return; 516 } 517 518 void SubGraph::RemoveBackwardConnections (int startPoint, int endPoint) 519 { 520 // Code to push back nodes for reverse connecting transitions 521 522 if (startPoint == -1 && endPoint == -1) { 523 startPoint= startId; 524 endPoint= lastId; 525 } 526 527 int *nodeList= new int [numVertex]; 528 int *visitList= new int [numVertex]; 529 for (int ii= 0; ii < numVertex; ii++) 530 visitList[ii]= 0; 531 532 SortLanguageReverse (); 533 ProcessEnds (endPoint, startPoint, ENDSCOPE_LABEL, nodeList, 0, visitList, numVertex); 534 ClearLabelledConnections (ENDSCOPE_LABEL); 535 RemoveDiscardedArcs (); 536 537 delete [] nodeList; 538 delete [] visitList; 539 return; 540 } 541 542 void SubGraph::PullUpEnds (int currId, int baseId, int initialId, int procLabel, 543 int *nodeList, int currNum, int maxNum) 544 { 545 int rix; 546 547 nodeList[currNum]= currId; 548 rix= FindToIndex (currId); 549 if (rix < 0) 550 return; 551 while (rix < sortRevNum && arc[backwardList[rix]]->GetToId() == currId) { 552 if (arc[backwardList[rix]]->GetInput() == procLabel) { 553 PullUpEnds (arc[backwardList[rix]]->GetFromId(), baseId, 554 initialId, procLabel, nodeList, currNum+1, maxNum); 555 } 556 else if (arc[backwardList[rix]]->GetInput() != DISCARD_LABEL) 557 InheritReverseArc (arc[backwardList[rix]], baseId); 558 rix++; 559 } 560 return; 561 } 562 563 void SubGraph::ProcessEnds (int currId, int initialId, int procLabel, 564 int *nodeList, int currNum, int *visitMark, int maxNum) 565 { 566 int rix, nextId; 567 568 nodeList[currNum]= currId; 569 rix= FindToIndex (currId); 570 if (rix < 0) { 571 visitMark[currId]= 1; 572 return; 573 } 574 while (rix < sortRevNum && arc[backwardList[rix]]->GetToId() == currId) { 575 if (arc[backwardList[rix]]->GetInput() == procLabel) { 576 PullUpEnds (arc[backwardList[rix]]->GetFromId(), currId, 577 initialId, procLabel, nodeList, currNum, maxNum); 578 } 579 nextId= arc[backwardList[rix]]->GetFromId(); 580 if (nextId != initialId && checkEntry (nodeList, currNum, nextId) < 0 581 && visitMark[nextId] == 0) 582 ProcessEnds (nextId, initialId, procLabel, nodeList, currNum+1, visitMark, maxNum); 583 rix++; 584 } 585 visitMark[currId]= 1; 586 return; 587 } 588 589 void SubGraph::RemoveUnreachedConnections (int startPoint, int endPoint) 590 { 591 // Obtain nodes with real transitions 592 // Code to pull up nodes for forward connecting transitions 593 // Code to push back nodes for reverse connecting transitions 594 595 if (startPoint == -1 && endPoint == -1) { 596 startPoint= startId; 597 endPoint= lastId; 598 } 599 600 ClearDuplicateArcs (); 601 RemoveUnvisitedArcs (startPoint, endPoint); 602 RemoveDiscardedArcs (); 603 RenumberNodes (); 604 UpdateVertexCount (0); 605 606 return; 607 } 608 609 void SubGraph::RemoveUnreachedConnectionsDebug (int startPoint, int endPoint) 610 { 611 // Obtain nodes with real transitions 612 // Code to pull up nodes for forward connecting transitions 613 // Code to push back nodes for reverse connecting transitions 614 615 if (startPoint == -1 && endPoint == -1) { 616 startPoint= startId; 617 endPoint= lastId; 618 } 619 620 // ClearDuplicateArcs (); 621 RemoveUnvisitedArcs (startPoint, endPoint); 622 RemoveDiscardedArcs (); 623 // RenumberNodes (); 624 UpdateVertexCount (0); 625 626 return; 627 } 628 629 void SubGraph::ReduceArcsByEquivalence () 630 { 631 int ii, *equivMap, *depthMap; 632 633 // Sort by Input, Output and to nodes 634 SortLanguage (); 635 SortLanguageReverse (); 636 637 // Calculate depth 638 depthMap= new int [numVertex]; 639 for (ii= 0; ii < numVertex; ii++) 640 depthMap[ii]= MAXNUM; 641 if (lastId >= 0) 642 ReverseDepthData (lastId, depthMap, 1); 643 ReverseDepthOnTerminal (depthMap); 644 for (ii= 0; ii < numVertex; ii++) 645 if (depthMap[ii] == MAXNUM) 646 depthMap[ii]= -1; 647 648 // Create equivalence list 649 equivMap= new int [numVertex]; 650 for (ii= 0; ii < numVertex; ii++) 651 equivMap[ii]= ii; 652 653 // Equivalence test to use equivalence list, duplicate transitions ignored 654 // Test nodes with same equivalence 655 IdentifyEquivalence (depthMap, equivMap); 656 657 // On identification of an equivalence 658 // Update equivalence entry 659 MapGraphVertices (equivMap); 660 RemoveDiscardedArcs (); 661 662 // Sort for general access 663 SortLanguage (); 664 665 delete [] depthMap; 666 delete [] equivMap; 667 return; 668 } 669 670 void SubGraph::DeterminizeArcs () 671 { 672 int ii; 673 bool allDone; 674 675 SortLanguage (); 676 DetCache *cache= new DetCache; 677 678 SetupVisitationCache (); 679 assert (VisitationConsistencyCheck () == 0); 680 printf ("Determinization\n"); 681 allDone= false; 682 while (!allDone) { 683 allDone= true; 684 for (ii= 0; ii < numVertex; ii++) { 685 if (QueryMinProperty(ii) == false) { 686 if (startId == ii || QueryNodeProperty(ii) > 0) { 687 DeterminizeAtVertex (ii, cache); 688 SetMinProperty (ii); 689 allDone= false; 690 //printf (" Node %d, Total %d, Arcs %d\n", ii, numVertex, numArc); 691 } 692 assert (VisitationConsistencyCheck () == 0); 693 // hmm .. this seems harmless but .. 694 // printf("assert(0) in SubGraph::DeterminizeArcs() ii=%d allDone=%d\n", ii, allDone); 695 // assert (0); 696 } 697 } 698 } 699 700 ClearVisitationCache (); 701 702 delete cache; 703 return; 704 } 705 706 int SubGraph::IsDeterminized (int currId) 707 { 708 int count, rix, lastInput; 709 710 count= 0; 711 lastInput= -1; 712 rix= FindFromIndex (currId); 713 if (rix < 0) 714 return -1; 715 while (rix < sortNum && arc[forwardList[rix]]->GetFromId() == currId) { 716 if (lastInput >= 0 && lastInput == arc[forwardList[rix]]->GetInput()) 717 count++; 718 else 719 lastInput= arc[forwardList[rix]]->GetInput(); 720 rix++; 721 } 722 return count; 723 } 724 725 void SubGraph::ReverseGraphForOutput () 726 { 727 int ii, incId, outId; 728 729 assert (startId == 0); 730 UpdateVertexCount (0); 731 for (ii= 0; ii < numArc; ii++) { 732 incId= arc[ii]->GetFromId(); 733 outId= arc[ii]->GetToId(); 734 if (outId == TERMINAL_LABEL) { 735 arc[ii]->AssignFromId (0); 736 arc[ii]->AssignInput (NONE_LABEL); 737 arc[ii]->AssignOutput (NONE_LABEL); 738 arc[ii]->AssignToId (incId); 739 } 740 else { 741 arc[ii]->AssignFromId (outId); 742 if (incId == 0) 743 arc[ii]->AssignToId (numVertex); 744 else 745 arc[ii]->AssignToId (incId); 746 } 747 } 748 (void) CreateArc (TERMINAL_LABEL, NONE_LABEL, numVertex, TERMINAL_LABEL); // Add terminal transition 749 numVertex++; 750 751 return; 752 } 753 754 void SubGraph::RemoveTagConnections (int startPoint, int endPoint) 755 { 756 // Code to push back nodes for reverse connecting transitions 757 758 if (startPoint == -1 && endPoint == -1) { 759 startPoint= startId; 760 endPoint= lastId; 761 } 762 763 int *nodeList= new int [numVertex]; 764 int *visitList= new int [numVertex]; 765 for (int ii= 0; ii < numVertex; ii++) 766 visitList[ii]= 0; 767 768 SortLanguageReverse (); 769 ProcessTags (endPoint, startPoint, nodeList, 0, visitList, numVertex); 770 ClearLabelledConnections (TAG_LABEL); 771 RemoveDiscardedArcs (); 772 773 delete [] nodeList; 774 delete [] visitList; 775 return; 776 } 777 778 bool SubGraph::PullUpTags (int currId, int baseId, int initialId, 779 int outTag, int *nodeList, int currNum, int maxNum) 780 { 781 int rix; 782 bool hasCascade= false; 783 784 nodeList[currNum]= currId; 785 rix= FindToIndex (currId); 786 if (rix < 0) 787 return hasCascade; 788 while (rix < sortRevNum && arc[backwardList[rix]]->GetToId() == currId) { 789 if (arc[backwardList[rix]]->GetInput() == TAG_LABEL) { 790 if (PullUpTags (arc[backwardList[rix]]->GetFromId(), baseId, initialId, 791 arc[backwardList[rix]]->GetOutput(), nodeList, currNum+1, maxNum)) 792 CreateCopyWithOutput (arc[backwardList[rix]], NONE_LABEL); 793 hasCascade= true; 794 } 795 else if (arc[backwardList[rix]]->GetInput() != DISCARD_LABEL) 796 InheritReverseArcWithTag (arc[backwardList[rix]], baseId, outTag); 797 rix++; 798 } 799 return hasCascade; 800 } 801 802 void SubGraph::ProcessTags (int currId, int initialId, int *nodeList, int currNum, 803 int *visitMark, int maxNum) 804 { 805 int rix, nextId; 806 807 nodeList[currNum]= currId; 808 rix= FindToIndex (currId); 809 if (rix < 0) { 810 visitMark[currId]= 1; 811 return; 812 } 813 while (rix < sortRevNum && arc[backwardList[rix]]->GetToId() == currId) { 814 if (arc[backwardList[rix]]->GetInput() == TAG_LABEL) { 815 if (PullUpTags (arc[backwardList[rix]]->GetFromId(), currId, initialId, 816 arc[backwardList[rix]]->GetOutput(), nodeList, currNum, maxNum)) 817 CreateCopyWithOutput (arc[backwardList[rix]], NONE_LABEL); 818 } 819 nextId= arc[backwardList[rix]]->GetFromId(); 820 if (nextId != initialId && checkEntry (nodeList, currNum, nextId) < 0 821 && visitMark[nextId] == 0) 822 ProcessTags (nextId, initialId, nodeList, currNum+1, visitMark, maxNum); 823 rix++; 824 } 825 visitMark[currId]= 1; 826 return; 827 } 828