summaryrefslogblamecommitdiff
path: root/sources/scalac/transformer/matching/DetWordAutom.java
blob: 7691715623b12856627b0d77e5d9272e8105ccf9 (plain) (tree)
1
2
3
4
5
6
7
8
9








                                     



                                   










































































































                                                                           

                                 
 

                                       
 
                                                    
                                                 
 
                                  
 


                                         
 

                         

 

                                                                        


                     
 

                        
 

                                                  
 
                                                       
 




                                                       
 


                                          
 




                                                         
 

                                                                   
 



                                                  
 






































                                                                   
                                                            


















































































































































































                                                                                                
 
     
 








                                                                          
 
 





                                                             
 

                                                                       
 

                                                             
 
                                                         
 
                                                              
 

                                                                
 
                                                  
 

                                                              
 
                                                                           
 
                                                                      
 




                                                  
 

         
 





                                                                     
 
 
                                                            
 
                                                                        
 
                                                                   
 

                                                                             
 
                                                                       
 
                                                          
 
                                  
 

                                                            
 
                                                           
 
                                                                  
 

                                                                    
 
                                                      
 
                                                      
 

                                      
 
                                                                          
 

                                                                        
 



                                                      
 
                 
 


             
 



                                                                                
 




                                                               
 
     
 



                                                                                
 




                                                               
 
     
 
 




                                                                    
 














                                                                      
 

                                                                 
 

                                                                     
 





                                                                              
 
                                                                 
 
                                                                                
 
                                                                               
 
 
                                                                                            
 




                                               
 

                                                                               
 
                                                                           
 


                                                                 
 
                                                                   
 
                                  
 

                                                                 
 
                                                
 



                                                          
 
                                                                              
 

                                                                              
 
                                                         
 

                                                              
 

                                                
 

                                                                   
 


                                                                 
 
                                                         
 
                                                                           
 
                                                          
 
                                                     
 




                                                                   
 
                                                                       
 
                                                                         
 
                                                           
 
             
 
 
                                            
 
                                                    
 
                                      
 

                                                                          
 
                                                                         
 

                                                                                                                                                                     
 
                                                          
 
                             
 
                                                  
 


                                         
 
             
 
                                                      
 

                                                           
 







                                                                            
 

                                                    
 
                                                                          
 
                                                                              
 



                                                              
 
                                                  
 


                                         
 
             
 
                                                                                            
 
         
 
                      
 
                                                                   
 

                                                                   
 
                                                         
 








                                                                          
 



                                                                                 
 
                                            
 
                                                                                  
 
                                                              
 




                                                                 
 

                                                        
 
                                           
 


                                                                     
 






                                                                       
 


                                                                   
 

                                                    
 
         
 


                                                                            
 
                                                                  
 




                                                                          
 

                                                                    
 

                                                              
 


                                                                       
 


                                         
 
                           
 
                                     
 

                                                           
 

                                                                    
 




























































                                                                                  
                                       





                                                
       
                         

       




























































































































                                                                                                   

 
package scalac.transformer.matching ;

import scalac.ast.Tree ;
import Tree.* ;

import java.util.* ;

import scalac.ApplicationError ;

public class DetWordAutom  {

    // BEGIN stuff from FiniteAutom

    //final static Integer FINTAG = new Integer(0);

    /** number of states */
    protected int nstates;

    /** the 'alphabet' */
    protected HashSet labels;

    /** the set of final states, here as a TreeMap */
    protected TreeMap finals;

    /** dfa: HashMap trans: Object -> Integer
     *  nfa: HashMap trans: Object -> Vector [ Integer ]
     *
     *  nfa: Integer  ->(Object -> Vector [ Int ])
     *       [q]     |->( a |-> { q' | (q,a,q') in \deltaright } )
     *
     *  dfa: Integer  ->(Object -> Int)
     *       [q]     |->( a |-> q' | \deltaright(q,a) = q' } )
     */

    public HashMap[] deltaq;

    public Integer[] defaultq; // this gives the default transitions

    //protected HashMap deltaq[];

    // --- accessor methods

    /** returns number of states
     */
    public int nstates() {
	return nstates;
    }

    /** returns the labels
     */
    public HashSet labels() {
	return labels;
    }

    /** returns the transitions
     */
    public HashMap deltaq( int state ) {
	return deltaq[ state ];
    }

    /** returns the transitions
     */
    public HashMap deltaq( Integer state ) {
	return deltaq[ state.intValue() ];
    }


    /** returns the transitions
     */
    public Integer defaultq( int state ) {
	return defaultq[ state ];
    }

    /** returns the transitions
     */
    public Integer defaultq( Integer state ) {
	return defaultq[ state.intValue() ];
    }


    /** returns true if the state is final
     */
    public boolean isFinal( int state ) {
	return ((finals != null)
		&& (finals.get( new Integer( state )) != null));
    }

    /** returns true if the state is final
     */
    public boolean isFinal( Integer state ) {
	return ((finals != null) && finals.containsKey( state ));
    }

    /** returns true if the state is final
     */
    public Integer finalTag( Integer state ) {
	return (Integer) finals.get( state );
    }


    public Integer finalTag( int state ) {
	return (Integer) finals.get( new Integer (state ));
    }

    /** returns true if the set of states contains at least one final state
     */
    boolean containsFinal( TreeSet Q ) {
	for( Iterator it = Q.iterator(); it.hasNext(); ) {
	    if( isFinal( (Integer) it.next()))
		return true;
	}
	return false;
    }


    /** returns true if there are no finite states
     */
    public boolean isEmpty() {
	return finals.isEmpty();
    }

    // END stuff from FiniteAutom

    static final int FIRST = 0;
    static final int LAST  = FIRST + 1;

    //static final int WHICH_LONGEST_MATCH = FIRST ;
    static final int WHICH_LONGEST_MATCH = LAST ;

    // inherited from FiniteAutom:

    // int nstates;   // number of states
    // HashSet labels;// the alphabet
    // TreeMap finals;

    // HashMap deltaq[];
    //Integer defaultq[];


    // TEMPORARY VAR used only during determinization and debug printing
    // Q -> (Label -> Q )
    HashMap delta;
    // Q -> Integer;
    HashMap indexMap;

    // Integer -> Q
    HashMap invIndexMap;

    // only not null if this is a right-transducer
    public Vector qbinders[];

    final static Integer NODEFAULT = new Integer( -1 );

    public boolean isSink( int i ) {
	return  ( deltaq[ i ].keySet().isEmpty()
		  && (defaultq != null )
		  && (defaultq( i ).intValue() == i) );
    }

    public boolean hasDefault( int i ) {
	return defaultq( i ) != NODEFAULT;
    }

    void determinize( NondetWordAutom nfa ) {
	//System.out.println("DetWordAutom:determinize");
	//System.out.println("nfa:");nfa.print();
	TreeSet states;// temp: Set[Set[Integer]]
	HashMap deftrans; // Set[Integer] -> Int

	HashMap trans; // always points to a mapping ( Label -> Q )
	int ix = 0;    // state index

	this.labels = nfa.labels;
	////System.out.println("Labels: "+labels);
	this.delta = new HashMap();
	//this.dead = -1;

	states = new TreeSet( new StateSetComparator() );
	deftrans = new HashMap();
	// temporarily: Map[Set[Integer]] later: Map[Integer]
	this.finals = new TreeMap( new StateSetComparator() );
	this.invIndexMap = new HashMap();
	this.indexMap = new HashMap();

	// new initial state (singleton set { q0 } by construction)

	TreeSet q0 = new TreeSet();
	q0.addAll( nfa.initials ); /*new Integer( 0 )); */
	states.add( q0 );

	TreeSet empty = new TreeSet();
	deftrans.put( q0, empty );
	states.add( empty );
	deftrans.put( empty, empty );

	Stack rest = new Stack();
	if( nfa.isFinal( 0 ) )
	    this.finals.put( q0, nfa.finalTag( 0 ) );


	rest.push( empty );
	rest.push( q0 );
	while( !rest.empty() ) {
	    TreeSet P1 = (TreeSet) rest.pop();

	    //System.out.println("states:"+ states);
	    //System.out.println("P1:"+ P1);

	    invIndexMap.put( new Integer( ix ), P1 );
	    indexMap.put( P1, new Integer( ix++ ));
	    delta.put( P1, trans = new HashMap());

	    // labelled transitions

	    for( Iterator it = labels.iterator(); it.hasNext(); ) {
		Object label = it.next();
		//System.out.print( "Label: " + label +" ");
		// Qdest will contain all states reachable via `label'
		// from some nfa state in P1;
		TreeSet Qdest = nfa.getSide( P1, label );
		//System.out.println("Qdest:"+Qdest);
		if( !states.contains( Qdest ) ) {
		    states.add( Qdest );
		    ////System.out.print(" (added)" );
		    rest.push( Qdest );
		    ////System.out.print(" (pushed)");

		    if( nfa.containsFinal( Qdest ) )
			this.finals.put( Qdest, nfa.finalTag( Qdest ));
		    ////System.out.print(" (added final)");

		}
		////System.out.println(".Qdest");

		trans.put( label, Qdest );
		// //System.out.println( "Qdest: " + Qdest);

	    }

	    // default transitions

	    TreeSet defTarget = (TreeSet) nfa.defaultq( P1 );
	    //System.out.println("defTarget:"+defTarget);
	    deftrans.put( P1, defTarget );

	    if( !states.contains( defTarget ) ) {
		states.add( defTarget );
		rest.push( defTarget );
		if( nfa.containsFinal( defTarget ) )
		    this.finals.put( defTarget, nfa.finalTag( defTarget ));
	    }
	}

	// <DEBUG>
	//printBefore( states, deftrans );

	// </DEBUG> do not call printBefore after this point
	// //System.out.println("indexMap: "+indexMap);

	this.nstates = states.size();
	deltaq = new HashMap[ nstates ];
	defaultq = new Integer[ nstates ];

	// we replace Set[Set[Integer]] by its index and clean up

	for( Iterator it = states.iterator(); it.hasNext(); ) {
	    TreeSet state   = (TreeSet) it.next();
	    Integer state_x = (Integer) indexMap.get( state );

	    TreeSet defTarget  = (TreeSet) deftrans.get( state );
	    Integer defTarget_x;
	    if( defTarget != null ) {
		defTarget_x = (Integer) indexMap.get( defTarget );
		////System.out.println("deftarget" + defTarget);
	    } else
		defTarget_x = NODEFAULT;

	    ////System.out.print(state.toString() + " --> " + state_x);
	    //System.out.println(" deftarget " + defTarget + " --> "+defTarget_x);

	    trans = (HashMap) delta.get( state );
	    HashMap newTrans = new HashMap();
	    for( Iterator labs = labels.iterator(); labs.hasNext() ;) {
		Object label = labs.next();
		TreeSet target   = (TreeSet) trans.get( label );
		Integer target_x;
		if( target != null ) {
		    // //System.out.println("target :"+target);
		    target_x = (Integer) indexMap.get( target );

		    if( target_x.intValue() != defTarget_x.intValue() ) {
			// replace target by target_x
			// (use type-unawareness)
			newTrans.put( label, target_x );
		    }
		    trans.remove( label );
		}

	    }
	    deltaq[ state_x.intValue() ] = newTrans;
	    defaultq[ state_x.intValue() ] = defTarget_x;

	    delta.remove( state );
	    deftrans.remove( state );

	}

	TreeMap oldfin = finals;
	this.finals = new TreeMap();
	for( Iterator it = oldfin.keySet().iterator(); it.hasNext(); ) {
	    TreeSet state = (TreeSet) it.next();
	    Integer state_x = (Integer) indexMap.get( state );
	    this.finals.put( state_x, oldfin.get( state ) );// conserve tags
	}

	// clean up, delete temporary stuff
	/*
	// we cannot clean up, indexmap is needed later
	for( Iterator it = states.iterator(); it.hasNext(); ) {
	((TreeSet) it.next()).clear();
	}
	*/
	states.clear();

	//minimize();
    }

    public DetWordAutom() {}

    public boolean isDead( int state ) {
	return state == nstates - 1; // by construction
    }

    public boolean isDead( Integer state ) {
	return state.intValue() == nstates - 1; // by construction
    }

    /** determinization -- standard algorithm considering only
     *                    reachable states
     */
    public DetWordAutom( NondetWordAutom nfa ) {
	determinize( nfa );
    }

    /** for a set of nfa states (that must exist), returns its transitions
     */
    HashMap deltaq( TreeSet nset ) {
	return deltaq( (Integer) indexMap.get( nset ) );
    }


    /** for a set of nfa states (that must exist), returns its transitions
     */
    Integer defaultq( TreeSet nset ) {
	return defaultq( (Integer) indexMap.get( nset ) );
    }

    /** returns target of the transition from state i with label label.
     *  null if no such transition exists.
     */
    Integer delta( int i, Label label ) {
	Integer target;
	switch( label ) {
	case DefaultLabel:
	    if( !hasDefault( i ) )
		return null;
	    return (Integer) defaultq( i ) ;
	case SimpleLabel( _ ):
	case TreeLabel( _ ):
	    return (Integer) deltaq[ i ].get( label ) ;
	    /*case Pair( Integer state, Label lab ):
	      return state;
	    */
	default:
	    throw new ApplicationError("whut's this: label="+label+", class "+label.getClass());
	}
    }

    Integer delta( Integer i, Label label ) {
	return delta( i.intValue(), label );
    }

    /** should maybe in nfa, not here
     */
    protected static Integer smallestFinal( NondetWordAutom nfa,
					    TreeSet states ) {

	int min = Integer.MAX_VALUE ;
	for( Iterator it = states.iterator(); it.hasNext(); ) {
	    Integer state = (Integer) it.next();
	    if( nfa.isFinal( state ) && (state.intValue() < min ))
		min = state.intValue();
	}
	if( min == Integer.MAX_VALUE )
	    throw new ApplicationError("I expected a final set of states");
	return new Integer( min );

    }

    protected Vector allSetsThatContain( Integer ndstate ) {
	Vector v = new Vector();
	for( Iterator it = indexMap.keySet().iterator(); it.hasNext(); ) {
	    TreeSet ndstateSet = (TreeSet) it.next();
	    if( ndstateSet.contains( ndstate ))
		v.add( ndstateSet );
	}
	return v;
    }


    protected void filterItOutQuoi( DetWordAutom dLeft,
				    Cartesian.Npair npTarget,
				    Label.Pair lab,
				    TreeMap nsrc ) {
	Label theLabel  = lab.lab;
	Integer ntarget = lab.state;

	// e.g.[2,(3),4] --> 7
	Integer dstate = (Integer) dLeft.indexMap.get( npTarget.nset );

	// eg. 3 -> [3] [2,3]
	Vector targets = dLeft.allSetsThatContain( ntarget );

	////System.out.println( targets+", of these " ) ;

	// filter out those source states which arrive here...

	for( Iterator su = targets.iterator(); su.hasNext(); ) {
	    TreeSet nset   = (TreeSet) su.next();

	    HashMap ddelta = dLeft.deltaq( nset );

	    // ...  at THIS dstate
	    if( (Integer) ddelta.get( theLabel ) == dstate ) {

		Cartesian.Npair np1 = new Cartesian.Npair( ntarget, nset );

		////System.out.print( np1.toString( dLeft.indexMap ));

		if( WHICH_LONGEST_MATCH == FIRST )
		    addTransitionFLM( nsrc, np1 );
		else
		    addTransitionLLM( nsrc, np1 );
	    }

	}
    }

    /** all default transitions from sets that contain nq to npTarget
     */
    protected void filterItOutQuoiDefault( DetWordAutom dLeft,
					   Cartesian.Npair npTarget,
					   Integer nq,
					   TreeMap nsrc ) {


	////System.out.println( "npTarget = " + npTarget ) ;

	Vector allSources = dLeft.allSetsThatContain( npTarget.nstate );

	for( Iterator it = allSources.iterator(); it.hasNext(); ) {

	    // e.g.[2,(3),4] --> 7
	    //Integer dstate = (Integer) dLeft.indexMap.get( npTarget.nset );

	    Integer dstate = (Integer) dLeft.indexMap.get( it.next() );

	    //System.out.println( "dstate = " + dstate ) ;

	    assert dstate != null;

	    // eg. 3 -> [3] [2,3]
	    Vector targets = dLeft.allSetsThatContain( nq );

	    //System.out.println( "targets: " + targets ) ;

	    // filter out those source states which arrive here...

	    for( Iterator su = targets.iterator(); su.hasNext(); ) {
		TreeSet nset   = (TreeSet) su.next();

		Integer ddef = dLeft.defaultq( nset );

		//System.out.println( "ddef ="+ddef );

		// ...  at THIS dstate
		if( ddef == dstate ) {

		    Cartesian.Npair np1 = new Cartesian.Npair( nq, nset );

		    // print target
		    //System.out.print( np1.toString( dLeft.indexMap ));

		    if( WHICH_LONGEST_MATCH == FIRST )
			addTransitionFLM( nsrc, np1 );
		    else
			addTransitionLLM( nsrc, np1 );

		}

	    }
	}
    }

    /** this implements the first longest match policy
     */
    protected static void addTransitionFLM( TreeMap nsrc, Cartesian.Npair np ) {
	Cartesian.Npair np2 = (Cartesian.Npair) nsrc.get( np.nset );

	// (policy) first longest match
	if(( np2 == null )
	   ||( np2.nstate.intValue() > np.nstate.intValue())) {
	    nsrc.put( np.nset, np  );
	}

    }

    /** this implements the last longest match policy (!)
     */
    protected static void addTransitionLLM( TreeMap nsrc, Cartesian.Npair np ) {
	Cartesian.Npair np2 = (Cartesian.Npair) nsrc.get( np.nset );

	// (policy) first longest match
	if(( np2 == null )
	   ||( np2.nstate.intValue() < np.nstate.intValue())) {
	    nsrc.put( np.nset, np  );
	}

    }


    /** build a deterministic right to left transducer from the args
     */
    public DetWordAutom( NondetWordAutom right,
			 NondetWordAutom left,
			 DetWordAutom    dLeft ) {

	/* System.out.println("DetWordAutom.<init>(nfa,nfa,dfa)");
	   System.out.println("nfa-left:");left.print();
	   System.out.println("nfa-right:");right.print();
	   System.out.println("dLeft:"+dLeft.print());
	   System.out.println("dLeft.finals"+dLeft.finals);
	*/
	this.indexMap = dLeft.indexMap;
	this.invIndexMap = dLeft.invIndexMap;
	// fix indexMap
	/* // unnecessary
	   TreeSet q0 = new TreeSet();
	   q0.add( new Integer( 0 ));
	   indexMap.put( q0, new Integer( 0 ));
	   //System.out.println("check out the indexMap!" + indexMap);
	   */

	TreeSet visited_n = new TreeSet( new NpairComparator() );
	Stack rest    = new Stack();

	// right is "nearly deterministic"
	// we can follow reverse traces paths by using dLeft.indexMap

	// start with right.initials, left.final, dLeft.final
	for( Iterator it = dLeft.finals.keySet().iterator(); it.hasNext(); ) {
	    Integer fstate  = (Integer) it.next();
	    TreeSet nfstate = (TreeSet) invIndexMap.get( fstate );
	    //System.out.print( "final state:"+fstate);
	    //System.out.print( " correspond to set of states:"+ nfstate );

	    Integer min_ndstate = smallestFinal( left, nfstate );

	    Cartesian.Npair npair = new Cartesian.Npair( min_ndstate, nfstate );

	    //System.out.println( "  smallest final of these: "+ min_ndstate );


	    //System.out.println( "push final nfa state "+npair.toString( dLeft.indexMap ));

	    if( !visited_n.contains( npair )) {
		visited_n.add( npair );
		rest.push( npair );
	    }
	}

	HashMap ratLab     = new HashMap(); // maps nset to label,HashMap
	HashMap ratDelta   = new HashMap(); // maps nset to Vector[ NP ]targets

	HashMap ratDefault = new HashMap(); // maps nset to NP (one target)

	int ix = 1;
	Stack ix_initial = (Stack) rest.clone();
	TreeSet ix_final = new TreeSet( new NpairComparator() );;

	TreeMap newIndexMap = new TreeMap( new NpairComparator() );

	while( !rest.isEmpty() ) {

	    Cartesian.Npair npair = (Cartesian.Npair) rest.pop();
	    newIndexMap.put( npair, new Integer(ix));

	    ratDelta.put( npair, new Vector() );

	    if( npair.nset.contains( new Integer( 0 )) ) {
		ix_final.add( npair );
	    }
	    ix++;

	    //System.out.println(" popped "+npair.toString( dLeft.indexMap ));

	    ////System.out.print(" binders: ");
	    ////System.out.print( right.qbinders[ npair.nstate.intValue() ] );

	    HashMap delta = right.deltaq( npair.nstate );

	    ////System.out.print(" we could have arrived : ");
	    //search the delta for target invIndexMap

	    HashMap labelToNset = new HashMap();
	    HashMap labelToFrom = new HashMap();

	    // maps nsets to the active nstates
	    TreeMap nsrc = new TreeMap( new StateSetComparator() );

	    // berry-sethi construction assures that
	    //   there is only one label for outgoing transitions
	    Label theLabel = null;

	    // collect all transition possible in the DFA

	    for( Iterator it = delta.keySet().iterator(); it.hasNext(); ) {

		Label.Pair   lab = (Label.Pair) it.next();

		// lab.state is the target in the NFA

		if( theLabel == null ) {
		    ratLab.put( npair, lab.lab );
		    ////System.out.print(" with \""+lab.lab+"\" ");
		}
		theLabel = lab.lab ;

		////System.out.print("\nfrom n" + lab.state +"  ... ");

		// these are too many, filter out those that exist in DFA

		filterItOutQuoi( dLeft, npair, lab, nsrc );

	    }


	    ////System.out.println( "---" );

	    ////System.out.println("all sources: ");

	    // !!  first longest match

	    for( Iterator ut = nsrc.keySet().iterator(); ut.hasNext(); ) {
		TreeSet nset  = (TreeSet) ut.next();

		Cartesian.Npair np2 = (Cartesian.Npair) nsrc.get( nset );

		assert( np2 != null );
		////System.out.println("target: n"+npair.nstate+" via: "+theLabel+" from "+ np2.toString( dLeft.indexMap ));// nset:"+nset+ " namely state n"+ dest);

		Vector v = (Vector) ratDelta.get( npair );

		v.add( np2 );

		if( !visited_n.contains( np2 ) ) {

		    visited_n.add( np2 );
		    rest.push( np2 );
		}

	    }

	    //System.out.println("default sources: ");

	    // maps nsets to the active nstates
	    nsrc = new TreeMap( new StateSetComparator() );

	    // now for all default transitions that arrive at this nfa state
	    Vector defqs = right.defaultq( npair.nstate );
	    for( Iterator it = defqs.iterator(); it.hasNext(); ) {
		Integer nq = (Integer) it.next();
		//System.out.println("checking nq="+nq);
		filterItOutQuoiDefault( dLeft, npair, nq, nsrc );
		//System.out.println( "nsrc after "+nq+" is "+nsrc );
	    }

	    //System.out.println( "defqs :"+defqs );
	    //System.out.println( "nsrc :"+nsrc );

	    for( Iterator ut = nsrc.keySet().iterator(); ut.hasNext(); ) {

		Cartesian.Npair np2 = (Cartesian.Npair) nsrc.get( ut.next() );

		Vector v = (Vector) ratDefault.get( npair );
		if( v == null )
		    ratDefault.put( npair, v = new Vector() );
		v.add( np2 );

		if( !visited_n.contains( np2 ) ) {

		    visited_n.add( np2 );
		    rest.push( np2 );
		}

	    }

	    ////System.out.println("zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz");

	}

	// Renumbering

	////System.out.println( "output: a dfa with "+ix+"states");

	// FIX: empty regular expression (as in "List()") is valid
	//assert ( !ix_final.isEmpty() ) : "no final states found";

	////System.out.println( "final state:"+ix_final);

	//System.out.println( "indexMap: " +indexMap);
	//System.out.println( "newIndexMap: " +newIndexMap);
	this.finals = new TreeMap();
	this.nstates = ix;
	HashMap dratDelta[] = new HashMap[ ix ];
	qbinders  = new Vector[ ix ];
	labels = new HashSet();
	for( Iterator it = ratDelta.keySet().iterator(); it.hasNext(); ) {
	    Cartesian.Npair np = (Cartesian.Npair) it.next();

	    //System.out.print( "\nstate: "+np);
	    TreeSet ndset = np.nset;
	    Integer dstate = (Integer) newIndexMap.get( np );
	    assert dstate != null : "no dstate for "+np.toString(dLeft.indexMap);

	    //System.out.print(" binders:");

	    qbinders[ dstate.intValue() ] = left.qbinders[ np.nstate.intValue() ];

	    //System.out.print( qbinders[dstate.intValue() ]);

	    //System.out.println(" transitions:");
	    if( ix_final.contains( np ) ) {
		Integer fin_ix = (Integer) newIndexMap.get( np );
		finals.put( fin_ix, new Integer( 0 ));
	    }

	    Label   lab   = (Label)  ratLab.get( np );
	    Vector  v     = (Vector) ratDelta.get( np );

	    HashMap ddelta = new HashMap();

	    // v might be null if there are only default transitions
	    if( v != null )
		for( Iterator it2 = v.iterator(); it2.hasNext() ; ) {

		    Cartesian.Npair np2= (Cartesian.Npair) it2.next();
		    //System.out.print( "("+lab+","+np2+") " );
		    Integer ddestR = (Integer) newIndexMap.get( np2 );
		    Integer ddest = (Integer) indexMap.get( np2.nset );
		    assert ddest != null :
			"no ddest for "
			+np2.toString(dLeft.indexMap);

		    Label.Pair newLab = new Label.Pair(ddest, lab);
		    ddelta.put( newLab, ddestR );
		    labels.add( newLab );

		}
	    dratDelta[ dstate.intValue() ] = ddelta;

	}

	for( Iterator it = ratDefault.keySet().iterator(); it.hasNext(); ) {
	    Cartesian.Npair np  = (Cartesian.Npair) it.next();
	    Integer         dstate = (Integer) newIndexMap.get( np );

	    //System.out.print("\nstate: "+np+" default trans: ");

	    Vector v = (Vector) ratDefault.get( np );
	    for( Iterator ut = v.iterator(); ut.hasNext(); ) {
		Cartesian.Npair np2  = (Cartesian.Npair) ut.next();
		Integer targetL      = (Integer) indexMap.get( np2.nset );
		Integer targetR      = (Integer) newIndexMap.get( np2 );

		Label defLab = new Label.Pair( targetL,
					       Label.DefaultLabel );

		labels.add( defLab );
		//System.out.print( "("+defLab+","+np2+") " );

		HashMap d = dratDelta[ dstate.intValue() ];
		if( d == null )
		    dratDelta[ dstate.intValue() ] = d = new HashMap();

		d.put( defLab, targetR );
	    }
	}

	deltaq = dratDelta;

	HashMap hmap = new HashMap();

	// final states of left are initial states of right
	// problem: still need to choose the one

	while( !ix_initial.isEmpty() ) {
	    Cartesian.Npair np = (Cartesian.Npair) ix_initial.pop();

	    Integer i          = (Integer) newIndexMap.get( np ); //R-state
	    Integer dtarget    = (Integer) indexMap.get( np.nset );// left-d-state

	    hmap.put( dtarget, i );
	}
	deltaq[ 0 ]  = hmap; // careful, this maps Int to Int

	qbinders[ 0 ] = new Vector();
	//((Vector[])defaultq)[ 0 ] = new Vector(); is null
	printBeforeRAT( dratDelta );

    }

    void printBeforeRAT1( String str ) {
	StringBuffer tmp = new StringBuffer( str );
	for( int j = tmp.length(); j < 20; j++ ) {
	    tmp.append(" ");
	}
	//System.out.print( tmp.toString() );
    }

    void printBeforeRAT( HashMap dratDelta[] ) {
	//System.out.println();
	printBeforeRAT1( "dratDelta" );
	printBeforeRAT1( "[index]" );
	//System.out.println();

	for( int i = 0; i < dratDelta.length; i++ ) {
	    if( isFinal( i ))
		printBeforeRAT1( "*"+i );
	    else
		printBeforeRAT1( " "+i );

	    //System.out.println( dratDelta[ i ] );
	}
    }

    /** you may only call this before the set[set[...]] representation
     *  gets flattened.
     */
    public void printBefore( TreeSet states, HashMap deftrans ) {
	HashMap trans;
	System.out.println( states );
	for( Iterator it = states.iterator(); it.hasNext(); ) {
	    TreeSet state = (TreeSet) it.next();
	    System.out.print("state:"+state.toString()+" transitions ");
	    trans = (HashMap) delta.get( state );
	    for( Iterator labs = labels.iterator(); labs.hasNext() ;) {
		Object label = labs.next();
		TreeSet target = (TreeSet) trans.get( label );
		System.out.print( "  (" + label.toString()
				  + "," + target.toString()+")");
	    }
	    System.out.print("default trans"+deftrans.get( state ));
	    System.out.println();
	}
	System.out.println("final states:" + finals );
    }


    /*
      public void minimize() { // TO DO
      //System.out.println("minimization");
      boolean mark[][] = new boolean[nstates][];
      for( int i = 0; i < nstates; i++ ) {
      mark[i] = new boolean[nstates - i];
      for( int j = 0; j < (nstates - i); j++ )
      mark[i][j] = false;
      }
      debugPrint( mark );
      }

      protected void debugPrint( boolean mark[][] ) {
      for( int i = 0; i < nstates; i++ ) {
      //System.out.print("[");
      for( int j = 0; j < nstates - i; j++ ) {
      //System.out.print(" "+mark[i][j]);
      if( mark[i][j] )
      //System.out.print(" ");
      }
      //System.out.println(" ]");
      }
      }

    */

    /*

    public void createDeadState() {
    assert dead == -1;
    this.dead = this.nstates++;
    Integer deadI = new Integer( dead );

    HashMap odelta[] = ((HashMap[])deltaq);
    deltaq = new HashMap[ this.nstates ];
    System.arraycopy(odelta, 0, ((HashMap[])deltaq), 0, odelta.length);
    HashMap trans = new HashMap();
    ((HashMap[])deltaq)[ this.dead ] = trans;
    for( Iterator labs = labels.iterator(); labs.hasNext(); ) {
    trans.put( labels, deadI );
    }
    //System.out.println("createDeadState, new dead state:"+dead);
    }



    // adjusts the alphabet of this automaton

    public void addLabels( HashSet labels ) {

    for(Iterator it = labels.iterator(); it.hasNext(); ) {
    Object label = it.next();
    if( this.labels.add( label )) { // new
    // adjust all transitions

    if( this.dead == -1 )
    createDeadState();

    Integer deadI = new Integer( this.dead );

    for( int i = 0; i < this.nstates; i++ ) {
    ((HashMap[])deltaq)[ i ].put( label, deadI );
    }
    }
    }
    }
    */

    // wishlist for jaco: why does Cartesian have to be static ?
    // if not, error "inner classes must not have static members"

    /** cartesian
     */

    static class Cartesian {
	/** Int x TreeSet[ Int ]
	 */
	case Npair(Integer nstate, TreeSet nset);

	public boolean equals( Object that ) {
	    if( !(that instanceof Cartesian ))
		return false;
	    switch( this ) {
	    case Npair( Integer nstate, TreeSet nset ):
		switch((Cartesian) that) {
		case Npair( Integer _nstate, TreeSet _nset ):
		    return ((nstate == _nstate)
			    &&( nset == _nset ));
		}
	    }
	    return false;
	}

	public String toString() {
	    switch( this ) {
	    case Npair( Integer nstate, TreeSet nset ):
		//Integer dstate = (Integer) indexMap.get( nset );
		return "<n"+nstate.toString()+" in "+nset /*+" = d"+dstate*/+">";
	    }
	    return null;
	}

	public String toString( HashMap indexMap ) {
	    //assert indexMap != null;
	    switch( this ) {
	    case Npair( Integer nstate, TreeSet nset ):
		assert nstate!=null;
		Integer dstate = (Integer) indexMap.get( nset );
		return "<n"+nstate.toString()+" in "+nset +" = d"+dstate +">";
	    }
	    return null;
	}


    }

    static class NpairComparator extends StateSetComparator {
	public int compare( Object o1, Object o2 ) {
	    if(( o1 instanceof Cartesian.Npair )&&
	       ( o2 instanceof Cartesian.Npair ))
		switch((Cartesian) o1) {
		case Npair( Integer nstate, TreeSet nset ):
		    switch( (Cartesian) o2 ) {
		    case Npair( Integer _nstate, TreeSet _nset ):
			int res = nstate.compareTo( _nstate );

			////System.out.println("nstate"+nstate+" <> _nstate "+ _nstate+" res"+res);
			if( res != 0 )
			    return res;
			else
			    return super.compare( nset, _nset );
		    }
		}
	    throw new ApplicationError( "illegal arg. to compare. "
					+o1.getClass()+" "+o2.getClass());
	}
    }

}