/// <summary> /// Compute the similarity between this contour and the given contour. /// </summary> /// <param name="mc2"></param> /// <returns></returns> public float ComputeSimilarity(MelodyContour mc2) { string strC1 = this.ToStringSimple(); string strC2 = mc2.ToStringSimple(); int lenMax = Math.Max(strC1.Length, strC2.Length); if (lenMax == 0) { return(0); } int distNormal = Utilities.EditDistance(strC1, strC2); string strC2Inverted = InvertContourString(strC2); int distInverted = Utilities.EditDistance(strC1, strC2Inverted) + Constants.INVERT_CONTOUR_COST; int dist = Math.Min(distNormal, distInverted); return(100f * (((float)lenMax - dist) / lenMax)); }
public override void Run() { if (ge1 == null) { ge1 = workspace.PickRandomGroupElementByRecencyAndStrength(); } if (ge1 == null) { return; } // Pick 2 more elements to the right if we can. // TODO: be smarter about adjacent picking -- go for same-level/same-size groups? GroupElement ge2 = workspace.PickRandomGroupElementRightOf(ge1); if (ge2 == null) { return; } GroupElement ge3 = workspace.PickRandomGroupElementRightOf(ge2); if (ge3 == null) { return; } if (!workspace.GroupElements.Contains(ge1) || !workspace.GroupElements.Contains(ge2) || !workspace.GroupElements.Contains(ge3)) { return; } //Make sure they are both of same level, or we can't group. // TODO: relax this appropriately for ge3 if (ge1.Level != ge2.Level) { return; } if (Math.Abs(ge2.Level - ge3.Level) > 1) { return; } // Add to attention history. workspace.RecordCodeletAttentionHistory(this, ge1.MinLocation, ge3.MaxLocation); // Check if sequence already exists! foreach (Group g in workspace.groups) { if (g is Sequence) { Sequence s = (Sequence)g; if (s.SequenceElements.Contains(ge1) && s.SequenceElements.Contains(ge2) && s.SequenceElements.Contains(ge3)) { return; // already exists. } } } // Estimate the sequence's score. MelodyContour mc1 = new MelodyContour(ge1); MelodyContour mc2 = new MelodyContour(ge2); MelodyContour mc3 = new MelodyContour(ge3); // Need exact matches for first 2 elements. string contourStart = mc1.ToStringSimple(); if (contourStart != mc2.ToStringSimple()) { return; } // Need initial match for elements 2 and 3 (in case 3 is longer). if (!mc3.ToStringSimple().StartsWith(contourStart)) { return; } // Strength based on # elements. double score = Math.Min(100, contourStart.Length * 30); double r = Utilities.rand.NextDouble() * 100; if (r < score) { Sequence s = new Sequence(workspace, ge1, ge2, ge3, score); workspace.AddSequence(s, score); // TODO: hack: forcing score in.... but should be computed from reasons... } }
public override void Run() { if (ge1 == null) { ge1 = workspace.PickRandomGroupByStrength(); } if (ge1 == null) { return; } if (ge2 == null) { ge2 = workspace.PickRandomGroupByRecencyAndStrength(); } if (ge2 == null || ge2 == ge1) { return; } // Reorder in time if out-of-order. m1 comes first. if (ge1.Location > ge2.Location) { GroupElement tmp = ge1; ge1 = ge2; ge2 = tmp; } // Add to attention history. workspace.RecordCodeletAttentionHistory(this, ge1.MinLocation, ge1.MaxLocation); workspace.RecordCodeletAttentionHistory(this, ge2.MinLocation, ge2.MaxLocation); // Compute and compare melody contours. //TODO! currently we require groups! //if (!(ge1 is Group && ge2 is Group)) // return; // Make sure contours are non-overlapping!!! //Group g1 = (Group)ge1; //Group g2 = (Group)ge2; // if (g1.Overlaps(g2)) // return; if (ge1.Overlaps(ge2)) { return; } //MelodyContour mc1 = new MelodyContour(g1); //MelodyContour mc2 = new MelodyContour(g2); MelodyContour mc1 = new MelodyContour(ge1); MelodyContour mc2 = new MelodyContour(ge2); //////////////// float similarity = mc1.ComputeSimilarity(mc2); // if (similarity < 75) // return; double r = Utilities.rand.NextDouble() * 100; if (r < similarity) { workspace.AddRelationship(new RelationshipMelodyContour(ge1, ge2, similarity)); } }