############################################################################## # # Copyright (c) 2003 Nexedi SARL and Contributors. All Rights Reserved. # Yoshinori Okuji <yo@nexedi.com> # # WARNING: This program as such is intended to be used by professional # programmers who take the whole responsability of assessing all potential # consequences resulting from its eventual inadequacies and bugs # End users who are looking for a ready-to-use solution with commercial # garantees and support are strongly adviced to contract a Free Software # Service Company # # This program is Free Software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ############################################################################## from numpy import shape, array MODEL_HEAD = """ /* The number of samples. */ param n, integer, > 0; /* The number of resources. */ param d, integer, > 0; /* The set of samples. */ set S := 1..n; /* The set of resources. */ set R := 1..d; /* The query. */ param q{i in R}; /* The samples. */ param s{j in S, i in R}; /* The normal vector of a hyperplane. */ var z{i in R}; /* The origin of a hyperplane. */ var z0; #display q; #display s; /* The objective. */ maximize obj: sum {i in R} (z[i] * q[i]) - z0; /* Constraints. */ subject to c{j in S}: sum{i in R} (z[i] * s[j,i]) - z0, <= 0; subject to c0: sum {i in R} (z[i] * q[i]) - z0, <= 1; data; """ MODEL_TAIL=""" end; """ def writeModelFile(file, matrix, point): """ Write an LP problem in MathProg. """ n = shape(matrix)[0] d = shape(matrix)[1] file.write(MODEL_HEAD) file.write("param n := %d;\n" % n) file.write("param d := %d;\n" % d) file.write("param s\n:\t") def insertTab(x,y): return str(x)+"\t"+str(y) file.write(reduce(insertTab, range(1,d+1))) file.write("\t:=\n") for i in range(n): file.write(repr(i+1)) file.write(reduce(insertTab, matrix[i], "")) file.write("\n") file.write(";\n") file.write("param q := ") def insertComma(x,y): return str(x)+','+str(y) def flatten(x): return str(x[0])+' '+str(x[1]) file.write(reduce(insertComma, map(flatten, map(None, range(1,d+1), point)))) file.write(";\n") file.write(MODEL_TAIL) def getOptimalValue(file): """ Solve an LP problem described in MathProg language, and return the result of its objective function. This version uses GNU Linear Programming Kit. """ import glpk lp = glpk.glp_lpx_read_model(file, None, None) try: glpk.glp_lpx_set_int_parm(lp, glpk.LPX_K_PRICE, 1) glpk.glp_lpx_set_int_parm(lp, glpk.LPX_K_PRESOL, 1) glpk.glp_lpx_set_int_parm(lp, glpk.LPX_K_BRANCH, 2) glpk.glp_lpx_set_int_parm(lp, glpk.LPX_K_BTRACK, 2) glpk.glp_lpx_set_real_parm(lp, glpk.LPX_K_TMLIM, 2000) # XXX ret = glpk.glp_lpx_simplex(lp) if ret != glpk.LPX_E_OK: raise RuntimeError, "The simplex method of GLPK failed" return glpk.glp_lpx_get_obj_val(lp) finally: glpk.glp_lpx_delete_prob(lp) def solve(matrix, point): """ Check if a point is inside a convex hull specified by a matrix. """ import tempfile import os if shape(point)[0] != shape(matrix)[1]: raise TypeError, "The argument 'point' has a different number of dimensions from the capacity" mod_name = tempfile.mktemp(suffix='.mod') mod = file(mod_name, 'w') try: writeModelFile(mod, matrix, point) mod.close() obj = getOptimalValue(mod_name) finally: os.remove(mod_name) return obj <= 0 # This is a test. if __name__ == '__main__': m = array([[ 0, 1, 2, 3, 4, 5], [10,11,12,13,14,15], [20,21,22,23,24,25], [30,31,32,33,34,35], [40,41,42,43,44,45], [50,51,52,53,54,55], [60,61,62,63,64,65], [70,71,72,73,74,75]]) print m p = ([1,2,3,4,5,6]) print p print solve(m, p)