lpsolve 5.5.10.i

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.
@@ -0,0 +1,187 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ #### Start of system configuration section. ####
5
+
6
+ srcdir = .
7
+ topdir = /usr/local/include/ruby-1.9.1
8
+ hdrdir = /usr/local/include/ruby-1.9.1
9
+ arch_hdrdir = /usr/local/include/ruby-1.9.1/$(arch)
10
+ VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby
11
+ prefix = $(DESTDIR)/usr/local
12
+ rubylibprefix = $(libdir)/$(RUBY_BASE_NAME)
13
+ exec_prefix = $(prefix)
14
+ vendorhdrdir = $(rubyhdrdir)/vendor_ruby
15
+ sitehdrdir = $(rubyhdrdir)/site_ruby
16
+ rubyhdrdir = $(includedir)/$(RUBY_BASE_NAME)-$(ruby_version)
17
+ vendordir = $(rubylibprefix)/vendor_ruby
18
+ sitedir = $(rubylibprefix)/site_ruby
19
+ ridir = $(datarootdir)/$(RI_BASE_NAME)
20
+ mandir = $(datarootdir)/man
21
+ localedir = $(datarootdir)/locale
22
+ libdir = $(exec_prefix)/lib
23
+ psdir = $(docdir)
24
+ pdfdir = $(docdir)
25
+ dvidir = $(docdir)
26
+ htmldir = $(docdir)
27
+ infodir = $(datarootdir)/info
28
+ docdir = $(datarootdir)/doc/$(PACKAGE)
29
+ oldincludedir = $(DESTDIR)/usr/include
30
+ includedir = $(prefix)/include
31
+ localstatedir = $(prefix)/var
32
+ sharedstatedir = $(prefix)/com
33
+ sysconfdir = $(prefix)/etc
34
+ datadir = $(datarootdir)
35
+ datarootdir = $(prefix)/share
36
+ libexecdir = $(exec_prefix)/libexec
37
+ sbindir = $(exec_prefix)/sbin
38
+ bindir = $(exec_prefix)/bin
39
+ rubylibdir = $(rubylibprefix)/$(ruby_version)
40
+ archdir = $(rubylibdir)/$(arch)
41
+ sitelibdir = $(sitedir)/$(ruby_version)
42
+ sitearchdir = $(sitelibdir)/$(sitearch)
43
+ vendorlibdir = $(vendordir)/$(ruby_version)
44
+ vendorarchdir = $(vendorlibdir)/$(sitearch)
45
+
46
+ CC = gcc
47
+ CXX = g++
48
+ LIBRUBY = $(LIBRUBY_A)
49
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
50
+ LIBRUBYARG_SHARED = -Wl,-R -Wl,$(libdir) -L$(libdir) -l$(RUBY_SO_NAME)
51
+ LIBRUBYARG_STATIC = -Wl,-R -Wl,$(libdir) -L$(libdir) -l$(RUBY_SO_NAME)-static
52
+ OUTFLAG = -o
53
+ COUTFLAG = -o
54
+
55
+ RUBY_EXTCONF_H =
56
+ cflags = $(optflags) $(debugflags) $(warnflags)
57
+ optflags = -O3
58
+ debugflags = -ggdb
59
+ warnflags = -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long
60
+ CFLAGS = -fPIC $(cflags)
61
+ INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir)
62
+ DEFS = -D_FILE_OFFSET_BITS=64
63
+ CPPFLAGS = $(DEFS) $(cppflags)
64
+ CXXFLAGS = $(CFLAGS) $(cxxflags)
65
+ ldflags = -L. -rdynamic -Wl,-export-dynamic
66
+ dldflags =
67
+ ARCH_FLAG =
68
+ DLDFLAGS = $(ldflags) $(dldflags)
69
+ LDSHARED = $(CC) -shared
70
+ LDSHAREDXX = $(CXX) -shared
71
+ AR = ar
72
+ EXEEXT =
73
+
74
+ RUBY_BASE_NAME = ruby
75
+ RUBY_INSTALL_NAME = ruby
76
+ RUBY_SO_NAME = ruby
77
+ arch = i686-linux
78
+ sitearch = $(arch)
79
+ ruby_version = 1.9.1
80
+ ruby = /usr/local/bin/ruby
81
+ RUBY = $(ruby)
82
+ RM = rm -f
83
+ RM_RF = $(RUBY) -run -e rm -- -rf
84
+ RMDIRS = $(RUBY) -run -e rmdir -- -p
85
+ MAKEDIRS = /bin/mkdir -p
86
+ INSTALL = /usr/bin/install -c
87
+ INSTALL_PROG = $(INSTALL) -m 0755
88
+ INSTALL_DATA = $(INSTALL) -m 644
89
+ COPY = cp
90
+
91
+ #### End of system configuration section. ####
92
+
93
+ preload =
94
+
95
+ libpath = . $(libdir)
96
+ LIBPATH = -L. -L$(libdir) -Wl,-R$(libdir)
97
+ DEFFILE =
98
+
99
+ CLEANFILES = mkmf.log
100
+ DISTCLEANFILES =
101
+ DISTCLEANDIRS =
102
+
103
+ extout =
104
+ extout_prefix =
105
+ target_prefix =
106
+ LOCAL_LIBS =
107
+ LIBS = -lm -ldl -llpsolve55 -lm -lpthread -lrt -ldl -lcrypt -lm -lc
108
+ SRCS = lpsolve.c lpconsts.c
109
+ OBJS = lpsolve.o lpconsts.o
110
+ TARGET = lpsolve
111
+ DLLIB = $(TARGET).so
112
+ EXTSTATIC =
113
+ STATIC_LIB =
114
+
115
+ BINDIR = $(bindir)
116
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
117
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
118
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
119
+ HDRDIR = $(rubyhdrdir)/ruby$(target_prefix)
120
+ ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix)
121
+
122
+ TARGET_SO = $(DLLIB)
123
+ CLEANLIBS = $(TARGET).so
124
+ CLEANOBJS = *.o *.bak
125
+
126
+ all: $(DLLIB)
127
+ static: $(STATIC_LIB)
128
+ .PHONY: all install static install-so install-rb
129
+ .PHONY: clean clean-so clean-rb
130
+
131
+ clean-rb-default::
132
+ clean-rb::
133
+ clean-so::
134
+ clean: clean-so clean-rb-default clean-rb
135
+ @-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
136
+
137
+ distclean-rb-default::
138
+ distclean-rb::
139
+ distclean-so::
140
+ distclean: clean distclean-so distclean-rb-default distclean-rb
141
+ @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
142
+ @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
143
+ @-$(RMDIRS) $(DISTCLEANDIRS)
144
+
145
+ realclean: distclean
146
+ install: install-so install-rb
147
+
148
+ install-so: $(RUBYARCHDIR)
149
+ install-so: $(RUBYARCHDIR)/$(DLLIB)
150
+ $(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
151
+ @-$(MAKEDIRS) $(@D)
152
+ $(INSTALL_PROG) $(DLLIB) $(@D)
153
+ install-rb: pre-install-rb install-rb-default
154
+ install-rb-default: pre-install-rb-default
155
+ pre-install-rb: Makefile
156
+ pre-install-rb-default: Makefile
157
+ $(RUBYARCHDIR):
158
+ $(MAKEDIRS) $@
159
+
160
+ site-install: site-install-so site-install-rb
161
+ site-install-so: install-so
162
+ site-install-rb: install-rb
163
+
164
+ .SUFFIXES: .c .m .cc .cxx .cpp .C .o
165
+
166
+ .cc.o:
167
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
168
+
169
+ .cxx.o:
170
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
171
+
172
+ .cpp.o:
173
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
174
+
175
+ .C.o:
176
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
177
+
178
+ .c.o:
179
+ $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<
180
+
181
+ $(DLLIB): $(OBJS) Makefile
182
+ @-$(RM) $(@)
183
+ $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
184
+
185
+
186
+
187
+ $(OBJS): $(hdrdir)/ruby.h $(hdrdir)/ruby/defines.h $(arch_hdrdir)/ruby/config.h
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ require 'mkmf'
3
+ dir_config('lpsolve')
4
+ $libs = append_library($libs, "m -ldl -llpsolve55 -lm")
5
+
6
+ config_file = File.join(File.dirname(__FILE__), 'config_options.rb')
7
+ load config_file if File.exist?(config_file)
8
+
9
+ # if debug:
10
+ # $CFLAGS = "-Wall -g -fno-strict-aliasing -fPIC"
11
+ create_makefile('lpsolve')
@@ -0,0 +1,174 @@
1
+ /* Copyright (C) 2007, 2010 Rocky Bernstein <rockyb@rubyforge.org>
2
+
3
+ This program is free software: you can redistribute it and/or modify
4
+ it under the terms of the GNU General Public License as published by
5
+ the Free Software Foundation, either version 3 of the License, or
6
+ (at your option) any later version.
7
+
8
+ This program is distributed in the hope that it will be useful,
9
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ GNU General Public License for more details.
12
+
13
+ You should have received a copy of the GNU General Public License
14
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+ */
16
+ #include <ruby.h>
17
+ #include <lpsolve/lp_lib.h>
18
+
19
+ extern VALUE rb_cLPSolve;
20
+
21
+ /** \file lpconsts.c
22
+ *
23
+ * \brief Provides Ruby bindings for LPSolve constants.
24
+
25
+ The constants below are all prefixed by \a LPSolve::, e.g.
26
+ \a LPSolve::EQ.
27
+ */
28
+
29
+ /**
30
+ Routine called by Init_lpsolve() create \a LPSolve:: constants, e.g.
31
+ \a LPSolve::EQ.
32
+ */
33
+ void
34
+ init_lpsolve_constants()
35
+ {
36
+
37
+ /* Equality/Inequality values */
38
+
39
+ rb_define_const(rb_cLPSolve,"EQ", INT2FIX(EQ));
40
+ rb_define_const(rb_cLPSolve,"FR", INT2FIX(FR));
41
+ rb_define_const(rb_cLPSolve,"GE", INT2FIX(GE));
42
+ rb_define_const(rb_cLPSolve,"LE", INT2FIX(LE));
43
+ rb_define_const(rb_cLPSolve,"OF", INT2FIX(OF));
44
+
45
+ /* Verbosity constants */
46
+ rb_define_const(rb_cLPSolve, "NEUTRAL", INT2FIX(NEUTRAL));
47
+ rb_define_const(rb_cLPSolve, "CRITICAL", INT2FIX(CRITICAL));
48
+ rb_define_const(rb_cLPSolve, "SEVERE", INT2FIX(SEVERE));
49
+ rb_define_const(rb_cLPSolve, "IMPORTANT",INT2FIX(IMPORTANT));
50
+ rb_define_const(rb_cLPSolve, "NORMAL", INT2FIX(NORMAL));
51
+ rb_define_const(rb_cLPSolve, "DETAILED", INT2FIX(DETAILED));
52
+ rb_define_const(rb_cLPSolve, "FULL", INT2FIX(FULL));
53
+
54
+ /* Branch and Bound constants */
55
+
56
+ rb_define_const(rb_cLPSolve, "NODE_FIRSTSELECT",
57
+ INT2FIX(NODE_FIRSTSELECT));
58
+ rb_define_const(rb_cLPSolve, "NODE_GAPSELECT",
59
+ INT2FIX(NODE_GAPSELECT));
60
+ rb_define_const(rb_cLPSolve, "NODE_RANGESELECT",
61
+ INT2FIX(NODE_RANGESELECT));
62
+ rb_define_const(rb_cLPSolve, "NODE_FRACTIONSELECT",
63
+ INT2FIX(NODE_FRACTIONSELECT));
64
+ rb_define_const(rb_cLPSolve, "NODE_PSEUDOCOSTSELECT",
65
+ INT2FIX(NODE_PSEUDOCOSTSELECT));
66
+ rb_define_const(rb_cLPSolve, "NODE_PSEUDONONINTSELECT",
67
+ INT2FIX(NODE_PSEUDONONINTSELECT));
68
+ rb_define_const(rb_cLPSolve, "NODE_PSEUDOFEASSELECT",
69
+ INT2FIX(NODE_PSEUDOFEASSELECT));
70
+ rb_define_const(rb_cLPSolve, "NODE_PSEUDORATIOSELECT",
71
+ INT2FIX(NODE_PSEUDORATIOSELECT));
72
+ rb_define_const(rb_cLPSolve, "NODE_USERSELECT",
73
+ INT2FIX(NODE_USERSELECT));
74
+ rb_define_const(rb_cLPSolve, "NODE_STRATEGYMASK",
75
+ INT2FIX(NODE_STRATEGYMASK));
76
+ rb_define_const(rb_cLPSolve, "NODE_WEIGHTREVERSEMODE",
77
+ INT2FIX(NODE_WEIGHTREVERSEMODE));
78
+ rb_define_const(rb_cLPSolve, "NODE_BRANCHREVERSEMODE",
79
+ INT2FIX(NODE_BRANCHREVERSEMODE));
80
+ rb_define_const(rb_cLPSolve, "NODE_GREEDYMODE",
81
+ INT2FIX(NODE_GREEDYMODE));
82
+ rb_define_const(rb_cLPSolve, "NODE_PSEUDOCOSTMODE",
83
+ INT2FIX(NODE_PSEUDOCOSTMODE));
84
+ rb_define_const(rb_cLPSolve, "NODE_DEPTHFIRSTMODE",
85
+ INT2FIX(NODE_DEPTHFIRSTMODE));
86
+ rb_define_const(rb_cLPSolve, "NODE_RANDOMIZEMODE",
87
+ INT2FIX(NODE_RANDOMIZEMODE));
88
+ rb_define_const(rb_cLPSolve, "NODE_GUBMODE",
89
+ INT2FIX(NODE_GUBMODE));
90
+ rb_define_const(rb_cLPSolve, "NODE_DYNAMICMODE",
91
+ INT2FIX(NODE_DYNAMICMODE));
92
+ rb_define_const(rb_cLPSolve, "NODE_RESTARTMODE",
93
+ INT2FIX(NODE_RESTARTMODE));
94
+ rb_define_const(rb_cLPSolve, "NODE_BREADTHFIRSTMODE",
95
+ INT2FIX(NODE_BREADTHFIRSTMODE));
96
+ rb_define_const(rb_cLPSolve, "NODE_AUTOORDER",
97
+ INT2FIX(NODE_AUTOORDER));
98
+ rb_define_const(rb_cLPSolve, "NODE_RCOSTFIXING",
99
+ INT2FIX(NODE_RCOSTFIXING));
100
+ rb_define_const(rb_cLPSolve, "NODE_STRONGINIT",
101
+ INT2FIX(NODE_STRONGINIT));
102
+
103
+ /* Presolve constants used in a bitmask */
104
+ rb_define_const(rb_cLPSolve, "PRESOLVE_NONE", INT2FIX(PRESOLVE_NONE));
105
+ rb_define_const(rb_cLPSolve, "PRESOLVE_ROWS", INT2FIX(PRESOLVE_ROWS));
106
+ rb_define_const(rb_cLPSolve, "PRESOLVE_COLS", INT2FIX(PRESOLVE_COLS));
107
+ rb_define_const(rb_cLPSolve, "PRESOLVE_LINDEP", INT2FIX(4));
108
+ rb_define_const(rb_cLPSolve, "PRESOLVE_SOS", INT2FIX(PRESOLVE_SOS));
109
+ rb_define_const(rb_cLPSolve, "PRESOLVE_REDUCEMIP", INT2FIX(64));
110
+ rb_define_const(rb_cLPSolve, "PRESOLVE_KNAPSACK", INT2FIX(128));
111
+ rb_define_const(rb_cLPSolve, "PRESOLVE_ELIMEQ2", INT2FIX(256));
112
+ rb_define_const(rb_cLPSolve, "PRESOLVE_IMPLIEDFREE", INT2FIX(512));
113
+ rb_define_const(rb_cLPSolve, "PRESOLVE_REDUCEGCD", INT2FIX(1024));
114
+ rb_define_const(rb_cLPSolve, "PRESOLVE_PROBEFIX", INT2FIX(2048));
115
+ rb_define_const(rb_cLPSolve, "PRESOLVE_PROBEREDUCE", INT2FIX(4096));
116
+ rb_define_const(rb_cLPSolve, "PRESOLVE_ROWDOMINATE", INT2FIX(8192));
117
+ rb_define_const(rb_cLPSolve, "PRESOLVE_COLDOMINATE", INT2FIX(16384));
118
+ rb_define_const(rb_cLPSolve, "PRESOLVE_MERGEROWS", INT2FIX(32768));
119
+ rb_define_const(rb_cLPSolve, "PRESOLVE_IMPLIEDSLK", INT2FIX(65536));
120
+ rb_define_const(rb_cLPSolve, "PRESOLVE_COLFIXDUAL", INT2FIX(131072));
121
+ rb_define_const(rb_cLPSolve, "PRESOLVE_BOUNDS", INT2FIX(262144));
122
+ rb_define_const(rb_cLPSolve, "PRESOLVE_LASTMASKMODE",
123
+ INT2FIX(PRESOLVE_DUALS - 1));
124
+ rb_define_const(rb_cLPSolve, "PRESOLVE_DUALS", INT2FIX(PRESOLVE_DUALS));
125
+ rb_define_const(rb_cLPSolve, "PRESOLVE_SENSDUALS", INT2FIX(1048576));
126
+
127
+
128
+ /* Scaling constants used in a bitmask */
129
+
130
+ rb_define_const(rb_cLPSolve, "SCALE_NONE", INT2FIX(SCALE_NONE));
131
+ rb_define_const(rb_cLPSolve, "SCALE_EXTREME", INT2FIX(SCALE_EXTREME));
132
+ rb_define_const(rb_cLPSolve, "SCALE_RANGE", INT2FIX(SCALE_RANGE));
133
+ rb_define_const(rb_cLPSolve, "SCALE_MEAN", INT2FIX(SCALE_MEAN));
134
+ rb_define_const(rb_cLPSolve, "SCALE_GEOMETRIC", INT2FIX(SCALE_GEOMETRIC));
135
+ rb_define_const(rb_cLPSolve, "SCALE_CURTISREID", INT2FIX(SCALE_CURTISREID));
136
+
137
+ /* Above can be Or'd with.. */
138
+ rb_define_const(rb_cLPSolve, "SCALE_QUADRATIC", INT2FIX(SCALE_QUADRATIC));
139
+ rb_define_const(rb_cLPSolve, "SCALE_LOGARITHMIC", INT2FIX(SCALE_LOGARITHMIC));
140
+ rb_define_const(rb_cLPSolve, "SCALE_USERWEIGHT", INT2FIX(SCALE_USERWEIGHT));
141
+ rb_define_const(rb_cLPSolve, "SCALE_POWER2", INT2FIX(SCALE_POWER2));
142
+ rb_define_const(rb_cLPSolve, "SCALE_EQUILIBRATE", INT2FIX(SCALE_EQUILIBRATE));
143
+ rb_define_const(rb_cLPSolve, "SCALE_INTEGERS", INT2FIX(SCALE_INTEGERS));
144
+ rb_define_const(rb_cLPSolve, "SCALE_DYNUPDATE", INT2FIX(SCALE_DYNUPDATE));
145
+ rb_define_const(rb_cLPSolve, "SCALE_ROWSONLY", INT2FIX(SCALE_ROWSONLY));
146
+ rb_define_const(rb_cLPSolve, "SCALE_COLSONLY", INT2FIX(SCALE_COLSONLY));
147
+
148
+ /* Simplex types */
149
+ rb_define_const(rb_cLPSolve, "SIMPLEX_PRIMAL_PRIMAL",
150
+ INT2FIX(SIMPLEX_PRIMAL_PRIMAL));
151
+ rb_define_const(rb_cLPSolve, "SIMPLEX_DUAL_PRIMAL",
152
+ INT2FIX(SIMPLEX_DUAL_PRIMAL));
153
+ rb_define_const(rb_cLPSolve, "SIMPLEX_PRIMAL_DUAL",
154
+ INT2FIX(SIMPLEX_PRIMAL_DUAL));
155
+ rb_define_const(rb_cLPSolve, "SIMPLEX_DUAL_DUAL",
156
+ INT2FIX(SIMPLEX_DUAL_DUAL));
157
+
158
+ /* Solve return codes. */
159
+ rb_define_const(rb_cLPSolve, "NOMEMORY", INT2FIX(NOMEMORY));
160
+ rb_define_const(rb_cLPSolve, "OPTIMAL", INT2FIX(OPTIMAL));
161
+ rb_define_const(rb_cLPSolve, "SUBOPTIMAL", INT2FIX(SUBOPTIMAL));
162
+ rb_define_const(rb_cLPSolve, "INFEASIBLE", INT2FIX(INFEASIBLE));
163
+ rb_define_const(rb_cLPSolve, "UNBOUNDED", INT2FIX(UNBOUNDED));
164
+ rb_define_const(rb_cLPSolve, "DEGENERATE", INT2FIX(DEGENERATE));
165
+ rb_define_const(rb_cLPSolve, "NUMFAILURE", INT2FIX(NUMFAILURE));
166
+ rb_define_const(rb_cLPSolve, "USERABORT", INT2FIX(USERABORT));
167
+ rb_define_const(rb_cLPSolve, "TIMEOUT", INT2FIX(TIMEOUT));
168
+ rb_define_const(rb_cLPSolve, "PRESOLVED", INT2FIX(PRESOLVED));
169
+ rb_define_const(rb_cLPSolve, "PROCFAIL", INT2FIX(PROCFAIL));
170
+ rb_define_const(rb_cLPSolve, "PROCBREAK", INT2FIX(PROCBREAK));
171
+ rb_define_const(rb_cLPSolve, "FEASFOUND", INT2FIX(FEASFOUND));
172
+ rb_define_const(rb_cLPSolve, "NOFEASFOUND", INT2FIX(NOFEASFOUND));
173
+ }
174
+
@@ -0,0 +1,2915 @@
1
+ /* Copyright (C) 2007, 2010 Rocky Bernstein <rockyb@rubyforge.org>
2
+
3
+ This program is free software: you can redistribute it and/or modify
4
+ it under the terms of the GNU General Public License as published by
5
+ the Free Software Foundation, either version 3 of the License, or
6
+ (at your option) any later version.
7
+
8
+ This program is distributed in the hope that it will be useful,
9
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ GNU General Public License for more details.
12
+
13
+ You should have received a copy of the GNU General Public License
14
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+ */
16
+ #include <ruby.h>
17
+ #include <stdio.h>
18
+ #include <lpsolve/lp_lib.h>
19
+ #include <lpsolve/lp_report.h>
20
+
21
+ /** \file lpsolve.c
22
+ *
23
+ * \brief Provides Ruby access to lpsolve.
24
+
25
+ Ruby LPSolve class is created.
26
+
27
+ In the documentation below, change "lpsolve_" to LPSolve:: to
28
+ get the corresponding Ruby method name. For example lpsolve_get_mat()
29
+ is visible in Ruby as LPSolve::get_mat().
30
+ */
31
+
32
+ #define DEBUG_GC 0
33
+
34
+ #define SOLVE_NOT_CALLED -10
35
+
36
+ /* Not part of API (yet). Return a column number for a given column name.
37
+ -1 is returned if the column was not found.
38
+ */
39
+ static int
40
+ get_col_num(lprec *lp, const char *psz_col_name)
41
+ {
42
+ if (lp->names_used && lp->use_col_names) {
43
+ unsigned int i;
44
+ for (i=0; i<= lp->columns; i++) {
45
+ if ((lp->col_name[i] != NULL) && (lp->col_name[i]->name != NULL)) {
46
+ #ifdef Paranoia
47
+ if(lp->col_name[i]->index != i)
48
+ report(lp, SEVERE,
49
+ "%s: Inconsistent column ordinal %d vs %d\n",
50
+ __FUNCTION__, i, lp->col_name[i]->index);
51
+ #endif
52
+ if (0 == strcmp(psz_col_name, lp->col_name[i]->name))
53
+ return i;
54
+ }
55
+ }
56
+ }
57
+ /* Not found. */
58
+ return -1;
59
+ }
60
+
61
+ /** \def INIT_LP
62
+
63
+ Boilerplate beginning of all functions: declares a pointer to the lp
64
+ structure, gets the internal object from Ruby (basically "self") and if
65
+ that's nil, fail immediately.
66
+ */
67
+ #define INIT_LP \
68
+ lprec *lp; \
69
+ Data_Get_Struct(self, lprec, lp); \
70
+ if (NULL == lp) return Qnil; \
71
+
72
+
73
+ #define RETURN_BOOL(x) \
74
+ return (x) ? Qtrue : Qfalse
75
+
76
+ /** \def LPSOLVE_0_IN_BOOL_OUT
77
+
78
+ A macro used in defining a Ruby method which takes no arguments
79
+ other than self and calls the corresponding C function returns the
80
+ boolean static back to Ruby. That is, if lp is not \a NULL we
81
+ return Qtrue. If lp is \a NULL, we return \a Qfalse.
82
+ */
83
+ #define LPSOLVE_0_IN_BOOL_OUT(fn) \
84
+ static VALUE \
85
+ lpsolve_ ## fn(VALUE self) \
86
+ { \
87
+ INIT_LP; \
88
+ RETURN_BOOL(fn(lp)); \
89
+ }
90
+
91
+ /** \def LPSOLVE_0_IN_INT_OUT
92
+
93
+ A macro used in defining a Ruby method which takes no arguments
94
+ other than self and calls the corresponding C function returns the
95
+ integer return value back to Ruby. That is, if \a lp is not \a
96
+ NULL. If it's \a NULL, we return \a nil.
97
+ */
98
+ #define LPSOLVE_0_IN_INT_OUT(fn) \
99
+ static VALUE \
100
+ lpsolve_ ## fn(VALUE self) \
101
+ { \
102
+ INIT_LP; \
103
+ return (NULL != lp) ? INT2FIX(fn(lp)) : Qnil; \
104
+ }
105
+
106
+ /** \def LPSOLVE_0_IN_NUM_OUT
107
+
108
+ A macro used in defining a Ruby method which takes no arguments
109
+ other than self and calls the corresponding C function returns the
110
+ number return value back to Ruby. That is, if \a lp is not \a
111
+ NULL. If it's \a NULL, we return \a nil.
112
+ */
113
+ #define LPSOLVE_0_IN_NUM_OUT(fn) \
114
+ static VALUE \
115
+ lpsolve_ ## fn(VALUE self) \
116
+ { \
117
+ INIT_LP; \
118
+ return rb_float_new(fn(lp)); \
119
+ }
120
+
121
+ /** \def LPSOLVE_0_IN_STATUS_OUT
122
+
123
+ A macro used in defining a Ruby method which takes no arguments
124
+ other than self and calls the corresponding C function returns the
125
+ boolean statuc back to Ruby. That is, if lp is not \a NULL we
126
+ return Qtrue. If lp is \a NULL, we return \a Qfalse.
127
+ */
128
+ #define LPSOLVE_0_IN_STATUS_OUT(fn) \
129
+ static VALUE \
130
+ lpsolve_ ## fn(VALUE self) \
131
+ { \
132
+ INIT_LP; \
133
+ fn(lp); \
134
+ return Qtrue; \
135
+ }
136
+
137
+ /** \def LPSOLVE_0_IN_TIME_OUT
138
+
139
+ A macro used in defining a Ruby method which takes no arguments
140
+ other than self returns a floating point number which is the
141
+ difference between to floating-point fields - time values.
142
+ */
143
+ #define LPSOLVE_0_IN_TIME_OUT(fn, field1, field2) \
144
+ static VALUE \
145
+ lpsolve_ ## fn(VALUE self) \
146
+ { \
147
+ INIT_LP; \
148
+ int status = NUM2INT(rb_ivar_get(self, rb_intern("@status"))); \
149
+ if (SOLVE_NOT_CALLED == status) \
150
+ return rb_float_new(0); \
151
+ return rb_float_new(lp->field2 - lp->field1); \
152
+ }
153
+
154
+ /** \def LPSOLVE_1_BOOL_IN_BOOL_OUT
155
+
156
+ A macro used in defining a Ruby method which takes one boolean
157
+ argument other than self and calls the corresponding C function
158
+ returns the boolean statuc back to Ruby. That is, if lp is not \a
159
+ NULL we return Qtrue. If lp is \a NULL, we return \a Qnil.
160
+ */
161
+ #define LPSOLVE_1_BOOL_IN_BOOL_OUT(fn) \
162
+ static VALUE \
163
+ lpsolve_ ## fn(VALUE self, VALUE param1) \
164
+ { \
165
+ INIT_LP; \
166
+ if (param1 != Qtrue && param1 != Qfalse) { \
167
+ report(lp, IMPORTANT, \
168
+ "%s: Parameter is not a boolean.\n", \
169
+ __FUNCTION__); \
170
+ return Qnil; \
171
+ } else { \
172
+ unsigned char turnon = param1 == Qtrue ? 1 : 0; \
173
+ RETURN_BOOL(fn(lp, turnon)); \
174
+ } \
175
+ }
176
+
177
+ /** \def LPSOLVE_1_IN_BOOL_OUT
178
+
179
+ A macro used in defining a Ruby method which takes one argument
180
+ other than self and calls the corresponding C function returns the
181
+ boolean statuc back to Ruby. That is, if lp is not \a NULL we
182
+ return Qtrue. If lp is \a NULL, we return \a Qnil
183
+
184
+ \a type is a Ruby typename like \a T_FIXNUM, \a typename is a type
185
+ name string to use in an error message, e.g "an integer"; \a
186
+ convert a Ruby conversion macro like \a FIX2INT.
187
+ */
188
+ #define LPSOLVE_1_IN_BOOL_OUT(fn, type, typename, convert) \
189
+ static VALUE \
190
+ lpsolve_ ## fn(VALUE self, VALUE param1) \
191
+ { \
192
+ INIT_LP; \
193
+ if (TYPE(param1) != type) { \
194
+ report(lp, IMPORTANT, \
195
+ "%s: Parameter is not %s.\n", \
196
+ __FUNCTION__, typename); \
197
+ return Qnil; \
198
+ } \
199
+ RETURN_BOOL(fn(lp, convert(param1))); \
200
+ }
201
+
202
+ /** \def LPSOLVE_1_IN_NUM_OUT
203
+
204
+ A macro used in defining a Ruby method which takes one argument
205
+ along with self and calls the corresponding C function returns the
206
+ integer return value back to Ruby. That is, if \a lp is not \a
207
+ NULL. If it's \a NULL, we return \a nil.
208
+
209
+ \a type is a Ruby typename like \a T_FIXNUM, \a typename is a type
210
+ name string to use in an error message, e.g "an integer"; \a
211
+ convert a Ruby conversion macro like \a FIX2INT.
212
+ \a fn is the lpsolve function to call.
213
+
214
+ */
215
+ #define LPSOLVE_1_IN_NUM_OUT(fn, type, typename, convert) \
216
+ static VALUE \
217
+ lpsolve_ ## fn (VALUE self, VALUE param1) \
218
+ { \
219
+ INIT_LP \
220
+ if (TYPE(param1) != type) { \
221
+ report(lp, IMPORTANT, \
222
+ "%s: Parameter is not %s.\n", \
223
+ __FUNCTION__, typename); \
224
+ return Qnil; \
225
+ } \
226
+ return rb_float_new(fn(lp, convert(param1))); \
227
+ }
228
+
229
+ /** \def LPSOLVE_1_IN_STR_OUT
230
+
231
+ A macro used in defining a Ruby method which takes one argument
232
+ along with self and calls the corresponding C function returns a
233
+ string back to Ruby. That is, if \a lp is not \a
234
+ NULL. If it's \a NULL, we return \a nil.
235
+
236
+ \a arg1 is passed to the \a lpsolve routine. It should be
237
+ a function of \a param1 which is the parameter of the wrapper
238
+ function. For example \a arg1 could be \a FIX2INT(param1).
239
+
240
+ */
241
+ #define LPSOLVE_1_IN_STR_OUT(fn, type, typename, convert) \
242
+ static VALUE \
243
+ lpsolve_ ## fn (VALUE self, VALUE param1) \
244
+ { \
245
+ INIT_LP \
246
+ if (TYPE(param1) != type) { \
247
+ report(lp, IMPORTANT, \
248
+ "%s: Parameter is not %s.\n", \
249
+ __FUNCTION__, typename); \
250
+ return Qnil; \
251
+ } \
252
+ return rb_str_new2(fn(lp, convert(param1))); \
253
+ }
254
+
255
+ /** \def LPSOLVE_1_IN_BOOL_OUT
256
+
257
+ A macro used in defining a Ruby method which takes one argument
258
+ along with self and calls the corresponding C function returns the
259
+ integer return value back to Ruby. That is, if \a lp is not \a
260
+ NULL. If it's \a NULL, we return \a nil.
261
+ */
262
+ #define LPSOLVE_1_STR_IN_BOOL_OUT(fn) \
263
+ static VALUE \
264
+ lpsolve_ ## fn (VALUE self, VALUE str) \
265
+ { \
266
+ INIT_LP; \
267
+ if (TYPE(str) != T_STRING) { \
268
+ report(lp, IMPORTANT, \
269
+ "%s: Parameter 1 is not a string\n", \
270
+ __FUNCTION__); \
271
+ return Qfalse; \
272
+ } \
273
+ RETURN_BOOL(fn(lp, RSTRING_PTR(str))); \
274
+ }
275
+
276
+ /** \def LPSOLVE_1_IN_STATUS_OUT
277
+
278
+ A macro used in defining a Ruby method which takes one argument
279
+ along with self and calls the corresponding C function returns the
280
+ integer return value back to Ruby. That is, if \a lp is not \a
281
+ NULL. If it's \a NULL, we return \a nil.
282
+
283
+ \a arg1 is passed to the \a lpsolve routine. It should be
284
+ a function of \a param1 which is the parameter of the wrapper
285
+ function. For example \a arg1 could be \a FIX2INT(param1).
286
+
287
+ */
288
+ #define LPSOLVE_1_IN_STATUS_OUT(fn, arg1) \
289
+ static VALUE \
290
+ lpsolve_ ## fn (VALUE self, VALUE param1) \
291
+ { \
292
+ INIT_LP \
293
+ fn(lp, arg1); \
294
+ return Qtrue; \
295
+ }
296
+
297
+ #define LPSOLVE_SET_VARTYPE(fn) \
298
+ static VALUE \
299
+ lpsolve_ ## fn (VALUE self, VALUE column_num, VALUE new_bool) \
300
+ { \
301
+ INIT_LP; \
302
+ if (new_bool != Qtrue && new_bool != Qfalse && new_bool != Qnil) { \
303
+ report(lp, IMPORTANT, \
304
+ "%s: Parameter is not a boolean or nil.\n", \
305
+ __FUNCTION__); \
306
+ return Qfalse; \
307
+ } else { \
308
+ RETURN_BOOL(fn(lp, FIX2INT(column_num), Qtrue == new_bool)); \
309
+ } \
310
+ }
311
+
312
+
313
+ static VALUE
314
+ lpsolve_set_binary (VALUE self, VALUE column_num, VALUE new_bool)
315
+ {
316
+ INIT_LP;
317
+ if (new_bool != Qtrue && new_bool != Qfalse && new_bool != Qnil) {
318
+ report(lp, IMPORTANT,
319
+ "%s: Parameter is not a boolean or nil.\n",
320
+ __FUNCTION__);
321
+ return Qfalse;
322
+ } else {
323
+ RETURN_BOOL(set_binary(lp, FIX2INT(column_num), Qtrue == new_bool));
324
+ }
325
+ }
326
+
327
+
328
+ /** Holder for LPSolve class object. A singleton value. */
329
+ VALUE rb_cLPSolve;
330
+
331
+ static void lpsolve_free(void *lp);
332
+
333
+ /**
334
+ A wrapper for add_constraintex.
335
+
336
+ Adds a constraint. These routines will perform much better when
337
+ lpsolve_set_add_rowmode() is called before adding constraints.
338
+
339
+ @param self self
340
+ @param name The name of the constraint or \a nil if no name.
341
+
342
+ @param row_coeffs A list of tuples. The first entry of the tuple is
343
+ the column number which should be in the range 0..columns-1; the
344
+ second entry in the tuple should be the coefficient value.
345
+
346
+ @param constr_type The constraint type. Should be one of
347
+ \a LPSolve::LE, \a LPSolve::EQ, \a LPSolve::GE.
348
+
349
+ @param rh The right-hand-side constant, a number.
350
+
351
+ @return number of rows, (the row number of the constraint added) if
352
+ successful or \a nil on error.
353
+
354
+ */
355
+ static VALUE
356
+ lpsolve_add_constraintex(VALUE self, VALUE name, VALUE row_coeffs,
357
+ VALUE constr_type, VALUE rh)
358
+ {
359
+ int i_constr_type = FIX2INT(constr_type);
360
+ REAL r_rh = NUM2DBL(rh);
361
+ REAL *row = NULL;
362
+ int *colno = NULL;
363
+ long int i, count;
364
+ VALUE ret = Qnil;
365
+ MYBOOL b_ret;
366
+ VALUE *p_row_coeff = NULL;
367
+
368
+ INIT_LP;
369
+
370
+ if (TYPE(name) != T_STRING && name != Qnil) {
371
+ report(lp, IMPORTANT,
372
+ "%s: constraint name, parameter 1, should be nil or a string.\n",
373
+ __FUNCTION__);
374
+ return Qnil;
375
+ }
376
+
377
+ if (TYPE(row_coeffs) != T_ARRAY) {
378
+ report(lp, IMPORTANT,
379
+ "%s: row coefficients, parameter 2 is not an array.\n",
380
+ __FUNCTION__);
381
+ return Qnil;
382
+ }
383
+
384
+ if (TYPE(constr_type) != T_FIXNUM) {
385
+ report(lp, IMPORTANT,
386
+ "%s: constraint type, parameter 3, is not a number.\n",
387
+ __FUNCTION__);
388
+ return Qnil;
389
+ }
390
+
391
+ switch (i_constr_type) {
392
+ case EQ:
393
+ case GE:
394
+ case LE: break;
395
+ default:
396
+ report(lp, IMPORTANT,
397
+ "%s: constraint type, parameter 3, should be LE, EQ, or GE.\n",
398
+ __FUNCTION__);
399
+ return Qnil;
400
+ }
401
+
402
+ /***FIXME: combine common parts of this with add_constraintex ****/
403
+ count = RARRAY_LEN(row_coeffs);
404
+
405
+ if (0 == count) {
406
+ report(lp, IMPORTANT,
407
+ "%s: row coefficients array has to have at least one item.\n",
408
+ __FUNCTION__);
409
+ return Qnil;
410
+ }
411
+
412
+ colno = ALLOC_N(int, count);
413
+ row = ALLOC_N(REAL, count);
414
+
415
+ p_row_coeff = RARRAY_PTR(row_coeffs);
416
+ for (i = 0; i < count; i++) {
417
+ int i_col;
418
+ if (TYPE(*p_row_coeff) != T_ARRAY) {
419
+ report(lp, IMPORTANT,
420
+ "%s: row coeffient element %d is not an array.\n",
421
+ __FUNCTION__, i);
422
+ goto done;
423
+ }
424
+ if (RARRAY_LEN(*p_row_coeff) != 2) {
425
+ report(lp, IMPORTANT,
426
+ "%s: row coeffient element %d is not an array tuple.\n",
427
+ __FUNCTION__, i);
428
+ goto done;
429
+ } else {
430
+ VALUE *tuple = RARRAY_PTR(*p_row_coeff);
431
+ if (TYPE(tuple[0]) != T_FIXNUM) {
432
+ report(lp, IMPORTANT,
433
+ "%s: Column number, first element, of row coefficients at " \
434
+ "tuple %d is not a integer.\n", __FUNCTION__, i);
435
+ goto done;
436
+ }
437
+ switch (TYPE(tuple[1])) {
438
+ case T_FIXNUM:
439
+ case T_FLOAT: break;
440
+ default:
441
+ report(lp, IMPORTANT,
442
+ "%s: Coefficient value, second element, of row coeffients at "
443
+ "tuple %d is not an integer.\n", __FUNCTION__, i);
444
+ goto done;
445
+ }
446
+
447
+ i_col = FIX2INT(tuple[0]);
448
+ if (i_col <= 0 || i_col > lp->columns) {
449
+ report(lp, IMPORTANT,
450
+ "%s: Column number, first element, of row coeffients at " \
451
+ "tuple %d, value %d, is not in the range 1..%d\n",
452
+ __FUNCTION__, i, i_col, lp->columns);
453
+ goto done;
454
+ }
455
+ colno[i] = i_col;
456
+ row[i] = NUM2DBL(tuple[1]);
457
+ }
458
+ p_row_coeff++;
459
+ }
460
+
461
+ b_ret = add_constraintex(lp, count, row, colno, i_constr_type, r_rh);
462
+ if (b_ret) {
463
+ ret = INT2FIX(lp->rows);
464
+ if (name != Qnil)
465
+ set_row_name(lp, lp->rows, RSTRING_PTR(name));
466
+ }
467
+
468
+ done:
469
+ free(row);
470
+ free(colno);
471
+ return ret;
472
+ }
473
+
474
+ /**
475
+ A wrapper for add_SOS.
476
+
477
+ Adds an SOS constraint. A Special Ordered Set of Type n is a way of
478
+ indicating that at most n of a set of variables may be nonzero.
479
+
480
+ @param self self
481
+ @param name The name of the SOS constraint.
482
+
483
+ @param sos_type The type of the SOS constraint, 1 means "at most 1" 2
484
+ means "at most 2". Must be >= 1.
485
+ @param priority Priority of the SOS constraint in the SOS set.
486
+ @param sos_vars A list of tuples of column numbers and weights
487
+
488
+ */
489
+ static VALUE
490
+ lpsolve_add_SOS(VALUE self, VALUE name, VALUE sos_type, VALUE priority,
491
+ VALUE sos_vars)
492
+ {
493
+ int i_sos_type = FIX2INT(sos_type);
494
+ int i_priority = FIX2INT(priority);
495
+ int *vars = NULL;
496
+ double *weights = NULL;
497
+ long int i, count;
498
+ VALUE *p_sos_var;
499
+ VALUE ret = Qnil;
500
+ int i_ret = 0;
501
+
502
+ INIT_LP;
503
+
504
+ if (TYPE(sos_type) != T_FIXNUM) {
505
+ report(lp, IMPORTANT,
506
+ "%s: SOS type, parameter 2, is not a number.\n", __FUNCTION__);
507
+ return Qnil;
508
+ }
509
+
510
+ if (TYPE(priority) != T_FIXNUM) {
511
+ report(lp, IMPORTANT,
512
+ "%s: priority, parameter 3, not a number.\n", __FUNCTION__);
513
+ return Qnil;
514
+ }
515
+ if (TYPE(name) != T_STRING) {
516
+ report(lp, IMPORTANT, "%s: name is not a string.\n", __FUNCTION__);
517
+ return Qnil;
518
+ }
519
+ if (i_sos_type < 1) {
520
+ report(lp, IMPORTANT, "%s: SOS type (%ld) is less than 1.\n",
521
+ __FUNCTION__, i_sos_type);
522
+ return Qnil;
523
+ }
524
+
525
+ if (TYPE(sos_vars) != T_ARRAY) {
526
+ report(lp, IMPORTANT, "%s: SOS vars is not an array.\n", __FUNCTION__);
527
+ return Qnil;
528
+ }
529
+
530
+ count = RARRAY_LEN(sos_vars);
531
+
532
+ if (0 == count) {
533
+ report(lp, IMPORTANT,
534
+ "%s: SOS vars array has to have at least one item.\n",
535
+ __FUNCTION__);
536
+ return Qnil;
537
+ }
538
+
539
+ vars = ALLOC_N(int, count);
540
+ weights = ALLOC_N(double, count);
541
+
542
+ p_sos_var = RARRAY_PTR(sos_vars);
543
+ for (i = 0; i < count; i++) {
544
+ if (TYPE(*p_sos_var) != T_ARRAY) {
545
+ report(lp, IMPORTANT,
546
+ "%s: SOS vars element %d is not an array.\n", __FUNCTION__, i);
547
+ goto done;
548
+ }
549
+ if (RARRAY_LEN(*p_sos_var) != 2) {
550
+ report(lp, IMPORTANT,
551
+ "%s: SOS vars element %d is not an array tuple.\n", __FUNCTION__,
552
+ i);
553
+ goto done;
554
+ } else {
555
+ VALUE *tuple = RARRAY_PTR(*p_sos_var);
556
+ if (TYPE(tuple[0]) != T_FIXNUM) {
557
+ report(lp, IMPORTANT,
558
+ "%s: First element of SOS vars at tuple %d " \
559
+ "is not a integer.\n", __FUNCTION__, i);
560
+ goto done;
561
+ }
562
+ if (TYPE(tuple[1]) != T_FIXNUM) {
563
+ report(lp, IMPORTANT,
564
+ "%s: Second element of SOS vars at tuple %d " \
565
+ "is not an integer.\n", __FUNCTION__, i);
566
+ goto done;
567
+ }
568
+ vars[i] = FIX2INT(tuple[0]);
569
+ weights[i] = FIX2INT(tuple[1]);
570
+ }
571
+ p_sos_var++;
572
+ }
573
+ i_ret = add_SOS(lp, RSTRING_PTR(name), i_sos_type, i_priority,
574
+ count, vars, weights);
575
+ if (i_ret != 0)
576
+ ret = INT2FIX(i_ret);
577
+
578
+ done:
579
+ free(vars);
580
+ free(weights);
581
+ return ret;
582
+ }
583
+
584
+ /** Allocate a Ruby container for a lprec * pointer. Ruby may call
585
+ this routine directly under various circumstances such as when
586
+ doing data marshalling. However usually the most common case is
587
+ when new() is called. Here, after the call to lpsolve_alloc(),
588
+ Ruby will call lpsolve_initialize().
589
+ */
590
+ static VALUE
591
+ lpsolve_alloc(VALUE klass)
592
+ {
593
+ VALUE obj;
594
+ obj = Data_Wrap_Struct(klass, 0, lpsolve_free, NULL);
595
+ return obj;
596
+ }
597
+
598
+ /** A wrapper for default_basis().
599
+
600
+ Sets the starting base to an all slack basis (the default simplex
601
+ starting basis).
602
+
603
+ @param self self
604
+ @return \a true unless we have an error.
605
+ */
606
+ static VALUE lpsolve_default_basis(VALUE self);
607
+ LPSOLVE_0_IN_STATUS_OUT(default_basis)
608
+
609
+ /** A wrapper for del_column().
610
+
611
+ @param self self
612
+ @param column_num column number
613
+
614
+ @return \a true if the operation was successful. false indicates an
615
+ error. An error occurs when column is not between 1 and the number
616
+ of columns in the lp. Note that row entry mode must be off, else
617
+ this function also fails.
618
+
619
+ @see lpsolve_set_add_rowmode()
620
+ */
621
+ static VALUE lpsolve_del_column(VALUE self, VALUE column_num);
622
+ LPSOLVE_1_IN_BOOL_OUT(del_column, T_FIXNUM, "an integer", FIX2INT);
623
+
624
+ /** A wrapper for del_constraint()
625
+
626
+ del_constraint returns true if the operation was successful.
627
+
628
+ @param self self
629
+ @param row_num row number
630
+
631
+ @return a \a false value indicates an error. An error occurs when
632
+ row_num is not between 1 and the number of rows self. Note that row
633
+ entry mode must be off, else this function also fails. @see
634
+ lpsolve_set_add_rowmode().
635
+ */
636
+ static VALUE lpsolve_del_constraint(VALUE self, VALUE row_num);
637
+ LPSOLVE_1_IN_BOOL_OUT(del_constraint, T_FIXNUM, "an integer", FIX2INT);
638
+
639
+
640
+ static void
641
+ lpsolve_free(void *lp)
642
+ {
643
+ #if DEBUG_GC
644
+ printf("lpsolve_free called\n");
645
+ #endif
646
+ if (NULL != lp) delete_lp((lprec *)lp);
647
+ }
648
+
649
+ /** A wrapper for get_bb_depthlimit(lprec *lp);
650
+
651
+ get_bb_depthlimit returns the maximum branch-and-bound depth.
652
+
653
+ Parameters
654
+
655
+ lp
656
+
657
+ Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI
658
+
659
+ Remarks
660
+
661
+ The get_bb_depthlimit function returns the maximum branch-and-bound
662
+ depth. This is only useful if there are integer, semi-continious
663
+ or SOS variables in the model so that the branch-and-bound
664
+ algorithm must be used to solve them. The branch-and-bound
665
+ algorithm will not go deeper than this level. When 0 then there is
666
+ no limit to the depth. Limiting the depth will speed up solving
667
+ time, but there is a chance that the found solution is not the most
668
+ optimal one. Be aware of this. It can also result in not finding a
669
+ solution at all. A positive value means that the depth is
670
+ absolute. NOTE: in the standard lpsolve an absolute depth is
671
+ *added* to the number of SOS vars and semi-continuous vars. In a
672
+ hacked version of lpsolve, absolute is, well, absolute.
673
+
674
+ A negative value means a relative B&B depth limit. The
675
+ "order" of a MIP problem is defined to be 2x the number of binary
676
+ variables plus the number of SC and SOS variables. A relative value
677
+ of -x results in a maximum depth of x times the order of the MIP
678
+ problem. The default is -50. The get_bb_rule function returns the
679
+ branch-and-bound rule for choosing which non-integer variable is to
680
+ be selected. This rule can influence solving times
681
+ considerably. Depending on the model one rule can be best and for
682
+ another model another rule. The default is NODE_PSEUDONONINTSELECT
683
+ + NODE_GREEDYMODE + NODE_DYNAMICMODE + NODE_RCOSTFIXING (17445).
684
+
685
+ @param self self
686
+ @return Returns the branch-and-bound rule.
687
+ */
688
+ static VALUE lpsolve_get_bb_depthlimit(VALUE self);
689
+ LPSOLVE_0_IN_NUM_OUT(get_bb_depthlimit);
690
+
691
+ /** A wrapper for get_bb_rule().
692
+
693
+ The get_bb_rule function returns the branch-and-bound rule for
694
+ choosing which non-integer variable is to be selected. This rule
695
+ can influence solving times considerably. Depending on the model
696
+ one rule can be best and for another model another rule. The
697
+ default is NODE_PSEUDONONINTSELECT + NODE_GREEDYMODE +
698
+ NODE_DYNAMICMODE + NODE_RCOSTFIXING (17445).
699
+
700
+ @param self self
701
+ @return Returns the branch-and-bound rule.
702
+
703
+ */
704
+ static VALUE lpsolve_get_bb_rule(VALUE self);
705
+ LPSOLVE_0_IN_NUM_OUT(get_bb_rule);
706
+
707
+ /** A wrapper for get_col_name().
708
+
709
+ get_col_name() returns the name of the specified column. The
710
+ difference between get_col_name and get_origcol_name is only
711
+ visible when a presolve (set_presolve) was done. Presolve can
712
+ result in deletion of columns in the model. In get_col_name(),
713
+ column specifies the column number after presolve was done.
714
+
715
+ @return the string name. A value of \a nil indicates an error.
716
+ */
717
+ static VALUE
718
+ lpsolve_get_col_name(VALUE self, VALUE column_num)
719
+ {
720
+ char *psz_col_name;
721
+ INIT_LP;
722
+
723
+ if (TYPE(column_num) != T_FIXNUM) {
724
+ report(lp, IMPORTANT,
725
+ "%s: column number, parameter 1, is not an integer.\n",
726
+ __FUNCTION__);
727
+ return Qnil;
728
+ }
729
+
730
+ psz_col_name = get_col_name(lp, FIX2INT(column_num));
731
+ return psz_col_name ? rb_str_new2(psz_col_name) : Qnil;
732
+ }
733
+
734
+ /** get_col_num(). - Not in API (yet)
735
+
736
+ get_col_num() returns the column number for the specified column
737
+ name.
738
+
739
+ @return the column number. A value of \a nil indicates an error.
740
+ */
741
+ static VALUE
742
+ lpsolve_get_col_num(VALUE self, VALUE column_name)
743
+ {
744
+ INIT_LP;
745
+
746
+ if (TYPE(column_name) != T_STRING) {
747
+ report(lp, IMPORTANT,
748
+ "%s: column number, parameter 1, is not a string.\n",
749
+ __FUNCTION__);
750
+ return Qnil;
751
+ } else {
752
+ int retval = get_col_num(lp, RSTRING_PTR(column_name));
753
+ return (-1 == retval) ? Qnil : INT2FIX(retval);
754
+ }
755
+ }
756
+
757
+ /** A wrapper for get_column().
758
+
759
+ Get all column elements from the matrix for a given column number.
760
+
761
+ @param self self
762
+
763
+ @param column_num the column number that you want. The value must be
764
+ between 1 and the number of columns.
765
+
766
+ @return an array of the column values. The size of the array is
767
+ the number of rows + 1. \a Nil is returned if there was an error.
768
+ */
769
+ static VALUE
770
+ lpsolve_get_column(VALUE self, VALUE column_num)
771
+ {
772
+ unsigned int i_column = FIX2INT(column_num);
773
+ unsigned int i_rows;
774
+ REAL *p_column;
775
+ INIT_LP;
776
+
777
+ i_rows = get_Nrows(lp); /* Yep, Nrows, not Ncolumns. */
778
+ p_column = ALLOC_N(REAL, i_rows + 1);
779
+
780
+ if (!get_column(lp, i_column, p_column)) {
781
+ free(p_column);
782
+ return Qnil;
783
+ } else {
784
+ VALUE ret_ary = rb_ary_new2(i_rows+1);
785
+ unsigned int i;
786
+ for (i=0; i<=i_rows; i++) {
787
+ rb_ary_push(ret_ary, rb_float_new(p_column[i]));
788
+ }
789
+ free(p_column);
790
+ return ret_ary;
791
+ }
792
+
793
+ }
794
+
795
+ /** A wrapper for get_infinite().
796
+
797
+ @param self self
798
+ @return Returns the value of "infinite".
799
+ */
800
+ static VALUE lpsolve_get_infinite(VALUE self);
801
+ LPSOLVE_0_IN_NUM_OUT(get_infinite);
802
+
803
+ /** A wrapper for get_lowbo().
804
+
805
+ Returns the upper bound on the variable identified by column.
806
+ Setting a bound on a variable is the way to go instead of adding an
807
+ extra constraint (row) to the model. Setting a bound doesn't
808
+ increase the model size that means that the model stays smaller and
809
+ will be solved faster. The default upper bound of a variable is
810
+ infinity (well not quite. It is a very big number. The value of
811
+ lpsolve_get_infinite().
812
+
813
+ @param self self
814
+
815
+ @param column_num the column number of the variable. It must be
816
+ between 1 and the number of columns in the lp.
817
+
818
+ */
819
+
820
+ static VALUE lpsolve_get_lowbo(VALUE self, VALUE column_num);
821
+ LPSOLVE_1_IN_NUM_OUT(get_lowbo, T_FIXNUM, "an integer", FIX2INT);
822
+
823
+ /** A wrapper for get_lp_name().
824
+
825
+ @return the name of the lp. The doc says the default name is
826
+ "Unnamed", but in fact we seem to return "".
827
+ */
828
+ static VALUE
829
+ lpsolve_get_lp_name(VALUE self)
830
+ {
831
+ char *psz_lp_name;
832
+ INIT_LP;
833
+ psz_lp_name = get_lp_name(lp);
834
+ return psz_lp_name ? rb_str_new2(psz_lp_name) : rb_str_new2("Unnamed");
835
+ }
836
+
837
+ /**
838
+ A wrapper for get_Ncolumns().
839
+
840
+ Return the number of columns (variables) in the lp object. Note
841
+ that the number of columns can change when a presolve is done or
842
+ when negative variables are split in a positive and a negative
843
+ part. Therefore it is advisable to use this function to determine
844
+ how many columns there are in the lp instead of relying one's own
845
+ count.
846
+
847
+ @param self self
848
+ @return the number of columns (variables) in the lp.
849
+ */
850
+ static VALUE lpsolve_get_Ncolumns(VALUE self);
851
+ LPSOLVE_0_IN_INT_OUT(get_Ncolumns)
852
+
853
+ /** A wrapper for get_nonzeros().
854
+
855
+ Return the number of non-zero elements in matrix of the the lp object.
856
+
857
+ @param self self
858
+ @return the number of non-zero elements in the matrix of the lp.
859
+ */
860
+ static VALUE lpsolve_get_nonzeros(VALUE self);
861
+ LPSOLVE_0_IN_INT_OUT(get_nonzeros)
862
+
863
+ /**
864
+ A wrapper for get_Norig_columns().
865
+
866
+ Return the number of original columns (variables) in the lp
867
+ object. Note that the number of row does not change, but the
868
+ number of original columns does not.
869
+
870
+ @param self self
871
+ @return the number of columns (variables) in the lp.
872
+ */
873
+ static VALUE lpsolve_get_Norig_columns(VALUE self);
874
+ LPSOLVE_0_IN_INT_OUT(get_Norig_columns)
875
+
876
+ /** A wrapper for get_Norig_rows().
877
+
878
+ Return the number of original rows (constraints) in the lp
879
+ object. Note that the number of row does not change, but the
880
+ number of original rows does not.
881
+
882
+ @param self self
883
+ @return the number of original rows (constraints) in the lp.
884
+ */
885
+ static VALUE lpsolve_get_Norig_rows(VALUE self);
886
+ LPSOLVE_0_IN_INT_OUT(get_Norig_rows)
887
+
888
+ /** A wrapper for get_Nrows().
889
+
890
+ Return the number of rows (variables) in the lp object. Note that
891
+ the number of columns can change when a presolve is done or when
892
+ negative variables are split in a positive and a negative part.
893
+ Therefore it is advisable to use this function to determine how
894
+ many columns there are in the lp instead of relying one's own
895
+ count.
896
+
897
+ @param self self
898
+ @return the number of rows (constraints) in the lp.
899
+ */
900
+ static VALUE lpsolve_get_Nrows(VALUE self);
901
+ LPSOLVE_0_IN_INT_OUT(get_Nrows)
902
+
903
+ /** A wrapper for get_mat().
904
+
905
+ Get a single element from the matrix.
906
+
907
+ @param self self
908
+ @param row_num row number
909
+ @param col_num column number
910
+
911
+ @return the value of the element on row \a row, column \a column. If no
912
+ value was set for this element, the function returns 0. Note that
913
+ row entry mode must be off, else this function also fails. @see
914
+ lpsolve_set_add_rowmode().
915
+
916
+ */
917
+ static VALUE
918
+ lpsolve_get_mat(VALUE self, VALUE row_num, VALUE col_num)
919
+ {
920
+ INIT_LP;
921
+ if (TYPE(row_num) != T_FIXNUM) {
922
+ report(lp, IMPORTANT,
923
+ "%s: row number, parameter 1, is not a number.\n", __FUNCTION__);
924
+ return Qnil;
925
+ }
926
+ if (TYPE(col_num) != T_FIXNUM) {
927
+ report(lp, IMPORTANT,
928
+ "%s: column number, parameter 2, is not a number.\n", __FUNCTION__);
929
+ return Qnil;
930
+ }
931
+ return rb_float_new(get_mat(lp, FIX2INT(row_num), FIX2INT(col_num)));
932
+ }
933
+
934
+ /** A wrapper for get_mip_gap().
935
+
936
+ Sets the MIP gap that specifies a tolerance for the branch and bound
937
+ algorithm. This tolerance is the difference between the best-found
938
+ solution yet and the current solution. If the difference is smaller
939
+ than this tolerance then the solution (and all the sub-solutions) is
940
+ rejected. This can result in faster solving times, but results in a
941
+ solution which is not the perfect solution. So be careful with this
942
+ tolerance. The default mip_gap value is 1e-9
943
+
944
+
945
+ @param self self
946
+ @param abs_rel: set to true if the gap is absolute, or false for relative.
947
+ @param val: gap value. The default mip_gap is 1e-9.
948
+ @return \a gap value or nil if there was an error.
949
+ */
950
+ static VALUE
951
+ lpsolve_get_mip_gap(VALUE self, VALUE abs_rel)
952
+ {
953
+ INIT_LP;
954
+ if (abs_rel != Qtrue && abs_rel != Qfalse && abs_rel != Qnil) {
955
+ report(lp, IMPORTANT,
956
+ "%s: Parameter is not a boolean or nil.\n",
957
+ __FUNCTION__);
958
+ return Qnil;
959
+ } else {
960
+ return rb_float_new(get_mip_gap(lp, Qtrue == abs_rel));
961
+ }
962
+ }
963
+
964
+ /** A wrapper for get_objective().
965
+
966
+ returns the value of the objective of the last solve().
967
+ This value is only valid after a successful lpsolve_solve() or
968
+ lag_solve.
969
+
970
+ In Ruby, you can also use accessor function objective.
971
+
972
+ @param self self
973
+ @return the objective value. It is a real value.
974
+ */
975
+ static VALUE lpsolve_get_objective(VALUE self);
976
+ LPSOLVE_0_IN_NUM_OUT(get_objective);
977
+
978
+ /** A wrapper for get_origcol_name().
979
+
980
+ Returns the name of the specified column.
981
+
982
+ The difference between lpsolve_get_col_name() and
983
+ lpsolve_get_origcol_name() is only visible when a presolve
984
+ (lpsolve_set_presolve()) was done. Presolve can result in deletion
985
+ of columns in the model. In lpsolve_get_col_name(), column
986
+ specifies the column number after presolve was done.
987
+
988
+ @param self self
989
+ @param column_num column number
990
+
991
+ @return nil indicates an error.
992
+ */
993
+ static VALUE
994
+ lpsolve_get_origcol_name(VALUE self, VALUE column_num)
995
+ {
996
+ lprec *lp;
997
+ char *psz_col_name;
998
+ Data_Get_Struct(self, lprec, lp);
999
+ if (TYPE(column_num) != T_FIXNUM) {
1000
+ report(lp, IMPORTANT,
1001
+ "%s: column number, parameter 1, is not an integer.\n",
1002
+ __FUNCTION__);
1003
+ return Qnil;
1004
+ }
1005
+ psz_col_name = get_origcol_name(lp, FIX2INT(column_num));
1006
+ return psz_col_name ? rb_str_new2(psz_col_name) : Qnil;
1007
+ }
1008
+
1009
+ /** A wrapper for get_origrow_name()
1010
+
1011
+ @param self self
1012
+ @param row_num row number
1013
+
1014
+ get_row_name and get_origrow_name return the name of the specified
1015
+ row. A return value of NULL indicates an error. The difference
1016
+ between lpsolve_get_row_name() and lpsolve_get_origrow_name() is
1017
+ only visible when a presolve (lpsovle_set_presolve()) was
1018
+ done. Presolve can result in deletion of rows in the model. In
1019
+ get_row_name, row specifies the row number after presolve was
1020
+ done. In lpsolve_get_origrow_name(), row specifies the row number
1021
+ before presolve was done, ie the original row number. If presolve
1022
+ is not active then both functions are equal.
1023
+
1024
+ @return a Ruby string row name.
1025
+ */
1026
+ static VALUE
1027
+ lpsolve_get_origrow_name(VALUE self, VALUE row_num)
1028
+ {
1029
+ char *psz_col_name;
1030
+ INIT_LP;
1031
+ if (TYPE(row_num) != T_FIXNUM) {
1032
+ report(lp, IMPORTANT,
1033
+ "%s: row number, parameter 1, is not a number.\n", __FUNCTION__);
1034
+ return Qnil;
1035
+ }
1036
+ psz_col_name = get_origrow_name(lp, FIX2INT(row_num));
1037
+ return psz_col_name ? rb_str_new2(psz_col_name) : Qnil;
1038
+ }
1039
+
1040
+ /**
1041
+ A wrapper for get_presolve().
1042
+
1043
+ @param self self
1044
+ @return the number of columns (variables) in the lp.
1045
+ */
1046
+ static VALUE lpsolve_get_presolve(VALUE self);
1047
+ LPSOLVE_0_IN_INT_OUT(get_presolve);
1048
+
1049
+ /**
1050
+ A wrapper for get_presolveloops().
1051
+
1052
+ Returns the number of times presolve is may be iterated. After a
1053
+ presolve is performed, another presolve may result in elimination
1054
+ of more rows and columns. This number specifies the maximum
1055
+ number of times this process may be repeated.
1056
+
1057
+ By default presolve repetition is performed until no simplification
1058
+ is done.
1059
+
1060
+ @param self self
1061
+ @return maximum number of presolve loops. A value of -1 means we
1062
+ loop for as many times as there is improvement.
1063
+ */
1064
+ static VALUE lpsolve_get_presolveloops(VALUE self);
1065
+ LPSOLVE_0_IN_INT_OUT(get_presolveloops);
1066
+
1067
+ /** A wrapper for get_row().
1068
+
1069
+ Get all row elements from the matrix for a given row number.
1070
+
1071
+ @param self self
1072
+
1073
+ @param row_num the row number that you want. The value must be
1074
+ between 1 and the number of rows.
1075
+
1076
+ @return an array of the row values. The size of the array is
1077
+ the number of columns + 1. Nil is returned if there was an error.
1078
+ */
1079
+ static VALUE
1080
+ lpsolve_get_row(VALUE self, VALUE row_num)
1081
+ {
1082
+ unsigned int i_row = FIX2INT(row_num);
1083
+ unsigned int i_columns;
1084
+ REAL *p_row;
1085
+
1086
+ INIT_LP;
1087
+
1088
+ if (TYPE(row_num) != T_FIXNUM) {
1089
+ report(lp, IMPORTANT,
1090
+ "%s: row number, parameter 1, is not a number.\n", __FUNCTION__);
1091
+ return Qnil;
1092
+ }
1093
+ i_columns = get_Ncolumns(lp); /* Yep, Ncolumns, not Nrows. */
1094
+ p_row = ALLOC_N(REAL, i_columns + 1);
1095
+
1096
+ if (!get_row(lp, i_row, p_row)) {
1097
+ free(p_row);
1098
+ return Qnil;
1099
+ } else {
1100
+ VALUE ret_ary = rb_ary_new2(i_columns+1);
1101
+ unsigned int i;
1102
+ for (i=0; i<=i_columns; i++) {
1103
+ rb_ary_push(ret_ary, rb_float_new(p_row[i]));
1104
+ }
1105
+ free(p_row);
1106
+ return ret_ary;
1107
+ }
1108
+
1109
+ }
1110
+
1111
+ /** A wrapper for get_row_name()
1112
+
1113
+ @param self self
1114
+ @param row_num row number
1115
+
1116
+ @return the name of the specified row. A return value of NULL
1117
+ indicates an error. The difference between lpsolve_get_row_name()
1118
+ and lpsolve_get_origrow_name() is only visible when a presolve
1119
+ (set_presolve) was done. Presolve can result in deletion of rows
1120
+ in the model. In lpsolve_get_row_name(), row specifies the row
1121
+ number after presolve was done. In lpsolve_aget_origrow_name(),
1122
+ row specifies the row number before presolve was done, ie the
1123
+ original row number. If presolve is not active then both functions
1124
+ are equal. Returns a Ruby string row name.
1125
+ */
1126
+ static VALUE
1127
+ lpsolve_get_row_name(VALUE self, VALUE row_num)
1128
+ {
1129
+ char *psz_col_name;
1130
+ INIT_LP;
1131
+ if (TYPE(row_num) != T_FIXNUM) {
1132
+ report(lp, IMPORTANT,
1133
+ "%s: row number, parameter 1, is not a number.\n", __FUNCTION__);
1134
+ return Qnil;
1135
+ }
1136
+ psz_col_name = get_row_name(lp, FIX2INT(row_num));
1137
+ return psz_col_name ? rb_str_new2(psz_col_name) : Qnil;
1138
+ }
1139
+
1140
+ /** A wrapper for get_scaling().
1141
+
1142
+ @param self self
1143
+ @return A Ruby integer indicating scaling algorithm is used.
1144
+
1145
+ In Ruby, you can also use accessor function scaling.
1146
+ */
1147
+ static VALUE lpsolve_get_scaling(VALUE self);
1148
+ LPSOLVE_0_IN_INT_OUT(get_scaling)
1149
+
1150
+ /**
1151
+ A wrapper for get_simplextype()
1152
+
1153
+ get_simplextype returns the desired combination of primal and dual
1154
+ simplex algorithms.
1155
+
1156
+ The default is SIMPLEX_DUAL_PRIMAL.
1157
+
1158
+ In Ruby, you can also use accessor function simplextype.
1159
+
1160
+ @param self self
1161
+
1162
+ @return a Ruby integer simplex type which is one of the following
1163
+ values:
1164
+ \a LPSolve::SIMPLEX_PRIMAL_PRIMAL,
1165
+ \a LPSolve::DUAL_PRIMAL,
1166
+ \a LPSolve::PRIMAL_DUAL,
1167
+ \a LPSolve::DUAL_DUAL
1168
+
1169
+ */
1170
+ static VALUE lpsolve_get_simplextype(VALUE self);
1171
+ LPSOLVE_0_IN_INT_OUT(get_simplextype)
1172
+
1173
+ /**
1174
+ A wrapper for get_solutioncount().
1175
+
1176
+ Returns the number of equal solutions. This is only valid if there
1177
+ are integer, semi-continious or SOS variables in the model so that
1178
+ the branch-and-bound algoritm is used. This count gives the number
1179
+ of solutions with the same optimal objective value. If there is
1180
+ only one optimal solution, this value is 1.
1181
+
1182
+ @param self self
1183
+
1184
+ @return the number of equal solutions to to
1185
+ lpsolve_get_solutionlimit.
1186
+
1187
+ */
1188
+ static VALUE lpsolve_get_solutioncount(VALUE self);
1189
+ LPSOLVE_0_IN_INT_OUT(get_solutioncount)
1190
+
1191
+ /**
1192
+ A wrapper for get_solutionlimit().
1193
+
1194
+ returns the number of solutions that must be returned.
1195
+
1196
+ @param self self
1197
+
1198
+ @return the number of solutions that must be returned.
1199
+
1200
+ This is only valid if there are integer, semi-continious or SOS
1201
+ variables in the model so that the branch-and-bound algoritm is
1202
+ used. If there are more solutions with the same objective value,
1203
+ then this number specifies which solution must be returned. This
1204
+ can be used to retrieve all possible solutions. Start with 1 till
1205
+ get_solutioncount
1206
+
1207
+ */
1208
+ static VALUE lpsolve_get_solutionlimit(VALUE self);
1209
+ LPSOLVE_0_IN_INT_OUT(get_solutionlimit)
1210
+
1211
+ /**
1212
+ return the status of the last solve.
1213
+ @param self self
1214
+ @return A return status number of the last solve.
1215
+ */
1216
+ static VALUE lpsolve_get_status(VALUE self)
1217
+ {
1218
+ return rb_ivar_get(self, rb_intern("@status"));
1219
+ }
1220
+
1221
+
1222
+ /**
1223
+ A wrapper for get_statustext(statuscode).
1224
+ However statuscode need not be supplied. If it isn't we use
1225
+ the status code from the last solve.
1226
+
1227
+ @param self self
1228
+ @param statuscode can be omitted or nil or an integer
1229
+ @return string description of statuscode
1230
+
1231
+ In Ruby, you can also use accessor function statustext.
1232
+ */
1233
+ static VALUE lpsolve_get_statustext(int argc, VALUE *argv, VALUE self)
1234
+ {
1235
+ VALUE statuscode;
1236
+ unsigned int i_scanned;
1237
+ int i_statuscode;
1238
+ INIT_LP;
1239
+ if ((argc > 1) || (argc < 0))
1240
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 or 1)", argc);
1241
+ i_scanned = rb_scan_args(argc, argv, "01", &statuscode);
1242
+ switch (i_scanned) {
1243
+ case 0:
1244
+ statuscode = rb_ivar_get(self, rb_intern("@status"));
1245
+ break;
1246
+ case 1:
1247
+ if (statuscode != Qnil)
1248
+ statuscode = rb_ivar_get(self, rb_intern("@status"));
1249
+ else if (TYPE(statuscode) != T_FIXNUM) {
1250
+ report(lp, IMPORTANT, "%s: Parameter is not nil or an integer.\n",
1251
+ __FUNCTION__);
1252
+ return Qnil;
1253
+ }
1254
+ break;
1255
+ default:
1256
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 or 1)",
1257
+ i_scanned);
1258
+ }
1259
+
1260
+ i_statuscode = FIX2INT(statuscode);
1261
+ if (i_statuscode == SOLVE_NOT_CALLED)
1262
+ return rb_str_new2("LPSolve method solve() not performed yet.");
1263
+ else
1264
+ return rb_str_new2(get_statustext(lp, FIX2INT(statuscode)));
1265
+ }
1266
+
1267
+ /** A wrapper for get_timeout().
1268
+
1269
+ @param self self
1270
+ @return the number of seconds after which a timeout occurs.
1271
+ */
1272
+ static VALUE lpsolve_get_timeout(VALUE self);
1273
+ LPSOLVE_0_IN_NUM_OUT(get_timeout);
1274
+
1275
+ /** A wrapper for get_timeout().
1276
+
1277
+ Returns the total number of iterations with Branch-and-bound of
1278
+ the last solution.
1279
+
1280
+ @param self self
1281
+
1282
+ @return the total number of iterations with Branch-and-bound of
1283
+ the last solution.
1284
+ */
1285
+ static VALUE lpsolve_get_total_iter(VALUE self);
1286
+ LPSOLVE_0_IN_NUM_OUT(get_total_iter);
1287
+
1288
+ /** A wrapper for get_upbo().
1289
+
1290
+ Returns the upper bound on the variable identified by column.
1291
+ Setting a bound on a variable is the way to go instead of adding an
1292
+ extra constraint (row) to the model. Setting a bound doesn't
1293
+ increase the model size that means that the model stays smaller and
1294
+ will be solved faster. The default upper bound of a variable is
1295
+ infinity (well not quite. It is a very big number. The value of
1296
+ lpsolve_get_infinite().
1297
+
1298
+ @param self self
1299
+
1300
+ @param column_num the column number of the variable. It must be
1301
+ between 1 and the number of columns in the lp.
1302
+
1303
+ */
1304
+
1305
+ static VALUE lpsolve_get_upbo(VALUE self, VALUE column_num);
1306
+ LPSOLVE_1_IN_NUM_OUT(get_upbo, T_FIXNUM, "an integer", FIX2INT);
1307
+
1308
+ /** A wrapper for get_var_dualresult()
1309
+
1310
+
1311
+
1312
+ @param self self
1313
+ @param index index
1314
+
1315
+ @return returns the reduced cost.
1316
+
1317
+ In contrast to get_dual_solution, the original index number is
1318
+ preserved.
1319
+ */
1320
+ static VALUE lpsolve_get_var_dualresult(VALUE self, VALUE index);
1321
+ LPSOLVE_1_IN_NUM_OUT(get_var_dualresult, T_FIXNUM, "an integer", FIX2INT);
1322
+
1323
+ /** A wrapper for get_var_primalresult()
1324
+
1325
+ @param self self
1326
+ @param index index
1327
+
1328
+ @return the name of the specified row. A return value of NULL
1329
+ indicates an error. The difference between lpsolve_get_row_name()
1330
+ and lpsovle_get_origrow_name() is only visible when a presolve
1331
+ (set_presolve) was done. Presolve can result in deletion of rows
1332
+ in the model. In lpsolve_get_row_name(), row specifies the row
1333
+ number after presolve was done. In lpsovle_aget_origrow_name(),
1334
+ row specifies the row number before presolve was done, ie the
1335
+ original row number. If presolve is not active then both functions
1336
+ are equal. Returns a Ruby string row name.
1337
+
1338
+ Retrieve the a value of the objective function, constraints and variables.
1339
+ These values are only valid after a successful solve or lag_solve.
1340
+
1341
+ In contrast to get_primal_solution, the original index number is
1342
+ preserved.
1343
+ */
1344
+ static VALUE lpsolve_get_var_primalresult(VALUE self, VALUE index);
1345
+ LPSOLVE_1_IN_NUM_OUT(get_var_primalresult, T_FIXNUM, "an integer", FIX2INT);
1346
+
1347
+ /** A wrapper for get_variables().
1348
+
1349
+ Get the values of the variables.
1350
+ @param self self
1351
+
1352
+ @return an array of the variable values. The size of the array is
1353
+ the number of columns + 1. Nil is returned if there was an error.
1354
+ */
1355
+ static VALUE
1356
+ lpsolve_get_variables(VALUE self)
1357
+ {
1358
+ unsigned int i_columns;
1359
+ REAL *p_variables;
1360
+
1361
+ INIT_LP;
1362
+ i_columns = get_Ncolumns(lp);
1363
+
1364
+ if (!get_ptr_variables(lp, &p_variables)) {
1365
+ return Qnil;
1366
+ } else {
1367
+ VALUE ret_ary = rb_ary_new2(i_columns);
1368
+ unsigned int i;
1369
+ for (i=0; i<i_columns; i++) {
1370
+ rb_ary_push(ret_ary, rb_float_new(p_variables[i]));
1371
+ }
1372
+ return ret_ary;
1373
+ }
1374
+
1375
+ }
1376
+
1377
+ /** A wrapper for get_verbose()
1378
+
1379
+ get_verbose returns the current verbose level. Can be one of the
1380
+ following values:
1381
+ \a LPSolve::NEUTRAL, \a LPSolve::CRITICAL, \a LPSolve::SEVERE,
1382
+ \a LPSolve::IMPORTANT, \a LPSolve::NORMAL, \a LPSolve::DETAILED, or
1383
+ \a LPSolve::FULL
1384
+
1385
+ How much information is reported depends on the verbose level. The
1386
+ default verbose level is \a LPSOLVE::NORMAL. lp_solve determines
1387
+ how verbose a given message is. For example specifying a wrong
1388
+ row/column index values is considered as a \a LPSOLVE::SEVERE
1389
+ error. All messages equal to and below the set level are reported.
1390
+ The default reporting device is the console screen. It is possible
1391
+ to set a used defined reporting routine via lpsolve_put_logfunc().
1392
+
1393
+ In Ruby, you can also use accessor function verbose.
1394
+
1395
+ @param self self
1396
+ @return a Ruby integer verbosity level.
1397
+
1398
+ */
1399
+ static VALUE lpsolve_get_verbose(VALUE self);
1400
+ LPSOLVE_0_IN_INT_OUT(get_verbose)
1401
+
1402
+ static VALUE
1403
+ lpsolve_initialize(VALUE self, VALUE num_vars, VALUE num_constraints)
1404
+ {
1405
+ int i_vars = NUM2INT(num_vars);
1406
+ int i_constraints = NUM2INT(num_constraints);
1407
+ lprec *lp = make_lp(i_vars, i_constraints);
1408
+ DATA_PTR(self) = lp;
1409
+ rb_ivar_set(self, rb_intern("@status"), INT2FIX(SOLVE_NOT_CALLED));
1410
+ return self;
1411
+ }
1412
+
1413
+ /** A wrapper for is_debug().
1414
+
1415
+ Returns a flag if all intermediate results and the
1416
+ branch-and-bound decisions must be printed while solving. This
1417
+ function is meant for debugging purposes. The default is not to
1418
+ debug.
1419
+
1420
+ Returns a flag if
1421
+ @param self self
1422
+
1423
+ @return true, false, or nil on error. If true is returned, all
1424
+ intermediate results and the branch-and-bound decisions will be
1425
+ printed while solving.
1426
+ */
1427
+ static VALUE lpsolve_is_debug(VALUE self);
1428
+ LPSOLVE_0_IN_BOOL_OUT(is_debug);
1429
+
1430
+ /** A wrapper for is_maxim().
1431
+
1432
+ @param self self
1433
+ @return boolean or nil on error.
1434
+ */
1435
+ static VALUE lpsolve_is_maxim(VALUE self);
1436
+ LPSOLVE_0_IN_BOOL_OUT(is_maxim);
1437
+
1438
+ /** A wrapper for is_SOS_var().
1439
+
1440
+ Returns if a variable is a SOS variable or not. By default a variable
1441
+ is not SOS. A variable becomes a SOS variable via lpsolve_add_SOS().
1442
+
1443
+ @param column the column number of the variable to be checked. It
1444
+ should be between 1 and the number of columns in the lp.
1445
+ @param self self
1446
+ @return boolean or nil on error.
1447
+ */
1448
+ static VALUE lpsolve_is_SOS_var(VALUE self, VALUE column);
1449
+ LPSOLVE_1_IN_BOOL_OUT(is_SOS_var, T_FIXNUM, "an integer", FIX2INT)
1450
+
1451
+ static void __WINAPI
1452
+ lpsolve_logfunction(lprec *lp, void *userhandle, char *buf)
1453
+ {
1454
+ printf("***%s\n", buf);
1455
+ }
1456
+
1457
+ /**
1458
+ Constructs a new LP. Sets all variables to initial values. The LP
1459
+ has rows rows and columns columns. The matrix contains no values,
1460
+ but space for one value. All arrays that depend on rows and columns
1461
+ are allocated.
1462
+
1463
+ @param class_or_model_name either the class or module name which this
1464
+ is to belong to (it will be equal to LPSolve or LPsolve). If you are
1465
+ calling from Ruby, this parameter will be taken care of automatically.
1466
+ @param num_vars number of variables or columns
1467
+ @param num_constraints number of constraints or rows
1468
+
1469
+ @return nil is returned if there was an error.
1470
+ */
1471
+
1472
+ static VALUE
1473
+ lpsolve_make_lp(VALUE class_or_model_name, VALUE num_constraints,
1474
+ VALUE num_vars)
1475
+ {
1476
+ int i_constraints = NUM2INT(num_constraints);
1477
+ int i_vars = NUM2INT(num_vars);
1478
+ lprec *lp = make_lp(i_constraints, i_vars);
1479
+ if (NULL == lp) {
1480
+ return Qnil;
1481
+ } else {
1482
+ VALUE obj = lpsolve_alloc(rb_cLPSolve);
1483
+ DATA_PTR(obj) = lp;
1484
+ return obj;
1485
+ }
1486
+ }
1487
+
1488
+ /** A wrapper for print_duals().
1489
+
1490
+ @param self self
1491
+ @return \a true unless we have an error.
1492
+ */
1493
+ LPSOLVE_0_IN_STATUS_OUT(print_duals)
1494
+
1495
+ /** A wrapper for print_debugdump().
1496
+
1497
+ The print_debugdump function creates a generic readable data dump
1498
+ of key lp_solve model variables; principally for run difference and
1499
+ debugging purposes This function is meant for debugging purposes.
1500
+
1501
+ @return \a true if we could write the output file.
1502
+ */
1503
+ static VALUE lpsolve_print_debugdump(VALUE self, VALUE filename);
1504
+ LPSOLVE_1_STR_IN_BOOL_OUT(print_debugdump)
1505
+
1506
+ /** A wrapper for print_lp.
1507
+
1508
+ @param self self
1509
+ @return \a true unless we have an error.
1510
+ */
1511
+ static VALUE lpsolve_print_lp(VALUE self);
1512
+ LPSOLVE_0_IN_STATUS_OUT(print_lp)
1513
+
1514
+ static VALUE lpsolve_print(VALUE self);
1515
+ void print(lprec *lp);
1516
+ LPSOLVE_0_IN_STATUS_OUT(print)
1517
+
1518
+ /** A wrapper for print_constraints.
1519
+ @param self self
1520
+ @param num constraint number.
1521
+ @return \a true unless we have an error.
1522
+ */
1523
+ static VALUE lpsolve_print_constraints(VALUE self, VALUE num);
1524
+ LPSOLVE_1_IN_STATUS_OUT(print_constraints, FIX2INT(param1));
1525
+
1526
+ /** A wrapper for print_logfunc
1527
+ @return nil.
1528
+ */
1529
+ static VALUE
1530
+ lpsolve_put_logfunc(VALUE self, VALUE logfunc_name)
1531
+ {
1532
+ lprec *lp;
1533
+ rb_define_readonly_variable("@logfunc_name", &logfunc_name);
1534
+ Data_Get_Struct(self, lprec, lp);
1535
+ put_logfunc(lp, lpsolve_logfunction, NULL);
1536
+ return Qnil;
1537
+ }
1538
+
1539
+ /** A wrapper for print_objective.
1540
+ @return nil.
1541
+ */
1542
+ LPSOLVE_0_IN_STATUS_OUT(print_objective)
1543
+
1544
+ /** A wrapper for print_tableau().
1545
+
1546
+ The print_tableau function prints the tableau. This function only
1547
+ works after a successful solve This function is meant for
1548
+ debugging purposes. By default, the output is stdout. However this
1549
+ can be changed via a call to set_outputstream, set_outputfile.
1550
+
1551
+ @param self self
1552
+ @return \a true unless we have an error.
1553
+ */
1554
+ LPSOLVE_0_IN_STATUS_OUT(print_tableau)
1555
+
1556
+ /** A wrapper for read_LP.
1557
+
1558
+ Create a LPSolve object and read an lp model from file.
1559
+
1560
+ Returns anew LPSolve object. A Nil return value indicates an
1561
+ error. Specifically file could not be opened or file has wrong
1562
+ structure or not enough memory available to setup an lprec
1563
+ structure.
1564
+
1565
+ */
1566
+ static VALUE
1567
+ lpsolve_read_LP(VALUE model, VALUE filename, VALUE verbosity,
1568
+ VALUE model_name)
1569
+ {
1570
+ lprec *lp;
1571
+
1572
+ if (TYPE(filename) != T_STRING) {
1573
+ return Qnil;
1574
+ }
1575
+
1576
+ if (TYPE(verbosity) != T_FIXNUM) {
1577
+ return Qnil;
1578
+ }
1579
+
1580
+ if (TYPE(model_name) != T_STRING) {
1581
+ return Qnil;
1582
+ }
1583
+
1584
+ lp = read_LP(RSTRING_PTR(filename), verbosity, RSTRING_PTR(model_name));
1585
+ if (NULL == lp) {
1586
+ return Qnil;
1587
+ } else {
1588
+ VALUE obj = lpsolve_alloc(rb_cLPSolve);
1589
+ DATA_PTR(obj) = lp;
1590
+ return obj;
1591
+ }
1592
+ }
1593
+
1594
+ /** A wrapper for read_MPS.
1595
+
1596
+ Create a LPSolve object and read an MPS model from a file.
1597
+
1598
+ Returns a new LPSolve Object. A Nil return value indicates an
1599
+ error. Specifically file could not be opened or file has wrong
1600
+ structure or not enough memory available to setup an lprec
1601
+ structure.
1602
+
1603
+ */
1604
+ static VALUE
1605
+ lpsolve_read_MPS(VALUE module, VALUE filename, VALUE verbosity)
1606
+ {
1607
+ lprec *lp;
1608
+
1609
+ if (TYPE(filename) != T_STRING) {
1610
+ return Qnil;
1611
+ }
1612
+
1613
+ if (TYPE(verbosity) != T_FIXNUM) {
1614
+ return Qnil;
1615
+ }
1616
+
1617
+ lp = read_MPS(RSTRING_PTR(filename), verbosity);
1618
+ if (NULL == lp) {
1619
+ return Qnil;
1620
+ } else {
1621
+ VALUE obj = lpsolve_alloc(rb_cLPSolve);
1622
+ DATA_PTR(obj) = lp;
1623
+ return obj;
1624
+ }
1625
+ }
1626
+
1627
+ /** A wrapper for print_str
1628
+
1629
+ Prints a string. By default, the output is stdout. However this
1630
+ can be changed via a call to lpsolve_set_outputfile(). Possibly
1631
+ useful for debugging/demo purposes.
1632
+
1633
+ @param self self
1634
+ @param str the string to print
1635
+
1636
+ @return \a true if string was printed; false on error such as the
1637
+ str parameter is not a string type.
1638
+ */
1639
+ static VALUE
1640
+ lpsolve_print_str(VALUE self, VALUE str)
1641
+ {
1642
+ lprec *lp;
1643
+ Data_Get_Struct(self, lprec, lp);
1644
+
1645
+ if (TYPE(str) != T_STRING) {
1646
+ report(lp, IMPORTANT,
1647
+ "%s: parameter 2 is not a string.\n",
1648
+ __FUNCTION__);
1649
+ return Qfalse;
1650
+ }
1651
+
1652
+ print_str(lp, RSTRING_PTR(str));
1653
+ return Qtrue;
1654
+ }
1655
+
1656
+ /** A wrapper for print_solution.
1657
+
1658
+ Prints the solution (variables) of the lp. This can only be done
1659
+ after a successful solve. This function is meant for debugging
1660
+ purposes. By default, the output is stdout. However this can be
1661
+ changed via a call to lpsolve_set_outputfile().
1662
+
1663
+ @param self self
1664
+ @param columns Number of columns to use in printing the solution.
1665
+ if columns is negative we will only print those variables which are
1666
+ nonzero.
1667
+
1668
+ @return \a true unless we have an error.
1669
+ */
1670
+ static VALUE lpsolve_print_solution(VALUE self, VALUE columns);
1671
+ static VALUE
1672
+ lpsolve_print_solution(VALUE self, VALUE columns)
1673
+ {
1674
+ lprec *lp;
1675
+ int i_columns = FIX2INT(columns);
1676
+ Data_Get_Struct(self, lprec, lp);
1677
+ if (NULL == lp) return Qfalse;
1678
+ if (i_columns < 0) {
1679
+ int print_sol_save = lp->print_sol;
1680
+ lp->print_sol = lp->print_sol | AUTOMATIC;
1681
+ print_solution(lp, -i_columns);
1682
+ lp->print_sol = print_sol_save;
1683
+ } else {
1684
+ print_solution(lp, i_columns);
1685
+ }
1686
+ return Qtrue;
1687
+ }
1688
+
1689
+ /** wrapper for set_bb_depthlimit
1690
+
1691
+ Sets the maximum branch-and-bound depth.
1692
+
1693
+ Parameters
1694
+
1695
+ lp
1696
+
1697
+ Pointer to previously created lp model. See return value of make_lp, copy_lp, read_lp, read_LP, read_mps, read_freemps, read_MPS, read_freeMPS, read_XLI
1698
+
1699
+ bb_maxlevel
1700
+
1701
+ Specifies the maximum branch-and-bound depth. A positive value means
1702
+ that the depth is absoluut. A negative value means a relative B&B
1703
+ depth limit. The "order" of a MIP problem is defined to be 2x the
1704
+ number of binary variables plus the number of SC and SOS variables. A
1705
+ relative value of -x results in a maximum depth of x times the order
1706
+ of the MIP problem.
1707
+
1708
+ Remarks
1709
+
1710
+ The set_bb_depthlimit function sets the maximum branch-and-bound
1711
+ depth. This is only useful if there are integer, semi-continious or
1712
+ SOS variables in the model so that the branch-and-bound algorithm must
1713
+ be used to solve them. The branch-and-bound algorithm will not go
1714
+ deeper than this level. When 0 then there is no limit to the
1715
+ depth. Limiting the depth will speed up solving time, but there is a
1716
+ chance that the found solution is not the most optimal one. Be aware
1717
+ of this. It can also result in not finding a solution at all. The
1718
+ default is -50.
1719
+ */
1720
+ static VALUE lpsolve_set_bb_depthlimit(VALUE self, VALUE limit);
1721
+ LPSOLVE_1_IN_STATUS_OUT(set_bb_depthlimit, FIX2INT(param1));
1722
+
1723
+ /** wrapper for set_bb_bb_rule
1724
+
1725
+ The set_bb_rule function specifies the branch-and-bound rule for
1726
+ choosing which non-integer variable is to be selected. This rule can
1727
+ influence solving times considerably. Depending on the model one rule
1728
+ can be best and for another model another rule. The default is
1729
+ NODE_FIRSTSELECT (0).
1730
+
1731
+ */
1732
+ static VALUE lpsolve_set_bb_rule(VALUE self, VALUE bb_rule);
1733
+ LPSOLVE_1_IN_STATUS_OUT(set_bb_rule, FIX2INT(param1));
1734
+
1735
+ /** A wrapper for set_add_rowmode().
1736
+
1737
+ Normally a model is built either column by column or row by row.
1738
+
1739
+ The default \a on_off setting is \a false, which assumes model
1740
+ building column by column. So lpsolve_add_column(),
1741
+ lpsolve_add_columnex(), and lpsolve_str_add_column() perform best
1742
+ here.
1743
+
1744
+ If the model is built row by row via lpsolve_add_constraint(),
1745
+ lpsolve_add_constraintex(), or lpsolve_str_add_constraint() calls,
1746
+ then these routines will be much faster if this routine is called
1747
+ with \a on_off set \a true. The speed improvement is spectacular,
1748
+ especially for bigger models, so it is advisable to call this
1749
+ routine to set the mode.
1750
+
1751
+ There are several restrictions with this mode. Only use this
1752
+ function after lpsolve_make_lp() is called, not when the model is
1753
+ read from a file. Also, if this function is used, first add the
1754
+ objective function via set_obj_fn, set_obj_fnex, str_set_obj_fn
1755
+ and after that add the constraints via add_constraint,
1756
+ add_constraintex, str_add_constraint. Don't call other API
1757
+ functions while in row entry mode. No other data matrix access is
1758
+ allowed while in row entry mode. After adding the contraints, turn
1759
+ row entry mode back off. Once turned off, you cannot switch back to
1760
+ row entry mode. So in short: - turn row entry mode on - set the
1761
+ objective function - create the constraints - turn row entry mode
1762
+ off
1763
+
1764
+ @param self self
1765
+ @param on_off \a true if are going to add by rows, \a false if not
1766
+ or addign by columns.
1767
+
1768
+ @return \a true if changed from mode and \a false if this mode was
1769
+ already set; \a nil if there was an error
1770
+ */
1771
+ static VALUE lpsolve_set_add_rowmode(VALUE self, VALUE on_off);
1772
+ LPSOLVE_1_BOOL_IN_BOOL_OUT(set_add_rowmode);
1773
+
1774
+ /** A wrapper for set_binary().
1775
+
1776
+ Set the type of the variable to be binary or floating point.
1777
+ The default type of a variable is floating point.
1778
+
1779
+ @param self self
1780
+
1781
+ @param column_num column number.
1782
+
1783
+ @param new_bool \a true if you want the column (variable) to take
1784
+ on a binary value, \a false or \a nil if you want the column to
1785
+ take on a floating-point value. If no value is given we assume \a
1786
+ true (set to binary).
1787
+
1788
+ @return \a true if the operation was successful, \a false if there
1789
+ was an error.
1790
+ */
1791
+ #if 0
1792
+ LPSOLVE_SET_VARTYPE(set_binary)
1793
+ #endif
1794
+
1795
+ /** A wrapper for set_bounds().
1796
+
1797
+ The set_bounds function sets a lower and upper bound on the
1798
+ variable identified by column. Setting a bound on a variable is
1799
+ the way to go instead of adding an extra constraint (row) to the
1800
+ model. Setting a bound doesn't increase the model size that means
1801
+ that the model stays smaller and will be solved faster. Note that
1802
+ the default lower bound of each variable is 0. So variables will
1803
+ never take negative values if no negative lower bound is set. The
1804
+ default upper bound of a variable is infinity (well not quite. It
1805
+ is a very big number. The value of get_infinite).
1806
+
1807
+ @return \a true if no errors.
1808
+ */
1809
+ static VALUE
1810
+ lpsolve_set_bounds(VALUE self, VALUE column_num, VALUE lower_bound,
1811
+ VALUE upper_bound)
1812
+ {
1813
+ INIT_LP;
1814
+ if (TYPE(column_num) != T_FIXNUM) {
1815
+ report(lp, IMPORTANT,
1816
+ "%s: column number, parameter 1, is not an integer.\n",
1817
+ __FUNCTION__);
1818
+ return Qfalse;
1819
+ }
1820
+
1821
+ RETURN_BOOL(set_bounds(lp, FIX2INT(column_num),
1822
+ NUM2DBL(lower_bound), NUM2DBL(upper_bound)));
1823
+ }
1824
+
1825
+ /** A wrapper for set_col_name
1826
+ Returns a Ruby string column name.
1827
+ */
1828
+ static VALUE
1829
+ lpsolve_set_col_name(VALUE self, VALUE column_num, VALUE new_name)
1830
+ {
1831
+ INIT_LP;
1832
+
1833
+ if (TYPE(column_num) != T_FIXNUM) {
1834
+ report(lp, IMPORTANT,
1835
+ "%s: column number, parameter 1, is not an integer.\n",
1836
+ __FUNCTION__);
1837
+ return Qnil;
1838
+ }
1839
+
1840
+ if (TYPE(new_name) != T_STRING) {
1841
+ report(lp, IMPORTANT,
1842
+ "%s: new name, parameter 2, is not a string.\n",
1843
+ __FUNCTION__);
1844
+ return Qnil;
1845
+ }
1846
+
1847
+ return set_col_name(lp, FIX2INT(column_num), RSTRING_PTR(new_name)) ?
1848
+ Qtrue: Qfalse;
1849
+ }
1850
+
1851
+ /** A wrapper for set_debug
1852
+
1853
+ Sets a flag if all intermediate results and the branch-and-bound
1854
+ decisions must be printed while solving.
1855
+
1856
+ @return \a true if no errors, false if an error (e.g. you didn't
1857
+ pass true or false).
1858
+ */
1859
+ static VALUE
1860
+ lpsolve_set_debug(VALUE self, VALUE new_bool)
1861
+ {
1862
+ if (new_bool != Qtrue && new_bool != Qfalse) {
1863
+ return Qfalse;
1864
+ } else {
1865
+ INIT_LP;
1866
+ set_debug(lp, Qtrue == new_bool);
1867
+ return Qtrue;
1868
+ }
1869
+ }
1870
+
1871
+ /** A wrapper for set_int
1872
+
1873
+ Set the type of the variable to be integer or floating point.
1874
+ The default type of a variable is floating point.
1875
+
1876
+ The argument \a new_bool specifies what the status of the variable
1877
+ becomes. From the moment there is at least one integer variable in
1878
+ the model, the Branch and Bound algorithm is used to make these
1879
+ variables integer. Note that solving times can be considerably
1880
+ larger when there are integer variables.
1881
+
1882
+ @param self self
1883
+
1884
+ @param column_num column number of variable
1885
+
1886
+ @param new_bool \a true if you want the column (variable) to be an
1887
+ integer, \a false or \a nil if you want the column not to take on
1888
+ a floating-point value. If no parameter is given, we assumed it
1889
+ to be true (set to integer).
1890
+
1891
+ @param new_bool
1892
+
1893
+ @return \a true if the operation was successful, \a false if there
1894
+ was an error.
1895
+ */
1896
+ LPSOLVE_SET_VARTYPE(set_int)
1897
+
1898
+ /** A wrapper for set_lp_name
1899
+
1900
+ Set the name of the lp. Returns true if the operation was
1901
+ successful. A return value of false indicates an error.
1902
+ */
1903
+ static VALUE lpsolve_set_lp_name(VALUE self, VALUE model_name);
1904
+ LPSOLVE_1_STR_IN_BOOL_OUT(set_lp_name)
1905
+
1906
+ /** A wrapper for set_lowbo().
1907
+ @return \a true if no errors.
1908
+ */
1909
+ static VALUE
1910
+ lpsolve_set_lowbo(VALUE self, VALUE column, VALUE val)
1911
+ {
1912
+ INIT_LP;
1913
+ if (TYPE(column) != T_FIXNUM) {
1914
+ report(lp, IMPORTANT,
1915
+ "%s: column number, parameter 1, is not an integer.\n",
1916
+ __FUNCTION__);
1917
+ return Qnil;
1918
+ }
1919
+ RETURN_BOOL(set_lowbo(lp, FIX2INT(column), NUM2DBL(val)));
1920
+ }
1921
+
1922
+ /** A wrapper for set_mat().
1923
+ @return \a true if no errors.
1924
+ */
1925
+ static VALUE
1926
+ lpsolve_set_mat(VALUE self, VALUE row, VALUE column, VALUE val)
1927
+ {
1928
+ INIT_LP;
1929
+ RETURN_BOOL(set_mat(lp, FIX2INT(row), FIX2INT(column), NUM2DBL(val)));
1930
+ }
1931
+
1932
+ /** A wrapper for set_maxim().
1933
+
1934
+ Sets the objective direction to maximize. The default is to
1935
+ minimize, except when reading a model in via lpsolve_read_LP.
1936
+
1937
+ @return \a true unless we have an error.
1938
+ */
1939
+ static VALUE lpsolve_set_maxim(VALUE self);
1940
+ LPSOLVE_0_IN_STATUS_OUT(set_maxim)
1941
+
1942
+ /** A wrapper for set_minim().
1943
+
1944
+ Sets the objective direction to minimize. The default is to
1945
+ minimize, except when reading a model in via lpsolve_read_LP.
1946
+
1947
+ @return \a true unless we have an error.
1948
+ */
1949
+ static VALUE lpsolve_set_minim(VALUE self);
1950
+ LPSOLVE_0_IN_STATUS_OUT(set_minim)
1951
+
1952
+ /** A wrapper for set_mip_gap().
1953
+
1954
+ Sets the MIP gap that specifies a tolerance for the branch and bound
1955
+ algorithm. This tolerance is the difference between the best-found
1956
+ solution yet and the current solution. If the difference is smaller
1957
+ than this tolerance then the solution (and all the sub-solutions) is
1958
+ rejected. This can result in faster solving times, but results in a
1959
+ solution which is not the perfect solution. So be careful with this
1960
+ tolerance. The default mip_gap value is 1e-9
1961
+
1962
+
1963
+ @param self self
1964
+ @param abs_rel: set to true if the gap is absolute, or false for relative.
1965
+ @param val: gap value. The default mip_gap is 1e-9.
1966
+ @return \a true if no errors.
1967
+ */
1968
+ static VALUE
1969
+ lpsolve_set_mip_gap(VALUE self, VALUE abs_rel, VALUE val)
1970
+ {
1971
+ INIT_LP;
1972
+ if (abs_rel != Qtrue && abs_rel != Qfalse && abs_rel != Qnil) {
1973
+ report(lp, IMPORTANT,
1974
+ "%s: Parameter is not a boolean or nil.\n",
1975
+ __FUNCTION__);
1976
+ return Qfalse;
1977
+ } else {
1978
+ set_mip_gap(lp, Qtrue == abs_rel, NUM2DBL(val));
1979
+ return Qtrue;
1980
+ }
1981
+ }
1982
+
1983
+ /** A wrapper for str_set_obj_fn().
1984
+
1985
+ Set the objective function (row 0) of the matrix.
1986
+
1987
+ @return \a true unless we have an error, then \a nil or \a false.
1988
+ */
1989
+ static VALUE
1990
+ lpsolve_set_obj_fnex(VALUE self, VALUE row_coeffs)
1991
+ {
1992
+ REAL *row = NULL;
1993
+ int *colno = NULL;
1994
+ long int i, count;
1995
+ VALUE ret = Qnil;
1996
+ VALUE *p_row_coeff = NULL;
1997
+
1998
+ INIT_LP;
1999
+
2000
+ /***FIXME: combine common parts of this with add_constraintex ****/
2001
+ if (TYPE(row_coeffs) != T_ARRAY) {
2002
+ report(lp, IMPORTANT,
2003
+ "%s: row coefficients parameter is not an array.\n",
2004
+ __FUNCTION__);
2005
+ return Qnil;
2006
+ }
2007
+
2008
+ count = RARRAY_LEN(row_coeffs);
2009
+ colno = ALLOC_N(int, count);
2010
+ row = ALLOC_N(REAL, count);
2011
+
2012
+ p_row_coeff = RARRAY_PTR(row_coeffs);
2013
+ for (i = 0; i < count; i++) {
2014
+ int i_col;
2015
+ if (TYPE(*p_row_coeff) != T_ARRAY) {
2016
+ report(lp, IMPORTANT,
2017
+ "%s: row coeffient element %d is not an array.\n",
2018
+ __FUNCTION__, i);
2019
+ goto done;
2020
+ }
2021
+ if (RARRAY_LEN(*p_row_coeff) != 2) {
2022
+ report(lp, IMPORTANT,
2023
+ "%s: row coeffient element %d is not an array tuple.\n",
2024
+ __FUNCTION__, i);
2025
+ goto done;
2026
+ } else {
2027
+ VALUE *tuple = RARRAY_PTR(*p_row_coeff);
2028
+ if (TYPE(tuple[0]) != T_FIXNUM) {
2029
+ report(lp, IMPORTANT,
2030
+ "%s: Column number, first element, of row coefficients at " \
2031
+ "tuple %d is not a integer.\n", __FUNCTION__, i);
2032
+ goto done;
2033
+ }
2034
+ switch (TYPE(tuple[1])) {
2035
+ case T_FIXNUM:
2036
+ case T_FLOAT: break;
2037
+ default:
2038
+ report(lp, IMPORTANT,
2039
+ "%s: Coefficient value, second element, of row coeffients at "
2040
+ "tuple %d is not an integer.\n", __FUNCTION__, i);
2041
+ goto done;
2042
+ }
2043
+
2044
+ i_col = FIX2INT(tuple[0]);
2045
+ if (i_col <= 0 || i_col > lp->columns) {
2046
+ report(lp, IMPORTANT,
2047
+ "%s: Column number, first element, of row coeffients at " \
2048
+ "tuple %d is in the range 1..%d\n",
2049
+ __FUNCTION__, i, lp->columns);
2050
+ goto done;
2051
+ }
2052
+ colno[i] = i_col;
2053
+ row[i] = NUM2DBL(tuple[1]);
2054
+ }
2055
+ p_row_coeff++;
2056
+ }
2057
+
2058
+ ret = set_obj_fnex(lp, count, row, colno) ? Qtrue : Qfalse ;
2059
+
2060
+ done:
2061
+ free(row);
2062
+ free(colno);
2063
+ return ret;
2064
+
2065
+ }
2066
+
2067
+ /** A wrapper for set_outputfile().
2068
+
2069
+ @return \a true if we could set the output file.
2070
+ */
2071
+ static VALUE lpsolve_set_outputfile(VALUE self, VALUE filename);
2072
+ LPSOLVE_1_STR_IN_BOOL_OUT(set_outputfile)
2073
+
2074
+ /** A wrapper for set_presolve().
2075
+
2076
+ @return \a true if no errors.
2077
+ */
2078
+ static VALUE lpsolve_set_presolve(VALUE self, VALUE do_presolve,
2079
+ VALUE maxloops)
2080
+ {
2081
+ INIT_LP;
2082
+ if (TYPE(do_presolve) != T_FIXNUM) {
2083
+ report(lp, IMPORTANT, "%s: Presolve parameter is not a number (bitmask).\n",
2084
+ __FUNCTION__);
2085
+ return Qnil;
2086
+ }
2087
+ if (TYPE(maxloops) != T_FIXNUM ) {
2088
+ report(lp, IMPORTANT,
2089
+ "%s: maxloops parameter should be a number (bitmask).\n",
2090
+ __FUNCTION__);
2091
+ return Qnil;
2092
+ }
2093
+ set_presolve(lp, FIX2INT(do_presolve), FIX2INT(maxloops));
2094
+ return Qtrue;
2095
+ }
2096
+
2097
+
2098
+ /** A wrapper for set_presolve().
2099
+
2100
+ @return \a true if no errors.
2101
+ */
2102
+ static VALUE lpsolve_set_presolve1(VALUE self, VALUE do_presolve)
2103
+ {
2104
+ int i_maxloops;
2105
+ INIT_LP;
2106
+ if (TYPE(do_presolve) != T_FIXNUM) {
2107
+ report(lp, IMPORTANT, "%s: Presolve parameter is not a number (bitmask).\n",
2108
+ __FUNCTION__);
2109
+ return Qnil;
2110
+ }
2111
+ i_maxloops = get_presolveloops(lp);
2112
+ set_presolve(lp, FIX2INT(do_presolve), i_maxloops);
2113
+ return Qtrue;
2114
+ }
2115
+
2116
+
2117
+ /** A wrapper for set_rh().
2118
+
2119
+ (Re)Set the value of the right hand side (RHS) vector (column 0) for
2120
+ the specified row.
2121
+
2122
+ @param self self
2123
+ @param row_num the row number for which the RHS is to be must be set.
2124
+ Must be between 0 and number of rows in the lp.
2125
+
2126
+ @param value The value to set the RHS to.
2127
+
2128
+ @return \a true of no error, or \a nil if there was an error.
2129
+ */
2130
+ static VALUE
2131
+ lpsolve_set_rh(VALUE self, VALUE row_num, VALUE value)
2132
+ {
2133
+ INIT_LP;
2134
+ set_rh(lp, FIX2INT(row_num), NUM2DBL(value));
2135
+ return Qnil;
2136
+ }
2137
+
2138
+ /** A wrapper for set_rh_range().
2139
+
2140
+ Set a range on the constraint (row) identified by row. Setting a
2141
+ range on a row is the way to go instead of another constraint (row) to
2142
+ the model. (Note that in either case, there are two API calls
2143
+ to set the lower and upper bound.
2144
+
2145
+ Setting a range doesn't increase the model size, and that means
2146
+ that the model stays smaller and will be solved faster. If the row
2147
+ previously had a less-than constraint, then the range means setting
2148
+ a minimum on the constraint that is equal to the RHS value minus
2149
+ the range. If the row has a greater-than constraint then the range
2150
+ means setting a maximum on the constraint that is equal to the RHS
2151
+ value plus the range. Note that the range value is the difference
2152
+ value and not the absolute value. Set the value of the right hand
2153
+ side (RHS) vector (column 0) for the specified row.
2154
+
2155
+ @param self self
2156
+ @param row_num the row number for which the RHS is to be must be set.
2157
+ Must be between 0 and number of rows in the lp.
2158
+
2159
+ @param value The value to set the RHS to.
2160
+
2161
+ @return \a true of no error, or \a nil if there was an error.
2162
+ */
2163
+ static VALUE
2164
+ lpsolve_set_rh_range(VALUE self, VALUE row_num, VALUE deltavalue)
2165
+ {
2166
+ INIT_LP;
2167
+ RETURN_BOOL(set_rh_range(lp, FIX2INT(row_num), NUM2DBL(deltavalue)));
2168
+ }
2169
+
2170
+ /** A wrapper for set_row_name.
2171
+
2172
+ Set the name of a constraint (row) in the lp.
2173
+
2174
+ @return \a true if the operation was successful, false if not.
2175
+ */
2176
+ static VALUE
2177
+ lpsolve_set_row_name(VALUE self, VALUE row_num, VALUE new_name)
2178
+ {
2179
+ INIT_LP;
2180
+
2181
+ if (TYPE(new_name) != T_STRING) {
2182
+ return Qfalse;
2183
+ }
2184
+
2185
+ RETURN_BOOL(set_row_name(lp, FIX2INT(row_num), RSTRING_PTR(new_name)));
2186
+ }
2187
+
2188
+ /** A wrapper for set_semicont().
2189
+
2190
+ Set the type of the variable (column) to be semi-continuous or not. By
2191
+ default, a variables are not semi-continuous. Note that a
2192
+ semi-continuous variable should have a nonzero lower bound to for this
2193
+ to have different effect. Recall that the default lower bound on
2194
+ variables is zero. The lower bound may be set before or after setting
2195
+ the semi-continuous status.
2196
+
2197
+ @param self self
2198
+
2199
+ @param column_num column number of the variable
2200
+
2201
+ @param new_bool true if you want the column (variable) to be a
2202
+ semi-continuous value, \a false or \a nil if you want the column
2203
+ not to take on a floating-point value. If no parameter specified,
2204
+ \a true is assumed
2205
+
2206
+ @return \a true if the operation was successful, \a false if there
2207
+ was an error.
2208
+ */
2209
+ LPSOLVE_SET_VARTYPE(set_semicont)
2210
+
2211
+ /**
2212
+ return the status status code of the last solve.
2213
+ @param self self
2214
+ @return A return status number of the last solve.
2215
+ */
2216
+ static VALUE lpsolve_set_status(VALUE self, VALUE newstatus)
2217
+ {
2218
+ INIT_LP;
2219
+ if (FIXNUM_P(newstatus))
2220
+ return rb_ivar_set(self, rb_intern("@status"), newstatus);
2221
+ else
2222
+ report(lp, IMPORTANT,
2223
+ "%s: status should be a Fixnum.\n", __FUNCTION__);
2224
+ return Qnil;
2225
+ }
2226
+
2227
+
2228
+ /** A wrapper for set_timeout().
2229
+
2230
+ In Ruby, you can also use accessor function timeout=.
2231
+
2232
+ The solve() and lag_solve() methods may not last longer than this
2233
+ time or the routines return with a timeout. The default timeout is
2234
+ 0, resulting in no timeout. If a timout occurs, but there was
2235
+ already an integer solution found (that is possibly not the best),
2236
+ then solve will return LPSolve::SUBOPTIMAL. If there was no integer
2237
+ solution found yet or there are no integers or the solvers is
2238
+ still in the first phase where a REAL optimal solution is searched
2239
+ for, then solve will return TIMEOUT.
2240
+
2241
+ Set a timeout for solving .
2242
+ @param self self
2243
+ @param sec_timeout floating-point timeout value in seconds.
2244
+ @return nil.
2245
+ */
2246
+ static VALUE
2247
+ lpsolve_set_timeout(VALUE self, VALUE sec_timeout)
2248
+ {
2249
+ INIT_LP;
2250
+ set_timeout(lp, NUM2DBL(sec_timeout));
2251
+ return Qnil;
2252
+ }
2253
+
2254
+ /** A wrapper for set_scaling().
2255
+
2256
+ Specifies which scaling algorithm must be used.
2257
+
2258
+ @return nil.
2259
+ */
2260
+ static VALUE
2261
+ lpsolve_set_scaling(VALUE self, VALUE new_scalemode)
2262
+ {
2263
+ INIT_LP;
2264
+ set_scaling(lp, FIX2INT(new_scalemode));
2265
+ return Qnil;
2266
+ }
2267
+
2268
+ /** A wrapper for set_simplextype().
2269
+
2270
+ In Ruby, you can also use accessor function simplextype=.
2271
+
2272
+ @param self
2273
+ @param new_simplextype desired level of verbosity, an integer. @see
2274
+ lpsolve_get_simplextype() for simplex types.
2275
+ @return nil on error.
2276
+ */
2277
+ static VALUE lpsolve_set_simplextype(VALUE self, VALUE new_simplextype);
2278
+ LPSOLVE_1_IN_STATUS_OUT(set_simplextype, FIX2INT(param1))
2279
+
2280
+ /** A wrapper for set_solutionlimit().
2281
+
2282
+ Sets the solution number that must be returned.
2283
+
2284
+ This function is only valid if there are integer, semi-continious
2285
+ or SOS variables in the model so that the branch-and-bound
2286
+ algoritm is used. If there are more solutions with the same
2287
+ objective value, then this number specifies which solution must be
2288
+ returned. This can be used to retrieve all possible
2289
+ solutions. Start with 1 till get_solutioncount
2290
+
2291
+ @param self
2292
+ @param limit number of solutions needed
2293
+ @return nil on error.
2294
+
2295
+ @return nil.
2296
+ */
2297
+ static VALUE lpsolve_set_solutionlimit(VALUE self, VALUE limit);
2298
+ LPSOLVE_1_IN_STATUS_OUT(set_solutionlimit, FIX2INT(param1))
2299
+
2300
+ /** A wrapper for set_trace
2301
+
2302
+ Sets a flag if pivot selection must be printed while solving.
2303
+
2304
+ @param self self
2305
+ @param print_bool print if true; don't print if false.
2306
+ @return \a true if the operation was successful, FALSE if there was an error.
2307
+ */
2308
+ static VALUE
2309
+ lpsolve_set_trace(VALUE self, VALUE print_bool)
2310
+ {
2311
+ if (print_bool != Qtrue && print_bool != Qfalse) {
2312
+ return Qfalse;
2313
+ } else {
2314
+ INIT_LP;
2315
+ set_trace(lp, Qtrue == print_bool);
2316
+ return Qtrue;
2317
+ }
2318
+ }
2319
+
2320
+ /** A wrapper for set_upbo().
2321
+
2322
+ @return \a true if no errors.
2323
+ */
2324
+ static VALUE
2325
+ lpsolve_set_upbo(VALUE self, VALUE column, VALUE val)
2326
+ {
2327
+ INIT_LP;
2328
+ RETURN_BOOL(set_upbo(lp, FIX2INT(column), NUM2DBL(val)));
2329
+ }
2330
+
2331
+ /** A wrapper for set_verbose().
2332
+
2333
+ In Ruby, you can also use accessor function verbose=.
2334
+
2335
+ @param self
2336
+ @param new_verbosity desired level of verbosity, an integer. @see
2337
+ lpsolve_get_verbose() for verbosity levels.
2338
+ @return \a true unless we have an error.
2339
+ */
2340
+ static VALUE lpsolve_set_verbose(VALUE self, VALUE new_verbosity);
2341
+ LPSOLVE_1_IN_STATUS_OUT(set_verbose, FIX2INT(param1))
2342
+
2343
+ /** A wrapper for solve().
2344
+ @returns 0 if no error.
2345
+ */
2346
+
2347
+ static VALUE lpsolve_solve(VALUE self)
2348
+ {
2349
+ INIT_LP;
2350
+ if (NULL != lp) {
2351
+ VALUE status = INT2FIX(solve(lp));
2352
+ rb_ivar_set(self, rb_intern("@status"), status);
2353
+ return status;
2354
+ } else {
2355
+ return Qnil;
2356
+ }
2357
+ }
2358
+
2359
+ /** A wrapper for str_add_column().
2360
+
2361
+ @return \a true if the operation was successful. A false value
2362
+ indicates an error.
2363
+ */
2364
+ static VALUE lpsolve_str_add_column(VALUE self, VALUE col_str);
2365
+ LPSOLVE_1_STR_IN_BOOL_OUT(str_add_column)
2366
+
2367
+ /** A wrapper for str_add_constraint().
2368
+ @return boolean
2369
+ */
2370
+ static VALUE
2371
+ lpsolve_str_add_constraint(VALUE self, VALUE constraint,
2372
+ VALUE compare, VALUE num_constraints)
2373
+ {
2374
+ char *psz_constraint = RSTRING_PTR(constraint);
2375
+ int i_compare = NUM2INT(compare);
2376
+ int i_constraints = NUM2INT(num_constraints);
2377
+ lprec *lp;
2378
+ Data_Get_Struct(self, lprec, lp);
2379
+ RETURN_BOOL(str_add_constraint(lp, psz_constraint, i_compare, i_constraints));
2380
+ }
2381
+
2382
+ /** A wrapper for str_set_obj_fn().
2383
+
2384
+ Set the objective function (row 0) of the matrix via a string.
2385
+
2386
+ @return \a true unless we have an error.
2387
+ */
2388
+ static VALUE
2389
+ lpsolve_str_set_obj_fn(VALUE self, VALUE obj_fn)
2390
+ {
2391
+ char *psz_obj_fn = RSTRING_PTR(obj_fn);
2392
+ lprec *lp;
2393
+ Data_Get_Struct(self, lprec, lp);
2394
+ RETURN_BOOL(str_set_obj_fn(lp, psz_obj_fn));
2395
+ }
2396
+
2397
+ /** A wrapper for time_elapsed().
2398
+
2399
+ The time_elapsed function returns the time in seconds since solve
2400
+ and lag_solve has started. In contrast to totaltime, the time does
2401
+ not include the load time. If solving has not completed he value
2402
+ will be the number of seconds of until the time of the call
2403
+ rather than the time the solve completed.
2404
+
2405
+ @param self self.
2406
+
2407
+ @return \a Floating-point number for time since solve and
2408
+ lag_solve has started
2409
+ */
2410
+ static VALUE lpsolve_time_elapsed(VALUE self);
2411
+ LPSOLVE_0_IN_NUM_OUT(time_elapsed);
2412
+
2413
+ /** \fn time_load Return the amount of time used to load in data
2414
+
2415
+ @param self self
2416
+
2417
+ @return A Ruby floating-point number indicating how long the
2418
+ presolver solver took.
2419
+
2420
+ */
2421
+ static VALUE lpsolve_time_load(VALUE self) ;
2422
+ LPSOLVE_0_IN_TIME_OUT(time_load, timecreate, timestart);
2423
+
2424
+ /** Return the amount of time used in the simplex solver
2425
+
2426
+ @param self self
2427
+
2428
+ @return A Ruby floating-point number indicating how long the
2429
+ simplex solver took.
2430
+
2431
+ This only makes sense if a problem was solved. See also
2432
+ the status instance variable.
2433
+
2434
+ In Ruby, you can also use accessor function simplextime
2435
+ */
2436
+ static VALUE lpsolve_time_simplex(VALUE self) ;
2437
+ LPSOLVE_0_IN_TIME_OUT(time_simplex, timepresolved, timeend);
2438
+
2439
+ /** \fn time_presolve
2440
+ Return the amount of time used in the presolver
2441
+
2442
+ @param self self
2443
+
2444
+ @return A Ruby floating-point number indicating how long the
2445
+ presolver solver took.
2446
+
2447
+ This only makes sense if a problem was solved. See also
2448
+ the status instance variable.
2449
+
2450
+ In Ruby, you can also use accessor function simplextime
2451
+ */
2452
+ static VALUE lpsolve_time_presolve(VALUE self) ;
2453
+ LPSOLVE_0_IN_TIME_OUT(time_presolve, timestart, timepresolved);
2454
+
2455
+ /** Return the total amount elapsed time from start to finish.
2456
+
2457
+ @param self self
2458
+
2459
+ @return A Ruby floating-point number indicating how long the
2460
+ simplex solver took.
2461
+
2462
+ This only makes sense if a problem was solved. See also
2463
+ the status instance variable.
2464
+ */
2465
+ static VALUE lpsolve_time_total(VALUE self) ;
2466
+ LPSOLVE_0_IN_TIME_OUT(time_total, timecreate, timeend);
2467
+
2468
+ /** A wrapper for solve_unscale().
2469
+
2470
+ The get_bb_rule function returns the branch-and-bound rule for
2471
+ choosing which non-integer variable is to be selected. This rule
2472
+ can influence solving times considerably. Depending on the model
2473
+ one rule can be best and for another model another rule. The
2474
+ default is NODE_PSEUDONONINTSELECT + NODE_GREEDYMODE +
2475
+ NODE_DYNAMICMODE + NODE_RCOSTFIXING (17445).
2476
+
2477
+ @param self self
2478
+ @return Returns the branch-and-bound rule.
2479
+
2480
+ */
2481
+ static VALUE lpsolve_unscale(VALUE self);
2482
+ LPSOLVE_0_IN_STATUS_OUT(unscale)
2483
+
2484
+ /** A wrapper for lp_solve_version().
2485
+ @return 4-tuple: [major_version, minor_version, release, build]
2486
+ */
2487
+ static VALUE
2488
+ lpsolve_version(VALUE module_or_class)
2489
+ {
2490
+ int major_version;
2491
+ int minor_version;
2492
+ int release;
2493
+ int build;
2494
+ lp_solve_version(&major_version, &minor_version, &release, &build);
2495
+ return rb_ary_new3(4,
2496
+ INT2FIX(major_version), INT2FIX(minor_version),
2497
+ INT2FIX(release), INT2FIX(build));
2498
+ }
2499
+
2500
+ /** A wrapper for write_basis().
2501
+
2502
+ The write_basis function writes the current basis to filename.
2503
+ This basis can later be reused by read_basis to reset a basis. Setting
2504
+ an initial basis can speed up the solver considerably. It is the
2505
+ starting point from where the algorithm continues to find an optimal
2506
+ solution. When a restart is done, lp_solve continues at the last
2507
+ basis, except if set_basis, default_basis, guess_basis or read_basis
2508
+ is called.
2509
+
2510
+ The basis in the file is written in MPS bas file format.
2511
+
2512
+ @return \a true if we could write the output file.
2513
+ */
2514
+ static VALUE lpsolve_write_basis(VALUE self, VALUE filename);
2515
+ LPSOLVE_1_STR_IN_BOOL_OUT(write_basis)
2516
+
2517
+ /** A wrapper for write_lp().
2518
+
2519
+ The model in the file will be written in LP-format unless there
2520
+ is an error.
2521
+ Note that row entry mode must be off, else this
2522
+ function also fails. @see lpsolve_set_add_rowmode()
2523
+
2524
+ @param self self
2525
+
2526
+ @param filename place to write LP file. If this is nil, then
2527
+ output is written the location specified by set_outputstream, or
2528
+ of that has not been set stdout.
2529
+
2530
+ @return \a true if we could write the output file.
2531
+ */
2532
+ static VALUE lpsolve_write_lp(int argc, VALUE *argv, VALUE self)
2533
+ {
2534
+ VALUE filename;
2535
+ unsigned int i_scanned;
2536
+ INIT_LP;
2537
+ if ((argc > 1) || (argc < 0))
2538
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 or 1)", argc);
2539
+ i_scanned = rb_scan_args(argc, argv, "01", &filename);
2540
+ switch (i_scanned) {
2541
+ case 0:
2542
+ RETURN_BOOL(write_lp(lp, NULL));
2543
+ break;
2544
+ case 1:
2545
+ if (filename == Qnil)
2546
+ RETURN_BOOL(write_lp(lp, NULL));
2547
+ else if (TYPE(filename) != T_STRING) {
2548
+ report(lp, IMPORTANT, "%s: Parameter is not nil or a string filename.\n",
2549
+ __FUNCTION__);
2550
+ return Qnil;
2551
+ } else
2552
+ RETURN_BOOL(write_lp(lp, RSTRING_PTR(filename)));
2553
+ default:
2554
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 or 1)",
2555
+ i_scanned);
2556
+ }
2557
+ return Qfalse;
2558
+ }
2559
+
2560
+ /** A wrapper for write_mps().
2561
+
2562
+ The model in the file will be written in MPS-format unless there is an
2563
+ error.
2564
+ Note that row entry mode must be off, else this function also fails.
2565
+ @see lpsolve_set_add_rowmode()
2566
+
2567
+ @param self self
2568
+
2569
+ @param filename place to write MPS file. If this is nil, then
2570
+ output is written the location specified by set_outputstream, or
2571
+ of that has not been set stdout.
2572
+
2573
+ @return \a true if we could write the output file.
2574
+ */
2575
+ static VALUE lpsolve_write_mps(int argc, VALUE *argv, VALUE self)
2576
+ {
2577
+ VALUE filename;
2578
+ unsigned int i_scanned;
2579
+ INIT_LP;
2580
+ if ((argc > 1) || (argc < 0))
2581
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 or 1)", argc);
2582
+ i_scanned = rb_scan_args(argc, argv, "01", &filename);
2583
+ switch (i_scanned) {
2584
+ case 0:
2585
+ RETURN_BOOL(write_mps(lp, NULL));
2586
+
2587
+ break;
2588
+ case 1:
2589
+ if (filename == Qnil)
2590
+ RETURN_BOOL(write_mps(lp, NULL));
2591
+ else if (TYPE(filename) != T_STRING) {
2592
+ report(lp, IMPORTANT, "%s: Parameter is not nil or a string filename.\n",
2593
+ __FUNCTION__);
2594
+ return Qnil;
2595
+ } else
2596
+ RETURN_BOOL(write_mps(lp, RSTRING_PTR(filename)));
2597
+ default:
2598
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0 or 1)",
2599
+ i_scanned);
2600
+ }
2601
+ return Qfalse;
2602
+ }
2603
+
2604
+ extern void init_lpsolve_constants();
2605
+ /*#include "lpconsts.h" */
2606
+
2607
+ /** Called when we issue from Ruby:
2608
+ \verbatim
2609
+ require "lpsolve"
2610
+ \endverbatim
2611
+ */
2612
+ void Init_lpsolve()
2613
+ {
2614
+ rb_cLPSolve = rb_define_class("LPSolve", rb_cObject);
2615
+ rb_define_alloc_func(rb_cLPSolve, lpsolve_alloc);
2616
+
2617
+ init_lpsolve_constants();
2618
+
2619
+ /* Class functions */
2620
+ rb_define_module_function(rb_cLPSolve, "make_lp", lpsolve_make_lp, 2);
2621
+ rb_define_module_function(rb_cLPSolve, "read_LP", lpsolve_read_LP, 3);
2622
+ rb_define_module_function(rb_cLPSolve, "read_MPS", lpsolve_read_MPS, 2);
2623
+ rb_define_module_function(rb_cLPSolve, "version", lpsolve_version, 0);
2624
+
2625
+ /* Class Methods */
2626
+ rb_define_method(rb_cLPSolve, "add_constraintex",
2627
+ lpsolve_add_constraintex, 4);
2628
+ rb_define_method(rb_cLPSolve, "add_SOS", lpsolve_add_SOS, 4);
2629
+ rb_define_method(rb_cLPSolve, "default_basis", lpsolve_default_basis, 0);
2630
+ rb_define_method(rb_cLPSolve, "del_column", lpsolve_del_column, 1);
2631
+ rb_define_method(rb_cLPSolve, "del_constraint", lpsolve_del_constraint, 1);
2632
+ rb_define_method(rb_cLPSolve, "get_bb_depthlimit",
2633
+ lpsolve_get_bb_depthlimit, 0);
2634
+ rb_define_method(rb_cLPSolve, "get_bb_rule", lpsolve_get_bb_rule, 0);
2635
+ rb_define_method(rb_cLPSolve, "get_col_name", lpsolve_get_col_name, 1);
2636
+ rb_define_method(rb_cLPSolve, "get_col_num", lpsolve_get_col_num, 1);
2637
+ rb_define_method(rb_cLPSolve, "get_column", lpsolve_get_column, 1);
2638
+ rb_define_method(rb_cLPSolve, "get_infinite", lpsolve_get_infinite, 0);
2639
+ rb_define_method(rb_cLPSolve, "get_lowbo", lpsolve_get_lowbo, 1);
2640
+ rb_define_method(rb_cLPSolve, "get_lp_name", lpsolve_get_lp_name, 0);
2641
+ rb_define_method(rb_cLPSolve, "get_mip_gap", lpsolve_get_mip_gap, 1);
2642
+ rb_define_method(rb_cLPSolve, "get_Ncolumns", lpsolve_get_Ncolumns, 0);
2643
+ rb_define_method(rb_cLPSolve, "get_Norig_columns",
2644
+ lpsolve_get_Norig_columns, 0);
2645
+ rb_define_method(rb_cLPSolve, "get_Norig_rows", lpsolve_get_Norig_rows, 0);
2646
+ rb_define_method(rb_cLPSolve, "get_Nrows", lpsolve_get_Nrows, 0);
2647
+ rb_define_method(rb_cLPSolve, "get_nonzeros", lpsolve_get_nonzeros, 0);
2648
+ rb_define_method(rb_cLPSolve, "get_mat", lpsolve_get_mat, 2);
2649
+ rb_define_method(rb_cLPSolve, "get_objective", lpsolve_get_objective, 0);
2650
+ rb_define_method(rb_cLPSolve, "get_origcol_name",
2651
+ lpsolve_get_origcol_name, 1);
2652
+ rb_define_method(rb_cLPSolve, "get_origrow_name",
2653
+ lpsolve_get_origrow_name, 1);
2654
+ rb_define_method(rb_cLPSolve, "get_presolve", lpsolve_get_presolve, 0);
2655
+ rb_define_method(rb_cLPSolve, "get_presolveloops",
2656
+ lpsolve_get_presolveloops, 0);
2657
+ rb_define_method(rb_cLPSolve, "get_row", lpsolve_get_row, 1);
2658
+ rb_define_method(rb_cLPSolve, "get_row_name", lpsolve_get_row_name, 1);
2659
+ rb_define_method(rb_cLPSolve, "get_scaling", lpsolve_get_scaling, 0);
2660
+ rb_define_method(rb_cLPSolve, "get_simplextype", lpsolve_get_simplextype, 0);
2661
+ rb_define_method(rb_cLPSolve, "get_solutioncount",
2662
+ lpsolve_get_solutioncount, 0);
2663
+ rb_define_method(rb_cLPSolve, "get_solutionlimit",
2664
+ lpsolve_get_solutionlimit, 0);
2665
+ rb_define_method(rb_cLPSolve, "get_status", lpsolve_get_status, 0);
2666
+ rb_define_method(rb_cLPSolve, "get_statustext", lpsolve_get_statustext, -1);
2667
+ rb_define_method(rb_cLPSolve, "get_timeout", lpsolve_get_timeout, 0);
2668
+ rb_define_method(rb_cLPSolve, "get_total_iter", lpsolve_get_total_iter, 0);
2669
+ rb_define_method(rb_cLPSolve, "get_upbo", lpsolve_get_upbo, 1);
2670
+ rb_define_method(rb_cLPSolve, "get_var_dualresult",
2671
+ lpsolve_get_var_dualresult, 1);
2672
+ rb_define_method(rb_cLPSolve, "get_var_primalresult",
2673
+ lpsolve_get_var_primalresult, 1);
2674
+ rb_define_method(rb_cLPSolve, "get_variables", lpsolve_get_variables, 0);
2675
+ rb_define_method(rb_cLPSolve, "get_verbose", lpsolve_get_verbose, 0);
2676
+ rb_define_method(rb_cLPSolve, "initialize", lpsolve_initialize, 2);
2677
+ rb_define_method(rb_cLPSolve, "is_debug", lpsolve_is_debug, 0);
2678
+ rb_define_method(rb_cLPSolve, "is_maxim", lpsolve_is_maxim, 0);
2679
+ rb_define_method(rb_cLPSolve, "is_SOS_var", lpsolve_is_SOS_var, 1);
2680
+ rb_define_method(rb_cLPSolve, "presolve=", lpsolve_set_presolve1, 1);
2681
+ rb_define_method(rb_cLPSolve, "print", lpsolve_print, 0);
2682
+ rb_define_method(rb_cLPSolve, "print_debugdump",
2683
+ lpsolve_print_debugdump, 1);
2684
+ rb_define_method(rb_cLPSolve, "print_constraints",
2685
+ lpsolve_print_constraints, 1);
2686
+ rb_define_method(rb_cLPSolve, "print_duals", lpsolve_print_duals, 0);
2687
+ rb_define_method(rb_cLPSolve, "print_lp", lpsolve_print_lp, 0);
2688
+ rb_define_method(rb_cLPSolve, "print_objective", lpsolve_print_objective, 0);
2689
+ rb_define_method(rb_cLPSolve, "print_str", lpsolve_print_str, 1);
2690
+ rb_define_method(rb_cLPSolve, "print_solution", lpsolve_print_solution, 1);
2691
+ rb_define_method(rb_cLPSolve, "print_tableau", lpsolve_print_tableau, 0);
2692
+ rb_define_method(rb_cLPSolve, "put_logfunc", lpsolve_put_logfunc, 1);
2693
+ rb_define_method(rb_cLPSolve, "set_add_rowmode", lpsolve_set_add_rowmode, 1);
2694
+ rb_define_method(rb_cLPSolve, "set_bb_depthlimit",
2695
+ lpsolve_set_bb_depthlimit, 1);
2696
+ rb_define_method(rb_cLPSolve, "set_bb_rule", lpsolve_set_bb_rule, 1);
2697
+ rb_define_method(rb_cLPSolve, "set_binary", lpsolve_set_binary, 2);
2698
+ rb_define_method(rb_cLPSolve, "set_bounds", lpsolve_set_bounds, 3);
2699
+ rb_define_method(rb_cLPSolve, "set_debug", lpsolve_set_debug, 1);
2700
+ rb_define_method(rb_cLPSolve, "set_col_name", lpsolve_set_col_name, 2);
2701
+ rb_define_method(rb_cLPSolve, "set_int", lpsolve_set_int, 2);
2702
+ rb_define_method(rb_cLPSolve, "set_mat", lpsolve_set_mat, 3);
2703
+ rb_define_method(rb_cLPSolve, "set_maxim", lpsolve_set_maxim, 0);
2704
+ rb_define_method(rb_cLPSolve, "set_minim", lpsolve_set_minim, 0);
2705
+ rb_define_method(rb_cLPSolve, "set_mip_gap", lpsolve_set_mip_gap, 2);
2706
+ rb_define_method(rb_cLPSolve, "set_lowbo", lpsolve_set_lowbo, 2);
2707
+ rb_define_method(rb_cLPSolve, "set_lp_name", lpsolve_set_lp_name, 1);
2708
+ rb_define_method(rb_cLPSolve, "set_obj_fnex", lpsolve_set_obj_fnex, 1);
2709
+ rb_define_method(rb_cLPSolve, "set_outputfile", lpsolve_set_outputfile, 1);
2710
+ rb_define_method(rb_cLPSolve, "set_presolve", lpsolve_set_presolve, 2);
2711
+ rb_define_method(rb_cLPSolve, "set_rh", lpsolve_set_rh, 2);
2712
+ rb_define_method(rb_cLPSolve, "set_rh_range", lpsolve_set_rh_range, 2);
2713
+ rb_define_method(rb_cLPSolve, "set_row_name", lpsolve_set_row_name, 2);
2714
+ rb_define_method(rb_cLPSolve, "set_semicont", lpsolve_set_semicont, 2);
2715
+ rb_define_method(rb_cLPSolve, "set_scaling", lpsolve_set_scaling, 1);
2716
+ rb_define_method(rb_cLPSolve, "set_simplextype", lpsolve_set_simplextype, 1);
2717
+ rb_define_method(rb_cLPSolve, "set_solutionlimit",
2718
+ lpsolve_set_solutionlimit, 1);
2719
+ rb_define_method(rb_cLPSolve, "set_status", lpsolve_set_status, 1);
2720
+ rb_define_method(rb_cLPSolve, "set_timeout", lpsolve_set_timeout, 1);
2721
+ rb_define_method(rb_cLPSolve, "set_trace", lpsolve_set_trace, 1);
2722
+ rb_define_method(rb_cLPSolve, "set_upbo", lpsolve_set_upbo, 2);
2723
+ rb_define_method(rb_cLPSolve, "set_verbose", lpsolve_set_verbose, 1);
2724
+ rb_define_method(rb_cLPSolve, "solve", lpsolve_solve, 0);
2725
+ rb_define_method(rb_cLPSolve, "str_add_column", lpsolve_str_add_column,
2726
+ 1);
2727
+ rb_define_method(rb_cLPSolve, "str_add_constraint",
2728
+ lpsolve_str_add_constraint, 3);
2729
+ rb_define_method(rb_cLPSolve, "str_set_obj_fn",
2730
+ lpsolve_str_set_obj_fn, 1);
2731
+ rb_define_method(rb_cLPSolve, "time_elapsed", lpsolve_time_elapsed, 0);
2732
+ rb_define_method(rb_cLPSolve, "time_load", lpsolve_time_load, 0);
2733
+ rb_define_method(rb_cLPSolve, "time_presolve", lpsolve_time_presolve, 0);
2734
+ rb_define_method(rb_cLPSolve, "time_simplex", lpsolve_time_simplex, 0);
2735
+ rb_define_method(rb_cLPSolve, "time_total", lpsolve_time_total, 0);
2736
+ rb_define_method(rb_cLPSolve, "unscale", lpsolve_unscale, 0);
2737
+ rb_define_method(rb_cLPSolve, "version", lpsolve_version, 0);
2738
+ rb_define_method(rb_cLPSolve, "write_basis", lpsolve_write_basis, 1);
2739
+ rb_define_method(rb_cLPSolve, "write_lp", lpsolve_write_lp, -1);
2740
+ rb_define_method(rb_cLPSolve, "write_mps", lpsolve_write_mps, -1);
2741
+
2742
+ /* Aliases accessors. */
2743
+ rb_define_alias(rb_cLPSolve, "bb_rule", "get_bb_rule");
2744
+ rb_define_alias(rb_cLPSolve, "bb_rule=", "set_bb_rule");
2745
+ rb_define_alias(rb_cLPSolve, "bb_depthlimit", "get_bb_depthlimit");
2746
+ rb_define_alias(rb_cLPSolve, "bb_depthlimit=", "set_bb_depthlimit");
2747
+ rb_define_alias(rb_cLPSolve, "debug?", "is_debug");
2748
+ rb_define_alias(rb_cLPSolve, "debug=", "set_debug");
2749
+ rb_define_alias(rb_cLPSolve, "infinite", "get_infinite");
2750
+ rb_define_alias(rb_cLPSolve, "maxim?", "is_maxim");
2751
+ rb_define_alias(rb_cLPSolve, "lp_name", "get_lp_name");
2752
+ rb_define_alias(rb_cLPSolve, "lp_name=", "set_lp_name");
2753
+ rb_define_alias(rb_cLPSolve, "Ncolumns", "get_Ncolumns");
2754
+ rb_define_alias(rb_cLPSolve, "Norig_columns", "get_Norig_columns");
2755
+ rb_define_alias(rb_cLPSolve, "nonzeros", "get_nonzeros");
2756
+ rb_define_alias(rb_cLPSolve, "Norig_rows", "get_Norig_rows");
2757
+ rb_define_alias(rb_cLPSolve, "Nrows", "get_Nrows");
2758
+ rb_define_alias(rb_cLPSolve, "objective", "get_objective");
2759
+ rb_define_alias(rb_cLPSolve, "presolve", "get_presolve");
2760
+ rb_define_alias(rb_cLPSolve, "presolveloops", "get_presolveloops");
2761
+ /* rb_define_alias(rb_cLPSolve, "print", "print_lp"); */
2762
+ rb_define_alias(rb_cLPSolve, "scaling", "get_scaling");
2763
+ rb_define_alias(rb_cLPSolve, "scaling=", "set_scaling");
2764
+ rb_define_alias(rb_cLPSolve, "status", "get_status");
2765
+ rb_define_alias(rb_cLPSolve, "status=", "set_status");
2766
+ rb_define_alias(rb_cLPSolve, "statustext", "get_statustext");
2767
+ rb_define_alias(rb_cLPSolve, "simplextype", "get_simplextype");
2768
+ rb_define_alias(rb_cLPSolve, "simplextype=", "set_simplextype");
2769
+ rb_define_alias(rb_cLPSolve, "solutioncount", "get_solutioncount");
2770
+ rb_define_alias(rb_cLPSolve, "solutionlimit", "get_solutionlimit");
2771
+ rb_define_alias(rb_cLPSolve, "solutionlimit=", "set_solutionlimit");
2772
+ rb_define_alias(rb_cLPSolve, "sos_var?", "is_SOS_var");
2773
+ rb_define_alias(rb_cLPSolve, "timeout", "get_timeout");
2774
+ rb_define_alias(rb_cLPSolve, "timeout=", "set_timeout");
2775
+ rb_define_alias(rb_cLPSolve, "total_iter", "get_total_iter");
2776
+ rb_define_alias(rb_cLPSolve, "trace=", "set_trace");
2777
+ rb_define_alias(rb_cLPSolve, "variables", "get_variables");
2778
+ rb_define_alias(rb_cLPSolve, "verbose", "get_verbose");
2779
+ rb_define_alias(rb_cLPSolve, "verbose=", "set_verbose");
2780
+ }
2781
+
2782
+
2783
+ /* A revised version of print_lp or REPORT_lp. */
2784
+ #include <lpsolve/lp_report.h>
2785
+ void print(lprec *lp)
2786
+ {
2787
+ int i, j;
2788
+ unsigned int max_rowname = sizeof("lowbo")-1;
2789
+ char row_fmt[30];
2790
+
2791
+ if(lp->outstream == NULL)
2792
+ return;
2793
+
2794
+ if(lp->matA->is_roworder) {
2795
+ report(lp, IMPORTANT, "REPORT_lp: Cannot print lp while in row entry mode.\n");
2796
+ return;
2797
+ }
2798
+
2799
+ fprintf(lp->outstream, "Model name: %s\n", get_lp_name(lp));
2800
+
2801
+ for(j = 1; j <= lp->rows; j++) {
2802
+ unsigned int row_len = strlen(get_row_name(lp, j));
2803
+ if (max_rowname < row_len)
2804
+ max_rowname = row_len;
2805
+ }
2806
+
2807
+ memset(row_fmt, 0, sizeof(row_fmt));
2808
+ snprintf(row_fmt, sizeof(row_fmt), "%%-%ds ", max_rowname);
2809
+ fprintf(lp->outstream, row_fmt, " ");
2810
+
2811
+ for(j = 1; j <= lp->columns; j++)
2812
+ fprintf(lp->outstream, "%8s ", get_col_name(lp,j));
2813
+
2814
+ fprintf(lp->outstream, "\n%simize:\n", (is_maxim(lp) ? "Max" : "Min"));
2815
+ fprintf(lp->outstream, row_fmt, " ");
2816
+
2817
+ for(j = 1; j <= lp->columns; j++)
2818
+ {
2819
+ REAL val = get_mat(lp, 0, j);
2820
+ if (0.0 == val)
2821
+ fprintf(lp->outstream, "%8s ", "");
2822
+ else {
2823
+ fprintf(lp->outstream, "%8g ", get_mat(lp, 0, j));
2824
+ }
2825
+ }
2826
+
2827
+ fprintf(lp->outstream, "\n\nSubject to:\n");
2828
+
2829
+ for(i = 1; i <= lp->rows; i++) {
2830
+ fprintf(lp->outstream, row_fmt, get_row_name(lp, i));
2831
+ for(j = 1; j <= lp->columns; j++)
2832
+ {
2833
+ REAL val = get_mat(lp, i, j);
2834
+ if (0.0 == val)
2835
+ fprintf(lp->outstream, "%8s ", "");
2836
+ else {
2837
+ fprintf(lp->outstream, "%8g ", val);
2838
+ }
2839
+ }
2840
+ if(is_constr_type(lp, i, GE))
2841
+ fprintf(lp->outstream, ">= ");
2842
+ else if(is_constr_type(lp, i, LE))
2843
+ fprintf(lp->outstream, "<= ");
2844
+ else
2845
+ fprintf(lp->outstream, " = ");
2846
+
2847
+ fprintf(lp->outstream, "%8g", get_rh(lp, i));
2848
+
2849
+ if(is_constr_type(lp, i, GE)) {
2850
+ if(get_rh_upper(lp, i) < lp->infinite)
2851
+ fprintf(lp->outstream, " %s = %8g", "upbo ", get_rh_upper(lp, i));
2852
+ }
2853
+ else if(is_constr_type(lp, i, LE)) {
2854
+ if(get_rh_lower(lp, i) > -lp->infinite)
2855
+ fprintf(lp->outstream, " %s = %8g", "lowbo", get_rh_lower(lp, i));
2856
+ }
2857
+ fprintf(lp->outstream, "\n");
2858
+ }
2859
+
2860
+ fprintf(lp->outstream, "\n");
2861
+ fprintf(lp->outstream, row_fmt, "Type");
2862
+ for(i = 1; i <= lp->columns; i++) {
2863
+ if(is_int(lp,i))
2864
+ fprintf(lp->outstream, " Int ");
2865
+ else
2866
+ fprintf(lp->outstream, " Real ");
2867
+ }
2868
+
2869
+ fprintf(lp->outstream, "\n");
2870
+ fprintf(lp->outstream, row_fmt, "upbo ");
2871
+ for(i = 1; i <= lp->columns; i++)
2872
+ if(get_upbo(lp, i) >= lp->infinite)
2873
+ fprintf(lp->outstream, " Inf ");
2874
+ else
2875
+ fprintf(lp->outstream, "%8g ", get_upbo(lp, i));
2876
+ fprintf(lp->outstream, "\n");
2877
+ fprintf(lp->outstream, row_fmt, "lowbo");
2878
+ for(i = 1; i <= lp->columns; i++)
2879
+ if(get_lowbo(lp, i) <= -lp->infinite)
2880
+ fprintf(lp->outstream, " -Inf ");
2881
+ else
2882
+ fprintf(lp->outstream, "%8g ", get_lowbo(lp, i));
2883
+ fprintf(lp->outstream, "\n");
2884
+ fprintf(lp->outstream, row_fmt, "SOS ");
2885
+ for(i = 1; i <= lp->columns; i++) {
2886
+ if(is_SOS_var(lp, i)) {
2887
+ fprintf(lp->outstream, " true ");
2888
+ } else
2889
+ fprintf(lp->outstream, " false ");
2890
+ }
2891
+ fprintf(lp->outstream, "\n");
2892
+ if (lp->SOS) {
2893
+ SOSgroup *SOS_group = lp->SOS;
2894
+ SOSrec **sos_list;
2895
+ sos_list = SOS_group->sos_list;
2896
+ fprintf(lp->outstream, "\nSOS groups:\n");
2897
+ for (i=0; i<lp->SOS->sos_count; i++) {
2898
+ unsigned int j;
2899
+ fprintf(lp->outstream, "\t%s: Type: %d, with %d members",
2900
+ sos_list[i]->name, sos_list[i]->type, sos_list[i]->size);
2901
+ for(j = 1; j <= sos_list[i]->size; j++) {
2902
+ int i_col_num = sos_list[i]->members[j];
2903
+ char *psz_col_name;
2904
+ if (i_col_num <= lp->columns) {
2905
+ psz_col_name = get_col_name(lp, i_col_num);
2906
+ if (NULL != psz_col_name)
2907
+ fprintf(lp->outstream, "%s%s", (j > 1) ? ", " : ": ",
2908
+ psz_col_name);
2909
+ }
2910
+ }
2911
+ fprintf(lp->outstream, "\n");
2912
+ }
2913
+ }
2914
+ fflush(lp->outstream);
2915
+ }