// Find adjacent intervals with smallest $\chi^2$ IntervalList::iterator find_min_chi_chi() { // Compute $\chi^2$ value for each adjacent interval, // keeping track of minimum value IntervalList::iterator lit = g_intervals.begin(), lend = g_intervals.end(); IntervalList::iterator next = lit, min_lit = lend; float min_chisquared = 1e6; bool first = true; for ( ; lit != lend; ++lit) { next = lit; ++next; if (next == lend) break; float chisquared = compute_chisquared(*lit, *next); // Debug print_interval_set(*lit); cout << "\\chi^2 = " << chisquared << endl; if (first || chisquared < min_chisquared) { min_lit = lit; min_chisquared = chisquared; } first = false; } cout << "min_chisquared = " << min_chisquared << endl; return min_lit; }
void print_interval_summary(ostream& os, int dimIndex) { IntervalList::iterator lit = g_intervals.begin(), lend = g_intervals.end(); IntervalList::iterator next = lit; vector<DataType> split_points; os << "\n" "Feature " << (dimIndex+1) << ":" << endl; os << "Ranges: "; for ( ; lit != lend; ++lit) { next = lit; ++next; pair<DataType, DataType> range, next_range; range = get_range(*lit, dimIndex); if (next != lend) { next_range = get_range(*next, dimIndex); float average = (range.second + next_range.first) * 0.5f; split_points.push_back(average); } os << "[" << range.first << ", " << range.second << "] "; } os << endl; os << "Split points: "; copy(split_points.begin(), split_points.end(), ostream_iterator<DataType>(os, ", ")); os << endl; }
// Initialize intervals, one for each unique attribute value void initialize_intervals(int dimIndex) { g_intervals.clear(); IntervalSet interval; TupleVec::iterator it = g_data.begin(), end = g_data.end(), next; int index = 0; for ( ; it != end; ++it, ++index) { next = it+1; // Add element (index) to interval interval.insert(index); bool insertInterval = (next == end) || ( (next->first)[dimIndex] != (it->first)[dimIndex] ); if (insertInterval) { // Insert interval into list if // (a) end of sequence or // (b) next element is not the same as current element g_intervals.push_back(interval); interval.clear(); } } // Debug print_all_intervals(); }
// Debugging -- print all intervals void print_all_intervals() { IntervalList::iterator lit = g_intervals.begin(), lend = g_intervals.end(); cout << "[intervals]" << endl; for ( ; lit != lend; ++lit) { IntervalSet& indices = *lit; print_interval_set(indices); } }
// $\chi^2$ just for one dimension void chi_chi_dim_analysis(int dimIndex) { // Sort and initialize one interval per unique attribute value sort(g_data.begin(), g_data.end(), tuple_less_than<Tuple>(dimIndex)); TupleVec::iterator tit = g_data.begin(), tend = g_data.end(); cout << "[sort]" << endl; int index = 0; for ( ; tit != tend; ++tit, ++index) { cout << index << ":"; copy(tit->first.begin(), tit->first.end(), ostream_iterator<float>(cout, ", ")); cout << tit->second << endl; } initialize_intervals(dimIndex); // Count instances of all classes count_classes(); while ((int)g_intervals.size() > g_max_intervals) { // Find adjacent intervals with smallest $\chi^2$ IntervalList::iterator min_lit = find_min_chi_chi(); assert(min_lit != g_intervals.end()); IntervalList::iterator min_lit_next = min_lit; ++min_lit_next; cout << "[before merge] "; print_all_intervals(); // Merge IntervalSet& interval_1 = *min_lit; IntervalSet& interval_2 = *min_lit_next; interval_1.insert(interval_2.begin(), interval_2.end()); g_intervals.erase(min_lit_next); cout << "[after merge] "; print_all_intervals(); } // Debugging print_interval_summary(cout, dimIndex); // Logged output print_interval_summary(olog, dimIndex); }
//-------------------------------------------------------------------------------------------------- void Index::get_reachable(unsigned x, std::vector<unsigned>& nodes){ x=g->getNodeId(x); if (!intervals[x]) return; IntervalList* intlist = intervals[x]; const std::vector<unsigned>& lower=intlist->get_lower(); const std::vector<unsigned>& upper=intlist->get_upper(); for (unsigned i=0; i < lower.size(); i++){ for (unsigned node=lower[i]; node<=upper[i];++node){ nodes.push_back(g->getNodeById(id2node[node])); } } }
void IntervalList::addIntervalList(const IntervalList& intervals) { const QList<Interval> list = intervals.getList(); QList<Interval>::const_iterator it = list.constBegin(); for( ; it != list.constEnd(); ++it) { addInterval((*it)); } }
bool IntervalList::isParsable(const QString &input, const IntervalList &container) { try { const IntervalList test(input); return container.contains(test); } catch (std::exception&) { return false; } }
IntervalList IntervalList::intersect(const IntervalList& a, const IntervalList& b) { IntervalList output; const QList<Interval> aList = a.getList(); const QList<Interval> bList = b.getList(); QList<Interval>::const_iterator aIt = aList.constBegin(); QList<Interval>::const_iterator bIt = bList.constBegin(); QList<Interval>::const_iterator aItEnd = aList.constEnd(); QList<Interval>::const_iterator bItEnd = bList.constEnd(); bool a_open = false; bool b_open = false; int start = 0; int end = 0; // This looks atrocious, but is probably one of the quickest available methods // to find the intersections of two lists of Intervals. An easier (but much // less effecient way) would be to define Interval::intersect(Interval a, Interval b) // for the Interval class, and then use that method to intersect two lists. // Plus, this is probably overkill anyway: who is going to spend time typing // in an interval list big enough to slow a computer down? while(aIt != aItEnd && bIt != bItEnd) { if(!a_open && !b_open) { if((*aIt).start() < (*bIt).start()) { a_open = true; } else if((*aIt).start() > (*bIt).start()) { b_open = true; } else { a_open = true; b_open = true; start = (*aIt).start(); } } else if(a_open && !b_open) { if((*aIt).end() < (*bIt).start()) { a_open = false; ++aIt; } else if((*aIt).end() > (*bIt).start()) { b_open = true; start = (*bIt).start(); } else { a_open = false; b_open = true; start = (*aIt).end(); end = (*bIt).start(); Interval interval(start, end); output.addInterval(interval); ++aIt; } } else if(!a_open && b_open) { if((*bIt).end() < (*aIt).start()) { b_open = false; ++bIt; } else if((*aIt).end() > (*bIt).start()) { a_open = true; start = (*aIt).start(); } else { b_open = false; a_open = true; start = (*bIt).end(); end = (*aIt).start(); Interval interval(start, end); output.addInterval(interval); ++bIt; } } else { if((*aIt).end() < (*bIt).end()) { a_open = false; end = (*aIt).end(); Interval interval(start, end); output.addInterval(interval); ++aIt; } else if((*aIt).end() > (*bIt).end()) { b_open = false; end = (*bIt).end(); Interval interval(start, end); output.addInterval(interval); ++bIt; } else { a_open = false; b_open = false; end = (*aIt).end(); Interval interval(start, end); output.addInterval(interval); ++aIt; ++bIt; } } } return output; }
void IntervalList::setIntervalList(const IntervalList& intervals) { m_list = QList<Interval>(intervals.getList()); }
/*! * \param other interval list to merge into this interval list */ void IntervalList::merge_exact(const IntervalList& other) { // find starting point if (other.empty()) { return; } int last_index = 0; // intervals of other list const std::vector<unsigned>& o_lower = other.get_lower(); const std::vector<unsigned>& o_upper = other.get_upper(); // is this interval list is empty, just copy other list if (empty()) { std::copy(o_lower.begin(), o_lower.end(), std::back_inserter(lower_)); std::copy(o_upper.begin(), o_upper.end(), std::back_inserter(upper_)); return; } else { // for each interval in other list, find relevant position to insert unsigned a, b; int idxa, idxb; bool insa, insb; for (unsigned i = 0; i < o_lower.size(); ++i) { a = o_lower[i], b = o_upper[i]; insa = false, insb = false; idxa = find(a); //, last_index_); (void) last_index; idxb = idxa + 1; /* distinguish 4 cases a,b between/within intervals */ // determine // - index of interval containing or left of a, flag: inside // - index of interval containing or right of b, flag: inside if (idxa != -1 && a <= upper_[idxa] + 1) { insa = true; } while (idxb < int(lower_.size()) && b >= lower_[idxb] - 1) { ++idxb; } if (idxb != 0 && b <= upper_[idxb - 1] + 1) { insb = true; --idxb; } else { insb = false; } // special cases if (!insb && idxb == 0) { // before everything lower_.insert(lower_.begin(), a); upper_.insert(upper_.begin(), b); last_index = 0; continue; // done } else if (!insa && idxa == int(lower_.size()) - 1) { // after everything lower_.push_back(a); upper_.push_back(b); last_index = lower_.size() - 1; continue; // done } if (!insa) { ++idxa; } if (!insb) { --idxb; } if (idxa > idxb) { // new interval between existing //assert(int(lower_.size()) > idxa); lower_.insert(lower_.begin() + idxa, a); upper_.insert(upper_.begin() + idxa, b); last_index = idxa; continue; // done } // update interval boundaries lower_[idxa] = std::min(lower_[idxa], a); upper_[idxb] = std::max(upper_[idxb], b); // general case lower_.erase(lower_.begin() + idxa + 1, lower_.begin() + idxb + 1); upper_.erase(upper_.begin() + idxa, upper_.begin() + idxb); last_index = idxb - idxa - 1; } } }
/*! * \param other interval list */ void IntervalList::merge(const IntervalList& other) { // find starting point if (other.empty()) { return; } int last_index = 0; // other interval list const std::vector<unsigned>& o_lower = other.get_lower(); const std::vector<unsigned>& o_upper = other.get_upper(); const std::vector<char>& o_exact = other.get_exact(); //assert((o_lower.size() == o_upper.size()) && (o_lower.size() == o_exact.size())); // if this list is empty, just copy other list if (empty()) { std::copy(o_lower.begin(), o_lower.end(), std::back_inserter(lower_)); std::copy(o_upper.begin(), o_upper.end(), std::back_inserter(upper_)); std::copy(o_exact.begin(), o_exact.end(), std::back_inserter(exact_)); return; } else { // for each interval in other list, find relevant position to insert unsigned a, b; char ex; int idxa, idxb; bool insa, insb; for (unsigned i = 0; i < o_lower.size(); ++i) { a = o_lower[i], b = o_upper[i]; ex = o_exact[i]; insa = false, insb = false; // determine idxa if (a < lower_.front()) { idxa = -1; } else if (a > upper_.back()) { idxa = upper_.size() - 1; } else { // no special case, perform binary search int _min = last_index, _max = lower_.size(), _mid; while (true) { if (_min == _max) { if (a < lower_[_min]) { idxa = _min - 1; // immediately to the left break; } else { idxa = _min; // included in interval, or immediately to the right break; } } _mid = (_max + _min) / 2; if (lower_[_mid] <= a && a <= upper_[_mid]) { idxa = _mid; break; } else if (a < lower_[_mid]) { _max = _mid; } else { _min = _mid + 1; } } } idxb = idxa + 1; /* distinguish 4 cases a,b between/within intervals */ // determine // - index of interval containing or left of a, flag: inside // - index of interval containing or right of b, flag: inside if (idxa != -1 && a <= upper_[idxa] + 1) { insa = true; } while (idxb < int(lower_.size()) && b >= lower_[idxb] - 1) { ++idxb; } if (idxb != 0 && b <= upper_[idxb - 1] + 1) { insb = true; --idxb; } else { insb = false; } // special cases if (!insb && idxb == 0) { // before everything lower_.insert(lower_.begin(), a); upper_.insert(upper_.begin(), b); exact_.insert(exact_.begin(), ex); last_index = 0; continue; // done } else if (!insa && idxa == int(lower_.size()) - 1) { // after everything lower_.push_back(a); upper_.push_back(b); exact_.push_back(ex); last_index = lower_.size() - 1; continue; // done } if (!insa) { ++idxa; } if (!insb) { --idxb; } if (idxa > idxb) { // new interval between existing //assert(int(lower_.size()) > idxa); lower_.insert(lower_.begin() + idxa, a); upper_.insert(upper_.begin() + idxa, b); exact_.insert(exact_.begin() + idxa, ex); last_index = idxa; continue; // done } // non-exact interval subsumed if (!ex && insa && insb && idxa == idxb && lower_[idxa] <= a && b <= upper_[idxa]) { last_index = idxa; continue; } // update interval boundaries lower_[idxa] = std::min(lower_[idxa], a); upper_[idxb] = std::max(upper_[idxb], b); // general case assert(idxb <= int(lower_.size())); lower_.erase(lower_.begin() + idxa + 1, lower_.begin() + idxb + 1); upper_.erase(upper_.begin() + idxa, upper_.begin() + idxb); char new_exact = ex; if (ex) { for (int i = idxa; i <= idxb; ++i) { if (!exact_[i]) { new_exact = 0; break; } } } exact_[idxa] = new_exact; exact_.erase(exact_.begin() + idxa + 1, exact_.begin() + idxb + 1); last_index = std::max(0, idxa); } } }
std::vector<Tuning*> *Tuning::getTunings() { // if already have tunings, return them // TODO: It would be polite to check the mtime on the tunings file // and to re-read it if it's been changed. For now, you need // to restart Rosegarden. if (!m_tunings.empty()) return &m_tunings; QString tuningsPath = ResourceFinder().getResourcePath("pitches", "tunings.xml"); if (tuningsPath == "") return NULL; # if (TUNING_DEBUG > 1) qDebug() << "Path to tunings file:" << tuningsPath; # endif QFile infile(tuningsPath); IntervalList *intervals = new IntervalList; SpellingList *spellings = new SpellingList; if (infile.open(QIODevice::ReadOnly) ) { QXmlStreamReader stream(&infile); QString tuningName, intervalRatio; stream.readNextStartElement(); if (stream.name() != "rosegarden_scales") { qDebug() << "Tunings configuration file " << tuningsPath << " is not a valid rosegarden scales file. " << "(Root element is " << stream.name() << ")"; return NULL; } enum {needTuning, needName, needInterval, needSpellings} state; # if (TUNING_DEBUG > 2) static const char * stateNames[] = { "expecting <tuning>", "expecting <name>", "expecting <interval>", "expecting <spelling>" }; # endif state = needTuning; while(!stream.atEnd()) { // Read to the next element delimiter do { stream.readNext(); } while(!stream.isStartElement() && !stream.isEndElement() && !stream.atEnd()); if (stream.atEnd()) break; // Perform state transistions at end elements if (stream.isEndElement()) { if (stream.name() == "tuning") { // Save the tuning and prepare for a new one saveTuning(tuningName, intervals, spellings); intervals = new IntervalList; spellings = new SpellingList; state = needTuning; } else if (stream.name() == "name") { // End of tuning name: expect intervals state = needInterval; } else if (stream.name() == "interval") { // After an </interval>, we're expecting another interval state = needInterval; } else if (stream.name() == "rosegarden_scales") { // XML's fininshed. Don't need the current tuning // or spelling lists created when the last tuning ended // so let's not leak memory. delete intervals; delete spellings; // Don't bother reading any more of the file break; } # if (TUNING_DEBUG > 2) qDebug() << "End of XML element " << stream.name() << "New state: " << state << " (" << stateNames[state] << ")"; # endif continue; } // So it's a start element. Parse it. // If we are in the needSpellings state but hit a new interval, // we need to process that. So force a state-change here. if (state == needSpellings && stream.name() == "interval") { state = needInterval; } # if (TUNING_DEBUG > 2) qDebug() << "XML Element: " << stream.name() << " Current XML parser state: " << state << " (" << stateNames[state] << ")"; # endif switch (state) { case needTuning: if (stream.name() != "tuning") { qDebug() << "Reading Tunings. Expected tuning element, " << "found " << stream.name(); stream.skipCurrentElement(); } else { // Require a name element state = needName; } break; case needName: if (stream.name() != "name") { qDebug() << "Tuning must start with a <name> element, " << "found <" << stream.name() << ">"; stream.skipCurrentElement(); } else { tuningName = stream.readElementText(); state = needInterval; # if (TUNING_DEBUG > 1) qDebug() << "\nNew Tuning: " << tuningName; # endif } break; case needInterval: if (stream.name() != "interval") { qDebug() << "Expecting an <interval> element, " << "found <" << stream.name() << ">"; // Bail out stream.skipCurrentElement(); } else { intervalRatio = stream.attributes().value("ratio").toString(); # if (TUNING_DEBUG > 1) qDebug() << "New Ratio: " << intervalRatio; # endif const double cents = scalaIntervalToCents(intervalRatio, stream.lineNumber()); intervals->push_back(cents); state = needSpellings; } break; case needSpellings: if (stream.name() != "spelling") { qDebug() << "Intervals may contain only spellings. " << "Found <" << stream.name() << ">"; // Keep looking for spellings stream.skipCurrentElement(); } else { // Parse this spelling parseSpelling(stream.readElementText(), intervals, spellings); } break; default: // Illegal state (can't happen: it's an enumerated type!) qDebug() << "Something nasty happened reading tunings. " "Illegal state at line " << stream.lineNumber(); stream.skipCurrentElement(); break; } // end switch(state) } // end while(!stream.atEnd()) # if (TUNING_DEBUG > 1) qDebug() << "Closing tunings file"; # endif infile.close(); } // end if (m_infile.open(... return &m_tunings; }
/** * 2DO extend to support non default references * If no tuning present, will default to 12ET */ Tuning *PMLDocument::getTuning(){ DOMElement *perf = getSingleElement(m_doc->getDocumentElement(), "performance"); if( !perf ){ //cerr << "No performance element! Defaulting to 12ET\n"; } else{ DOMElement *tuningEl = getSingleElement(perf, "tuning"); if( !tuningEl ){ cout << "No tuning element! Defaulting to 12ET\n"; } else{ string tuningName = XS( tuningEl->getAttribute(XS("name")) ); IntervalList *intervals = new IntervalList; SpellingList *spellingList = new SpellingList; /* Get intervals */ DOMElement* intList = getSingleElement(tuningEl,"intervallist"); DOMNodeList *intervalEls = intList->getElementsByTagName(XS("interval")); for( int i=0; i<intervalEls->getLength(); i++ ){ string is = getText((DOMElement*)intervalEls->item(i)); //cout << "Interval " << is << endl; intervals->push_back( atof(is.c_str()) ); } /* Get enharmonic equivalent spellings */ DOMElement *spellingListEl = getSingleElement( tuningEl, "spellinglist" ); DOMNodeList *equivs = spellingListEl->getElementsByTagName(XS("enharmequiv")); for( int e=0; e<equivs->getLength(); e++ ){ DOMElement *equiv = (DOMElement*)equivs->item(e); DOMNodeList *spellings = equiv->getElementsByTagName(XS("spelling")); for( int i=0; i<spellings->getLength(); i++ ){ DOMElement* spEl = (DOMElement*)spellings->item(i); Accidental acc; if( spEl->getAttributeNode(XS("acc")) == NULL ) acc = Accidentals::NoAccidental; else acc = XS( spEl->getAttribute(XS("acc")) ); //cout << "Acc " << acc << endl; string notest = XS(spEl->getAttribute(XS("note"))); char note = notest[0]; PitchSpelling ps(note,acc); SpellingListItem spi( e, ps ); spellingList->insert( spi); } } Tuning *tuning = new Tuning( tuningName, intervals, spellingList); return tuning; } } std::vector<Tuning*>* tunings = Tuning::getTunings( "/usr/local/lib/tunings" ); Tuning *tuning = tunings->at(0); return tuning; }