/** * This is the feature that is fired for each position in the given window. * The window.minLength specify the minimum length of the segment for which * the feature at a particular position should be considered. The window.maxLength * similarly specifies the maximum segment length for which the feature * is to be fired. */ package iitb.BSegment; import iitb.CRF.DataSequence; import iitb.Model.FeatureTypes; import iitb.Model.WindowFeatures; import java.io.Serializable; public class BWindowFeatureMultiNew extends WindowFeatures implements BoundaryFeatureFunctions { /** * Comment for <code>serialVersionUID</code> */ private static final long serialVersionUID = 1L; int currPos; int currBdry; int currWin; boolean DEBUG = false; transient DataSequence dataSeq; int dataLen; boolean allFeaturesFlag; boolean featureValid = false; boolean firstCall = true; int maxGap = 1; int minWinLength = 0; boolean directSegmentMode = false; /* * The multifeature is fired for x(i) at various positions. * - posBdry stores the valid starting and ending position for a sequence. * - featureBdry stores the valid starting and ending f._startB and f._endB values in a sequence. * - fboundary stores the boundaries of the feature. * - cfRange stores the indexes of the starting(or ending) of the segments for which the feature fired * at currPos will hold true. */ BFeatureImpl bfeatureImpl = new BFeatureImpl(); Boundary posBdry = new Boundary(); Boundary featureBdry = new Boundary(); BFeatureImpl fboundary = new BFeatureImpl(); Boundary cfRange = new Boundary(); /* * WIN_LEFT : Window defined over left end * WIN_RIGHT : Window defined over right end * WIN_MIDDLE : Window defined over both ends */ final static int WIN_LEFT = 0; final static int WIN_RIGHT = 1; final static int WIN_MIDDLE = 2; private class Boundary implements Serializable{ /** * */ private static final long serialVersionUID = 1L; public int start; public int end; public Boundary() { start = end = 0;} public String toString() { return "Start : "+ start + " : End : " + end; } }; public BWindowFeatureMultiNew(Window twindows[], FeatureTypes tsingle) { super(twindows,tsingle); if(checkValidity(windows) == false) { System.exit(0); } } public boolean startScanFeaturesAt(DataSequence tdataSeq, int tprevPos, int tpos) { directSegmentMode = true; return super.startScanFeaturesAt(tdataSeq, tprevPos, tpos); } public boolean startScanFeaturesAt(DataSequence tdataSeq, int tpos) { directSegmentMode = false; dataSeq = tdataSeq; dataLen = dataSeq.length(); currPos = tpos; if(checkWinLength(windows[currWin]) == false) { allFeaturesFlag = true; return false; } allFeaturesFlag = false; init(); if(currPos < posBdry.start || currPos > posBdry.end || single.startScanFeaturesAt(dataSeq, tpos) == false) { allFeaturesFlag = true; return false; } return advance(); } private void init() { currWin = 0; Window twindow = windows[currWin]; initBoundary(twindow); initFeatureOpenFlag(twindow, fboundary); featureValid = false; firstCall = true; } /* * This method sets the range of the segments' boundaries that will have the feature fired at tpos */ private void initCurrFeaturePosBdry(Window twindow, int tpos) { switch(getWindowType(twindow)) { case WIN_LEFT: case WIN_RIGHT: cfRange.start = Math.max(featureBdry.start, tpos - twindow.end); cfRange.end = Math.min(featureBdry.end, tpos - twindow.start); maxGap = twindow.minLength; break; case WIN_MIDDLE: if(twindow.start >= 0 && twindow.end <= 0) { maxGap = twindow.start - twindow.end + 1; cfRange.start = tpos - twindow.start; cfRange.end = tpos - twindow.start; } else if(twindow.start > twindow.end) { maxGap = twindow.start - twindow.end + 1; cfRange.start = tpos - twindow.start; cfRange.end = tpos - twindow.start; //TODO - To be checked if maxGap > } else if(twindow.start < twindow.end) { maxGap = twindow.minLength; cfRange.start = Math.max(featureBdry.start, tpos - twindow.end - ((maxGap>1)?(maxGap - 1):0)); cfRange.end = Math.min(featureBdry.end, tpos - twindow.start - ((maxGap>1)?(maxGap - 2):0)); } break; } currBdry = cfRange.start - 1; } private void initFeatureOpenFlag(Window twindow, BFeatureImpl tfeatureImpl) { switch(getWindowType(twindow)) { case WIN_LEFT: tfeatureImpl._startOpen = false; tfeatureImpl._endOpen = (twindow.maxLength == Integer.MAX_VALUE); break; case WIN_RIGHT: tfeatureImpl._startOpen = (twindow.maxLength == Integer.MAX_VALUE); tfeatureImpl._endOpen = false; break; case WIN_MIDDLE: tfeatureImpl._startOpen = twindow.maxLength == Integer.MAX_VALUE; tfeatureImpl._endOpen = twindow.maxLength == Integer.MAX_VALUE; break; default: assert(false); } } private void initBoundary(Window twindow) { switch(getWindowType(twindow)) { case WIN_LEFT: posBdry.start = Math.max(0, twindow.start); posBdry.end = Math.min(dataLen - 1, dataLen - 1 - (twindow.minLength - 1) + twindow.end); featureBdry.start = Math.max(0, -1 * twindow.end); featureBdry.end = Math.min(dataLen - 1 - twindow.minLength + 1, dataLen - 1 - twindow.start); minWinLength = getLeftWinMinLen(twindow); break; case WIN_RIGHT: posBdry.start = Math.max(0, twindow.minLength - 1 + twindow.start); posBdry.end = Math.min(dataLen - 1, dataLen - 1 + twindow.end); featureBdry.start = Math.max(twindow.minLength - 1, -1 * twindow.end); featureBdry.end = Math.min(dataLen - 1, dataLen - 1 - twindow.start); minWinLength = getRightWinMinLen(twindow); break; case WIN_MIDDLE: posBdry.start = Math.max(0, twindow.start); posBdry.end = Math.min(dataLen - 1, dataLen - 1 + twindow.end); featureBdry.start = Math.max(0, -1 * twindow.start); featureBdry.end = Math.min(dataLen - 1, dataLen - 1 - twindow.start); minWinLength = getMidWinMinLen(twindow); break; } if(posBdry.start > posBdry.end || featureBdry.start > featureBdry.end) { if(DEBUG) System.out.println("TODO : check the initBoundary method : " + posBdry + " : " + featureBdry); } } private boolean nextFeatureNew() { Window twindow = windows[currWin]; currBdry++; if(currBdry <= cfRange.end) { switch(getWindowType(twindow)) { case WIN_LEFT: fboundary._startB = currBdry; fboundary._endB = fboundary._startB + minWinLength - 1; break; case WIN_RIGHT: fboundary._endB = currBdry; fboundary._startB = fboundary._endB - minWinLength + 1; break; case WIN_MIDDLE: fboundary._startB = currBdry; fboundary._endB = fboundary._startB + maxGap - 1; break; } return true; } else { featureValid = false; return false; } } private boolean advance() { if(featureValid && nextFeatureNew()) { return true; } else { if(single.hasNext()) { single.next(bfeatureImpl); initCurrFeaturePosBdry(windows[currWin], currPos); featureValid = true; return advance(); } else { allFeaturesFlag = true; return false; } } } public boolean hasNext() {return directSegmentMode?super.hasNext():allFeaturesFlag==false;} public void next(BFeatureImpl f) { if (directSegmentMode) { super.next(f); return; } assignBoundary(bfeatureImpl, currPos); f.copy(bfeatureImpl); advance(); } public int maxBoundaryGap() { return maxGap; } public void assignBoundary(BFeatureImpl tfeatureImpl, int tpos) { tfeatureImpl.copyBoundary(fboundary); } /* * Methods for checking the validity of the parameters. */ private boolean checkValidity(Window twindowArr[]) { if(twindowArr.length > 1) { System.out.println("BWindowFeatureMulti : Only a single window is currently supported."); return false; } for(int i=0; i<twindowArr.length; i++) { Window twindow = twindowArr[i]; switch(getWindowType(twindow)) { case WIN_LEFT: case WIN_RIGHT: if(twindow.maxLength < Integer.MAX_VALUE) { System.out.println("BWindowFeatureMulti : The maxLength of windows defined for either end can not be less than Integer.MAX_VALUE"); return false; } break; case WIN_MIDDLE: if(twindow.start < 0 && twindow.end > 0) { System.out.println("BWindowFeatureMulti : The given window is not supported."); return false; } break; } } return true; } private boolean checkWinLength(Window twindow) { switch(getWindowType(twindow)) { case WIN_LEFT: return getMinLenSeqLeftWin(twindow) <= dataLen && getLeftWinMinLen(twindow) <= twindow.maxLength; case WIN_RIGHT: return getMinLenSeqRightWin(twindow) <= dataLen && getRightWinMinLen(twindow) <= twindow.maxLength; case WIN_MIDDLE: return getMinLenSeqMidWin(twindow) <= dataLen && getMidWinMinLen(twindow) <= twindow.maxLength; default: assert(false); return false; } } /* * A window should have atleast some minimum length for it to have* valid featrues. */ private int getMidWinMinLen(Window twindow) { return Math.max(twindow.minLength, twindow.start - twindow.end + 1); } private int getLeftWinMinLen(Window twindow) { return Math.max(twindow.minLength, twindow.start + 1); } private int getRightWinMinLen(Window twindow) { return Math.max(twindow.minLength, -1*twindow.end + 1); } /* * This returns the minimum length of a sequence in which the given window will be valid for some segment */ private int getMinLenSeqLeftWin(Window twindow) { int tminLen = getLeftWinMinLen(twindow); return Math.max(tminLen, tminLen - twindow.end); } private int getMinLenSeqRightWin(Window twindow) { int tminLen = getRightWinMinLen(twindow); return Math.max(tminLen, tminLen + twindow.start); } private int getMinLenSeqMidWin(Window twindow) { return Math.max(getMidWinMinLen(twindow), Math.max(twindow.start, -1*twindow.end)+1); } /* * Get the type of the window */ int getWindowType(Window twindow) { if(twindow.startRelativeToLeft && twindow.endRelativeToLeft) { return WIN_LEFT; } else if(!twindow.startRelativeToLeft && !twindow.endRelativeToLeft) { return WIN_RIGHT; } else if(twindow.startRelativeToLeft && !twindow.endRelativeToLeft) { return WIN_MIDDLE; } else { assert(false); return -1; } } int winSize(Window twindow) { return twindow.end - twindow.start + 1; } public boolean requiresTraining() { return super.requiresTraining(); } public void train(DataSequence tdataSeq, int tpos) { super.train(tdataSeq, tpos); } };