/* * AutomatonDeterminizationHelp.java * * Copyright (c) 2010-2011, Ontotext (www.ontotext.com). * * This file is part of GATE (see http://gate.ac.uk/), and is free * software, licenced under the GNU Library General Public License, * Version 2, June 1991 (in the distribution as file licence.html, * and also available at http://gate.ac.uk/gate/licence.html). * * * $Id$ */ package com.ontotext.jape.automaton; /** * This class is needed while determinizing an automaton. * * @author petar.mitankin * */ public class AutomatonDeterminizationHelp { protected int[] hash; protected IntSequence states; protected IntSequence sets; protected IntSequence set; protected IntSequence heap; protected int firstSet; protected AutomatonDeterminizationHelp() { hash = new int[511]; for (int i = 0; i < hash.length; i++) { hash[i] = Constants.NO; } states = new IntSequence(); sets = new IntSequence(); set = new IntSequence(); heap = new IntSequence(); } protected boolean queueIsEmpty() { return (firstSet == sets.seqStored); } public int pop() { int s = firstSet; firstSet++; return (s); } protected int push() { set.sortAndRemoveIdentical(); int i; for (i = getHashCode(); hash[i] != Constants.NO; i = (i + Constants.hashStep) % hash.length) { if (set.equals(states.seq, sets.seq[hash[i]], Constants.NO, true)) { return (hash[i]); } } int ret = sets.seqStored; hash[i] = ret; sets.add(states.seqStored); states.append(set); states.add(Constants.NO); if (10 * sets.seqStored > 9 * hash.length) { hash = new int[2 * hash.length + 1]; int j; for (j = 0; j < hash.length; j++) { hash[j] = Constants.NO; } for (i = 0; i < sets.seqStored; i++) { for (j = getHashCode(states.seq, sets.seq[i]); hash[j] != Constants.NO; j = (j + Constants.hashStep) % hash.length) ; hash[j] = i; } } return (ret); } protected int getHashCode() { int code = 0; for (int i = 0; i < set.seqStored; i++) { code = CodeInt.code(set.seq[i], code, hash.length); } return (code); } protected int getHashCode(int[] seq, int pos) { int code = 0; for (; seq[pos] != Constants.NO; pos++) { code = CodeInt.code(seq[pos], code, hash.length); } return (code); } protected void addTransitions(int s, Automaton a) { for (int i = sets.seq[s]; states.seq[i] != Constants.NO; i++) { if (a.stateNumberOfTransitions.elementAt(states.seq[i]) == 0) { continue; } heapPush(a.stateTransitions[states.seq[i]], a); } } protected void heapPush(int tr, Automaton a) { int c = heap.seqStored; heap.add(tr); int p, tmp; while (c > 0) { p = (c - 1) / 2; if (a.trLabelCmp(heap.seq[c], heap.seq[p]) < 0) { tmp = heap.seq[c]; heap.seq[c] = heap.seq[p]; heap.seq[p] = tmp; c = p; } else { break; } } } protected int getNextTransition(Automaton a) { if (heap.seqStored == 0) { return (Constants.NO); } int tr = heap.seq[0]; int stateFrom = a.transitionsFrom[tr]; if (tr + 1 < a.stateTransitions[stateFrom] + a.stateNumberOfTransitions.elementAt(stateFrom)) { heap.seq[0]++; heapSink(a); return (tr); } heap.seqStored--; if (heap.seqStored == 0) { return (tr); } heap.seq[0] = heap.seq[heap.seqStored]; heapSink(a); return (tr); } protected void heapSink(Automaton a) { int c, l, r, tmp; c = 0; while (true) { l = 2 * c + 1; if (l < heap.seqStored) { r = l + 1; if (r < heap.seqStored) { if (a.trLabelCmp(heap.seq[l], heap.seq[r]) < 0) { if (a.trLabelCmp(heap.seq[l], heap.seq[c]) < 0) { tmp = heap.seq[l]; heap.seq[l] = heap.seq[c]; heap.seq[c] = tmp; c = l; } else { break; } } else if (a.trLabelCmp(heap.seq[c], heap.seq[r]) > 0) { tmp = heap.seq[r]; heap.seq[r] = heap.seq[c]; heap.seq[c] = tmp; c = r; } else { break; } } else if (a.trLabelCmp(heap.seq[l], heap.seq[c]) < 0) { tmp = heap.seq[l]; heap.seq[l] = heap.seq[c]; heap.seq[c] = tmp; c = l; } else { break; } } else { break; } } } }