internal virtual bool IsCorrect(ITransition other) { if (transition != null && transition.Equals(other)) { return(true); } if (allowsShift && (other is ShiftTransition)) { return(true); } if (allowsBinary && (other is BinaryTransition)) { return(true); } if (allowsEitherSide && (other is BinaryTransition) && (transition is BinaryTransition)) { if (((BinaryTransition)other).label.Equals(((BinaryTransition)transition).label)) { return(true); } } return(false); }
/// <summary> /// Given a predicted transition and a state, this method rearranges /// the list of transitions and returns whether or not training can /// continue. /// </summary> internal virtual bool Reorder(State state, ITransition chosenTransition, IList <ITransition> transitions) { if (transitions.Count == 0) { throw new AssertionError(); } ITransition goldTransition = transitions[0]; // If the transition is gold, we are already satisfied. if (chosenTransition.Equals(goldTransition)) { transitions.Remove(0); return(true); } // If the transition should have been a Unary/CompoundUnary // transition and it was something else or a different Unary // transition, see if the transition sequence can be continued // after skipping past the unary if ((goldTransition is UnaryTransition) || (goldTransition is CompoundUnaryTransition)) { transitions.Remove(0); return(Reorder(state, chosenTransition, transitions)); } // If the chosen transition was an incorrect Unary/CompoundUnary // transition, skip past it and hope to continue the gold // transition sequence. However, if we have Unary/CompoundUnary // in a row, we have to return false to prevent loops. // Also, if the state stack size is 0, can't keep going if ((chosenTransition is UnaryTransition) || (chosenTransition is CompoundUnaryTransition)) { if (state.transitions.Size() > 0) { ITransition previous = state.transitions.Peek(); if ((previous is UnaryTransition) || (previous is CompoundUnaryTransition)) { return(false); } } if (state.stack.Size() == 0) { return(false); } return(true); } if (chosenTransition is BinaryTransition) { if (state.stack.Size() < 2) { return(false); } if (goldTransition is ShiftTransition) { // Helps, but adds quite a bit of size to the model and only helps a tiny bit return(op.TrainOptions().oracleBinaryToShift&& ReorderIncorrectBinaryTransition(transitions)); } if (!(goldTransition is BinaryTransition)) { return(false); } BinaryTransition chosenBinary = (BinaryTransition)chosenTransition; BinaryTransition goldBinary = (BinaryTransition)goldTransition; if (chosenBinary.IsBinarized()) { // Binarized labels only work (for now, at least) if the side // is wrong but the label itself is correct if (goldBinary.IsBinarized() && chosenBinary.label.Equals(goldBinary.label)) { transitions.Remove(0); return(true); } else { return(false); } } // In all other binarized situations, essentially what has // happened is we added a bracket error, but future brackets can // still wind up being correct transitions.Remove(0); return(true); } if ((chosenTransition is ShiftTransition) && (goldTransition is BinaryTransition)) { // can't shift at the end of the queue if (state.EndOfQueue()) { return(false); } // doesn't help, sadly BinaryTransition goldBinary = (BinaryTransition)goldTransition; if (!goldBinary.IsBinarized()) { return(op.TrainOptions().oracleShiftToBinary&& ReorderIncorrectShiftTransition(transitions)); } } return(false); }