예제 #1
0
//==========================================================================================================
// Create a DFA from an NFA using the Subset-Construction algorithm
//==========================================================================================================
void DFA::nfa_to_dfa(NFA& nfa) {
    vector<set<int>> epsilon_closures; // Epsilon closures per NFA state
    
    //------------------------------------------------------------------------------------------------------
    // Calculate epsilon-closures for each state in the NFA
    //------------------------------------------------------------------------------------------------------
    for(int i = 0; i < nfa.get_num_states(); ++i) {
        epsilon_closures.push_back(calc_epsilon_closure(i, nfa));     
    }
    
    // Map between DFA state, and a set of NFA states it was constructed from (the index in the vector is the DFA state)
    vector<set<int>> nfa_states;
    nfa_states.push_back(epsilon_closures[0]); // Initial, starting state
    table.push_back(vector<int>(NUM_SYMBOLS, -1)); // Adding the start state
    
    //------------------------------------------------------------------------------------------------------
    // As long as there are new states in the DFA, calcuate the transitions for them, while creating new
    // states if needed
    //------------------------------------------------------------------------------------------------------
    for(int i = 0; i < table.size(); ++i) {
        for(int sym = 0; sym < NUM_SYMBOLS; ++sym) { // For each possible symbol
            
            //----------------------------------------------------------------------------------------------
            // Get the set of reachable NFA states from the current DFA state for the current symbol
            //----------------------------------------------------------------------------------------------
            set<int> reachable_set = nfa.get_rechable_set(nfa_states[i], Symbol(sym));
            for(auto& s: reachable_set) { // Add the epsilon-closure
                reachable_set.insert(epsilon_closures[s].begin(), epsilon_closures[s].end());
            }
            
            if(reachable_set.empty())
                continue;
            
            //----------------------------------------------------------------------------------------------
            // Check if this set already exists as a DFA state
            //----------------------------------------------------------------------------------------------
            int state = table.size();
            for(int j = 0; j < nfa_states.size(); ++j) {
                if(reachable_set == nfa_states[j]) {
                    state = j;
                    break;
                }
            }
            
            table[i][sym] = state; // Add this transition
            if(state == table.size()) { // New state
                nfa_states.push_back(reachable_set);
                table.push_back(vector<int>(NUM_SYMBOLS, -1));
            }
            
        } // for each symbol
    } // for each new state
    
    //------------------------------------------------------------------------------------------------------
    // Mark a state as accepting if any of the NFA states corresponding to it are accepting
    //------------------------------------------------------------------------------------------------------
    accepting.resize(get_num_states(), -1);
    for(int i = 0; i < nfa_states.size(); ++i) {
        for(auto s: nfa_states[i]) {
            if(nfa.accepting[s] >= 0) { 
                if(accepting[i] >= 0)
                    throw string("DFA state contain accepting NFA states with different production rules");
                accepting[i] = nfa.accepting[s];
                break;
            }
        }
    }
} // nfa_to_dfa()
예제 #2
0
gi::dfaEDSM* gi::dfaEDSM::to_canonical_dfaEDSM_from_red_states(){

	//////////////////////////////////////////////////////////////
	// - Pulisco l'automo dagli stati irragiungibili, aggiorno le transizioni

	// Conto il numero effettivo di stati finali
	int n_final_states = 0;
	for (int i = 0; i < get_num_states(); ++i)
		if (is_inside_red_states(i))
			n_final_states++;

	//TODO: Aggiungi la copia degli stati red e blue nei vectors

	// Creo un nuovo automa senza stati irragiungibili
	int count = 0;
	dfaEDSM* finalDFA = new dfaEDSM(n_final_states, get_dim_alphabet(), get_alphabet());
	map<int, int> updated_transition;

	for (int i = 0; i < num_states; ++i) {
		if (is_inside_red_states(i)) {

			for (int j = 0; j <get_dim_alphabet() + 1; ++j) {

				// Aggiungo lo stato al nuovo automa
				finalDFA->get_ttable()[count][j] = ttable[i][j];

				updated_transition[i] = count;
			}
			++count;
		}
	}
	updated_transition[ND] = ND;


//	if(updated_transition.size() <= 2){
//		cout << "There is only one or zero red state. Returned a copy of originale dfa."<<endl;
//		delete finalDFA;
//		return new dfaEDSM(*this);
//	}


	bool stato_pozzo = false;
	// Aggiorno le transizioni
	for (int i = 0; i < finalDFA->get_num_states(); ++i)
		for (int j = 0; j < finalDFA->get_dim_alphabet(); ++j) {

			if (finalDFA->get_ttable()[i][j] == ND)										// Rilevo che c'è una transizione mancante, quindi serve uno stato pozzo
				stato_pozzo = true;

			if(updated_transition.find(finalDFA->get_ttable()[i][j]) != updated_transition.end())
				finalDFA->set_ttable_entry(i, j, updated_transition[ finalDFA->get_ttable()[i][j] ]);
			else {
				cerr << "Errore nell'aggiornamento delle stringhe"<<endl;
				exit(EXIT_FAILURE);
			}

		}

	// Stampo l'automa prima di applicare il pozzo e la minimizzazione
	//finalDFA->print_dfa_with_color("AUTOMA FINALE PREPOZZO");
	//finalDFA->print_dfa_dot("FINALEPREPOZZO", percorso.c_str());

	//finalDFA->print_dfa_dot_mapped_alphabet("FINALE_PREPOZZO", (base_path + "pulito_pre_pozzo.dot").c_str());



	//////////////////////////////////////////////////////////////
	// Controllo stato pozzo
	// - Se ci sono transizioni non definite le imposto tutte verso lo stato pozzo
	if (stato_pozzo) {
		dfaEDSM* finalDFAPozzo = new dfaEDSM(finalDFA->get_num_states() + 1, finalDFA->get_dim_alphabet(), finalDFA->get_alphabet(), 0);

		int** table = finalDFAPozzo->get_ttable();

		for (int i = 0; i < finalDFA->get_num_states(); ++i)
			for (int j = 0; j < finalDFA->get_dim_alphabet() + 1; ++j) {
				if (finalDFA->get_ttable()[i][j] == ND)
					table[i][j] = finalDFA->get_num_states();
				else
					table[i][j] = finalDFA->get_ttable()[i][j];
			}

		for (int j = 0; j < finalDFA->get_dim_alphabet(); ++j)
			table[finalDFA->get_num_states()][j] = finalDFA->get_num_states();

		delete finalDFA;
		finalDFA = finalDFAPozzo;
	}

	return finalDFA;
}
예제 #3
0
//==========================================================================================================
// Mimimize the DFA using Myphill-Nerode based algorithm. The algorithm consider all state pairs, marking
// them as non-equivalent if possible. When finished, those not marked are put in the same new state.
// Steps:
// 1. Mark as non-equivalent those pairs with different accepting values
// 2. Iteratively mark pairs that for any input symbol go to a marked pair (or transition defined just for
//    one of them on that symbol).
// 3. Combine unmarked pairs to form new states.
// 4. Write the new transitions, mark accepting new states
//==========================================================================================================
void DFA::minimize() {
    //------------------------------------------------------------------------------------------------------
    // Create the pairs and do initial mark (true means pair is non-equivalent)
    //------------------------------------------------------------------------------------------------------
    vector<bool*> pairs;
    int num_states = get_num_states();
    
    for(int i = 0; i < num_states - 1; ++i) {
        pairs.push_back(new bool[num_states - i - 1]);
        pairs[i] -= (i+1); // This ugly trick enables accessing pairs[i][j], but actually using just half the memory
        
        for(int j = i+1; j < num_states; ++j) {
            pairs[i][j] = (accepting[i] != accepting[j]);
        }
    }
    
    //------------------------------------------------------------------------------------------------------
    // Mark until an iteration where no changes are made
    //------------------------------------------------------------------------------------------------------
    bool changed = true;
    while(changed) {
        changed = false;
        
        for(int i = 0; i < num_states - 1; ++i) {
            for(int j = i+1; j < num_states; ++j) {
                if(pairs[i][j]) continue; // Pair already marked
                
                for(int sym = 0; sym < NUM_SYMBOLS; ++sym) {
                    int x = get_next_state(i, sym), y = get_next_state(j, sym);
                    if(x == y) continue;

                    sort_pair(x,y); // Must have the smaller index first to access pairs table
                    
                    if(x == -1 or pairs[x][y]) {
                        pairs[i][j] = true;
                        changed = true;
                    }
                } // for each symbol
            }
        }
    }
    
    //------------------------------------------------------------------------------------------------------
    // Combine states:
    // 1. A new state is a set of old states which are equivalent
    // 2. If an old state is not equivalent to any other state, a new state is created that contains only it
    // 3. After adding a pair {i,j} (i < j}, there's no need to look at pairs {j,x} (j < x), because pair
    // {i,x} must have already been added.
    //------------------------------------------------------------------------------------------------------
    vector<vector<int>> new_states;
    vector<int> old_to_new(num_states, -1);
    set<int> added_states;
    
    for(int i = 0; i < num_states - 1; ++i) {
        if(added_states.count(i) != 0) continue;
        
        new_states.push_back({i});
        old_to_new[i] = new_states.size() - 1;
        
        for(int j = i+1; j < num_states; ++j) {
            if(not pairs[i][j]) {
                new_states.back().push_back(j);
                old_to_new[j] = new_states.size() - 1;
                added_states.insert(j);
            }
        }
    }
    
    if(added_states.empty()) // No minimization occurred
        return;
    
    // If the last state wasn't combined with any other state, add a new state that contains only it;
    // This is needed because the last state has no entry in the pairs table as a first of any pair
    if(added_states.count(num_states-1) == 0)
        new_states.push_back({num_states-1});
    
    //------------------------------------------------------------------------------------------------------
    // Write new transitions and mark accepting new states. Then replace the old DFA with the new one.
    //------------------------------------------------------------------------------------------------------
    vector<int> new_accepting(new_states.size(), -1);
    vector<vector<int>> new_table(new_states.size(), vector<int>(NUM_SYMBOLS, -1));
    
    for(int i = 0; i < new_states.size(); ++i) {
        for(auto s: new_states[i])
            if(accepting[s] != accepting[new_states[i][0]])
                throw string("DFA states found to be equivalent yet have different accepting values");
        
        new_accepting[i] = accepting[new_states[i][0]]; // If the first is accepting they all are, and vice versa
        
        for(int sym = 0; sym < NUM_SYMBOLS; ++sym) {
            // Since all old states in this new states are equivalent, need to check only one
            int old_next_state = get_next_state(new_states[i][0], sym);
            if(old_next_state != -1)
                new_table[i][sym] = old_to_new[old_next_state];
        }
    }
    
    accepting = new_accepting;
    table = new_table;
    

    //------------------------------------------------------------------------------------------------------
    // Free memory
    //------------------------------------------------------------------------------------------------------
    for(int i = 0; i < num_states - 1; ++i) {
        delete (pairs[i] + i + 1);
    }    
} // minimize()