lemongraph 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +8 -0
  3. data/LICENSE +674 -0
  4. data/README.md +6 -0
  5. data/ext/lemon-1.3.1/AUTHORS +26 -0
  6. data/ext/lemon-1.3.1/CMakeLists.txt +371 -0
  7. data/ext/lemon-1.3.1/INSTALL +167 -0
  8. data/ext/lemon-1.3.1/LICENSE +32 -0
  9. data/ext/lemon-1.3.1/NEWS +337 -0
  10. data/ext/lemon-1.3.1/README +50 -0
  11. data/ext/lemon-1.3.1/cmake/FindCOIN.cmake +110 -0
  12. data/ext/lemon-1.3.1/cmake/FindGLPK.cmake +55 -0
  13. data/ext/lemon-1.3.1/cmake/FindGhostscript.cmake +10 -0
  14. data/ext/lemon-1.3.1/cmake/FindILOG.cmake +102 -0
  15. data/ext/lemon-1.3.1/cmake/FindSOPLEX.cmake +23 -0
  16. data/ext/lemon-1.3.1/cmake/LEMONConfig.cmake.in +13 -0
  17. data/ext/lemon-1.3.1/cmake/nsis/lemon.ico +0 -0
  18. data/ext/lemon-1.3.1/cmake/nsis/uninstall.ico +0 -0
  19. data/ext/lemon-1.3.1/cmake/version.cmake +1 -0
  20. data/ext/lemon-1.3.1/cmake/version.cmake.in +1 -0
  21. data/ext/lemon-1.3.1/contrib/CMakeLists.txt +19 -0
  22. data/ext/lemon-1.3.1/lemon/CMakeLists.txt +91 -0
  23. data/ext/lemon-1.3.1/lemon/adaptors.h +3638 -0
  24. data/ext/lemon-1.3.1/lemon/arg_parser.cc +474 -0
  25. data/ext/lemon-1.3.1/lemon/arg_parser.h +440 -0
  26. data/ext/lemon-1.3.1/lemon/assert.h +214 -0
  27. data/ext/lemon-1.3.1/lemon/base.cc +37 -0
  28. data/ext/lemon-1.3.1/lemon/bellman_ford.h +1116 -0
  29. data/ext/lemon-1.3.1/lemon/bfs.h +1754 -0
  30. data/ext/lemon-1.3.1/lemon/bin_heap.h +347 -0
  31. data/ext/lemon-1.3.1/lemon/binomial_heap.h +445 -0
  32. data/ext/lemon-1.3.1/lemon/bits/alteration_notifier.h +472 -0
  33. data/ext/lemon-1.3.1/lemon/bits/array_map.h +351 -0
  34. data/ext/lemon-1.3.1/lemon/bits/bezier.h +174 -0
  35. data/ext/lemon-1.3.1/lemon/bits/default_map.h +182 -0
  36. data/ext/lemon-1.3.1/lemon/bits/edge_set_extender.h +627 -0
  37. data/ext/lemon-1.3.1/lemon/bits/enable_if.h +131 -0
  38. data/ext/lemon-1.3.1/lemon/bits/graph_adaptor_extender.h +401 -0
  39. data/ext/lemon-1.3.1/lemon/bits/graph_extender.h +1332 -0
  40. data/ext/lemon-1.3.1/lemon/bits/lock.h +65 -0
  41. data/ext/lemon-1.3.1/lemon/bits/map_extender.h +332 -0
  42. data/ext/lemon-1.3.1/lemon/bits/path_dump.h +177 -0
  43. data/ext/lemon-1.3.1/lemon/bits/solver_bits.h +194 -0
  44. data/ext/lemon-1.3.1/lemon/bits/traits.h +388 -0
  45. data/ext/lemon-1.3.1/lemon/bits/variant.h +494 -0
  46. data/ext/lemon-1.3.1/lemon/bits/vector_map.h +244 -0
  47. data/ext/lemon-1.3.1/lemon/bits/windows.cc +166 -0
  48. data/ext/lemon-1.3.1/lemon/bits/windows.h +44 -0
  49. data/ext/lemon-1.3.1/lemon/bucket_heap.h +594 -0
  50. data/ext/lemon-1.3.1/lemon/capacity_scaling.h +1014 -0
  51. data/ext/lemon-1.3.1/lemon/cbc.cc +460 -0
  52. data/ext/lemon-1.3.1/lemon/cbc.h +129 -0
  53. data/ext/lemon-1.3.1/lemon/christofides_tsp.h +254 -0
  54. data/ext/lemon-1.3.1/lemon/circulation.h +807 -0
  55. data/ext/lemon-1.3.1/lemon/clp.cc +464 -0
  56. data/ext/lemon-1.3.1/lemon/clp.h +164 -0
  57. data/ext/lemon-1.3.1/lemon/color.cc +44 -0
  58. data/ext/lemon-1.3.1/lemon/color.h +204 -0
  59. data/ext/lemon-1.3.1/lemon/concept_check.h +77 -0
  60. data/ext/lemon-1.3.1/lemon/concepts/bpgraph.h +1029 -0
  61. data/ext/lemon-1.3.1/lemon/concepts/digraph.h +491 -0
  62. data/ext/lemon-1.3.1/lemon/concepts/graph.h +788 -0
  63. data/ext/lemon-1.3.1/lemon/concepts/graph_components.h +2134 -0
  64. data/ext/lemon-1.3.1/lemon/concepts/heap.h +324 -0
  65. data/ext/lemon-1.3.1/lemon/concepts/maps.h +223 -0
  66. data/ext/lemon-1.3.1/lemon/concepts/path.h +312 -0
  67. data/ext/lemon-1.3.1/lemon/config.h.in +22 -0
  68. data/ext/lemon-1.3.1/lemon/connectivity.h +1688 -0
  69. data/ext/lemon-1.3.1/lemon/core.h +2506 -0
  70. data/ext/lemon-1.3.1/lemon/cost_scaling.h +1607 -0
  71. data/ext/lemon-1.3.1/lemon/counter.h +249 -0
  72. data/ext/lemon-1.3.1/lemon/cplex.cc +994 -0
  73. data/ext/lemon-1.3.1/lemon/cplex.h +292 -0
  74. data/ext/lemon-1.3.1/lemon/cycle_canceling.h +1230 -0
  75. data/ext/lemon-1.3.1/lemon/dfs.h +1637 -0
  76. data/ext/lemon-1.3.1/lemon/dheap.h +352 -0
  77. data/ext/lemon-1.3.1/lemon/dijkstra.h +1303 -0
  78. data/ext/lemon-1.3.1/lemon/dim2.h +726 -0
  79. data/ext/lemon-1.3.1/lemon/dimacs.h +448 -0
  80. data/ext/lemon-1.3.1/lemon/edge_set.h +1420 -0
  81. data/ext/lemon-1.3.1/lemon/edmonds_karp.h +556 -0
  82. data/ext/lemon-1.3.1/lemon/elevator.h +982 -0
  83. data/ext/lemon-1.3.1/lemon/error.h +276 -0
  84. data/ext/lemon-1.3.1/lemon/euler.h +287 -0
  85. data/ext/lemon-1.3.1/lemon/fib_heap.h +475 -0
  86. data/ext/lemon-1.3.1/lemon/fractional_matching.h +2139 -0
  87. data/ext/lemon-1.3.1/lemon/full_graph.h +1082 -0
  88. data/ext/lemon-1.3.1/lemon/glpk.cc +1012 -0
  89. data/ext/lemon-1.3.1/lemon/glpk.h +263 -0
  90. data/ext/lemon-1.3.1/lemon/gomory_hu.h +568 -0
  91. data/ext/lemon-1.3.1/lemon/graph_to_eps.h +1186 -0
  92. data/ext/lemon-1.3.1/lemon/greedy_tsp.h +251 -0
  93. data/ext/lemon-1.3.1/lemon/grid_graph.h +699 -0
  94. data/ext/lemon-1.3.1/lemon/grosso_locatelli_pullan_mc.h +840 -0
  95. data/ext/lemon-1.3.1/lemon/hao_orlin.h +1015 -0
  96. data/ext/lemon-1.3.1/lemon/hartmann_orlin_mmc.h +654 -0
  97. data/ext/lemon-1.3.1/lemon/howard_mmc.h +651 -0
  98. data/ext/lemon-1.3.1/lemon/hypercube_graph.h +459 -0
  99. data/ext/lemon-1.3.1/lemon/insertion_tsp.h +533 -0
  100. data/ext/lemon-1.3.1/lemon/karp_mmc.h +590 -0
  101. data/ext/lemon-1.3.1/lemon/kruskal.h +324 -0
  102. data/ext/lemon-1.3.1/lemon/lemon.pc.in +10 -0
  103. data/ext/lemon-1.3.1/lemon/lgf_reader.h +3854 -0
  104. data/ext/lemon-1.3.1/lemon/lgf_writer.h +2687 -0
  105. data/ext/lemon-1.3.1/lemon/list_graph.h +2510 -0
  106. data/ext/lemon-1.3.1/lemon/lp.h +95 -0
  107. data/ext/lemon-1.3.1/lemon/lp_base.cc +30 -0
  108. data/ext/lemon-1.3.1/lemon/lp_base.h +2147 -0
  109. data/ext/lemon-1.3.1/lemon/lp_skeleton.cc +143 -0
  110. data/ext/lemon-1.3.1/lemon/lp_skeleton.h +234 -0
  111. data/ext/lemon-1.3.1/lemon/maps.h +4057 -0
  112. data/ext/lemon-1.3.1/lemon/matching.h +3505 -0
  113. data/ext/lemon-1.3.1/lemon/math.h +77 -0
  114. data/ext/lemon-1.3.1/lemon/max_cardinality_search.h +794 -0
  115. data/ext/lemon-1.3.1/lemon/min_cost_arborescence.h +808 -0
  116. data/ext/lemon-1.3.1/lemon/nagamochi_ibaraki.h +702 -0
  117. data/ext/lemon-1.3.1/lemon/nauty_reader.h +113 -0
  118. data/ext/lemon-1.3.1/lemon/nearest_neighbor_tsp.h +238 -0
  119. data/ext/lemon-1.3.1/lemon/network_simplex.h +1659 -0
  120. data/ext/lemon-1.3.1/lemon/opt2_tsp.h +367 -0
  121. data/ext/lemon-1.3.1/lemon/pairing_heap.h +474 -0
  122. data/ext/lemon-1.3.1/lemon/path.h +1164 -0
  123. data/ext/lemon-1.3.1/lemon/planarity.h +2754 -0
  124. data/ext/lemon-1.3.1/lemon/preflow.h +985 -0
  125. data/ext/lemon-1.3.1/lemon/quad_heap.h +343 -0
  126. data/ext/lemon-1.3.1/lemon/radix_heap.h +438 -0
  127. data/ext/lemon-1.3.1/lemon/radix_sort.h +487 -0
  128. data/ext/lemon-1.3.1/lemon/random.cc +29 -0
  129. data/ext/lemon-1.3.1/lemon/random.h +1005 -0
  130. data/ext/lemon-1.3.1/lemon/smart_graph.h +1344 -0
  131. data/ext/lemon-1.3.1/lemon/soplex.cc +465 -0
  132. data/ext/lemon-1.3.1/lemon/soplex.h +158 -0
  133. data/ext/lemon-1.3.1/lemon/static_graph.h +476 -0
  134. data/ext/lemon-1.3.1/lemon/suurballe.h +776 -0
  135. data/ext/lemon-1.3.1/lemon/time_measure.h +610 -0
  136. data/ext/lemon-1.3.1/lemon/tolerance.h +242 -0
  137. data/ext/lemon-1.3.1/lemon/unionfind.h +1824 -0
  138. data/ext/lemon-1.3.1/scripts/unify-sources.sh +390 -0
  139. data/ext/lemon-1.3.1/scripts/valgrind-wrapper.sh +22 -0
  140. data/ext/lemongraph/arc_map.cc +1007 -0
  141. data/ext/lemongraph/digraph.cc +282 -0
  142. data/ext/lemongraph/digraph_arc.cc +153 -0
  143. data/ext/lemongraph/digraph_node.cc +277 -0
  144. data/ext/lemongraph/edge_map.cc +770 -0
  145. data/ext/lemongraph/extconf.rb +53 -0
  146. data/ext/lemongraph/graph.cc +351 -0
  147. data/ext/lemongraph/graph_arc.cc +95 -0
  148. data/ext/lemongraph/graph_edge.cc +153 -0
  149. data/ext/lemongraph/graph_item.cc +76 -0
  150. data/ext/lemongraph/graph_node.cc +321 -0
  151. data/ext/lemongraph/lemongraph.cc +260 -0
  152. data/ext/lemongraph/lemongraph.hh +295 -0
  153. data/ext/lemongraph/lemongraph.map +6 -0
  154. data/ext/lemongraph/lemongraph_export.hh +31 -0
  155. data/ext/lemongraph/node_map.cc +1011 -0
  156. data/lemongraph.gemspec +176 -0
  157. data/lib/lemongraph/graphviz.rb +240 -0
  158. data/lib/lemongraph/version.rb +4 -0
  159. data/lib/lemongraph.rb +21 -0
  160. data/samples/lemondeps.rb +38 -0
  161. metadata +202 -0
@@ -0,0 +1,994 @@
1
+ /* -*- mode: C++; indent-tabs-mode: nil; -*-
2
+ *
3
+ * This file is a part of LEMON, a generic C++ optimization library.
4
+ *
5
+ * Copyright (C) 2003-2013
6
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
+ *
9
+ * Permission to use, modify and distribute this software is granted
10
+ * provided that this copyright notice appears in all copies. For
11
+ * precise terms see the accompanying LICENSE file.
12
+ *
13
+ * This software is provided "AS IS" with no warranty of any kind,
14
+ * express or implied, and with no claim as to its suitability for any
15
+ * purpose.
16
+ *
17
+ */
18
+
19
+ #include <iostream>
20
+ #include <vector>
21
+ #include <cstring>
22
+
23
+ #include <lemon/cplex.h>
24
+
25
+ extern "C" {
26
+ #include <ilcplex/cplex.h>
27
+ }
28
+
29
+
30
+ ///\file
31
+ ///\brief Implementation of the LEMON-CPLEX lp solver interface.
32
+ namespace lemon {
33
+
34
+ CplexEnv::LicenseError::LicenseError(int status) {
35
+ if (!CPXgeterrorstring(0, status, _message)) {
36
+ std::strcpy(_message, "Cplex unknown error");
37
+ }
38
+ }
39
+
40
+ CplexEnv::CplexEnv() {
41
+ int status;
42
+ _cnt = new int;
43
+ (*_cnt) = 1;
44
+ _env = CPXopenCPLEX(&status);
45
+ if (_env == 0) {
46
+ delete _cnt;
47
+ _cnt = 0;
48
+ throw LicenseError(status);
49
+ }
50
+ }
51
+
52
+ CplexEnv::CplexEnv(const CplexEnv& other) {
53
+ _env = other._env;
54
+ _cnt = other._cnt;
55
+ ++(*_cnt);
56
+ }
57
+
58
+ CplexEnv& CplexEnv::operator=(const CplexEnv& other) {
59
+ _env = other._env;
60
+ _cnt = other._cnt;
61
+ ++(*_cnt);
62
+ return *this;
63
+ }
64
+
65
+ CplexEnv::~CplexEnv() {
66
+ --(*_cnt);
67
+ if (*_cnt == 0) {
68
+ delete _cnt;
69
+ CPXcloseCPLEX(&_env);
70
+ }
71
+ }
72
+
73
+ CplexBase::CplexBase() : LpBase() {
74
+ int status;
75
+ _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
76
+ messageLevel(MESSAGE_NOTHING);
77
+ }
78
+
79
+ CplexBase::CplexBase(const CplexEnv& env)
80
+ : LpBase(), _env(env) {
81
+ int status;
82
+ _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
83
+ messageLevel(MESSAGE_NOTHING);
84
+ }
85
+
86
+ CplexBase::CplexBase(const CplexBase& cplex)
87
+ : LpBase() {
88
+ int status;
89
+ _prob = CPXcloneprob(cplexEnv(), cplex._prob, &status);
90
+ rows = cplex.rows;
91
+ cols = cplex.cols;
92
+ messageLevel(MESSAGE_NOTHING);
93
+ }
94
+
95
+ CplexBase::~CplexBase() {
96
+ CPXfreeprob(cplexEnv(),&_prob);
97
+ }
98
+
99
+ int CplexBase::_addCol() {
100
+ int i = CPXgetnumcols(cplexEnv(), _prob);
101
+ double lb = -INF, ub = INF;
102
+ CPXnewcols(cplexEnv(), _prob, 1, 0, &lb, &ub, 0, 0);
103
+ return i;
104
+ }
105
+
106
+
107
+ int CplexBase::_addRow() {
108
+ int i = CPXgetnumrows(cplexEnv(), _prob);
109
+ const double ub = INF;
110
+ const char s = 'L';
111
+ CPXnewrows(cplexEnv(), _prob, 1, &ub, &s, 0, 0);
112
+ return i;
113
+ }
114
+
115
+ int CplexBase::_addRow(Value lb, ExprIterator b,
116
+ ExprIterator e, Value ub) {
117
+ int i = CPXgetnumrows(cplexEnv(), _prob);
118
+ if (lb == -INF) {
119
+ const char s = 'L';
120
+ CPXnewrows(cplexEnv(), _prob, 1, &ub, &s, 0, 0);
121
+ } else if (ub == INF) {
122
+ const char s = 'G';
123
+ CPXnewrows(cplexEnv(), _prob, 1, &lb, &s, 0, 0);
124
+ } else if (lb == ub){
125
+ const char s = 'E';
126
+ CPXnewrows(cplexEnv(), _prob, 1, &lb, &s, 0, 0);
127
+ } else {
128
+ const char s = 'R';
129
+ double len = ub - lb;
130
+ CPXnewrows(cplexEnv(), _prob, 1, &lb, &s, &len, 0);
131
+ }
132
+
133
+ std::vector<int> indices;
134
+ std::vector<int> rowlist;
135
+ std::vector<Value> values;
136
+
137
+ for(ExprIterator it=b; it!=e; ++it) {
138
+ indices.push_back(it->first);
139
+ values.push_back(it->second);
140
+ rowlist.push_back(i);
141
+ }
142
+
143
+ CPXchgcoeflist(cplexEnv(), _prob, values.size(),
144
+ &rowlist.front(), &indices.front(), &values.front());
145
+
146
+ return i;
147
+ }
148
+
149
+ void CplexBase::_eraseCol(int i) {
150
+ CPXdelcols(cplexEnv(), _prob, i, i);
151
+ }
152
+
153
+ void CplexBase::_eraseRow(int i) {
154
+ CPXdelrows(cplexEnv(), _prob, i, i);
155
+ }
156
+
157
+ void CplexBase::_eraseColId(int i) {
158
+ cols.eraseIndex(i);
159
+ cols.shiftIndices(i);
160
+ }
161
+ void CplexBase::_eraseRowId(int i) {
162
+ rows.eraseIndex(i);
163
+ rows.shiftIndices(i);
164
+ }
165
+
166
+ void CplexBase::_getColName(int col, std::string &name) const {
167
+ int size;
168
+ CPXgetcolname(cplexEnv(), _prob, 0, 0, 0, &size, col, col);
169
+ if (size == 0) {
170
+ name.clear();
171
+ return;
172
+ }
173
+
174
+ size *= -1;
175
+ std::vector<char> buf(size);
176
+ char *cname;
177
+ int tmp;
178
+ CPXgetcolname(cplexEnv(), _prob, &cname, &buf.front(), size,
179
+ &tmp, col, col);
180
+ name = cname;
181
+ }
182
+
183
+ void CplexBase::_setColName(int col, const std::string &name) {
184
+ char *cname;
185
+ cname = const_cast<char*>(name.c_str());
186
+ CPXchgcolname(cplexEnv(), _prob, 1, &col, &cname);
187
+ }
188
+
189
+ int CplexBase::_colByName(const std::string& name) const {
190
+ int index;
191
+ if (CPXgetcolindex(cplexEnv(), _prob,
192
+ const_cast<char*>(name.c_str()), &index) == 0) {
193
+ return index;
194
+ }
195
+ return -1;
196
+ }
197
+
198
+ void CplexBase::_getRowName(int row, std::string &name) const {
199
+ int size;
200
+ CPXgetrowname(cplexEnv(), _prob, 0, 0, 0, &size, row, row);
201
+ if (size == 0) {
202
+ name.clear();
203
+ return;
204
+ }
205
+
206
+ size *= -1;
207
+ std::vector<char> buf(size);
208
+ char *cname;
209
+ int tmp;
210
+ CPXgetrowname(cplexEnv(), _prob, &cname, &buf.front(), size,
211
+ &tmp, row, row);
212
+ name = cname;
213
+ }
214
+
215
+ void CplexBase::_setRowName(int row, const std::string &name) {
216
+ char *cname;
217
+ cname = const_cast<char*>(name.c_str());
218
+ CPXchgrowname(cplexEnv(), _prob, 1, &row, &cname);
219
+ }
220
+
221
+ int CplexBase::_rowByName(const std::string& name) const {
222
+ int index;
223
+ if (CPXgetrowindex(cplexEnv(), _prob,
224
+ const_cast<char*>(name.c_str()), &index) == 0) {
225
+ return index;
226
+ }
227
+ return -1;
228
+ }
229
+
230
+ void CplexBase::_setRowCoeffs(int i, ExprIterator b,
231
+ ExprIterator e)
232
+ {
233
+ std::vector<int> indices;
234
+ std::vector<int> rowlist;
235
+ std::vector<Value> values;
236
+
237
+ for(ExprIterator it=b; it!=e; ++it) {
238
+ indices.push_back(it->first);
239
+ values.push_back(it->second);
240
+ rowlist.push_back(i);
241
+ }
242
+
243
+ CPXchgcoeflist(cplexEnv(), _prob, values.size(),
244
+ &rowlist.front(), &indices.front(), &values.front());
245
+ }
246
+
247
+ void CplexBase::_getRowCoeffs(int i, InsertIterator b) const {
248
+ int tmp1, tmp2, tmp3, length;
249
+ CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
250
+
251
+ length = -length;
252
+ std::vector<int> indices(length);
253
+ std::vector<double> values(length);
254
+
255
+ CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2,
256
+ &indices.front(), &values.front(),
257
+ length, &tmp3, i, i);
258
+
259
+ for (int i = 0; i < length; ++i) {
260
+ *b = std::make_pair(indices[i], values[i]);
261
+ ++b;
262
+ }
263
+ }
264
+
265
+ void CplexBase::_setColCoeffs(int i, ExprIterator b, ExprIterator e) {
266
+ std::vector<int> indices;
267
+ std::vector<int> collist;
268
+ std::vector<Value> values;
269
+
270
+ for(ExprIterator it=b; it!=e; ++it) {
271
+ indices.push_back(it->first);
272
+ values.push_back(it->second);
273
+ collist.push_back(i);
274
+ }
275
+
276
+ CPXchgcoeflist(cplexEnv(), _prob, values.size(),
277
+ &indices.front(), &collist.front(), &values.front());
278
+ }
279
+
280
+ void CplexBase::_getColCoeffs(int i, InsertIterator b) const {
281
+
282
+ int tmp1, tmp2, tmp3, length;
283
+ CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
284
+
285
+ length = -length;
286
+ std::vector<int> indices(length);
287
+ std::vector<double> values(length);
288
+
289
+ CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2,
290
+ &indices.front(), &values.front(),
291
+ length, &tmp3, i, i);
292
+
293
+ for (int i = 0; i < length; ++i) {
294
+ *b = std::make_pair(indices[i], values[i]);
295
+ ++b;
296
+ }
297
+
298
+ }
299
+
300
+ void CplexBase::_setCoeff(int row, int col, Value value) {
301
+ CPXchgcoef(cplexEnv(), _prob, row, col, value);
302
+ }
303
+
304
+ CplexBase::Value CplexBase::_getCoeff(int row, int col) const {
305
+ CplexBase::Value value;
306
+ CPXgetcoef(cplexEnv(), _prob, row, col, &value);
307
+ return value;
308
+ }
309
+
310
+ void CplexBase::_setColLowerBound(int i, Value value) {
311
+ const char s = 'L';
312
+ CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
313
+ }
314
+
315
+ CplexBase::Value CplexBase::_getColLowerBound(int i) const {
316
+ CplexBase::Value res;
317
+ CPXgetlb(cplexEnv(), _prob, &res, i, i);
318
+ return res <= -CPX_INFBOUND ? -INF : res;
319
+ }
320
+
321
+ void CplexBase::_setColUpperBound(int i, Value value)
322
+ {
323
+ const char s = 'U';
324
+ CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
325
+ }
326
+
327
+ CplexBase::Value CplexBase::_getColUpperBound(int i) const {
328
+ CplexBase::Value res;
329
+ CPXgetub(cplexEnv(), _prob, &res, i, i);
330
+ return res >= CPX_INFBOUND ? INF : res;
331
+ }
332
+
333
+ CplexBase::Value CplexBase::_getRowLowerBound(int i) const {
334
+ char s;
335
+ CPXgetsense(cplexEnv(), _prob, &s, i, i);
336
+ CplexBase::Value res;
337
+
338
+ switch (s) {
339
+ case 'G':
340
+ case 'R':
341
+ case 'E':
342
+ CPXgetrhs(cplexEnv(), _prob, &res, i, i);
343
+ return res <= -CPX_INFBOUND ? -INF : res;
344
+ default:
345
+ return -INF;
346
+ }
347
+ }
348
+
349
+ CplexBase::Value CplexBase::_getRowUpperBound(int i) const {
350
+ char s;
351
+ CPXgetsense(cplexEnv(), _prob, &s, i, i);
352
+ CplexBase::Value res;
353
+
354
+ switch (s) {
355
+ case 'L':
356
+ case 'E':
357
+ CPXgetrhs(cplexEnv(), _prob, &res, i, i);
358
+ return res >= CPX_INFBOUND ? INF : res;
359
+ case 'R':
360
+ CPXgetrhs(cplexEnv(), _prob, &res, i, i);
361
+ {
362
+ double rng;
363
+ CPXgetrngval(cplexEnv(), _prob, &rng, i, i);
364
+ res += rng;
365
+ }
366
+ return res >= CPX_INFBOUND ? INF : res;
367
+ default:
368
+ return INF;
369
+ }
370
+ }
371
+
372
+ //This is easier to implement
373
+ void CplexBase::_set_row_bounds(int i, Value lb, Value ub) {
374
+ if (lb == -INF) {
375
+ const char s = 'L';
376
+ CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
377
+ CPXchgrhs(cplexEnv(), _prob, 1, &i, &ub);
378
+ } else if (ub == INF) {
379
+ const char s = 'G';
380
+ CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
381
+ CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
382
+ } else if (lb == ub){
383
+ const char s = 'E';
384
+ CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
385
+ CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
386
+ } else {
387
+ const char s = 'R';
388
+ CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
389
+ CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
390
+ double len = ub - lb;
391
+ CPXchgrngval(cplexEnv(), _prob, 1, &i, &len);
392
+ }
393
+ }
394
+
395
+ void CplexBase::_setRowLowerBound(int i, Value lb)
396
+ {
397
+ LEMON_ASSERT(lb != INF, "Invalid bound");
398
+ _set_row_bounds(i, lb, CplexBase::_getRowUpperBound(i));
399
+ }
400
+
401
+ void CplexBase::_setRowUpperBound(int i, Value ub)
402
+ {
403
+
404
+ LEMON_ASSERT(ub != -INF, "Invalid bound");
405
+ _set_row_bounds(i, CplexBase::_getRowLowerBound(i), ub);
406
+ }
407
+
408
+ void CplexBase::_setObjCoeffs(ExprIterator b, ExprIterator e)
409
+ {
410
+ std::vector<int> indices;
411
+ std::vector<Value> values;
412
+ for(ExprIterator it=b; it!=e; ++it) {
413
+ indices.push_back(it->first);
414
+ values.push_back(it->second);
415
+ }
416
+ CPXchgobj(cplexEnv(), _prob, values.size(),
417
+ &indices.front(), &values.front());
418
+
419
+ }
420
+
421
+ void CplexBase::_getObjCoeffs(InsertIterator b) const
422
+ {
423
+ int num = CPXgetnumcols(cplexEnv(), _prob);
424
+ std::vector<Value> x(num);
425
+
426
+ CPXgetobj(cplexEnv(), _prob, &x.front(), 0, num - 1);
427
+ for (int i = 0; i < num; ++i) {
428
+ if (x[i] != 0.0) {
429
+ *b = std::make_pair(i, x[i]);
430
+ ++b;
431
+ }
432
+ }
433
+ }
434
+
435
+ void CplexBase::_setObjCoeff(int i, Value obj_coef)
436
+ {
437
+ CPXchgobj(cplexEnv(), _prob, 1, &i, &obj_coef);
438
+ }
439
+
440
+ CplexBase::Value CplexBase::_getObjCoeff(int i) const
441
+ {
442
+ Value x;
443
+ CPXgetobj(cplexEnv(), _prob, &x, i, i);
444
+ return x;
445
+ }
446
+
447
+ void CplexBase::_setSense(CplexBase::Sense sense) {
448
+ switch (sense) {
449
+ case MIN:
450
+ CPXchgobjsen(cplexEnv(), _prob, CPX_MIN);
451
+ break;
452
+ case MAX:
453
+ CPXchgobjsen(cplexEnv(), _prob, CPX_MAX);
454
+ break;
455
+ }
456
+ }
457
+
458
+ CplexBase::Sense CplexBase::_getSense() const {
459
+ switch (CPXgetobjsen(cplexEnv(), _prob)) {
460
+ case CPX_MIN:
461
+ return MIN;
462
+ case CPX_MAX:
463
+ return MAX;
464
+ default:
465
+ LEMON_ASSERT(false, "Invalid sense");
466
+ return CplexBase::Sense();
467
+ }
468
+ }
469
+
470
+ void CplexBase::_clear() {
471
+ CPXfreeprob(cplexEnv(),&_prob);
472
+ int status;
473
+ _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
474
+ }
475
+
476
+ void CplexBase::_messageLevel(MessageLevel level) {
477
+ switch (level) {
478
+ case MESSAGE_NOTHING:
479
+ _message_enabled = false;
480
+ break;
481
+ case MESSAGE_ERROR:
482
+ case MESSAGE_WARNING:
483
+ case MESSAGE_NORMAL:
484
+ case MESSAGE_VERBOSE:
485
+ _message_enabled = true;
486
+ break;
487
+ }
488
+ }
489
+
490
+ void CplexBase::_applyMessageLevel() {
491
+ CPXsetintparam(cplexEnv(), CPX_PARAM_SCRIND,
492
+ _message_enabled ? CPX_ON : CPX_OFF);
493
+ }
494
+
495
+ void CplexBase::_write(std::string file, std::string format) const
496
+ {
497
+ if(format == "MPS" || format == "LP")
498
+ CPXwriteprob(cplexEnv(), cplexLp(), file.c_str(), format.c_str());
499
+ else if(format == "SOL")
500
+ CPXsolwrite(cplexEnv(), cplexLp(), file.c_str());
501
+ else throw UnsupportedFormatError(format);
502
+ }
503
+
504
+
505
+
506
+ // CplexLp members
507
+
508
+ CplexLp::CplexLp()
509
+ : LpBase(), LpSolver(), CplexBase() {}
510
+
511
+ CplexLp::CplexLp(const CplexEnv& env)
512
+ : LpBase(), LpSolver(), CplexBase(env) {}
513
+
514
+ CplexLp::CplexLp(const CplexLp& other)
515
+ : LpBase(), LpSolver(), CplexBase(other) {}
516
+
517
+ CplexLp::~CplexLp() {}
518
+
519
+ CplexLp* CplexLp::newSolver() const { return new CplexLp; }
520
+ CplexLp* CplexLp::cloneSolver() const {return new CplexLp(*this); }
521
+
522
+ const char* CplexLp::_solverName() const { return "CplexLp"; }
523
+
524
+ void CplexLp::_clear_temporals() {
525
+ _col_status.clear();
526
+ _row_status.clear();
527
+ _primal_ray.clear();
528
+ _dual_ray.clear();
529
+ }
530
+
531
+ // The routine returns zero unless an error occurred during the
532
+ // optimization. Examples of errors include exhausting available
533
+ // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
534
+ // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
535
+ // user-specified CPLEX limit, or proving the model infeasible or
536
+ // unbounded, are not considered errors. Note that a zero return
537
+ // value does not necessarily mean that a solution exists. Use query
538
+ // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
539
+ // further information about the status of the optimization.
540
+ CplexLp::SolveExitStatus CplexLp::convertStatus(int status) {
541
+ #if CPX_VERSION >= 800
542
+ if (status == 0) {
543
+ switch (CPXgetstat(cplexEnv(), _prob)) {
544
+ case CPX_STAT_OPTIMAL:
545
+ case CPX_STAT_INFEASIBLE:
546
+ case CPX_STAT_UNBOUNDED:
547
+ return SOLVED;
548
+ default:
549
+ return UNSOLVED;
550
+ }
551
+ } else {
552
+ return UNSOLVED;
553
+ }
554
+ #else
555
+ if (status == 0) {
556
+ //We want to exclude some cases
557
+ switch (CPXgetstat(cplexEnv(), _prob)) {
558
+ case CPX_OBJ_LIM:
559
+ case CPX_IT_LIM_FEAS:
560
+ case CPX_IT_LIM_INFEAS:
561
+ case CPX_TIME_LIM_FEAS:
562
+ case CPX_TIME_LIM_INFEAS:
563
+ return UNSOLVED;
564
+ default:
565
+ return SOLVED;
566
+ }
567
+ } else {
568
+ return UNSOLVED;
569
+ }
570
+ #endif
571
+ }
572
+
573
+ CplexLp::SolveExitStatus CplexLp::_solve() {
574
+ _clear_temporals();
575
+ _applyMessageLevel();
576
+ return convertStatus(CPXlpopt(cplexEnv(), _prob));
577
+ }
578
+
579
+ CplexLp::SolveExitStatus CplexLp::solvePrimal() {
580
+ _clear_temporals();
581
+ _applyMessageLevel();
582
+ return convertStatus(CPXprimopt(cplexEnv(), _prob));
583
+ }
584
+
585
+ CplexLp::SolveExitStatus CplexLp::solveDual() {
586
+ _clear_temporals();
587
+ _applyMessageLevel();
588
+ return convertStatus(CPXdualopt(cplexEnv(), _prob));
589
+ }
590
+
591
+ CplexLp::SolveExitStatus CplexLp::solveBarrier() {
592
+ _clear_temporals();
593
+ _applyMessageLevel();
594
+ return convertStatus(CPXbaropt(cplexEnv(), _prob));
595
+ }
596
+
597
+ CplexLp::Value CplexLp::_getPrimal(int i) const {
598
+ Value x;
599
+ CPXgetx(cplexEnv(), _prob, &x, i, i);
600
+ return x;
601
+ }
602
+
603
+ CplexLp::Value CplexLp::_getDual(int i) const {
604
+ Value y;
605
+ CPXgetpi(cplexEnv(), _prob, &y, i, i);
606
+ return y;
607
+ }
608
+
609
+ CplexLp::Value CplexLp::_getPrimalValue() const {
610
+ Value objval;
611
+ CPXgetobjval(cplexEnv(), _prob, &objval);
612
+ return objval;
613
+ }
614
+
615
+ CplexLp::VarStatus CplexLp::_getColStatus(int i) const {
616
+ if (_col_status.empty()) {
617
+ _col_status.resize(CPXgetnumcols(cplexEnv(), _prob));
618
+ CPXgetbase(cplexEnv(), _prob, &_col_status.front(), 0);
619
+ }
620
+ switch (_col_status[i]) {
621
+ case CPX_BASIC:
622
+ return BASIC;
623
+ case CPX_FREE_SUPER:
624
+ return FREE;
625
+ case CPX_AT_LOWER:
626
+ return LOWER;
627
+ case CPX_AT_UPPER:
628
+ return UPPER;
629
+ default:
630
+ LEMON_ASSERT(false, "Wrong column status");
631
+ return CplexLp::VarStatus();
632
+ }
633
+ }
634
+
635
+ CplexLp::VarStatus CplexLp::_getRowStatus(int i) const {
636
+ if (_row_status.empty()) {
637
+ _row_status.resize(CPXgetnumrows(cplexEnv(), _prob));
638
+ CPXgetbase(cplexEnv(), _prob, 0, &_row_status.front());
639
+ }
640
+ switch (_row_status[i]) {
641
+ case CPX_BASIC:
642
+ return BASIC;
643
+ case CPX_AT_LOWER:
644
+ {
645
+ char s;
646
+ CPXgetsense(cplexEnv(), _prob, &s, i, i);
647
+ return s != 'L' ? LOWER : UPPER;
648
+ }
649
+ case CPX_AT_UPPER:
650
+ return UPPER;
651
+ default:
652
+ LEMON_ASSERT(false, "Wrong row status");
653
+ return CplexLp::VarStatus();
654
+ }
655
+ }
656
+
657
+ CplexLp::Value CplexLp::_getPrimalRay(int i) const {
658
+ if (_primal_ray.empty()) {
659
+ _primal_ray.resize(CPXgetnumcols(cplexEnv(), _prob));
660
+ CPXgetray(cplexEnv(), _prob, &_primal_ray.front());
661
+ }
662
+ return _primal_ray[i];
663
+ }
664
+
665
+ CplexLp::Value CplexLp::_getDualRay(int i) const {
666
+ if (_dual_ray.empty()) {
667
+
668
+ }
669
+ return _dual_ray[i];
670
+ }
671
+
672
+ // Cplex 7.0 status values
673
+ // This table lists the statuses, returned by the CPXgetstat()
674
+ // routine, for solutions to LP problems or mixed integer problems. If
675
+ // no solution exists, the return value is zero.
676
+
677
+ // For Simplex, Barrier
678
+ // 1 CPX_OPTIMAL
679
+ // Optimal solution found
680
+ // 2 CPX_INFEASIBLE
681
+ // Problem infeasible
682
+ // 3 CPX_UNBOUNDED
683
+ // Problem unbounded
684
+ // 4 CPX_OBJ_LIM
685
+ // Objective limit exceeded in Phase II
686
+ // 5 CPX_IT_LIM_FEAS
687
+ // Iteration limit exceeded in Phase II
688
+ // 6 CPX_IT_LIM_INFEAS
689
+ // Iteration limit exceeded in Phase I
690
+ // 7 CPX_TIME_LIM_FEAS
691
+ // Time limit exceeded in Phase II
692
+ // 8 CPX_TIME_LIM_INFEAS
693
+ // Time limit exceeded in Phase I
694
+ // 9 CPX_NUM_BEST_FEAS
695
+ // Problem non-optimal, singularities in Phase II
696
+ // 10 CPX_NUM_BEST_INFEAS
697
+ // Problem non-optimal, singularities in Phase I
698
+ // 11 CPX_OPTIMAL_INFEAS
699
+ // Optimal solution found, unscaled infeasibilities
700
+ // 12 CPX_ABORT_FEAS
701
+ // Aborted in Phase II
702
+ // 13 CPX_ABORT_INFEAS
703
+ // Aborted in Phase I
704
+ // 14 CPX_ABORT_DUAL_INFEAS
705
+ // Aborted in barrier, dual infeasible
706
+ // 15 CPX_ABORT_PRIM_INFEAS
707
+ // Aborted in barrier, primal infeasible
708
+ // 16 CPX_ABORT_PRIM_DUAL_INFEAS
709
+ // Aborted in barrier, primal and dual infeasible
710
+ // 17 CPX_ABORT_PRIM_DUAL_FEAS
711
+ // Aborted in barrier, primal and dual feasible
712
+ // 18 CPX_ABORT_CROSSOVER
713
+ // Aborted in crossover
714
+ // 19 CPX_INForUNBD
715
+ // Infeasible or unbounded
716
+ // 20 CPX_PIVOT
717
+ // User pivot used
718
+ //
719
+ // Pending return values
720
+ // ??case CPX_ABORT_DUAL_INFEAS
721
+ // ??case CPX_ABORT_CROSSOVER
722
+ // ??case CPX_INForUNBD
723
+ // ??case CPX_PIVOT
724
+
725
+ //Some more interesting stuff:
726
+
727
+ // CPX_PARAM_PROBMETHOD 1062 int LPMETHOD
728
+ // 0 Automatic
729
+ // 1 Primal Simplex
730
+ // 2 Dual Simplex
731
+ // 3 Network Simplex
732
+ // 4 Standard Barrier
733
+ // Default: 0
734
+ // Description: Method for linear optimization.
735
+ // Determines which algorithm is used when CPXlpopt() (or "optimize"
736
+ // in the Interactive Optimizer) is called. Currently the behavior of
737
+ // the "Automatic" setting is that CPLEX simply invokes the dual
738
+ // simplex method, but this capability may be expanded in the future
739
+ // so that CPLEX chooses the method based on problem characteristics
740
+ #if CPX_VERSION < 900
741
+ void statusSwitch(CPXENVptr cplexEnv(),int& stat){
742
+ int lpmethod;
743
+ CPXgetintparam (cplexEnv(),CPX_PARAM_PROBMETHOD,&lpmethod);
744
+ if (lpmethod==2){
745
+ if (stat==CPX_UNBOUNDED){
746
+ stat=CPX_INFEASIBLE;
747
+ }
748
+ else{
749
+ if (stat==CPX_INFEASIBLE)
750
+ stat=CPX_UNBOUNDED;
751
+ }
752
+ }
753
+ }
754
+ #else
755
+ void statusSwitch(CPXENVptr,int&){}
756
+ #endif
757
+
758
+ CplexLp::ProblemType CplexLp::_getPrimalType() const {
759
+ // Unboundedness not treated well: the following is from cplex 9.0 doc
760
+ // About Unboundedness
761
+
762
+ // The treatment of models that are unbounded involves a few
763
+ // subtleties. Specifically, a declaration of unboundedness means that
764
+ // ILOG CPLEX has determined that the model has an unbounded
765
+ // ray. Given any feasible solution x with objective z, a multiple of
766
+ // the unbounded ray can be added to x to give a feasible solution
767
+ // with objective z-1 (or z+1 for maximization models). Thus, if a
768
+ // feasible solution exists, then the optimal objective is
769
+ // unbounded. Note that ILOG CPLEX has not necessarily concluded that
770
+ // a feasible solution exists. Users can call the routine CPXsolninfo
771
+ // to determine whether ILOG CPLEX has also concluded that the model
772
+ // has a feasible solution.
773
+
774
+ int stat = CPXgetstat(cplexEnv(), _prob);
775
+ #if CPX_VERSION >= 800
776
+ switch (stat)
777
+ {
778
+ case CPX_STAT_OPTIMAL:
779
+ return OPTIMAL;
780
+ case CPX_STAT_UNBOUNDED:
781
+ return UNBOUNDED;
782
+ case CPX_STAT_INFEASIBLE:
783
+ return INFEASIBLE;
784
+ default:
785
+ return UNDEFINED;
786
+ }
787
+ #else
788
+ statusSwitch(cplexEnv(),stat);
789
+ //CPXgetstat(cplexEnv(), _prob);
790
+ switch (stat) {
791
+ case 0:
792
+ return UNDEFINED; //Undefined
793
+ case CPX_OPTIMAL://Optimal
794
+ return OPTIMAL;
795
+ case CPX_UNBOUNDED://Unbounded
796
+ return INFEASIBLE;//In case of dual simplex
797
+ //return UNBOUNDED;
798
+ case CPX_INFEASIBLE://Infeasible
799
+ // case CPX_IT_LIM_INFEAS:
800
+ // case CPX_TIME_LIM_INFEAS:
801
+ // case CPX_NUM_BEST_INFEAS:
802
+ // case CPX_OPTIMAL_INFEAS:
803
+ // case CPX_ABORT_INFEAS:
804
+ // case CPX_ABORT_PRIM_INFEAS:
805
+ // case CPX_ABORT_PRIM_DUAL_INFEAS:
806
+ return UNBOUNDED;//In case of dual simplex
807
+ //return INFEASIBLE;
808
+ // case CPX_OBJ_LIM:
809
+ // case CPX_IT_LIM_FEAS:
810
+ // case CPX_TIME_LIM_FEAS:
811
+ // case CPX_NUM_BEST_FEAS:
812
+ // case CPX_ABORT_FEAS:
813
+ // case CPX_ABORT_PRIM_DUAL_FEAS:
814
+ // return FEASIBLE;
815
+ default:
816
+ return UNDEFINED; //Everything else comes here
817
+ //FIXME error
818
+ }
819
+ #endif
820
+ }
821
+
822
+ // Cplex 9.0 status values
823
+ // CPX_STAT_ABORT_DUAL_OBJ_LIM
824
+ // CPX_STAT_ABORT_IT_LIM
825
+ // CPX_STAT_ABORT_OBJ_LIM
826
+ // CPX_STAT_ABORT_PRIM_OBJ_LIM
827
+ // CPX_STAT_ABORT_TIME_LIM
828
+ // CPX_STAT_ABORT_USER
829
+ // CPX_STAT_FEASIBLE_RELAXED
830
+ // CPX_STAT_INFEASIBLE
831
+ // CPX_STAT_INForUNBD
832
+ // CPX_STAT_NUM_BEST
833
+ // CPX_STAT_OPTIMAL
834
+ // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
835
+ // CPX_STAT_OPTIMAL_INFEAS
836
+ // CPX_STAT_OPTIMAL_RELAXED
837
+ // CPX_STAT_UNBOUNDED
838
+
839
+ CplexLp::ProblemType CplexLp::_getDualType() const {
840
+ int stat = CPXgetstat(cplexEnv(), _prob);
841
+ #if CPX_VERSION >= 800
842
+ switch (stat) {
843
+ case CPX_STAT_OPTIMAL:
844
+ return OPTIMAL;
845
+ case CPX_STAT_UNBOUNDED:
846
+ return INFEASIBLE;
847
+ default:
848
+ return UNDEFINED;
849
+ }
850
+ #else
851
+ statusSwitch(cplexEnv(),stat);
852
+ switch (stat) {
853
+ case 0:
854
+ return UNDEFINED; //Undefined
855
+ case CPX_OPTIMAL://Optimal
856
+ return OPTIMAL;
857
+ case CPX_UNBOUNDED:
858
+ return INFEASIBLE;
859
+ default:
860
+ return UNDEFINED; //Everything else comes here
861
+ //FIXME error
862
+ }
863
+ #endif
864
+ }
865
+
866
+ // CplexMip members
867
+
868
+ CplexMip::CplexMip()
869
+ : LpBase(), MipSolver(), CplexBase() {
870
+
871
+ #if CPX_VERSION < 800
872
+ CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MIP);
873
+ #else
874
+ CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MILP);
875
+ #endif
876
+ }
877
+
878
+ CplexMip::CplexMip(const CplexEnv& env)
879
+ : LpBase(), MipSolver(), CplexBase(env) {
880
+
881
+ #if CPX_VERSION < 800
882
+ CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MIP);
883
+ #else
884
+ CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MILP);
885
+ #endif
886
+
887
+ }
888
+
889
+ CplexMip::CplexMip(const CplexMip& other)
890
+ : LpBase(), MipSolver(), CplexBase(other) {}
891
+
892
+ CplexMip::~CplexMip() {}
893
+
894
+ CplexMip* CplexMip::newSolver() const { return new CplexMip; }
895
+ CplexMip* CplexMip::cloneSolver() const {return new CplexMip(*this); }
896
+
897
+ const char* CplexMip::_solverName() const { return "CplexMip"; }
898
+
899
+ void CplexMip::_setColType(int i, CplexMip::ColTypes col_type) {
900
+
901
+ // Note If a variable is to be changed to binary, a call to CPXchgbds
902
+ // should also be made to change the bounds to 0 and 1.
903
+
904
+ switch (col_type){
905
+ case INTEGER: {
906
+ const char t = 'I';
907
+ CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
908
+ } break;
909
+ case REAL: {
910
+ const char t = 'C';
911
+ CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
912
+ } break;
913
+ default:
914
+ break;
915
+ }
916
+ }
917
+
918
+ CplexMip::ColTypes CplexMip::_getColType(int i) const {
919
+ char t;
920
+ CPXgetctype (cplexEnv(), _prob, &t, i, i);
921
+ switch (t) {
922
+ case 'I':
923
+ return INTEGER;
924
+ case 'C':
925
+ return REAL;
926
+ default:
927
+ LEMON_ASSERT(false, "Invalid column type");
928
+ return ColTypes();
929
+ }
930
+
931
+ }
932
+
933
+ CplexMip::SolveExitStatus CplexMip::_solve() {
934
+ int status;
935
+ _applyMessageLevel();
936
+ status = CPXmipopt (cplexEnv(), _prob);
937
+ if (status==0)
938
+ return SOLVED;
939
+ else
940
+ return UNSOLVED;
941
+
942
+ }
943
+
944
+
945
+ CplexMip::ProblemType CplexMip::_getType() const {
946
+
947
+ int stat = CPXgetstat(cplexEnv(), _prob);
948
+
949
+ //Fortunately, MIP statuses did not change for cplex 8.0
950
+ switch (stat) {
951
+ case CPXMIP_OPTIMAL:
952
+ // Optimal integer solution has been found.
953
+ case CPXMIP_OPTIMAL_TOL:
954
+ // Optimal soluton with the tolerance defined by epgap or epagap has
955
+ // been found.
956
+ return OPTIMAL;
957
+ //This also exists in later issues
958
+ // case CPXMIP_UNBOUNDED:
959
+ //return UNBOUNDED;
960
+ case CPXMIP_INFEASIBLE:
961
+ return INFEASIBLE;
962
+ default:
963
+ return UNDEFINED;
964
+ }
965
+ //Unboundedness not treated well: the following is from cplex 9.0 doc
966
+ // About Unboundedness
967
+
968
+ // The treatment of models that are unbounded involves a few
969
+ // subtleties. Specifically, a declaration of unboundedness means that
970
+ // ILOG CPLEX has determined that the model has an unbounded
971
+ // ray. Given any feasible solution x with objective z, a multiple of
972
+ // the unbounded ray can be added to x to give a feasible solution
973
+ // with objective z-1 (or z+1 for maximization models). Thus, if a
974
+ // feasible solution exists, then the optimal objective is
975
+ // unbounded. Note that ILOG CPLEX has not necessarily concluded that
976
+ // a feasible solution exists. Users can call the routine CPXsolninfo
977
+ // to determine whether ILOG CPLEX has also concluded that the model
978
+ // has a feasible solution.
979
+ }
980
+
981
+ CplexMip::Value CplexMip::_getSol(int i) const {
982
+ Value x;
983
+ CPXgetmipx(cplexEnv(), _prob, &x, i, i);
984
+ return x;
985
+ }
986
+
987
+ CplexMip::Value CplexMip::_getSolValue() const {
988
+ Value objval;
989
+ CPXgetmipobjval(cplexEnv(), _prob, &objval);
990
+ return objval;
991
+ }
992
+
993
+ } //namespace lemon
994
+