29 #include <boost/range/algorithm/set_algorithm.hpp>
31 #include <boost/program_options.hpp>
36 #define INIT_TIMER auto start = std::chrono::high_resolution_clock::now()
37 #define START_TIMER start = std::chrono::high_resolution_clock::now()
38 #define STOP_TIMER() ( \
39 std::chrono::duration_cast<std::chrono::milliseconds>( \
40 std::chrono::high_resolution_clock::now()-start \
42 #define STOP_TIMER_SEC() (STOP_TIMER() / 60)
46 #define STOP_TIMER() (0)
47 #define STOP_TIMER_SEC() (0)
59 namespace po = boost::program_options;
62 void printCounts(std::string detail_name, std::vector<T> &vec, std::vector<T> &vecother);
65 void printCounts(std::string detail_name, std::vector<lpcompare::Bound> &vec, std::vector<lpcompare::Bound> &vecother);
68 void printCounts(std::string detail_name, std::vector<lpcompare::Constraint> &vec, std::vector<lpcompare::Constraint> &vecother);
71 void printCountsWithSort(std::string detail_name, std::vector<T> &vec, std::vector<T> &vecother);
76 void dumpdiff_if_requested(std::string detail_name, std::vector<T> &set1Except2, std::vector<T> &set2Except1);
91 po::positional_options_description p;
95 po::options_description desc(
"Usage");
97 (
"help",
"show usage information")
98 (
"first", po::value<std::string>(&
first_filename)->required(),
"model 1 cplex lp file")
99 (
"second", po::value<std::string>(&
second_filename)->required(),
"model 2 cplex lp file")
100 (
"dump-prefix", po::value<std::string>()->default_value(
"diffdump"),
"filename prefix for difference dumps")
101 (
"dump-diffs", po::value<bool>()->default_value(
true),
"filename prefix for difference dumps")
106 po::store(po::command_line_parser(argc, argv).
107 options(desc).positional(p).run(),
vm);
109 if (
vm.count(
"help")) {
110 cout << desc <<
"\n";
116 catch (po::required_option& e)
118 std::cerr <<
"Error: " << e.what() << std::endl << std::endl;
120 cout << desc <<
"\n";
133 return vm[
"dump-prefix"].as<std::string>() +
"-" + model +
"-" + detail +
".log";
142 return vm[
"dump-diffs"].as<
bool>();
145 int main(
int argc,
char *argv [])
149 cout <<
"lpcompare: Compares two LP files created in cplex format and dumps differences to files." << endl;
161 cout <<
" First model:" << endl;
164 cout <<
" Model read in " << first_model_read_sec <<
" s" << endl;
171 cout <<
" Second Model:" << endl;
174 cout <<
" Model read in " << second_model_read_sec <<
" s" << endl;
185 cout <<
" Bounds check completed in " << bounds_check_sec <<
" s" << endl;
190 cout <<
" Constraints check completed in " << cons_check_sec <<
" s" << endl;
201 cout <<
"Binaries: " << model->
Binaries.size() << endl;
202 cout <<
"Bounds: " << model->
Bounds.size() << endl;
203 cout <<
"Constraints: " << model->
Constraints.size() << endl;
204 cout <<
"Generals: " << model->
Generals.size() << endl;
205 cout <<
"SosVars: " << model->
SosVars.size() << endl;
214 template <
typename T>
220 if (set1Except2.size() > 0) {
223 std::ofstream out_file_1(filename1e2);
226 cout <<
"Cannot open or create file for writing: " << filename1e2;
230 out_file_1 <<
"firstEXCEPTsecond " << detail_name << std::endl;
231 for (
auto item : set1Except2) {
232 out_file_1 << item << std::endl;
238 cout <<
"firstEXCEPTsecond diff written for " << detail_name <<
" to " << filename1e2 << std::endl;
241 if (set2Except1.size() > 0) {
244 std::ofstream out_file_2(filename2e1);
247 cout <<
"Cannot open or create file for writing: " << filename2e1;
251 out_file_2 <<
"secondEXCEPTfirst " << detail_name << std::endl;
252 for (
auto item : set2Except1) {
253 out_file_2 << item << std::endl;
259 cout <<
"secondEXCEPTfirst diff written for " << detail_name <<
" to " << filename2e1 << std::endl;
270 template <
typename T>
271 void printCounts(std::string detail_name, std::vector<T> &vec, std::vector<T> &vecother)
273 cout << detail_name <<
" First Model: " << vec.size() << endl;
274 cout << detail_name <<
" Second Model: " << vecother.size() << endl;
276 std::vector<T> set1Except2;
277 std::set_difference(vec.begin(), vec.end(), vecother.begin(), vecother.end(), std::back_inserter(set1Except2));
279 std::vector<T> set2Except1;
280 std::set_difference(vecother.begin(), vecother.end(), vec.begin(), vec.end(), std::back_inserter(set2Except1));
282 auto size1e2 = set1Except2.size();
283 auto size2e1 = set1Except2.size();
285 if (size1e2 == 0 && size2e1 == 0) {
286 cout << detail_name <<
" are equivalent." << endl;
289 cout << detail_name <<
" First except Second: " << set1Except2.size() << endl;
290 cout << detail_name <<
" Second except First: " << set2Except1.size() << endl;
303 template <
typename T>
306 cout << name <<
" First Model: " << vec.size() << endl;
307 cout << name <<
" Second Model: " << vecother.size() << endl;
309 std::vector<T> set1Except2;
310 std::vector<T> set2Except1;
312 std::sort(vec.begin(), vec.end());
313 std::sort(vecother.begin(), vecother.end());
315 auto it = vec.begin();
316 auto ot = vecother.begin();
318 while (it != vec.end() && ot != vecother.end())
327 else if (item < other) {
328 set1Except2.push_back(item);
332 set2Except1.push_back(other);
337 while (it != vec.end())
339 set1Except2.push_back(*it);
343 while (ot != vecother.end())
345 set2Except1.push_back(*ot);
349 auto size1e2 = set1Except2.size();
350 auto size2e1 = set2Except1.size();
352 if (size1e2 == 0 && size2e1 == 0) {
353 cout << name <<
" are equivalent." << endl;
356 cout << name <<
" First except Second: " << set1Except2.size() << endl;
357 cout << name <<
" Second except First: " << set2Except1.size() << endl;
371 void printCounts(std::string detail_name, std::vector<lpcompare::Constraint> &vec, std::vector<lpcompare::Constraint> &vecother)
384 void printCounts(std::string detail_name, std::vector<lpcompare::Bound> &vec, std::vector<lpcompare::Bound> &vecother)
std::string second_filename
Filename of the second LP model.
Represents an LP model composed of a bounds, constraints and variables of different kinds...
std::vector< Constraint > Constraints
int main(int argc, char *argv[])
void printCountsWithSort(std::string detail_name, std::vector< T > &vec, std::vector< T > &vecother)
Prints count of a given detail for both models, including differences.
std::vector< std::string > SosVars
std::string first_filename
Filename of the first LP model.
std::vector< std::string > Generals
void setup_options(int argc, char *argv[])
Parses program arguments using boost program_options.
std::string get_dump_filename(std::string model, std::string detail)
Creates a filename to dump differences into.
void printCounts(std::string detail_name, std::vector< T > &vec, std::vector< T > &vecother)
Prints count of a given detail for both models, including differences.
std::vector< std::string > Binaries
void printStats(LPModel *model)
Prints statistics for a model.
void dumpdiff_if_requested(std::string detail_name, std::vector< T > &set1Except2, std::vector< T > &set2Except1)
Dumps diffs to a file if dumping is requested.
bool is_diffdumps_requested()
Checks if diff dumps are requested.
po::variables_map vm
Variable map for boost::program_options.
std::vector< Bound > Bounds
bool ReadModel(std::string filename)
Parses an LP file to build an LPModel instance.