#include #include #include "HCheckConfig.h" #include "catch.hpp" #include "lp_data/HConst.h" #include "util/HighsRandom.h" #include "util/HighsSort.h" using std::vector; const bool dev_run = false; // No commas in test case name. void getRandomValues(const HighsInt num_values, vector& values, vector& indices) { // Set up a vector of random number and their corresponding indices HighsRandom random; for (HighsInt ix = 0; ix < num_values; ix++) { values[1 + ix] = random.fraction(); indices[1 + ix] = ix; } } void doFullSort(const HighsInt num_values, vector& values, vector& indices) { // Sort the vector of random number and their corresponding indices maxheapsort(values.data(), indices.data(), num_values); } void doAddSort(HighsInt& num_values_sorted, const HighsInt& max_num_values_sorted, vector& best_double_values, vector& best_indices, const HighsInt num_values, const vector& values, const vector& indices) { num_values_sorted = 0; for (HighsInt ix = 1; ix <= num_values; ix++) { addToDecreasingHeap(num_values_sorted, max_num_values_sorted, best_double_values, best_indices, values[ix], indices[ix]); } sortDecreasingHeap(num_values_sorted, best_double_values, best_indices); } void reportValuesIndices(const HighsInt num_values, const vector& values, const vector& indices) { if (!dev_run) return; printf("\n Ix Value Index\n"); for (HighsInt ix = 1; ix <= num_values; ix++) { printf("%4" HIGHSINT_FORMAT " %10.8f %4" HIGHSINT_FORMAT "\n", ix, values[ix], indices[ix]); } } void checkIncreasingSort(const HighsInt num_sorted, const vector& values, const vector& indices, const vector& original_values) { // Check that the random numbers are ascending and that the indices // point from the original values to their new positions bool error0 = false; bool error1 = false; double previous = -kHighsInf; for (HighsInt ix = 0; ix < num_sorted; ix++) { if (values[1 + ix] < previous) { printf("Values[%2" HIGHSINT_FORMAT "] = %f5.4 < %f5.4 = previous\n", 1 + ix, values[1 + ix], previous); error0 = true; } previous = values[1 + ix]; if (values[1 + ix] != original_values[1 + indices[1 + ix]]) { printf("Values[%2" HIGHSINT_FORMAT "] = %f5.4 != %f5.4 = original_values[indices[%2" HIGHSINT_FORMAT "]]\n", 1 + ix, values[1 + ix], original_values[indices[1 + ix]], 1 + ix); error1 = true; } } REQUIRE(error0 == false); REQUIRE(error1 == false); } void checkDecreasingSort(const HighsInt num_sorted, const vector& values, const vector& indices, const vector& original_values) { // Check that the random numbers are ascending and that the indices // point from the original values to their new positions bool error0 = false; bool error1 = false; double previous = kHighsInf; for (HighsInt ix = 0; ix < num_sorted; ix++) { if (values[1 + ix] > previous) { printf("Values[%2" HIGHSINT_FORMAT "] = %f5.4 < %f5.4 = previous\n", 1 + ix, values[1 + ix], previous); error0 = true; } previous = values[1 + ix]; if (values[1 + ix] != original_values[1 + indices[1 + ix]]) { printf("Values[%2" HIGHSINT_FORMAT "] = %f5.4 != %f5.4 = original_values[indices[%2" HIGHSINT_FORMAT "]]\n", 1 + ix, values[1 + ix], original_values[indices[1 + ix]], 1 + ix); error1 = true; } } REQUIRE(error0 == false); REQUIRE(error1 == false); } TEST_CASE("HiGHS_sort", "[highs_data]") { HighsInt num_values = 10; vector indices; vector int_values; vector double_values; vector original_double_values; indices.resize(1 + num_values); int_values.resize(num_values); double_values.resize(1 + num_values); original_double_values.resize(1 + num_values); getRandomValues(num_values, double_values, indices); reportValuesIndices(num_values, double_values, indices); original_double_values = double_values; doFullSort(num_values, double_values, indices); reportValuesIndices(num_values, double_values, indices); checkIncreasingSort(num_values, double_values, indices, original_double_values); // Use the indices of the previous sort as a vector of integers to sort for (HighsInt ix = 0; ix < num_values; ix++) { double_values[ix] = double_values[ix + 1]; int_values[ix] = indices[1 + ix]; } double_values.resize(num_values); int_values.resize(num_values); std::make_heap(int_values.begin(), int_values.end()); std::sort_heap(int_values.begin(), int_values.end()); // maxheapsort(int_values.data(), num_values); bool ok; // Check that the values in the vector of doubles are ascending - can do // strict test ok = increasingSetOk(double_values, 0, 1, true); REQUIRE(ok == true); // Check that the values in the vector of integers are ascending - maybe can't // do strict test ok = increasingSetOk(int_values, 0, num_values, false); REQUIRE(ok == true); num_values = 14; vector set; vector lb; vector ub; set.resize(num_values); lb.resize(num_values); ub.resize(num_values); set[0] = 6; lb[0] = 60; ub[0] = 60; set[1] = 7; lb[1] = 6; ub[1] = 6; set[2] = 8; lb[2] = 60; ub[2] = 60; set[3] = 13; lb[3] = 600; ub[3] = 1200; set[4] = 4; lb[4] = 70; ub[4] = 70; set[5] = 5; lb[5] = 16; ub[5] = 16; set[6] = 2; lb[6] = 70; ub[6] = 70; set[7] = 3; lb[7] = 7; ub[7] = 7; set[8] = 11; lb[8] = 200; ub[8] = 1400; set[9] = 0; lb[9] = 75; ub[9] = 75; set[10] = 1; lb[10] = 12; ub[10] = 12; set[11] = 14; lb[11] = 0; ub[11] = 1400; set[12] = 9; lb[12] = 6; ub[12] = 6; set[13] = 15; lb[13] = 600; ub[13] = 1200; vector sorted_set = set; vector sorted_lb; vector sorted_ub; sorted_lb.resize(num_values); sorted_ub.resize(num_values); sortSetData(num_values, sorted_set, lb.data(), ub.data(), NULL, sorted_lb.data(), sorted_ub.data(), NULL); HighsInt prev_ix = -kHighsIInf; for (HighsInt k0 = 0; k0 < num_values; k0++) { HighsInt ix = sorted_set[k0]; REQUIRE(ix >= prev_ix); HighsInt k1 = -kHighsIInf; for (HighsInt k_1 = 0; k_1 < num_values; k_1++) { if (set[k_1] == ix) { k1 = k_1; break; } } REQUIRE(k1 > -kHighsIInf); REQUIRE(sorted_lb[k0] == lb[k1]); REQUIRE(sorted_ub[k0] == ub[k1]); } num_values = 10; HighsInt max_num_values_sorted = 5; vector best_indices; vector best_double_values; indices.assign(1 + num_values, 0); double_values.assign(1 + num_values, 0); best_indices.assign(1 + max_num_values_sorted, 0); best_double_values.assign(1 + max_num_values_sorted, 0); HighsInt num_values_sorted; getRandomValues(num_values, double_values, indices); reportValuesIndices(num_values, double_values, indices); doAddSort(num_values_sorted, max_num_values_sorted, best_double_values, best_indices, num_values, double_values, indices); reportValuesIndices(num_values_sorted, best_double_values, best_indices); checkDecreasingSort(num_values_sorted, best_double_values, best_indices, double_values); }