1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /*                                                                       */
3 /*    This file is part of the HiGHS linear optimization suite           */
4 /*                                                                       */
5 /*    Written and engineered 2008-2021 at the University of Edinburgh    */
6 /*                                                                       */
7 /*    Available as open-source under the MIT License                     */
8 /*                                                                       */
9 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10 /**@file util/HighsMatrixPic.cpp
11  * @brief Class-independent utilities for HiGHS
12  * @author Julian Hall, Ivet Galabova, Qi Huangfu and Michael Feldmeier
13  */
14 
15 #include "util/HighsMatrixPic.h"
16 
17 #include <algorithm>
18 #include <cassert>
19 #include <cmath>
20 #include <fstream>
21 
writeLpMatrixPicToFile(const HighsOptions & options,const std::string fileprefix,const HighsLp & lp)22 HighsStatus writeLpMatrixPicToFile(const HighsOptions& options,
23                                    const std::string fileprefix,
24                                    const HighsLp& lp) {
25   return writeMatrixPicToFile(options, fileprefix, lp.numRow_, lp.numCol_,
26                               lp.Astart_, lp.Aindex_);
27 }
28 
writeMatrixPicToFile(const HighsOptions & options,const std::string fileprefix,const int numRow,const int numCol,const std::vector<int> & Astart,const std::vector<int> & Aindex)29 HighsStatus writeMatrixPicToFile(const HighsOptions& options,
30                                  const std::string fileprefix, const int numRow,
31                                  const int numCol,
32                                  const std::vector<int>& Astart,
33                                  const std::vector<int>& Aindex) {
34   std::vector<int> ARlength;
35   std::vector<int> ARstart;
36   std::vector<int> ARindex;
37   assert(numRow > 0);
38   assert(numCol > 0);
39   const int numNz = Astart[numCol];
40   ARlength.assign(numRow, 0);
41   ARstart.resize(numRow + 1);
42   ARindex.resize(numNz);
43   for (int iEl = 0; iEl < numNz; iEl++) ARlength[Aindex[iEl]]++;
44   ARstart[0] = 0;
45   for (int iRow = 0; iRow < numRow; iRow++)
46     ARstart[iRow + 1] = ARstart[iRow] + ARlength[iRow];
47   for (int iCol = 0; iCol < numCol; iCol++) {
48     for (int iEl = Astart[iCol]; iEl < Astart[iCol + 1]; iEl++) {
49       int iRow = Aindex[iEl];
50       ARindex[ARstart[iRow]++] = iCol;
51     }
52   }
53   ARstart[0] = 0;
54   for (int iRow = 0; iRow < numRow; iRow++)
55     ARstart[iRow + 1] = ARstart[iRow] + ARlength[iRow];
56 
57   return writeRmatrixPicToFile(options, fileprefix, numRow, numCol, ARstart,
58                                ARindex);
59 }
60 
writeRmatrixPicToFile(const HighsOptions & options,const std::string fileprefix,const int numRow,const int numCol,const std::vector<int> & ARstart,const std::vector<int> & ARindex)61 HighsStatus writeRmatrixPicToFile(const HighsOptions& options,
62                                   const std::string fileprefix,
63                                   const int numRow, const int numCol,
64                                   const std::vector<int>& ARstart,
65                                   const std::vector<int>& ARindex) {
66   if (fileprefix == "") return HighsStatus::Error;
67   std::string filename = fileprefix + ".pbm";
68   std::ofstream f;
69   f.open(filename, std::ios::out);
70   const int border_width = 1;
71   const int max_num_pixel_wide = 1600;
72   const int max_num_pixel_deep = 900;
73   const int max_num_matrix_pixel_wide = max_num_pixel_wide - 2 * border_width;
74   const int max_num_matrix_pixel_deep = max_num_pixel_deep - 2 * border_width;
75   int num_col_per_pixel = 1;
76   int num_row_per_pixel = 1;
77   if (numCol > max_num_matrix_pixel_wide) {
78     num_col_per_pixel = numCol / max_num_matrix_pixel_wide;
79     if (num_col_per_pixel * max_num_matrix_pixel_wide < numCol)
80       num_col_per_pixel++;
81   }
82   if (numRow > max_num_matrix_pixel_deep) {
83     num_row_per_pixel = numRow / max_num_matrix_pixel_deep;
84     if (num_row_per_pixel * max_num_matrix_pixel_deep < numRow)
85       num_row_per_pixel++;
86   }
87   const int dim_per_pixel = std::max(num_col_per_pixel, num_row_per_pixel);
88   int num_pixel_wide = numCol / dim_per_pixel;
89   if (dim_per_pixel * num_pixel_wide < numCol) num_pixel_wide++;
90   int num_pixel_deep = numRow / dim_per_pixel;
91   if (dim_per_pixel * num_pixel_deep < numRow) num_pixel_deep++;
92   // Account for the borders
93   num_pixel_wide += 2;
94   num_pixel_deep += 2;
95   assert(num_pixel_wide <= max_num_pixel_wide);
96   assert(num_pixel_deep <= max_num_pixel_deep);
97 
98   HighsLogMessage(
99       options.logfile, HighsMessageType::INFO,
100       "Representing LP constraint matrix sparsity pattern %dx%d .pbm file,"
101       " mapping entries in square of size %d onto one pixel",
102       num_pixel_wide, num_pixel_deep, dim_per_pixel);
103 
104   std::vector<int> value;
105   value.assign(num_pixel_wide, 0);
106   f << "P1" << std::endl;
107   f << num_pixel_wide << " " << num_pixel_deep << std::endl;
108   int pic_num_row = 0;
109   // Top border
110   for (int pixel = 0; pixel < num_pixel_wide; pixel++) f << "1 ";
111   f << std::endl;
112   pic_num_row++;
113   int from_row = 0;
114   for (;;) {
115     int to_row = std::min(from_row + dim_per_pixel, numRow);
116     for (int iRow = from_row; iRow < to_row; iRow++) {
117       for (int iEl = ARstart[iRow]; iEl < ARstart[iRow + 1]; iEl++) {
118         int iCol = ARindex[iEl];
119         int pixel = iCol / dim_per_pixel;
120         assert(pixel < num_pixel_wide - 2);
121         value[pixel] = 1;
122       }
123     }
124     // LH border
125     f << "1 ";
126     for (int pixel = 0; pixel < num_pixel_wide - 2; pixel++)
127       f << value[pixel] << " ";
128     // LH border
129     f << "1 " << std::endl;
130     pic_num_row++;
131     for (int pixel = 0; pixel < num_pixel_wide - 2; pixel++) value[pixel] = 0;
132     if (to_row == numRow) break;
133     from_row = to_row;
134   }
135 
136   // Bottom border
137   for (int pixel = 0; pixel < num_pixel_wide; pixel++) f << "1 ";
138   f << std::endl;
139   pic_num_row++;
140   assert(pic_num_row == num_pixel_deep);
141 
142   return HighsStatus::OK;
143 }
144