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