From 49c619552723f2d6ebfad3ec58557134815f6f1e Mon Sep 17 00:00:00 2001 From: "John P. McCrae" Date: Tue, 3 Dec 2024 13:03:49 +0000 Subject: [PATCH] Add some new automaton language from the new editor --- src/automaton.rs | 135 +++++++++++++++++++++++++++++++++++------- src/change_manager.rs | 32 ++++++++++ src/wordnet.rs | 28 ++++++++- 3 files changed, 171 insertions(+), 24 deletions(-) diff --git a/src/automaton.rs b/src/automaton.rs index aa643fd..f81b5dd 100644 --- a/src/automaton.rs +++ b/src/automaton.rs @@ -1,5 +1,5 @@ use crate::change_manager; -use crate::wordnet::{Lexicon,SynsetId,PosKey,SenseId}; +use crate::wordnet::{Lexicon,SynsetId,PosKey,SenseId,ILIID}; use crate::rels::{SenseRelType, SynsetRelType}; use crate::change_manager::ChangeList; use crate::validate; @@ -95,15 +95,27 @@ pub fn apply_automaton(actions : Vec, wn : &mut Lexicon, change_manager::delete_ex(wn, &synset.resolve(&last_synset_id)?, number - 1, changes); }, - Action::AddRelation { source, source_sense, relation, target, target_sense } => { + Action::AddRelation { source, source_sense, relation, target, target_sense, source_lemma, target_lemma } => { + let source = source.resolve(&last_synset_id)?; + let source_sense = if let Some(source_sense) = source_sense { + Some(source_sense.resolve(&last_sense_id, wn, &source)?) + } else if let Some(lemma) = source_lemma.as_ref() { + Some(wn.get_sense_id2(&lemma, &source).ok_or(format!("No sense with lemma {} in {}", lemma, source.as_str()))?.clone()) + } else { + None + }; + let target = target.resolve(&last_synset_id)?; + let target_sense = if let Some(target_sense) = target_sense { + Some(target_sense.resolve(&last_sense_id, wn, &target)?) + } else if let Some(lemma) = target_lemma.as_ref() { + Some(wn.get_sense_id2(&lemma, &target).ok_or(format!("No sense with lemma {} in {}", lemma, target.as_str()))?.clone()) + } else { + None + }; match source_sense { Some(sense) => { - let sense = sense.resolve(&last_sense_id, wn, - &source.resolve(&last_synset_id)?)?; let target_sense = target_sense - .ok_or(format!("Source sense {} with target sense", sense.as_str()))? - .resolve(&last_sense_id, wn, - &target.resolve(&last_synset_id)?)?; + .ok_or(format!("Source sense {} with target sense", sense.as_str()))?; change_manager::insert_sense_relation(wn, sense.clone(), @@ -113,27 +125,43 @@ pub fn apply_automaton(actions : Vec, wn : &mut Lexicon, }, None => { change_manager::insert_rel(wn, - &source.resolve(&last_synset_id)?, + &source, &SynsetRelType::from(&relation) .ok_or(format!("Bad relation {}", relation))?, - &target.resolve(&last_synset_id)?, changes); + &target, changes); } } }, - Action::DeleteRelation { source, source_sense, target, target_sense } => { + Action::DeleteRelation { source, source_sense, target, target_sense, source_lemma, target_lemma } => { + let source = source.resolve(&last_synset_id)?; + let source_sense = if let Some(source_sense) = source_sense { + Some(source_sense.resolve(&last_sense_id, wn, &source)?) + } else if let Some(lemma) = source_lemma.as_ref() { + Some(wn.get_sense_id2(&lemma, &source).ok_or(format!("No sense with lemma {} in {}", lemma, source.as_str()))?.clone()) + } else { + None + }; + let target = target.resolve(&last_synset_id)?; + let target_sense = if let Some(target_sense) = target_sense { + Some(target_sense.resolve(&last_sense_id, wn, &target)?) + } else if let Some(lemma) = target_lemma.as_ref() { + Some(wn.get_sense_id2(&lemma, &target).ok_or(format!("No sense with lemma {} in {}", lemma, target.as_str()))?.clone()) + } else { + None + }; + match source_sense { Some(source_sense) => { - let source_sense = source_sense.resolve(&last_sense_id, wn, - &source.resolve(&last_synset_id)?)?; - + let target_sense = target_sense + .ok_or(format!("Source sense {} with target sense", source_sense.as_str()))?; change_manager::delete_sense_rel(wn, &source_sense, - &target_sense.ok_or(format!("Source sense {} with target sense", source_sense.as_str()))?.resolve(&last_sense_id, wn, &target.resolve(&last_synset_id)?)?, changes); + &target_sense, changes); }, None => { change_manager::delete_rel(wn, - &source.resolve(&last_synset_id)?, - &target.resolve(&last_synset_id)?, changes); + &source, + &target, changes); } } }, @@ -169,7 +197,28 @@ pub fn apply_automaton(actions : Vec, wn : &mut Lexicon, }, Action::FixTransitivity => { change_manager::fix_indirect_relations(wn, changes); - } + }, + Action::ChangeILI { synset, ili } => { + let synset = synset.resolve(&last_synset_id)?; + wn.synset_by_id_mut(&synset) + .ok_or(format!("Synset {} not found", synset.as_str()))? + .ili = Some(ILIID::new(&ili)); + }, + Action::ChangeWikidata { synset, wikidata } => { + let synset = synset.resolve(&last_synset_id)?; + wn.synset_by_id_mut(&synset) + .ok_or(format!("Synset {} not found", synset.as_str()))? + .wikidata = Some(wikidata); + }, + Action::ChangeSource { synset, source } => { + let synset = synset.resolve(&last_synset_id)?; + wn.synset_by_id_mut(&synset) + .ok_or(format!("Synset {} not found", synset.as_str()))? + .source = Some(source); + }, + Action::ChangeMembers { synset, members } => { + change_manager::change_members(wn, &synset.resolve(&last_synset_id)?, members, changes); + }, } } Ok(()) @@ -307,6 +356,11 @@ pub enum Action { lemma : String, target_synset : SynsetRef }, + #[serde(rename = "change_members")] + ChangeMembers { + synset : SynsetRef, + members : Vec + }, #[serde(rename = "add_synset")] AddSynset { definition : String, @@ -328,6 +382,21 @@ pub enum Action { synset : SynsetRef, definition : String }, + #[serde(rename = "change_ili")] + ChangeILI { + synset : SynsetRef, + ili : String + }, + #[serde(rename = "change_wikidata")] + ChangeWikidata { + synset : SynsetRef, + wikidata : String + }, + #[serde(rename = "change_source")] + ChangeSource { + synset : SynsetRef, + source : String + }, #[serde(rename = "add_example")] AddExample { synset : SynsetRef, @@ -351,7 +420,13 @@ pub enum Action { target : SynsetRef, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - target_sense : Option + target_sense : Option, + #[serde(default)] + #[serde(skip_serializing_if = "Option::is_none")] + source_lemma : Option, + #[serde(default)] + #[serde(skip_serializing_if = "Option::is_none")] + target_lemma : Option }, #[serde(rename = "delete_relation")] DeleteRelation { @@ -362,7 +437,13 @@ pub enum Action { target : SynsetRef, #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] - target_sense : Option + target_sense : Option, + #[serde(default)] + #[serde(skip_serializing_if = "Option::is_none")] + source_lemma : Option, + #[serde(default)] + #[serde(skip_serializing_if = "Option::is_none")] + target_lemma : Option }, #[serde(rename = "reverse_relation")] ReverseRelation { @@ -433,13 +514,17 @@ mod tests { source_sense: None, relation: "hypernym".to_string(), target: SynsetRef::id("00001741-n"), - target_sense: None + target_sense: None, + source_lemma: None, + target_lemma: None }, Action::DeleteRelation { source: SynsetRef::id("00001740-n"), source_sense: Some(SenseRef::id("example%1:09:00::")), target: SynsetRef::id("00001741-n"), - target_sense: Some(SenseRef::id("target%1:10:00::'")) + target_sense: Some(SenseRef::id("target%1:10:00::'")), + source_lemma: None, + target_lemma: None }, Action::ReverseRelation { source: SynsetRef::id("00001740-n"), @@ -470,7 +555,9 @@ mod tests { source_sense: None, relation: "hypernym".to_string(), target: SynsetRef::id("00001741-n"), - target_sense: None + target_sense: None, + source_lemma: None, + target_lemma: None }]; let mut lexicon = Lexicon::new(); lexicon.add_lexfile("noun.animal"); @@ -511,7 +598,9 @@ mod tests { target: SynsetRef::Id(ssid2), relation: "antonym".to_string(), source_sense: Some(SenseRef::lemma("bar")), - target_sense: Some(SenseRef::lemma("baz")) + target_sense: Some(SenseRef::lemma("baz")), + source_lemma: None, + target_lemma: None }]; apply_automaton(actions, &mut lexicon, &mut ChangeList::new()).unwrap(); } diff --git a/src/change_manager.rs b/src/change_manager.rs index 2969ff6..65cdc76 100644 --- a/src/change_manager.rs +++ b/src/change_manager.rs @@ -169,6 +169,38 @@ pub fn delete_entry(wn : &mut Lexicon, synset_id : &SynsetId, lemma : &str, } +/// Change the order of members in a synset +pub fn change_members(wn : &mut Lexicon, synset_id : &SynsetId, members : Vec, + change_list : &mut ChangeList) { + let mut to_add = Vec::new(); + let mut to_delete = Vec::new(); + match wn.synset_by_id_mut(synset_id) { + Some(ref mut synset) => { + for member in synset.members.iter() { + if !members.contains(member) { + to_delete.push(member.clone()); + } + } + for member in members.iter() { + if !synset.members.contains(member) { + to_add.push(member.clone()); + } + } + synset.members = members; + change_list.mark(); + }, + None => { + eprintln!("Changing members of non-existant synset"); + } + } + for member in to_delete { + delete_entry(wn, synset_id, &member, &wn.pos_for_entry_synset(&member, synset_id).unwrap(), false, change_list); + } + for member in to_add { + add_entry(wn, synset_id.clone(), member.clone(), wn.pos_for_entry_synset(&member, synset_id).unwrap(), Vec::new(), None, change_list); + } +} + /// Move an entry to another synset pub fn move_entry(wn : &mut Lexicon, synset_id : SynsetId, target_synset_id : SynsetId, diff --git a/src/wordnet.rs b/src/wordnet.rs index 8e969b1..db5ff5b 100644 --- a/src/wordnet.rs +++ b/src/wordnet.rs @@ -415,6 +415,15 @@ impl Lexicon { } } + // Get a sense ID for a lemma and synset + pub fn get_sense_id2<'a>(&'a self, lemma : &str, synset_id : &SynsetId) -> + Option<&'a SenseId> { + match self.entries.get(&entry_key(lemma)) { + Some(e) => e.get_sense_id2(lemma, synset_id), + None => None + } + } + /// Add a relation between two senses pub fn add_sense_rel(&mut self, source : &SenseId, rel : SenseRelType, target : &SenseId) { @@ -927,6 +936,23 @@ impl Entries { } } + fn get_sense_id2<'a>(&'a self, lemma : &str, synset_id : &SynsetId) -> + Option<&'a SenseId> { + match self.0.get(lemma) { + Some(m) => { + for (_, e) in m.iter() { + for sense in e.sense.iter() { + if sense.synset == *synset_id { + return Some(&sense.id); + } + } + } + None + }, + None => None + } + } + fn add_rel(&mut self, lemma : &str, pos : &PosKey, source : &SenseId, rel : SenseRelType, target : &SenseId) { @@ -1454,7 +1480,7 @@ pub struct Synset { #[serde(default)] pub example : Vec, pub ili : Option, - wikidata : Option, + pub wikidata : Option, pub source : Option, pub members : Vec, #[serde(rename="partOfSpeech")]