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

net.automatalib.serialization.saf.SAFInput Maven / Gradle / Ivy

There is a newer version: 0.11.0
Show newest version
/* Copyright (C) 2015 TU Dortmund
 * This file is part of AutomataLib, http://www.automatalib.net/.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.automatalib.serialization.saf;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import net.automatalib.automata.AutomatonCreator;
import net.automatalib.automata.MutableAutomaton;
import net.automatalib.automata.fsa.impl.compact.CompactDFA;
import net.automatalib.automata.fsa.impl.compact.CompactNFA;
import net.automatalib.serialization.saf.SAFSerialization.AutomatonType;
import net.automatalib.words.Alphabet;
import net.automatalib.words.impl.Alphabets;

class SAFInput {
	
	private static final AutomatonType[] types = SAFSerialization.AutomatonType.values();
	
	private final DataInput in;
	
	public SAFInput(DataInput in) {
		this.in = in;
	}
	
	public SAFInput(InputStream is) {
		this((DataInput)new DataInputStream(is));
	}
	
	public SAFInput(byte[] data) {
		this(new ByteArrayInputStream(data));
	}
	
	public SAFInput(File file) throws FileNotFoundException {
		this(new BufferedInputStream(new FileInputStream(file)));
	}
	
	
	public AutomatonType readHeader() throws IOException {
		byte[] header = new byte[4];
		in.readFully(header);
		if (header[0] != 'S' || header[1] != 'A' || header[2] != 'F') {
			throw new RuntimeException();
		}
		byte type = header[3];
		if (type < 0 || type >= types.length) {
			throw new RuntimeException();
		}
		return types[type];
	}
	
	private  void decodeTransitionsDet(
			MutableAutomaton result,
			List stateList,
			Alphabet alphabet,
			SinglePropertyDecoder tpDecoder) throws IOException {
		int numStates = stateList.size();
		assert result.size() == numStates;
		
		int numInputs = alphabet.size();
		
		for (S state : stateList) {
			for (int j = 0; j < numInputs; j++) {
				int tgt = in.readInt();
				if (tgt != -1) {
					I sym = alphabet.getSymbol(j);
					S tgtState = stateList.get(tgt);
					TP prop = tpDecoder.readProperty(in);
					result.addTransition(state, sym, tgtState, prop);
				}
			}
		}
	}
	
	private  void decodeTransitionsNondet(
			MutableAutomaton result,
			List stateList,
			Alphabet alphabet,
			SinglePropertyDecoder tpDecoder) throws IOException {
		int numStates = stateList.size();
		assert result.size() == numStates;
		
		int numInputs = alphabet.size();
		
		for (S state : stateList) {
			for (int j = 0; j < numInputs; j++) {
				int numTgts = in.readInt();
				I sym = alphabet.getSymbol(j);
				for (int k = 0; k < numTgts; k++) {
					int tgt = in.readInt();
					TP prop = tpDecoder.readProperty(in);
					S tgtState = stateList.get(tgt);
					result.addTransition(state, sym, tgtState, prop);
				}
			}
		}
	}
	
	
	private  List decodeStateProperties(
			MutableAutomaton result,
			int numStates,
			BlockPropertyDecoder decoder) throws IOException {
		List stateList = new ArrayList<>(numStates);
		
		decoder.start(in);
		for (int i = 0; i < numStates; i++) {
			SP prop = decoder.readProperty(in);
			S state = result.addState(prop);
			stateList.add(state);
		}
		
		return stateList;
	}
	
	private  List decodeStatesDet(
			MutableAutomaton result,
			int numStates,
			BlockPropertyDecoder decoder) throws IOException {
		int initStateId = in.readInt();
		
		List stateList = decodeStateProperties(result, numStates, decoder);
		
		S initState = stateList.get(initStateId);
		
		result.setInitial(initState, true);
		
		return stateList;
	}
	
	private  List decodeStatesNondet(
			MutableAutomaton result,
			int numStates,
			BlockPropertyDecoder decoder) throws IOException {
		int[] initStates = readInts(in);
		
		List stateList = decodeStateProperties(result, numStates, decoder);
		
		for (int initId : initStates) {
			S initState = stateList.get(initId);
			result.setInitial(initState, true);
		}
		
		return stateList;
	}
	
	private  List decodeBodyDet(
			MutableAutomaton result,
			Alphabet alphabet,
			int numStates,
			BlockPropertyDecoder spDecoder,
			SinglePropertyDecoder tpDecoder) throws IOException {
		
		List stateList = decodeStatesDet(result, numStates, spDecoder);
		decodeTransitionsDet(result, stateList, alphabet, tpDecoder);
		
		return stateList;
	}
	
	private  List decodeBodyNondet(
			MutableAutomaton result,
			Alphabet alphabet,
			int numStates,
			BlockPropertyDecoder spDecoder,
			SinglePropertyDecoder tpDecoder) throws IOException {
		
		List stateList = decodeStatesNondet(result, numStates, spDecoder);
		decodeTransitionsNondet(result, stateList, alphabet, tpDecoder);
		
		return stateList;
	}
	
	private static int[] readInts(DataInput in) throws IOException {
		int n = in.readInt();
		int[] result = new int[n];
		for (int i = 0; i < n; i++) {
			result[i] = in.readInt();
		}
		return result;
	}
	
	private > A readAutomatonBody(
			Alphabet alphabet,
			boolean deterministic,
			AutomatonCreator creator,
			BlockPropertyDecoder spDecoder,
			SinglePropertyDecoder tpDecoder) throws IOException {
		int numStates = in.readInt();
		A result = creator.createAutomaton(alphabet, numStates);
		
		// this cast is required ..
		MutableAutomaton result_ = (MutableAutomaton)result;
		if (deterministic) {
			decodeBodyDet(result_, alphabet, numStates, spDecoder, tpDecoder);
		}
		else {
			decodeBodyNondet(result_, alphabet, numStates, spDecoder, tpDecoder);
		}
		
		return result;
	}
	
	public > A readAutomaton(
			AutomatonType expectedType,
			Alphabet alphabet,
			AutomatonCreator creator,
			BlockPropertyDecoder spDecoder,
			SinglePropertyDecoder tpDecoder) throws IOException {
		AutomatonType type = readHeader();
		if (type != expectedType) {
			throw new RuntimeException();
		}
		int alphabetSize = in.readInt();
		if (alphabetSize != alphabet.size()) {
			throw new RuntimeException();
		}
		return readAutomatonBody(alphabet, type.isDeterministic(), creator, spDecoder, tpDecoder);
	}
	
	public > A readNativeAutomaton(
			AutomatonType expectedType,
			AutomatonCreator creator,
			BlockPropertyDecoder spDecoder,
			SinglePropertyDecoder tpDecoder) throws IOException {
		AutomatonType type = readHeader();
		if (type != expectedType) {
			throw new RuntimeException();
		}
		int alphabetSize = in.readInt();
		if (alphabetSize <= 0) {
			throw new RuntimeException();
		}
		Alphabet alphabet = Alphabets.integers(0, alphabetSize - 1);
		return readAutomatonBody(alphabet, type.isDeterministic(), creator, spDecoder, tpDecoder);
	}
	
	public  CompactDFA readDFA(Alphabet alphabet) throws IOException {
		return readAutomaton(
				AutomatonType.DFA,
				alphabet,
				new CompactDFA.Creator<>(),
				new AcceptanceDecoder(),
				in -> null);
	}
	
	public CompactDFA readNativeDFA() throws IOException {
		return readNativeAutomaton(
				AutomatonType.DFA,
				new CompactDFA.Creator<>(),
				new AcceptanceDecoder(),
				in -> null);
	}
	
	public  CompactNFA readNFA(Alphabet alphabet) throws IOException {
		return readAutomaton(
				AutomatonType.NFA,
				alphabet,
				new CompactNFA.Creator<>(),
				new AcceptanceDecoder(),
				in -> null);
	}
	
	public CompactNFA readNativeNFA() throws IOException {
		return readNativeAutomaton(
				AutomatonType.NFA,
				new CompactNFA.Creator<>(),
				new AcceptanceDecoder(),
				in -> null);
	}
}