Пример #1
0
    def values(self, p_map, v_note):
        if v_note != self.actor_note:
            raise Exception('v_note {0} not in ScalarConstraint actors.'.format(v_note.note))

        policy_context = p_map[self.actor_note].policy_context
        tones = list(policy_context.harmonic_context.tonality.annotation)
        tones = tones[:-1]   # remove final note (same as first)
        if len(self.scalar_roles) != 0:
            tones = [tones[i] for i in self.scalar_roles]
        if p_map[v_note].note is not None:
            tone = p_map[v_note].note.diatonic_pitch.diatonic_tone
            return OrderedSet([self.actor_note]) if tone in tones else None

        pitch_range = policy_context.pitch_range
        start_partition = max(ChromaticScale.index_to_location(pitch_range.start_index)[0] - 1, 0)
        end_partition = min(ChromaticScale.index_to_location(pitch_range.end_index)[0] + 1,
                            ChromaticScale.CHROMATIC_END[0])

        valid_set = OrderedSet()

        for tone in tones:
            for j in range(start_partition, end_partition + 1):
                pitch = DiatonicPitch(j, tone)
                if pitch_range.is_pitch_inbounds(pitch):
                    note = Note(pitch, self.actor_note.base_duration, self.actor_note.num_dots)
                    valid_set.add(note)

        return valid_set
Пример #2
0
    def values(self, p_map, v_target_note):
        if v_target_note == self.note_two:
            up_down = self.up_down
            v_source_note = self.note_one
        elif v_target_note == self.note_one:
            up_down = not self.up_down
            v_source_note = self.note_two
        else:
            raise Exception(
                'v_note specification does not match any v_note in constraints.'
            )

        if p_map[v_target_note].note is not None:
            return OrderedSet([p_map[v_target_note].note])

        arg_contextual_note = p_map[v_source_note]
        target_contextual_note = p_map[v_target_note]

        if arg_contextual_note.note is None:
            pitches = p_map.all_tonal_pitches(v_target_note)
            result = OrderedSet()
            for p in pitches:
                result.add(
                    Note(p, v_target_note.base_duration,
                         v_target_note.num_dots))
            return result

        return self.compute_result(arg_contextual_note, target_contextual_note,
                                   up_down)
Пример #3
0
    def values(self, p_map, v_note):
        if v_note != self.actor_note:
            raise Exception("Illegal v_note {0} for constraints".format(v_note))
        if p_map[v_note].note is not None:
            if p_map[v_note].note.diatonic_pitch.diatonic_tone == self.tone:
                return {p_map[v_note].note}
            raise Exception('Fixed Tone Policy Violated has {0} should be {1}'.format(
                p_map[v_note].note.diatonic_pitch.diatonic_tone, self.tone))

        contextual_note = p_map[self.actor_note]
        policy_context = contextual_note.policy_context
        pitch_range = contextual_note.policy_context.pitch_range
        start_partition = max(ChromaticScale.index_to_location(pitch_range.start_index)[0] - 1, 0)
        end_partition = min(ChromaticScale.index_to_location(pitch_range.end_index)[0] + 1,
                            ChromaticScale.CHROMATIC_END[0])

        # Try to find that tone in target's tonality/scale.
        tone = self.tone
        for t_str in self.tone.enharmonics():
            t = DiatonicToneCache.get_tone(t_str)
            for scale_tone in PitchScale(policy_context.harmonic_context.tonality,
                                         policy_context.pitch_range).tone_scale:
                if scale_tone == t:
                    tone = t
                    break

        valid_set = OrderedSet()
        for i in range(start_partition, end_partition + 1):
            pitch = DiatonicPitch(i, tone)
            if pitch_range.is_pitch_inbounds(pitch):
                note = Note(pitch, self.actor_note.base_duration, self.actor_note.num_dots)
                valid_set.add(note)

        return valid_set
Пример #4
0
    def values(self, p_map, v_note):
        if v_note != self.actor_note:
            raise Exception("Illegal v_note {0} for constraint".format(v_note))
        if p_map[v_note].note is not None:
            if p_map[v_note].note.diatonic_pitch.chromatic_distance in (p.chromatic_distance for p in self.pitches):
                return OrderedSet[p_map[v_note].note]
            raise Exception('Fixed Pitch Select Set Constraint Violated has {0} not in pitch set'.format(
                p_map[v_note].note.diatonic_pitch))

        # Return all pitches (self.pitches) except though, for each
        # select a representation closest to the target tonality, if it exists.
        tonality = p_map[self.actor_note].policy_context.harmonic_context.tonality
        result_pitches = []
        for pitch in self.pitches:
            found_pitch = pitch
            for p in pitch.enharmonics():
                if p.diatonic_tone in tonality.annotation:
                    found_pitch = p
                    break
            result_pitches.append(found_pitch)

        result = OrderedSet()
        for p in result_pitches:
            result.add(Note(p, self.actor_note.base_duration, self.actor_note.num_dots))
        return result
Пример #5
0
    def test_copy(self):
        s = OrderedSet()
        for i in range(1, 10):
            to = TestObject(i)
            s.add(to)

        s1 = s.copy()
        assert id(s1) != id(s)

        objects = [t.ord_value() for t in s1]
        assert objects == [1, 2, 3, 4, 5, 6, 7, 8, 9]
Пример #6
0
    def compute_full_result(p_map, v_note, e_set):
        pitches = p_map.all_tonal_pitches(v_note)
        e_chrm_list = [n.diatonic_pitch.chromatic_distance for n in e_set]
        del_set = OrderedSet()
        for p in pitches:
            if p.chromatic_distance in e_chrm_list:
                del_set.add(p)

        pitches = [p for p in pitches if p not in del_set]

        return OrderedSet([Note(p, v_note.base_duration, v_note.num_dots) for p in pitches])
    def compute_result(self, arg_contextual_note, target_contextual_note,
                       down_steps, up_steps):
        arg_pitch = arg_contextual_note.note.diatonic_pitch

        pitches = PitchScale.compute_tonal_pitch_range(
            target_contextual_note.policy_context.harmonic_context.tonality,
            arg_pitch, down_steps, up_steps)

        result = OrderedSet()
        for pitch in pitches:
            result.add(
                Note(pitch, self.note_two.base_duration,
                     self.note_two.num_dots))

        return result
Пример #8
0
    def test_union(self):
        s1 = OrderedSet()
        for i in range(1, 10):
            s1.add(TestObject(i))

        s2 = OrderedSet()
        for i in range(100, 110):
            to = TestObject(i)
            s2.add(to)

        s = s1.union(s2)
        objects = [t.ord_value() for t in s]
        assert objects == [
            1, 2, 3, 4, 5, 6, 7, 8, 9, 100, 101, 102, 103, 104, 105, 106, 107,
            108, 109
        ]
Пример #9
0
    def values(self, p_map, v_note):
        """
        Compute possible values for v_note's target.
        :param p_map: 
        :param v_note: 
        :return: 
        
        Note: Here is why the intervals are reversed for solving for note_one:
              Suppose x --> [x-a, x + b].  Then for some value y, 
              for t with y-b<=t<=y+a, we have t -->[t-a, t+b], but
              from the inequalities, t-a<=y<t+b - so the reverse map is
              [y-b, y+a] <-- y, which is exactly what happens below.
        """
        if v_note == self.note_two:
            source = self.note_one
            target = self.note_two
            up_intvl = self.up_interval
            down_intvl = self.down_interval
        elif v_note == self.note_one:
            source = self.note_two
            target = self.note_one
            up_intvl = self.down_interval
            down_intvl = self.up_interval
        else:
            raise Exception(
                'v_note specification does not match any v_note in constraints.'
            )

        if p_map[target].note is not None:
            return OrderedSet([p_map[target].note])

        arg_contextual_note = p_map[source]
        target_contextual_note = p_map[target]

        if arg_contextual_note.note is None:
            pitches = p_map.all_tonal_pitches(v_note)
            result = OrderedSet()
            for p in pitches:
                result.add(Note(p, v_note.base_duration, v_note.num_dots))
            return result
            # return {Note(p, v_note.base_duration, v_note.num_dots) for p in pitches}

        return self.compute_result(arg_contextual_note, target_contextual_note,
                                   up_intvl, down_intvl)
Пример #10
0
    def values(self, p_map, v_note):
        assigned = p_map.assigned_actors(self)
        unassigned = p_map.unassigned_actors(self)
        if v_note in unassigned:
            tonality = p_map[v_note].policy_context.harmonic_context.tonality
            pitches = PitchScale.compute_tonal_pitches(tonality,
                                                       self.pitch_range)
            answer = OrderedSet()
            for p in pitches:
                answer.add(Note(p, v_note.base_duration, v_note.num_dots))
            return answer
            # return {Note(p, v_note.base_duration, v_note.num_dots) for p in pitches}

        if v_note in assigned:
            return OrderedSet([p_map[v_note].note])

        raise Exception(
            '{0} is not in actor list for pitch range constraints.'.format(
                v_note.note))
Пример #11
0
    def test_remove(self):
        s = OrderedSet()
        fone = None
        fmid = None
        flast = None
        for i in range(1, 10):
            item = TestObject(i)
            if i == 1:
                fone = item
            elif i == 6:
                fmid = item
            elif i == 9:
                flast = item
            s.add(item)

        s.remove(fmid)
        s.remove(flast)
        s.remove(fone)
        objects = [t.ord_value() for t in s]
        assert objects == [2, 3, 4, 5, 7, 8]
Пример #12
0
    def values(self, pdi, note):
        position = pdi.correct_position(
            note.get_absolute_position())  # position should be adjusted
        ts = pdi.ts_event_sequence.floor_event(position).object
        beat_position = TimeConversion(pdi.tempo_event_sequence, pdi.ts_event_sequence, Position(pdi.line_duration())).\
            position_to_bp(position)
        num_beats = ts.beats_per_measure if beat_position.beat_fraction > 0 else ts.beats_per_measure - 1
        beat_index = (beat_position.beat + 1) % ts.beats_per_measure
        delta_t = ts.beat_duration if beat_position.beat_fraction == 0 else \
            ts.beat_duration * (1 - beat_position.beat_fraction)

        deltas = OrderedSet()
        for i in range(0, num_beats):
            if (self.beat_ids is not None and beat_index in self.beat_ids) or \
               (self.beat_type is not None and self.beat_type == ts.beat_type(beat_index)):
                deltas.add(delta_t)
            delta_t += ts.beat_duration
            beat_index = (beat_index + 1) % ts.beats_per_measure

        return deltas
Пример #13
0
    def values(self, p_map, v_note):
        """
        Return a set of possible pitches that v_note can take that must be in p_map target's chord.
        :param p_map: 
        :param v_note: 
        :return: 
        """
        if v_note != self.actor_note:
            raise Exception(
                'v_note {0} not in ChordalToneConstraint actors.'.format(
                    v_note.note))

        policy_context = p_map[self.actor_note].policy_context
        tones = policy_context.harmonic_context.chord.tones
        if p_map[v_note].note is not None:
            note = p_map[v_note].note
            if note.diatonic_pitch.diatonic_tone in tones:
                return {note}
            raise Exception(
                'Chordal Pitch Policy Violated has {0} should be member of chord {1}'
                .format(p_map[v_note].note.diatonic_pitch,
                        policy_context.harmonic_context.chord))

        pitch_range = policy_context.pitch_range
        start_partition = max(
            ChromaticScale.index_to_location(pitch_range.start_index)[0] - 1,
            0)
        end_partition = min(
            ChromaticScale.index_to_location(pitch_range.end_index)[0] + 1,
            ChromaticScale.CHROMATIC_END[0])

        valid_set = OrderedSet()
        for tone in tones:
            for i in range(start_partition, end_partition + 1):
                pitch = DiatonicPitch(i, tone[0])
                if pitch_range.is_pitch_inbounds(str(pitch)):
                    note = Note(pitch, self.actor_note.base_duration,
                                self.actor_note.num_dots)
                    valid_set.add(note)

        return valid_set
Пример #14
0
    def compute_result(self, arg_contextual_note, target_contextual_note,
                       up_intvl, down_intvl):
        """
        
        :param arg_contextual_note: 
        :param target_contextual_note: 
        :param up_intvl: 
        :param down_intvl: 
        :return: 
        """

        starting_pitch = arg_contextual_note.note.diatonic_pitch
        chromatic_distance_start = starting_pitch.chromatic_distance - down_intvl.chromatic_distance
        chromatic_distance_end = starting_pitch.chromatic_distance + up_intvl.chromatic_distance

        r_start = max(
            chromatic_distance_start,
            target_contextual_note.policy_context.pitch_range.start_index)
        r_end = min(
            chromatic_distance_end,
            target_contextual_note.policy_context.pitch_range.end_index)

        if r_start > r_end:
            return OrderedSet()

        pitch_range = PitchRange(r_start, r_end)
        pitch_scale = PitchScale(
            target_contextual_note.policy_context.harmonic_context.tonality,
            pitch_range)

        result = OrderedSet()
        for pitch in pitch_scale.pitch_scale:
            result.add(
                Note(pitch, self.note_two.base_duration,
                     self.note_two.num_dots))
        # v_result = {Note(pitch, self.note_two.base_duration, self.note_two.num_dots)
        #             for pitch in pitch_scale.pitch_scale}

        return result
Пример #15
0
    def _policy_values(self, p_map, v_note):
        """
        For v_note, find all note values for its target that satisfy all policies in which v_note is involved.
        :param p_map: PMap
        :param v_note: ContextualNote
        :return: A set of notes with same duration as v_note, varying in pitch.
        """
        pitches = None
        for p in self.v_policy_map[v_note]:
            p_values = p.values(p_map, v_note)
            if p_values is None:
                returned_pitches = OrderedSet()  # None means p cannot be satisfied!
            else:
                returned_pitches = OrderedSet()
                for n in p_values:
                    returned_pitches.add(n.diatonic_pitch)
            pitches = returned_pitches if pitches is None else pitches.intersection(returned_pitches)

        retset = OrderedSet()
        for p in pitches:
            retset.add(Note(p, v_note.base_duration, v_note.num_dots))
        return retset
Пример #16
0
    def values(self, p_map, v_note):
        """
        Find value candidates for v_note target, given p_map.
        In this constraints, we are more interested in the set of values that v_note target cannot take.
        
        :param p_map: 
        :param v_note: 
        :return: 
        """
        assigned = p_map.assigned_actors(self)
        unassigned = p_map.unassigned_actors(self)
        if len(assigned) == 0:
            pitches = p_map.all_tonal_pitches(v_note)
            return {Note(p, v_note.note.base_duration, v_note.note.num_dots) for p in pitches}
        if v_note in assigned:
            return {p_map[v_note].note}
        if v_note not in unassigned:
            raise Exception('{0} is not in actor list of not equal pitch constraints.'.format(v_note.note))

        e_set = OrderedSet()
        for v in assigned:
            e_set.add(p_map[v].note)

        return NotEqualPitchConstraint.compute_full_result(p_map, v_note, e_set)
Пример #17
0
    def test_for_book_example_2(self):
        print('----- test for book example 2 -----')

        source_instance_expression = '{<A-Major:i> [sA:4 A A A] qA:4 [iA:4 A] <:iv> qA:4 [sA:4 A A A] qA:4}'
        target_instance_expression = '{<G-Major:i> wA:4 <:iv> wA:4}'
        lge = LineGrammarExecutor()

        source_instance_line, source_instance_hct = lge.parse(
            source_instance_expression)

        actors = source_instance_line.get_all_notes()
        for a in actors:
            print("{0}".format(a))

        target_instance_line, target_instance_hct = lge.parse(
            target_instance_expression)
        target_hcs = target_instance_hct.hc_list()
        for hc in target_hcs:
            print("{0}".format(hc))

        pitch_range = PitchRange(
            DiatonicPitch.parse('C:4').chromatic_distance,
            DiatonicPitch.parse('C:6').chromatic_distance)

        p_map = PMap.create(source_instance_expression, pitch_range,
                            [('G-Major:I', Duration(3, 4)),
                             ('G-Major:IV', Duration(3, 4))])

        actors = p_map.actors

        policies = OrderedSet()
        policies.add(
            StepSequenceConstraint(
                [actors[0], actors[1], actors[2], actors[3]], [1, 1, 1]))
        policies.add(ChordalPitchConstraint(actors[0]))
        policies.add(ChordalPitchConstraint(actors[4]))
        policies.add(ChordalPitchConstraint(actors[8]))
        policies.add(
            StepSequenceConstraint(
                [actors[8], actors[9], actors[10], actors[11]], [1, -1, -1]))
        policies.add(EqualPitchConstraint([actors[0], actors[12]]))
        policies.add(EqualPitchConstraint([actors[4], actors[7]]))
        policies.add(
            RelativeDiatonicConstraint(actors[4], actors[5],
                                       Interval(3, IntervalType.Major),
                                       Interval(1, IntervalType.Perfect)))
        policies.add(StepSequenceConstraint([actors[5], actors[6]], [-1]))

        # policies.add(ChordalPitchConstraint(actors[7]))

        solver = PitchConstraintSolver(policies)

        full_results, partial_results = solver.solve(p_map)
        print('Results has {0} results.'.format(len(full_results)))

        for pm in full_results:
            if str(pm[actors[7]].note.diatonic_pitch) == 'D:4' and str(
                    pm[actors[0]].note.diatonic_pitch) == 'G:4':
                print("{0}".format(pm))
Пример #18
0
    def _visit(self, p_map, v_note):
        """
        Recursive method used to derive sets of solution to the constraints constraint problem.

        :param p_map: PMap
        :param v_note: ContextualNote, source key of PMap
        :return: A set of pmaps
        """

        if p_map[v_note].note is not None:  # setting means visited
            return {}

        results = OrderedSet()

        # list of tuples (v_note, {solution to v_note's policies})
        result_values = self._build_potential_values(p_map, {v_note})
        if len(result_values) == 0:
            return results

        for value in result_values[0][1]:  # [0] is for v_note; [1] is the set of values.
            p_map[v_note].note = value
            value_results = OrderedSet()  # results for this value for v_note + solutions for ALL peers to v_note

            # Advantage in the following, setting above partially solves each policy v_note is involved in.
            # For this 'value' for v_note, dive depth first through all v_note peers (all policies v_note is in)
            #    which collectively we call a branch.
            # peer_candidates are all unassigned actors in v_note's policies.
            peer_candidates = self._candidate_closure(p_map, v_note)
            if len(peer_candidates) == 0:

                # We reached the end of a branch, save the result.
                if self._full_check_and_validate(p_map):
                    if self.instance_limit != -1 and self.__num_instances >= self.instance_limit:
                        return results
                    self.full_results.append(p_map.replicate())
                    self.__num_instances = self.__num_instances + 1
                else:
                    value_results.add(p_map.replicate())  # We only need a shallow copy

            else:
                for c_note in peer_candidates:
                    if self.instance_limit != -1 and self.__num_instances >= self.instance_limit:
                        results = results.union(value_results)
                        return results

                    if len(value_results) == 0:  # first time through this loop per value, visit with p_map!
                        value_results = self._visit(p_map, c_note)
                        if len(value_results) == 0:  # Indicates failure to assign c_note, move to next value.
                            break  # If one peer fails, they all will, for this 'value'!
                    else:
                        value_results_copy = value_results.copy()
                        # for peer c_note, if all r below fails (len(cand_results) == 0) should we also move on to
                        # next value? Add 'found' flag, set after union, after loop, check if False, to break
                        found = False
                        for r in value_results_copy:
                            if r[c_note].note is None:
                                cand_results = self._visit(r, c_note)
                                if len(cand_results) != 0:
                                    value_results = value_results.union(cand_results)
                                    found = True
                                value_results.remove(r)  # r has no c_note assigned, what was returned did!
                                # If not, r's peers cannot be assigned!
                        if found is False:  # Same as if part, if c_note produces no results, it cannot be assigned.
                            break  # If one peer fails, they all will!
            results = results.union(value_results)

        p_map[v_note].note = None
        return results
Пример #19
0
 def test_ordering(self):
     s1 = OrderedSet()
     for i in range(1, 10):
         s1.add(TestObject(i))
     objects = [t.ord_value() for t in s1]
     assert objects == [1, 2, 3, 4, 5, 6, 7, 8, 9]
    def values(self, p_map, v_note):
        """
        Compute possible values for v_note's target.
        :param p_map: note-->contextual_note
        :param v_note: Note
        :return: Candidate Notes.

        Note: Here is why the intervals are reversed for solving for note_one:
              Suppose x --> [x-a, x + b].  Then for some value y, 
              for t with y-b<=t<=y+a, we have t -->[t-a, t+b], but
              from the inequalities, t-a<=y<t+b - so the reverse map is
              [y-b, y+a] <-- y, which is exactly what happens below.
        """
        if v_note == self.note_two:
            source = self.note_one
            target = self.note_two
            comparative = self.comparative
        elif v_note == self.note_one:
            source = self.note_two
            target = self.note_one
            comparative = 4 - self.comparative
        else:
            raise Exception(
                'v_note specification does not match any v_note in constraints.'
            )

        if p_map[target].note is not None:
            return {p_map[target].note}

        if p_map[source].note is None:
            answer_range = p_map[target].policy_context.pitch_range
            source_pitch = None
        else:
            # Establish a pitch range commensurate with comparative.
            qrange = p_map[target].policy_context.pitch_range
            source_pitch = p_map[source].note.diatonic_pitch

            if comparative > 2:
                answer_range = PitchRange(qrange.start_index,
                                          source_pitch.chromatic_distance)
            elif comparative < 2:
                answer_range = PitchRange(source_pitch.chromatic_distance,
                                          qrange.end_index)
            else:
                answer_range = PitchRange(source_pitch.chromatic_distance,
                                          source_pitch.chromatic_distance)

        pitches = PitchScale.compute_tonal_pitches(
            p_map[target].policy_context.harmonic_context.tonality,
            answer_range)
        if comparative == 4 and len(pitches) > 0 and source_pitch is not None and \
                source_pitch.chromatic_distance == pitches[-1].chromatic_distance:
            pitches.pop(-1)
        if comparative == 0 and len(pitches) > 0 and source_pitch is not None and \
                source_pitch.chromatic_distance == pitches[0].chromatic_distance:
            del pitches[0]

        answer = OrderedSet()
        for pitch in pitches:
            answer.add(Note(pitch, target.base_duration, target.num_dots))
        return answer