#include #include #include #include #include #include using std::stringstream; using std::vector; using std::cin; using std::cout; using std::endl; typedef unsigned long ULong; enum EVerbosity { eNone = 0, eSome = 1, eAll = 2 }; class SDefeat { public: SDefeat( void ) {} ~SDefeat( void ) {} ULong x; ULong y; ULong strength; ULong margin; }; #define ThrowIf_( x, theException ) if ( x ) throw theException static void PrintHTMLMatrix( vector &matrix, ULong nOptions ); static bool CondorcetRankedPairs( vector &matrix, ULong nOptions, EVerbosity verbosity ); static void SortUnconsideredDefeats( vector &defeats, vector &considered, vector &matrix, ULong nOptions, vector &outSorted ); static void FloydsAlgorithm( vector &a, ULong nOptions ); int main( int argc, const char * argv[] ) { ULong x; ULong nOptions = 0; ULong matrixSize; vector matrix; ULong inVerbosity; int exitStatus = 0; EVerbosity verbosity; ULong i = 1; try { stringstream strStream; strStream << argv[i]; strStream >> nOptions; strStream.clear(); i++; matrixSize = nOptions * nOptions; ThrowIf_( ULong(argc) != matrixSize + 3, 1 ); matrix.resize(matrixSize); for ( x = 0; x < matrixSize; x++ ) { strStream.str( "" ); strStream << argv[i]; strStream >> matrix[x]; strStream.clear(); i++; } strStream << argv[i]; strStream >> inVerbosity; verbosity = EVerbosity(inVerbosity); if ( verbosity > eNone ) { cout << "The input matrix was:
" << endl; PrintHTMLMatrix( matrix, nOptions ); } CondorcetRankedPairs( matrix, nOptions, verbosity ); } catch( ... ) { exitStatus = 1; } return exitStatus; } bool CondorcetRankedPairs( vector &matrix, ULong nOptions, EVerbosity verbosity ) { ULong x, y; vector defeats; vector kept; vector considered; vector tie; vector sortedDefeats; vector consideringDefeats; ULong matrixSize = nOptions * nOptions; bool success = true; bool hasDefeat; ULong xyIndex; ULong yxIndex; ULong yyIndex; try { defeats.resize( matrixSize ); kept.resize( matrixSize ); considered.resize( matrixSize ); tie.resize( matrixSize ); for ( x = 0; x < nOptions; x++ ) { for ( y = 0; y < nOptions; y++ ) { xyIndex = ( x * nOptions ) + y; yxIndex = ( y * nOptions ) + x; defeats[xyIndex] = matrix[xyIndex]; if ( matrix[xyIndex] > matrix[yxIndex] ) defeats[yxIndex] = 0; else if ( matrix[xyIndex] < matrix[yxIndex] ) defeats[xyIndex] = 0; else if ( matrix[xyIndex] == matrix[yxIndex] ) defeats[xyIndex] = defeats[yxIndex]; if ( defeats[xyIndex] > 0 ) tie[xyIndex] = 1; kept[xyIndex] = 0; considered[xyIndex] = 0; } } if ( verbosity > eNone ) { cout << "The defeats matrix was:
" << endl; PrintHTMLMatrix( defeats, nOptions ); cout << "
" << endl; } // first pass // vertices that don't cycle back to themselves // have defeats we can keep FloydsAlgorithm( tie, nOptions ); for ( x = 0; x < nOptions; x++ ) { for ( y = 0; y < nOptions; y++ ) { xyIndex = ( x * nOptions ) + y; if ( defeats[xyIndex] > 0 ) { if ( tie[ ( y * nOptions ) + y ] == 0 ) { kept[xyIndex] = considered[xyIndex] = 1; if ( verbosity > eNone ) cout << "Now Keeping: " << x << " defeats " << y << "
" << endl; } } } } if ( verbosity > eSome ) { std::cout << "The first pass Floyd Results:
" << std::endl; PrintHTMLMatrix( tie, nOptions ); std::cout << "
" << std::endl; std::cout << "The first pass results were (kept/considered):
" << std::endl; PrintHTMLMatrix( kept, nOptions ); std::cout << "
" << std::endl; } SortUnconsideredDefeats( defeats, considered, matrix, nOptions, sortedDefeats ); if ( verbosity > eSome ) { std::cout << "Sorted defeats count = " << sortedDefeats.size() << "
" << std::endl; for ( x = 0; x < sortedDefeats.size(); x++ ) std::cout << sortedDefeats[x].x << " " << sortedDefeats[x].y << " " << sortedDefeats[x].strength << " " << sortedDefeats[x].margin << " " << "
" << std::endl; } while ( sortedDefeats.size() > 0 ) { // add in the already kept defeats tie.assign( kept.begin(), kept.end() ); // find the next set of defeats to check cycles for consideringDefeats.clear(); consideringDefeats.push_back( sortedDefeats.back() ); sortedDefeats.pop_back(); xyIndex = ( consideringDefeats.back().x * nOptions ) + consideringDefeats.back().y; tie[xyIndex] = 1; considered[xyIndex] = 1; while ( sortedDefeats.size() > 0 && sortedDefeats.back().strength == consideringDefeats.back().strength && sortedDefeats.back().margin == consideringDefeats.back().margin ) { consideringDefeats.push_back( sortedDefeats.back() ); sortedDefeats.pop_back(); xyIndex = ( consideringDefeats.back().x * nOptions ) + consideringDefeats.back().y; tie[xyIndex] = 1; considered[xyIndex] = 1; } if ( verbosity > eSome ) { cout << "Now considering:
" << endl; for ( x = 0; x < consideringDefeats.size(); x++ ) cout << consideringDefeats[x].x << " " << consideringDefeats[x].y << " " << consideringDefeats[x].strength << " " << consideringDefeats[x].margin << " " << "
" << endl; cout << "Checking cycles on:
" << endl; PrintHTMLMatrix( tie, nOptions ); cout << "
" << endl; } FloydsAlgorithm( tie, nOptions ); if ( verbosity > eSome ) { cout << "Floyd Result:
" << endl; PrintHTMLMatrix( tie, nOptions ); cout << "
" << endl; } for ( x = 0; x < consideringDefeats.size(); x++ ) { //yyIndex = ( consideringDefeats[x].y * nOptions ) + consideringDefeats[x].y; yxIndex = ( consideringDefeats[x].y * nOptions ) + consideringDefeats[x].x; xyIndex = ( consideringDefeats[x].x * nOptions ) + consideringDefeats[x].y; if ( tie[yxIndex] == 0 ) { kept[xyIndex] = 1; if ( verbosity > eNone ) cout << "Now Keeping: " << consideringDefeats[x].x << " defeats " << consideringDefeats[x].y << "
" << endl; } } if ( verbosity > eSome ) { cout << "Kept Matrix:
" << endl; PrintHTMLMatrix( kept, nOptions ); cout << "
" << endl; cout << "Considered Matrix:
" << endl; PrintHTMLMatrix( considered, nOptions ); cout << "
" << endl; } } cout << "WIN"; for ( x = 0; x < nOptions; x++ ) { hasDefeat = false; for ( y = 0; y < nOptions && !hasDefeat; y++ ) { yxIndex = ( y * nOptions ) + x; if ( kept[yxIndex] > 0 ) hasDefeat = true; } cout << "-"; if ( !hasDefeat ) cout << "1"; else cout << "0"; } } catch( ... ) { success = false; } return success; } void SortUnconsideredDefeats( vector &defeats, vector &considered, vector &matrix, ULong nOptions, vector &outSorted ) { ULong x, y; ULong i = 0; ULong xyIndex; ULong yxIndex; SDefeat defeat; // obtain the defeats for ( x = 0; x < nOptions; x++ ) { for ( y = 0; y < nOptions; y++ ) { xyIndex = ( x * nOptions ) + y; yxIndex = ( y * nOptions ) + x; if ( defeats[xyIndex] > 0 && considered[xyIndex] == 0 ) { defeat.x = x; defeat.y = y; defeat.strength = defeats[xyIndex]; defeat.margin = matrix[xyIndex] - matrix[yxIndex]; outSorted.push_back( defeat ); i++; } } } sort( outSorted.begin(), outSorted.end() ); } void FloydsAlgorithm( vector &a, ULong nOptions ) { ULong xyIndex; ULong yjIndex; ULong xjIndex; ULong x, y, j; ULong value; for ( y = 0; y < nOptions; y++ ) { for ( x = 0; x < nOptions; x++ ) { xyIndex = ( x * nOptions ) + y; if ( a[xyIndex] > 0 ) { for ( j = 0; j < nOptions; j++ ) { yjIndex = ( y * nOptions ) + j; if ( a[yjIndex] > 0 ) { xjIndex = ( x * nOptions ) + j; value = a[xyIndex] + a[yjIndex]; if ( a[xjIndex] == 0 || value < a[xyIndex] ) a[xjIndex] = value; } } } } } } void PrintHTMLMatrix( vector &matrix, ULong nOptions ) { ULong x, y; cout << "" << endl; // output first row cout << "" << endl; // upper left corner of table cout << "" << endl; // build remainder of row for ( x = 0; x < nOptions; x++ ) { cout << "" << endl; } cout << "" << endl; // output remaining rows for ( x = 0; x < nOptions; x++ ) { cout << "" << endl; cout << "" << endl; for ( y = 0; y < nOptions; y++ ) { cout << "" << endl; } cout << "" << endl; } cout << "
Option" << x << "
" << x << "" << endl; cout << matrix[ ( x * nOptions ) + y ]; cout << "
" << endl; } bool operator< ( const SDefeat &a, const SDefeat &b ) { if ( a.strength > b.strength ) return false; else if ( a.strength < b.strength ) return true; else if ( a.margin > b.margin ) return false; else if ( a.margin < b.margin ) return true; else return false; } bool operator== ( const SDefeat &a, const SDefeat &b ) { if ( a.strength > b.strength ) return false; else if ( a.strength < b.strength ) return false; else if ( a.margin > b.margin ) return false; else if ( a.margin < b.margin ) return false; else return true; }