lpsolve 5.5.10.i

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }