/// <summary> /// Adds a frame element to this set /// </summary> /// <param name="frameElement">Frame element to add</param> public void Add(FrameElement frameElement) { _frameElements.Add(frameElement); _idFrameElement.Add(frameElement.ID, frameElement); string lowerName = frameElement.Name.ToLower(); _nameFrameElements.EnsureContainsKey(lowerName, typeof(Set <FrameElement>)); _nameFrameElements[lowerName].Add(frameElement); }
/// <summary> /// Equals override /// </summary> /// <param name="obj">Object to compare this one to</param> /// <returns>True if object is a FE with the same ID, False otherwise</returns> public override bool Equals(object obj) { if (!(obj is FrameElement)) { return(false); } FrameElement fe = obj as FrameElement; return(_id == fe.ID); }
/// <summary> /// Removes a frae element from this set /// </summary> /// <param name="frameElement">Frame element to remove</param> public void Remove(FrameElement frameElement) { _frameElements.Remove(frameElement); _idFrameElement.Remove(frameElement.ID); _nameFrameElements[frameElement.Name.ToLower()].Remove(frameElement); }
/// <summary> /// Checks for a frame element /// </summary> /// <param name="frameElement">Frame element to check for</param> /// <returns>True if frame element is present and false otherwise</returns> public bool Contains(FrameElement frameElement) { return(_frameElements.Contains(frameElement)); }
/// <summary> /// Gets the shortest network path from the current frame element to another frame element /// </summary> /// <param name="destinationFrameElement">Destination frame element</param> /// <param name="searchRelations">Relations to search</param> /// <param name="searchDirection">Relation direction to search</param> /// <param name="maxDepth">Maximum depth to search within the network (i.e., maximum distance destination frame element can be from the current one)</param> /// <param name="frameElementPath">Path from this frame element to the destination frame element, or null for no path</param> /// <param name="relationPath">Relation path between this frame element and the destination frame element, or null for no path</param> /// <returns>True if path exists, false otherwise</returns> public bool GetShortestPathTo(FrameElement destinationFrameElement, Set <Frame.FrameRelation> searchRelations, Frame.FrameRelationDirection searchDirection, int maxDepth, out List <FrameElement> frameElementPath, out List <Frame.FrameRelation> relationPath) { frameElementPath = null; relationPath = null; // breadth-first search originating at the current frame element Queue <FrameElement> searchQueue = new Queue <FrameElement>(); _frameElementSearchBackPointer = null; // make sure to null out the source frame element back pointer searchQueue.Enqueue(this); Set <FrameElement> frameElementsEncountered = new Set <FrameElement>(); // keep track of frame elements we see so we don't enter any cycles frameElementsEncountered.Add(this); int currentDepth = 0; // tracks current search depth int nodesAtCurrentDepth = 1; // tracks nodes at current search depth int nodesAtCurrentDepthPlusOne = 0; // tracks nodes at one beyond the current search depth while (searchQueue.Count > 0 && currentDepth <= maxDepth) { FrameElement currentFrameElement = searchQueue.Dequeue(); // check for destination frame element if (currentFrameElement == destinationFrameElement) { // create path by following backpointers frameElementPath = new List <FrameElement>(); relationPath = new List <Frame.FrameRelation>(); while (destinationFrameElement != null) { frameElementPath.Add(destinationFrameElement); // back up to previous frame element FrameElement previousFrameElement = destinationFrameElement.FrameElementSearchBackPointer; // if the previous frame element isn't null, record the relationship if (previousFrameElement != null) { relationPath.Add(destinationFrameElement.FrameRelationSearchBackPointer); } destinationFrameElement = previousFrameElement; } // reverse paths to be from the current to the destination frame elements frameElementPath.Reverse(); relationPath.Reverse(); if (frameElementPath[0] != this) { throw new Exception("Path should start at current frame element"); } if (frameElementPath.Count != relationPath.Count + 1) { throw new Exception("Path length mismatch between frame elements and relations"); } if (frameElementPath.Count - 1 > maxDepth) { throw new Exception("Exceeded maximum allowed search depth"); } return(true); } // queue up frame elements related to the current one by any of the given relations int nodesAdded = 0; foreach (Frame.FrameRelation searchRelation in searchRelations) { // add sub-FEs if (searchDirection == Frame.FrameRelationDirection.Sub || searchDirection == Frame.FrameRelationDirection.Both) { foreach (FrameElement subFE in currentFrameElement._relationSubFrameElements[searchRelation]) { if (!frameElementsEncountered.Contains(subFE)) { subFE._frameElementSearchBackPointer = currentFrameElement; subFE._frameRelationSearchBackPointer = searchRelation; searchQueue.Enqueue(subFE); frameElementsEncountered.Add(subFE); ++nodesAdded; } } } // add super-FEs if (searchDirection == Frame.FrameRelationDirection.Super || searchDirection == Frame.FrameRelationDirection.Both) { foreach (FrameElement superFE in currentFrameElement._relationSuperFrameElements[searchRelation]) { if (!frameElementsEncountered.Contains(superFE)) { superFE._frameElementSearchBackPointer = currentFrameElement; superFE._frameRelationSearchBackPointer = searchRelation; searchQueue.Enqueue(superFE); frameElementsEncountered.Add(superFE); ++nodesAdded; } } } } // all generated search nodes belong in the next depth level nodesAtCurrentDepthPlusOne += nodesAdded; // if there aren't any nodes left at the current depth level, move to next level out if (--nodesAtCurrentDepth == 0) { nodesAtCurrentDepth = nodesAtCurrentDepthPlusOne; nodesAtCurrentDepthPlusOne = 0; currentDepth++; } } return(false); }
/// <summary> /// Adds a frame element to the super-FE collection for a relation /// </summary> /// <param name="frameElement">Frame element to add</param> /// <param name="relation">Relation between current and given frame element</param> internal void AddSuperFrameElement(FrameElement frameElement, Frame.FrameRelation relation) { _relationSuperFrameElements[relation].Add(frameElement); }
/// <summary> /// Gets annotations for a lexical unit /// </summary> /// <param name="frame">Frame for which we're getting annotations</param> /// <param name="lexicalUnitID">ID of lexical unit for which to get annotations</param> /// <returns>Annotation information</returns> public List <Attestation> GetAttestations(Frame frame, int lexicalUnitID) { List <Attestation> attestations = new List <Attestation>(); // return nothing if no file exists string attestationFilePath = Path.Combine(_annotationDirectory, "lu" + lexicalUnitID + ".xml"); if (!File.Exists(attestationFilePath)) { return(attestations); } // constraints to skip to FE layer Dictionary <string, string> feAttributeConstraints = new Dictionary <string, string>(); feAttributeConstraints.Add("name", "FE"); // constraints to skip to Target layer Dictionary <string, string> targetAttributeConstraints = new Dictionary <string, string>(); targetAttributeConstraints.Add("name", "Target"); // get all attestations XmlParser attestationP = new XmlParser(File.ReadAllText(attestationFilePath)); if (_version == FrameNetEngine.Version.FrameNet_1_3) { string annotationSetXML; while ((annotationSetXML = attestationP.OuterXML("annotationSet")) != null) { Attestation annotation = new Attestation(); // parser for entire annotation set XmlParser annotationSetP = new XmlParser(annotationSetXML); // first get sentence...it is below the annotation layers annotation.Sentence = new XmlParser(annotationSetP.OuterXML("sentence")).ElementText("text").Trim(); #region get fe bindings // parser is forward-only, so rewind annotationSetP.Reset(); // get FE bindings if (!annotationSetP.SkipToElement("layer", feAttributeConstraints)) { throw new Exception("Failed to find FE layer in annotation set"); } string feBindingXML = annotationSetP.OuterXML("layer"); XmlParser feBindingP = new XmlParser(feBindingXML); // read off FE binding labels string labelXML; while ((labelXML = feBindingP.OuterXML("label")) != null) { XmlParser labelP = new XmlParser(labelXML); // skip null instantiations, which don't have start/end values if (!labelP.GetAttributeNames("label").Contains("start")) { continue; } // get annotated span of text int feStart = int.Parse(labelP.AttributeValue("label", "start")); int feEnd = int.Parse(labelP.AttributeValue("label", "end")); string feText = annotation.Sentence.Substring(feStart, feEnd - feStart + 1); AnnotatedSpan span = new AnnotatedSpan(feStart, feText); // add FE binding...we shouldn't have to check for the existence of a frame element, but errors abound! string feName = labelP.AttributeValue("label", "name"); if (frame.FrameElements.Contains(feName)) { FrameElement fe = frame.FrameElements.Get(feName); annotation.FrameElementBindings.EnsureContainsKey(fe, typeof(List <AnnotatedSpan>)); annotation.FrameElementBindings[fe].Add(span); } } #endregion #region targets // get target annotation...reset parser...sometimes the target comes before the FE layer annotationSetP.Reset(); if (!annotationSetP.SkipToElement("layer", targetAttributeConstraints)) { throw new Exception("Failed to find target layer in annotation set"); } // read all targets XmlParser targetP = new XmlParser(annotationSetP.OuterXML("layer")); while ((labelXML = targetP.OuterXML("label")) != null) { XmlParser labelP = new XmlParser(labelXML); int targetStart = int.Parse(labelP.AttributeValue("label", "start")); int targetEnd = int.Parse(labelP.AttributeValue("label", "end")); string targetText = annotation.Sentence.Substring(targetStart, targetEnd - targetStart + 1); annotation.Targets.Add(new AnnotatedSpan(targetStart, targetText)); } #endregion attestations.Add(annotation); } } else if (_version == FrameNetEngine.Version.FrameNet_1_5) { string sentenceXML; while ((sentenceXML = attestationP.OuterXML("sentence")) != null) { Attestation annotation = new Attestation(); XmlParser sentenceP = new XmlParser(sentenceXML); annotation.Sentence = sentenceP.ElementText("text").Trim(); #region get fe bindings if (!sentenceP.SkipToElement("layer", feAttributeConstraints)) { throw new Exception("Failed to find FE layer in annotation set"); } // read off FE binding labels XmlParser feBindingP = new XmlParser(sentenceP.OuterXML("layer")); string labelXML; while ((labelXML = feBindingP.OuterXML("label")) != null) { XmlParser labelP = new XmlParser(labelXML); // skip null instantiations, which don't have start/end values if (!labelP.GetAttributeNames("label").Contains("start")) { continue; } // get annotated span of text int feStart = int.Parse(labelP.AttributeValue("label", "start")); int feEnd = int.Parse(labelP.AttributeValue("label", "end")); string feText = annotation.Sentence.Substring(feStart, feEnd - feStart + 1); AnnotatedSpan span = new AnnotatedSpan(feStart, feText); // add FE binding...we shouldn't have to check for the existence of a frame element, but errors abound! int feID = int.Parse(labelP.AttributeValue("label", "feID")); if (frame.FrameElements.Contains(feID)) { FrameElement fe = frame.FrameElements.Get(feID); annotation.FrameElementBindings.EnsureContainsKey(fe, typeof(List <AnnotatedSpan>)); annotation.FrameElementBindings[fe].Add(span); } } #endregion #region targets // get target annotation...reset parser...sometimes the target comes before the FE layer sentenceP.Reset(); if (!sentenceP.SkipToElement("layer", targetAttributeConstraints)) { throw new Exception("Failed to find target layer in annotation set"); } // read all targets XmlParser targetP = new XmlParser(sentenceP.OuterXML("layer")); while ((labelXML = targetP.OuterXML("label")) != null) { XmlParser labelP = new XmlParser(labelXML); int targetEnd = int.Parse(labelP.AttributeValue("label", "end")); int targetStart = int.Parse(labelP.AttributeValue("label", "start")); // bug in framenet: bad sentence if (targetStart >= annotation.Sentence.Length || targetEnd >= annotation.Sentence.Length) { continue; } string targetText = annotation.Sentence.Substring(targetStart, targetEnd - targetStart + 1); annotation.Targets.Add(new AnnotatedSpan(targetStart, targetText)); } #endregion attestations.Add(annotation); } } else { throw new Exception("Unrecognized FrameNet version: " + _version); } return(attestations); }
/// <summary> /// Constructor /// </summary> /// <param name="frameNetDirectory">Path to FrameNet distribution directory</param> /// <param name="version">FrameNet version</param> public FrameNetEngine(string frameNetDirectory, Version version) { if (!System.IO.Directory.Exists(frameNetDirectory)) { throw new DirectoryNotFoundException("Invalid FrameNet directory"); } _frameNameFrame = new Dictionary <string, Frame>(); _frameElementIdFrameElement = new Dictionary <int, FrameElement>(); _lexemeLexicalUnitIDs = new Dictionary <string, Set <int> >(); _lexicalUnitIdFrame = new Dictionary <int, Frame>(); _lexicalUnitLexicalUnitIDs = new Dictionary <string, Set <int> >(); _lexicalUnitIdLexicalUnit = new Dictionary <int, LexicalUnit>(); if (version == Version.FrameNet_1_3) { // init annotation engine _lexicalUnitAnnotationEngine = new LexicalUnitAnnotationEngine(LAIR.CommonPort.IO.Directory.FindDirectory(frameNetDirectory, "luXML"), version); #region get frames Set <int> uniqueFrameIDCheck = new Set <int>(); XmlParser framesP = new XmlParser(System.IO.File.ReadAllText(LAIR.CommonPort.IO.Directory.FindFile(frameNetDirectory, "frames.xml"))); while (framesP.SkipToElement("frame")) { // create frame string frameXML = framesP.OuterXML("frame"); XmlParser frameP = new XmlParser(frameXML); int frameID = int.Parse(frameP.AttributeValue("frame", "ID")); string frameName = frameP.AttributeValue("frame", "name").ToLower().Trim(); // use lowercase for all frame names string frameDefinition = frameP.ElementText("definition"); Frame frame = new Frame(frameName, frameDefinition, frameID); // add to frame index index _frameNameFrame.Add(frame.Name, frame); uniqueFrameIDCheck.Add(frame.ID); // get frame elements string fesXML = frameP.OuterXML("fes"); XmlParser fesP = new XmlParser(fesXML); string feXML; while ((feXML = fesP.OuterXML("fe")) != null) { // get frame element XmlParser feParser = new XmlParser(feXML); int feID = int.Parse(feParser.AttributeValue("fe", "ID")); string feName = feParser.AttributeValue("fe", "name").Trim().ToLower(); string feDef = feParser.ElementText("definition"); FrameElement fe = new FrameElement(feID, feName, feDef, frame); frame.FrameElements.Add(fe); // add to index _frameElementIdFrameElement.Add(fe.ID, fe); } // get lexical units string lusXML = frameP.OuterXML("lexunits"); XmlParser lusParser = new XmlParser(lusXML); string luXML; while ((luXML = lusParser.OuterXML("lexunit")) != null) { XmlParser luParser = new XmlParser(luXML); int luID = int.Parse(luParser.AttributeValue("lexunit", "ID")); string luName = luParser.AttributeValue("lexunit", "name"); luName = luName.Substring(0, luName.IndexOf('.')); string luPos = luParser.AttributeValue("lexunit", "pos"); string luDef = luParser.ElementText("definition"); // get lexemes for this lexunit...we may get duplicates...don't worry about them Set <Lexeme> lexemes = new Set <Lexeme>(false); string lexemesXML = luParser.OuterXML("lexemes"); XmlParser lexemesP = new XmlParser(lexemesXML); string lexemeXML; while ((lexemeXML = lexemesP.OuterXML("lexeme")) != null) { XmlParser lexemeP = new XmlParser(lexemeXML); string pos = lexemeP.AttributeValue("lexeme", "pos"); bool breakBefore = bool.Parse(lexemeP.AttributeValue("lexeme", "breakBefore")); bool head = bool.Parse(lexemeP.AttributeValue("lexeme", "headword")); string value = lexemeP.ElementText("lexeme"); lexemes.Add(new Lexeme(value, pos, breakBefore, head)); } // create lexical unit and add to frame LexicalUnit lexicalUnit = new LexicalUnit(luID, luName, luPos, luDef, lexemes); frame.LexicalUnits.Add(lexicalUnit); // add map from full lexeme string to lexical unit id string lexemeString = lexicalUnit.ToString(); _lexemeLexicalUnitIDs.EnsureContainsKey(lexemeString, typeof(Set <int>), false); _lexemeLexicalUnitIDs[lexemeString].Add(luID); // add map from lexical unit to frame _lexicalUnitIdFrame.Add(lexicalUnit.ID, frame); // add map from lexical unit to lexical unit id _lexicalUnitLexicalUnitIDs.EnsureContainsKey(lexicalUnit.Name, typeof(Set <int>)); _lexicalUnitLexicalUnitIDs[lexicalUnit.Name].Add(lexicalUnit.ID); // add map from lexical unit ID to lexical unit _lexicalUnitIdLexicalUnit.Add(lexicalUnit.ID, lexicalUnit); } } #endregion #region get frame relations framesP = new XmlParser(System.IO.File.ReadAllText(LAIR.CommonPort.IO.Directory.FindFile(frameNetDirectory, "frRelation.xml"))); string relationsXML; while ((relationsXML = framesP.OuterXML("frame-relation-type")) != null) { // get relation type XmlParser relationsP = new XmlParser(relationsXML); Frame.FrameRelation relation = Frame.GetFrameRelation(relationsP.AttributeValue("frame-relation-type", "name")); string relationXML; while ((relationXML = relationsP.OuterXML("frame-relation")) != null) { XmlParser relationP = new XmlParser(relationXML); string superFrameName = relationP.AttributeValue("frame-relation", "superFrameName").ToLower(); string subFrameName = relationP.AttributeValue("frame-relation", "subFrameName").ToLower(); Frame superFrame = _frameNameFrame[superFrameName]; Frame subFrame = _frameNameFrame[subFrameName]; superFrame.GetSubFrames(relation).Add(subFrame); subFrame.GetSuperFrames(relation).Add(superFrame); // add FE relations while (relationP.SkipToElement("fe-relation")) { int superFeID = int.Parse(relationP.AttributeValue("fe-relation", "supId")); int subFeID = int.Parse(relationP.AttributeValue("fe-relation", "subId")); FrameElement superFE = superFrame.FrameElements.Get(superFeID); FrameElement subFE = subFrame.FrameElements.Get(subFeID); superFE.AddSubFrameElement(subFE, relation); subFE.AddSuperFrameElement(superFE, relation); } } } #endregion } else if (version == Version.FrameNet_1_5) { // init annotation engine _lexicalUnitAnnotationEngine = new LexicalUnitAnnotationEngine(LAIR.CommonPort.IO.Directory.FindDirectory(frameNetDirectory, "lu"), version); #region get frames Set <int> uniqueFrameIDCheck = new Set <int>(); foreach (string framePath in System.IO.Directory.GetFiles(LAIR.CommonPort.IO.Directory.FindDirectory(frameNetDirectory, "frame"), "*.xml")) { // create frame XmlParser frameP = new XmlParser(System.IO.File.ReadAllText(framePath)); int frameID = int.Parse(frameP.AttributeValue("frame", "ID")); string frameName = frameP.AttributeValue("frame", "name").ToLower().Trim(); // use lowercase for all frame names string frameDefinition = frameP.ElementText("definition"); Frame frame = new Frame(frameName, frameDefinition, frameID); // add to frame index index _frameNameFrame.Add(frame.Name, frame); uniqueFrameIDCheck.Add(frame.ID); // get frame elements string feXML; while ((feXML = frameP.OuterXML("FE")) != null) { // get frame element XmlParser feParser = new XmlParser(feXML); int feID = int.Parse(feParser.AttributeValue("FE", "ID")); string feName = feParser.AttributeValue("FE", "name").Trim().ToLower(); string feDef = feParser.ElementText("definition"); FrameElement fe = new FrameElement(feID, feName, feDef, frame); frame.FrameElements.Add(fe); // add to index _frameElementIdFrameElement.Add(fe.ID, fe); } // get lexical units frameP.Reset(); string luXML; while ((luXML = frameP.OuterXML("lexUnit")) != null) { XmlParser luParser = new XmlParser(luXML); string luPos = luParser.AttributeValue("lexUnit", "POS"); string luName = luParser.AttributeValue("lexUnit", "name"); luName = luName.Substring(0, luName.IndexOf('.')); int luID = int.Parse(luParser.AttributeValue("lexUnit", "ID")); string luDef = luParser.ElementText("definition"); // get lexemes for this lexunit...we may get duplicates...don't worry about them Set <Lexeme> lexemes = new Set <Lexeme>(false); string lexemeXML; while ((lexemeXML = luParser.OuterXML("lexeme")) != null) { XmlParser lexemeP = new XmlParser(lexemeXML); bool head = bool.Parse(lexemeP.AttributeValue("lexeme", "headword")); bool breakBefore = bool.Parse(lexemeP.AttributeValue("lexeme", "breakBefore")); string pos = lexemeP.AttributeValue("lexeme", "POS"); string value = lexemeP.AttributeValue("lexeme", "name"); lexemes.Add(new Lexeme(value, pos, breakBefore, head)); } // create lexical unit and add to frame LexicalUnit lexicalUnit = new LexicalUnit(luID, luName, luPos, luDef, lexemes); frame.LexicalUnits.Add(lexicalUnit); // add map from full lexeme string to lexical unit id string lexemeString = lexicalUnit.ToString(); _lexemeLexicalUnitIDs.EnsureContainsKey(lexemeString, typeof(Set <int>), false); _lexemeLexicalUnitIDs[lexemeString].Add(luID); // add map from lexical unit to frame _lexicalUnitIdFrame.Add(lexicalUnit.ID, frame); // add map from lexical unit to lexical unit id _lexicalUnitLexicalUnitIDs.EnsureContainsKey(lexicalUnit.Name, typeof(Set <int>)); _lexicalUnitLexicalUnitIDs[lexicalUnit.Name].Add(lexicalUnit.ID); // add map from lexical unit ID to lexical unit _lexicalUnitIdLexicalUnit.Add(lexicalUnit.ID, lexicalUnit); } } #endregion #region get relations XmlParser allRelationsP = new XmlParser(System.IO.File.ReadAllText(LAIR.CommonPort.IO.Directory.FindFile(frameNetDirectory, "frRelation.xml"))); string relationsXML; while ((relationsXML = allRelationsP.OuterXML("frameRelationType")) != null) { // get relation type XmlParser relationsP = new XmlParser(relationsXML); Frame.FrameRelation relation = Frame.GetFrameRelation(relationsP.AttributeValue("frameRelationType", "name")); // read each instance of the relation string relationXML; while ((relationXML = relationsP.OuterXML("frameRelation")) != null) { XmlParser relationP = new XmlParser(relationXML); // get related frames Frame subFrame = _frameNameFrame[relationP.AttributeValue("frameRelation", "subFrameName").ToLower()]; Frame superFrame = _frameNameFrame[relationP.AttributeValue("frameRelation", "superFrameName").ToLower()]; subFrame.GetSuperFrames(relation).Add(superFrame); superFrame.GetSubFrames(relation).Add(subFrame); // add FE relations while (relationP.SkipToElement("FERelation")) { FrameElement subFE = subFrame.FrameElements.Get(int.Parse(relationP.AttributeValue("FERelation", "subID"))); FrameElement superFE = superFrame.FrameElements.Get(int.Parse(relationP.AttributeValue("FERelation", "supID"))); subFE.AddSuperFrameElement(superFE, relation); superFE.AddSubFrameElement(subFE, relation); } } } #endregion } else { throw new Exception("Unrecognized FrameNet version: " + version); } }