def _build_p_map_dict(self, partial_pitch_results=None): actors = OrderedSet() for p in self.pitch_constraints: actors = actors.union(p.actors) d = OrderedDict() for note in actors: hc = self.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, self.pitch_range)) d[note] = contextual if partial_pitch_results is not None: for k, v in partial_pitch_results.items(): if not isinstance(k, Note): raise Exception( 'key of partial_pitch_results must be a Note.') if not isinstance(v, DiatonicPitch): raise Exception( 'value of partial_pitch_results must be a DiatonicPitch.' ) if k not in d: raise Exception( 'Note \'{0}\' of partial result is not a constraint actor.' .format(k)) d[k].note = Note(v, k.base_duration, k.num_dots) return d
def _candidate_closure(self, p_map, v_note): """ Find all policies that have v_note as a parameter, and collect their unassigned actors into a set without replication. :param p_map: PMap :param v_note: ContextualNote :return: """ policies = self.v_policy_map[v_note] candidates = OrderedSet() for p in policies: candidates = candidates.union(p_map.unassigned_actors(p)) return candidates
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 ]
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