public void Process(VarietyPair data) { IWordAligner aligner = _project.WordAligners[_alignerId]; var correspondenceColls = new Dictionary <FeatureSymbol, SoundCorrespondenceCollection> { { CogFeatureSystem.Onset, new SoundCorrespondenceCollection() }, { CogFeatureSystem.Nucleus, new SoundCorrespondenceCollection() }, { CogFeatureSystem.Coda, new SoundCorrespondenceCollection() } }; foreach (WordPair wordPair in data.WordPairs.Where(wp => wp.Cognacy)) { Alignment <Word, ShapeNode> alignment = aligner.Compute(wordPair).GetAlignments().First(); for (int i = 0; i < alignment.ColumnCount; i++) { AlignmentCell <ShapeNode> cell1 = alignment[0, i]; AlignmentCell <ShapeNode> cell2 = alignment[1, i]; if (!cell1.IsNull && !cell2.IsNull && cell1.Count == 1 && cell2.Count == 1) { SymbolicFeatureValue pos1, pos2; if (cell1.First.Annotation.FeatureStruct.TryGetValue(CogFeatureSystem.SyllablePosition, out pos1) && cell2.First.Annotation.FeatureStruct.TryGetValue(CogFeatureSystem.SyllablePosition, out pos2) && (FeatureSymbol)pos1 == (FeatureSymbol)pos2) { Ngram <Segment> ngram1 = cell1.ToNgram(_segmentPool); Ngram <Segment> ngram2 = cell2.ToNgram(_segmentPool); Segment seg1 = ngram1.First; Segment seg2 = ngram2.First; if (!seg1.Equals(seg2)) { SoundCorrespondenceCollection correspondences = correspondenceColls[(FeatureSymbol)pos1]; SoundCorrespondence corr; if (!correspondences.TryGet(seg1, seg2, out corr)) { corr = new SoundCorrespondence(seg1, seg2); correspondences.Add(corr); } corr.Frequency++; corr.WordPairs.Add(wordPair); } } } } } foreach (KeyValuePair <FeatureSymbol, SoundCorrespondenceCollection> kvp in correspondenceColls) { data.CognateSoundCorrespondencesByPosition[kvp.Key].ReplaceAll(kvp.Value); } }
public IBidirectionalGraph <GlobalCorrespondencesGraphVertex, GlobalCorrespondencesGraphEdge> GenerateGlobalCorrespondencesGraph(SyllablePosition syllablePosition, IEnumerable <Variety> varieties) { var varietiesSet = new HashSet <Variety>(varieties); CogProject project = _projectService.Project; var graph = new BidirectionalGraph <GlobalCorrespondencesGraphVertex, GlobalCorrespondencesGraphEdge>(); var vertices = new Dictionary <object, GlobalSegmentVertex>(); var edges = new Dictionary <UnorderedTuple <object, object>, GlobalCorrespondencesGraphEdge>(); int maxFreq = 0; if (syllablePosition == SyllablePosition.Nucleus) { graph.AddVertexRange(new GlobalCorrespondencesGraphVertex[] { new VowelBacknessVertex(VowelBackness.Front), new VowelBacknessVertex(VowelBackness.Central), new VowelBacknessVertex(VowelBackness.Back), new VowelHeightVertex(VowelHeight.Close), new VowelHeightVertex(VowelHeight.CloseMid), new VowelHeightVertex(VowelHeight.OpenMid), new VowelHeightVertex(VowelHeight.Open) }); foreach (VarietyPair vp in project.VarietyPairs.Where(vp => varietiesSet.Contains(vp.Variety1) && varietiesSet.Contains(vp.Variety2))) { foreach (SoundCorrespondence corr in vp.CognateSoundCorrespondencesByPosition[CogFeatureSystem.Nucleus]) { VowelHeight height1, height2; VowelBackness backness1, backness2; bool round1, round2; if (GetVowelInfo(corr.Segment1, out height1, out backness1, out round1) && GetVowelInfo(corr.Segment2, out height2, out backness2, out round2) && (height1 != height2 || backness1 != backness2 || round1 != round2)) { Tuple <VowelHeight, VowelBackness, bool> key1 = Tuple.Create(height1, backness1, round1); GlobalSegmentVertex vertex1 = vertices.GetValue(key1, () => new GlobalVowelVertex(height1, backness1, round1)); vertex1.StrReps.Add(corr.Segment1.StrRep); Tuple <VowelHeight, VowelBackness, bool> key2 = Tuple.Create(height2, backness2, round2); GlobalSegmentVertex vertex2 = vertices.GetValue(key2, () => new GlobalVowelVertex(height2, backness2, round2)); vertex2.StrReps.Add(corr.Segment2.StrRep); int freq = AddEdge(edges, corr, key1, vertex1, key2, vertex2); maxFreq = Math.Max(freq, maxFreq); } } } } else { graph.AddVertexRange(new GlobalCorrespondencesGraphVertex[] { new ConsonantPlaceVertex(ConsonantPlace.Bilabial), new ConsonantPlaceVertex(ConsonantPlace.Labiodental), new ConsonantPlaceVertex(ConsonantPlace.Dental), new ConsonantPlaceVertex(ConsonantPlace.Alveolar), new ConsonantPlaceVertex(ConsonantPlace.Postalveolar), new ConsonantPlaceVertex(ConsonantPlace.Retroflex), new ConsonantPlaceVertex(ConsonantPlace.Palatal), new ConsonantPlaceVertex(ConsonantPlace.Velar), new ConsonantPlaceVertex(ConsonantPlace.Uvular), new ConsonantPlaceVertex(ConsonantPlace.Pharyngeal), new ConsonantPlaceVertex(ConsonantPlace.Glottal), new ConsonantMannerVertex(ConsonantManner.Nasal), new ConsonantMannerVertex(ConsonantManner.Stop), new ConsonantMannerVertex(ConsonantManner.Affricate), new ConsonantMannerVertex(ConsonantManner.Fricative), new ConsonantMannerVertex(ConsonantManner.Approximant), new ConsonantMannerVertex(ConsonantManner.FlapOrTap), new ConsonantMannerVertex(ConsonantManner.Trill), new ConsonantMannerVertex(ConsonantManner.LateralFricative), new ConsonantMannerVertex(ConsonantManner.LateralApproximant) }); foreach (VarietyPair vp in project.VarietyPairs.Where(vp => varietiesSet.Contains(vp.Variety1) && varietiesSet.Contains(vp.Variety2))) { SoundCorrespondenceCollection corrs = null; switch (syllablePosition) { case SyllablePosition.Onset: corrs = vp.CognateSoundCorrespondencesByPosition[CogFeatureSystem.Onset]; break; case SyllablePosition.Coda: corrs = vp.CognateSoundCorrespondencesByPosition[CogFeatureSystem.Coda]; break; } Debug.Assert(corrs != null); foreach (SoundCorrespondence corr in corrs) { ConsonantPlace place1, place2; ConsonantManner manner1, manner2; bool voiced1, voiced2; if (GetConsonantPosition(corr.Segment1, out place1, out manner1, out voiced1) && GetConsonantPosition(corr.Segment2, out place2, out manner2, out voiced2) && (place1 != place2 || manner1 != manner2 || voiced1 != voiced2)) { Tuple <ConsonantPlace, ConsonantManner, bool> key1 = Tuple.Create(place1, manner1, voiced1); GlobalSegmentVertex vertex1 = vertices.GetValue(key1, () => new GlobalConsonantVertex(place1, manner1, voiced1)); vertex1.StrReps.Add(corr.Segment1.StrRep); Tuple <ConsonantPlace, ConsonantManner, bool> key2 = Tuple.Create(place2, manner2, voiced2); GlobalSegmentVertex vertex2 = vertices.GetValue(key2, () => new GlobalConsonantVertex(place2, manner2, voiced2)); vertex2.StrReps.Add(corr.Segment2.StrRep); int freq = AddEdge(edges, corr, key1, vertex1, key2, vertex2); maxFreq = Math.Max(freq, maxFreq); } } } } graph.AddVertexRange(vertices.Values); foreach (GlobalCorrespondencesGraphEdge edge in edges.Values) { edge.NormalizedFrequency = (double)edge.Frequency / maxFreq; graph.AddEdge(edge); } return(graph); }