def test_for_debugging(self): logging.debug('Start test_for_debugging') p_map, policies = TestPitchConstraintSolver.generate_generic_sample( TestPitchConstraintSolver.example_2) solver = PitchConstraintSolver(policies) try: full_results, partial_results = solver.solve(p_map) if full_results is None: print("Full Results is None") else: print("Full Results is not None") if len(full_results) == 0: print("Results is empty") else: print('Results has {0} results.'.format(len(full_results))) # verify for pm in full_results: for p in policies: if not p.verify(pm.p_map): print('Policy failure: {0}'.format( type(p).__name__)) print(pm) continue for pm in full_results: print(pm) except Exception as e: print(e) # print >> sys.stderr, traceback.format_exc() traceback.print_exc() logging.debug('End test_for_debugging')
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))
def solve(self, partial_pitch_results=None, num_solutions=-1): if partial_pitch_results is not None: if not isinstance(partial_pitch_results, dict): raise Exception( 'partial_pitch_results argument must be a dict.') beat_solver = BeatConstraintSolver(self.line, self.tempo_event_sequence, self.ts_event_sequence, self.hct, self.on_beat_constraints) beat_results = beat_solver.solve() # list of PositionDeltaInfo's pitch_solver = PitchConstraintSolver(self.pitch_constraints) p_map_dict = self._build_p_map_dict(partial_pitch_results) full_results, pitch_results = pitch_solver.solve( p_map_dict, num_solutions) return MCSResults(self.line, self.tempo_event_sequence, self.ts_event_sequence, self.hct, beat_results, full_results)
def test_compute_simple_scale_tones(self): logging.debug('Start test_compute_simple_scale_tones') lower_policy_context = TestPMap.policy_creator(ModalityType.Major, DiatonicTone('G'), 'tV', 'C:2', 'C:8') upper_pitch_txts = [ 'C:5', 'D:5', 'E:5', 'G:5', 'B:5', 'C:6', 'B:5', 'G:5', 'E:5', 'D:5', 'C:5', 'C:5' ] actors = list() differentials = [1, 1, 2, 2, 1, -1, -2, -2, -1, -1, 0] p_map = OrderedDict() for pitch_txt in upper_pitch_txts: upper_note = Note(DiatonicPitch.parse(pitch_txt), Duration(1, 8)) lower_note = ContextualNote(lower_policy_context) p_map[upper_note] = lower_note actors.append(upper_note) policy = StepSequenceConstraint(actors, differentials) p_map[actors[2]].note = Note(DiatonicPitch.parse('G:5'), Duration(1, 8)) solver = PitchConstraintSolver([policy]) results = None try: results, _ = solver.solve(p_map) if results is None: print("Results is None") else: print("Results is not None") if len(results) == 0: print("Results is empty") else: print('Results has {0} results.'.format(len(results))) # verify for pm in results: if not policy.verify(pm.p_map): print('Policy failure: {0}'.format( type(policy).__name__)) print(pm) continue for pm in results: print(pm) except Exception as e: print(e) # print >> sys.stderr, traceback.format_exc() traceback.print_exc() assert results is not None assert len(results) == 1 pm = next(iter(results)) answers = [ 'E:5', 'F#:5', 'G:5', 'B:5', 'D:6', 'E:6', 'D:6', 'B:5', 'G:5', 'F#:5', 'E:5', 'E:5' ] for i in range(0, len(actors)): assert str(pm[actors[i]].note.diatonic_pitch) == answers[i] print('-----') # Build a line and test apply on pm line = Line() begin_note = Note(DiatonicPitch.parse('A:2'), Duration(1, 2)) end_note = Note(DiatonicPitch.parse('B:2'), Duration(1, 2)) offset = Offset(0) line.pin(begin_note, offset) offset = offset + begin_note.duration.duration for note in actors: line.pin(note, offset) offset += note.duration.duration line.pin(end_note, offset) new_line = pm.apply(line) assert new_line is not None assert new_line != line all_notes = new_line.get_all_notes() assert len(all_notes) == 2 + len(actors) assert str(all_notes[0].diatonic_pitch) == 'A:2' assert str(all_notes[-1].diatonic_pitch) == 'B:2' for i in range(1, len(all_notes) - 1): assert str(all_notes[i].diatonic_pitch) == answers[i - 1]
def _build_pitch_solutions_old(self, beat_score_results, pitch_constraints): """ Build the final results using the beat results, then the pitch results, then the reshape constraints. :param beat_score_results: Set of (PositionDeltaInfo, LiteScore)'s :param pitch_constraints: Set of Constraints :return: """ final_results = list() pitch_results = list() # Solve the pitch constraints using the beat constraint results. if beat_score_results is not None: for beat_result_pdi, beat_result_score in beat_score_results: revised_constraints = TReshape._regenerate_constraints( pitch_constraints, self.score.line, beat_result_score.line) pitch_solver = PitchConstraintSolver(revised_constraints) p_map_dict = PMap( self._build_p_map_dict(beat_result_pdi.hct, revised_constraints)) pitch_solver_results = pitch_solver.solve(p_map_dict) for pitch_pmap in pitch_solver_results: line = pitch_pmap.apply(beat_result_score.line) pitch_results.append( (pitch_pmap, beat_result_score, LiteScore(line, beat_result_pdi.hct, self.score.instrument, beat_result_pdi.tempo_event_sequence, beat_result_pdi.ts_event_sequence))) else: pitch_solver = PitchConstraintSolver(pitch_constraints) p_map_dict = PMap( self._build_p_map_dict(self.score.hct, pitch_constraints)) pitch_solver_results = pitch_solver.solve(p_map_dict) for pitch_pmap in pitch_solver_results: line = pitch_pmap.apply(self.score.line) pitch_results.append( (pitch_pmap, self.score, LiteScore(line, self.score.hct, self.score.instrument, self.score.tempo_sequence, self.score.time_signature_sequence))) # Solve the reshape constraints using the pitch constraint solutions. for pitch_result_pmap, beat_result_score, pitch_result_score in pitch_results: # Issue 1. we generate constraints for ALL NOTES on pitch_result_score's line, note that this means # we cannot reliably use pitch_result_pmap further on since pitch_result_score is buily with # an apply - meaning the notes are in the pmap's range, not domain. # tersely: pitch_result_pmap: self.score.line --> pitch_result_score.line q = { key: value for key, value in zip(beat_result_score.line.get_all_notes(), pitch_result_score.line.get_all_notes()) } ignore_notes = { q[n] for n in pitch_result_pmap.keys() if pitch_result_pmap[n].note is not None } reshape_constraints = self._generate_reshape_constraints( pitch_result_score.line, pitch_result_score.tempo_sequence, pitch_result_score.time_signature_sequence, ignore_notes) p_map = PMap() for c in reshape_constraints: note = c.actor_note hc = pitch_result_score.hct[ note.get_absolute_position().position] if hc is None: raise Exception( 'Cannot locate harmonic context for note \'{0}\''. format(note)) contextual = ContextualNote( PolicyContext( hc, pitch_result_score.instrument.sounding_pitch_range() if pitch_result_score.instrument is not None else PitchRange.create('A:0', 'C:8'))) # Note: p_map maps from pitch_result_score's line notes to something else (does not matter) p_map[note] = contextual pitch_solver = PitchConstraintSolver(reshape_constraints) reshape_results = pitch_solver.solve(p_map) # reshape_pmap_result maps pitch_result_score's line notes to something else with a pitch designation. # Issue 2): we are getting failures on some notes due to being too close to chord on beat. In these cases, # the solve is not failing, but giving back a partial result. for reshape_pmap_result in reshape_results: master_pmap = PMap() # Not sure pitch_result_pmap maps from beat_score_result.line notes to a note with pitch desig. # reshape_pmap_result pitch_result_score's line notes to something else with a pitch designation. # mm: beat_result_score --> self.score or beat_result_score mm = { key: value for key, value in zip( beat_result_score.line.get_all_notes() if beat_result_score else self.score.line.get_all_notes(), pitch_result_score.line.get_all_notes()) } for note in pitch_result_pmap.keys(): # map notes in pitch_result_score to what beat_score_result would master_pmap[mm[note]] = pitch_result_pmap[note] for note in reshape_pmap_result.keys(): if note not in master_pmap.keys(): master_pmap[note] = reshape_pmap_result[note] line_answer = master_pmap.apply(pitch_result_score.line) final_results.append( LiteScore(line_answer, pitch_result_score.hct, pitch_result_score.instrument, pitch_result_score.tempo_sequence, pitch_result_score.time_signature_sequence)) return final_results
def _build_pitch_solutions(self, beat_score_results, pitch_constraints): """ Build the final results using the beat results, then the pitch results, then the reshape constraints. :param beat_score_results: Set of (PositionDeltaInfo, LiteScore)'s :param pitch_constraints: Set of Constraints :return: """ final_results = list() pitch_results = list() # Solve the pitch constraints using the beat constraint results. if beat_score_results is not None: for beat_result_pdi, beat_result_score in beat_score_results: revised_constraints = TReshape._regenerate_constraints( pitch_constraints, self.score.line, beat_result_score.line) pitch_solver = PitchConstraintSolver(revised_constraints) p_map_dict = PMap( self._build_p_map_dict(beat_result_pdi.hct, revised_constraints)) pitch_solver_results, _ = pitch_solver.solve(p_map_dict) for pitch_pmap in pitch_solver_results: line = pitch_pmap.apply(beat_result_score.line) pitch_results.append( (pitch_pmap, beat_result_score, LiteScore(line, beat_result_pdi.hct, self.score.instrument, beat_result_pdi.tempo_event_sequence, beat_result_pdi.ts_event_sequence))) else: pitch_solver = PitchConstraintSolver(pitch_constraints) p_map_dict = PMap( self._build_p_map_dict(self.score.hct, pitch_constraints)) pitch_solver_results, _ = pitch_solver.solve(p_map_dict) for pitch_pmap in pitch_solver_results: line = pitch_pmap.apply(self.score.line) pitch_results.append( (pitch_pmap, self.score, LiteScore(line, self.score.hct, self.score.instrument, self.score.tempo_sequence, self.score.time_signature_sequence))) # Solve the reshape constraints using the pitch constraint solutions. for pitch_result_pmap, beat_result_score, pitch_result_score in pitch_results: # pitch_result_pmap: self.score.line --> pitch_result_score.line q = { key: value for key, value in zip(beat_result_score.line.get_all_notes(), pitch_result_score.line.get_all_notes()) } # ignore_notes are notes that were satisfied by constraints. ignore_notes = { q[n] for n in pitch_result_pmap.keys() if pitch_result_pmap[n].note is not None } # note_to_pitch_map maps each ignore-note in line to a curve fit pitch. note_to_pitch_map = self._generate_reshape_map( pitch_result_score.line, ignore_notes) # Map pitch result score notes to their resolved pitches master_map = dict() # mm: beat_result_score.line --> pitch_reslt_score.line (self.score or beat_result_score) # For pitch constraint notes, map them to their pitch constraint results. mm = { key: value for key, value in zip( beat_result_score.line.get_all_notes() if beat_result_score else self.score.line.get_all_notes(), pitch_result_score.line.get_all_notes()) } # Put the constraint based notes into master for note in pitch_result_pmap.keys(): # map notes in pitch_result_score to what beat_score_result would if pitch_result_pmap[note].note is None: raise Exception( 'Note {0} not solved for value in constraint.'.format( note)) master_map[ mm[note]] = pitch_result_pmap[note].note.diatonic_pitch # Map reshaped notes in pitch_result_score to their resolved notes into master for note in note_to_pitch_map.keys(): if note not in master_map.keys(): master_map[note] = note_to_pitch_map[note] # Clone pitch_result_score, and build a map from pitch_result_score.line to the clone's notes (mmm) line_answer = pitch_result_score.line.clone() mmm = { key: value for key, value in zip(pitch_result_score.line.get_all_notes(), line_answer.get_all_notes()) } # A shallow form of apply (use mmm and master_map to reset the diatonic pitches on line_answer. for note in master_map.keys(): if master_map[note] is not None: mmm[note].diatonic_pitch = master_map[note] final_results.append( LiteScore(line_answer, pitch_result_score.hct, pitch_result_score.instrument, pitch_result_score.tempo_sequence, pitch_result_score.time_signature_sequence)) return final_results
def test_for_book_example_1(self): print('----- test for book example 1 -----') source_instance_expression = '{<C-Major:IV> [sC:5 B:4 A G] qF:4 [sA:4 B C:5 D] qD:5}' target_instance_expression = '{<G-Major:V> wA:4}' lge = LineGrammarExecutor() 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.create('C:2', 'C:8') p_map = PMap.create(source_instance_expression, pitch_range, [('G-Major:V', 1)]) actors = p_map.actors for a in actors: print("{0}".format(a)) policies = set() policies.add( PitchStepConstraint(actors[0], actors[1], 1, PitchStepConstraint.Down)) policies.add( PitchStepConstraint(actors[1], actors[2], 1, PitchStepConstraint.Down)) policies.add( PitchStepConstraint(actors[2], actors[3], 1, PitchStepConstraint.Down)) policies.add( PitchStepConstraint(actors[5], actors[6], 1, PitchStepConstraint.UP)) policies.add( PitchStepConstraint(actors[6], actors[7], 1, PitchStepConstraint.UP)) policies.add( PitchStepConstraint(actors[7], actors[8], 1, PitchStepConstraint.UP)) policies.add(EqualPitchConstraint([actors[3], actors[4]])) policies.add(EqualPitchConstraint([actors[8], actors[9]])) policies.add( RelativeDiatonicConstraint(actors[4], actors[5], Interval(3, IntervalType.Major), Interval(1, IntervalType.Perfect))) policies.add( RelativeDiatonicConstraint(actors[3], actors[8], Interval(5, IntervalType.Perfect), Interval(1, IntervalType.Perfect))) policies.add(ChordalPitchConstraint(actors[4])) policies.add(ChordalPitchConstraint(actors[9])) solver = PitchConstraintSolver(policies) full_results, _ = solver.solve(p_map) print('Results has {0} results.'.format(len(full_results))) for pm in full_results: print("{0}".format(pm))