All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.automatalib.util.automata.fsa.NFAs Maven / Gradle / Ivy

Go to download

This artifact provides various common utility operations for analyzing and manipulating automata and graphs, such as traversal, minimization and copying.

There is a newer version: 0.11.0
Show newest version
/* Copyright (C) 2014 TU Dortmund
 * This file is part of AutomataLib, http://www.automatalib.net/.
 * 
 * AutomataLib is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 3.0 as published by the Free Software Foundation.
 * 
 * AutomataLib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with AutomataLib; if not, see
 * http://www.gnu.de/documents/lgpl.en.html.
 */
package net.automatalib.util.automata.fsa;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.automatalib.automata.concepts.InputAlphabetHolder;
import net.automatalib.automata.concepts.StateIDs;
import net.automatalib.automata.fsa.MutableDFA;
import net.automatalib.automata.fsa.NFA;
import net.automatalib.automata.fsa.impl.compact.CompactDFA;
import net.automatalib.util.automata.Automata;
import net.automatalib.words.Alphabet;



public abstract class NFAs {
	
	public static  void determinize(NFA nfa,
			Collection inputs,
			MutableDFA out,
			boolean partial,
			boolean minimize) {
		doDeterminize(nfa, inputs, out, partial);
		if(minimize) {
			Automata.invasiveMinimize(out, inputs);
		}
	}
	
	public static  CompactDFA determinize(NFA nfa,
			Alphabet inputAlphabet,
			boolean partial,
			boolean minimize) {
		CompactDFA result = new CompactDFA(inputAlphabet);
		determinize(nfa, inputAlphabet, result, partial, minimize);
		return result;
	}
	
	public static  CompactDFA determinize(NFA nfa,
			Alphabet inputAlphabet) {
		return determinize(nfa, inputAlphabet, false, true);
	}
	
	public static  & InputAlphabetHolder>
	CompactDFA determinize(A nfa, boolean partial, boolean minimize) {
		return determinize(nfa, nfa.getInputAlphabet(), partial, minimize);
	}
	
	public static  & InputAlphabetHolder>
	CompactDFA determinize(A nfa) {
		return determinize(nfa, false, true);
	}
	
	public static  void determinize(NFA nfa,
			Collection inputs,
			MutableDFA out) {
		determinize(nfa, inputs, out, false, true);
	}
	
	private static final class DeterminizeRecord {
		private final List inputStates;
		private final SO outputState;
		
		public DeterminizeRecord(List inputStates, SO outputState) {
			this.inputStates = inputStates;
			this.outputState = outputState;
		}
	}
	
	private static  void doDeterminize(NFA nfa,
			Collection inputs,
			MutableDFA out,
			boolean partial) {
		
		Map outStateMap = new HashMap<>();
		StateIDs stateIds = nfa.stateIDs();
		
		Deque> stack = new ArrayDeque<>();
		
		List initList = new ArrayList<>(nfa.getInitialStates());
		BitSet initBs = new BitSet();
		for(SI init : initList) {
			initBs.set(stateIds.getStateId(init));
		}
		
		boolean initAcc = nfa.isAccepting(initList);
		SO initOut = out.addInitialState(initAcc);
		
		outStateMap.put(initBs, initOut);
		
		stack.push(new DeterminizeRecord<>(initList, initOut));
		
		while(!stack.isEmpty()) {
			DeterminizeRecord curr = stack.pop();
			
			List inStates = curr.inputStates;
			SO outState = curr.outputState;
			
			for(I sym : inputs) {
				BitSet succBs = new BitSet();
				List succList = new ArrayList<>();
				
				for(SI inState : inStates) {
					for(SI succState : nfa.getSuccessors(inState, sym)) {
						int succId = stateIds.getStateId(succState);
						if(!succBs.get(succId)) {
							succBs.set(succId);
							succList.add(succState);
						}
					}
				}
				
				if(!partial || !succList.isEmpty()) {
					SO outSucc = outStateMap.get(succBs);
					if(outSucc == null) {
						outSucc = out.addState(nfa.isAccepting(succList));
						outStateMap.put(succBs, outSucc);
						stack.push(new DeterminizeRecord<>(succList, outSucc));
					}
					out.setTransition(outState, sym, outSucc);
				}
			}
		}
		
	}	
	private NFAs() {}
}