def Shinohara1(retI = False): """ no = 12: Shinohara1 { y(0) = p*p*p*p*p - 10.*p*p*p*q*q + 5.*p*q*q*q*q - 2.*p*p*p*p + 12.*p*p*q*q - 2.*q*q*q*q + 10.*p*p*p - 30.*p*q*q - 9.*p + 3. { y(1) = q*q*q*q*q - 10.*p*p*q*q*q + 5.*p*p*p*p*q - 8.*p*p*p*q + 8.*p*q*q*q + 30.*p*p*q -10.*q*q*q - 9.*q true value = ? """ y = [0.0 for i in range(2)] x[0], x[1] = fd.oovars('x0', 'x1') p = x[0] q= x[1] y[0] = p*p*p*p*p - 10.*p*p*p*q*q + 5.*p*q*q*q*q\ - 2.*p*p*p*p + 12.*p*p*q*q - 2.*q*q*q*q\ + 10.*p*p*p - 30.*p*q*q - 9.*p + 3. y[1] = q*q*q*q*q - 10.*p*p*q*q*q + 5.*p*p*p*p*q\ - 8.*p*p*p*q + 8.*p*q*q*q + 30.*p*p*q\ -10.*q*q*q - 9.*q if retI == True: return np.matrix([[interval(-5.1, 5.)], [interval(-5., 5.1)]]) return y
def Shinohara3(retI = False): """ no = 14: Shinohara3 { y(0) = p*p*p - 2.*p*q + r + 0.75*p + 1. { y(1) = p*p*q - q*q - p*r +s + 0.75*q + 0.25 { y(2) = p*p*r - p*s - q*r + t + 0.75*r + 0.75 { y(3) = p*p*s - p*t - q*s + 0.75*s { y(4) = p*p*t - q*t + 0.75*t - 0.25 true value = ? """ y = [0.0 for i in range(5)] x[0], x[1], x[2], x[3], x[4] = fd.oovars('x0', 'x1', 'x2', 'x3', 'x4') p = x[0]; q = x[1]; r = x[2]; s = x[3]; t = x[4]; y[0] = p*p*p - 2.*p*q + r + 0.75*p + 1. y[1] = p*p*q - q*q - p*r +s + 0.75*q + 0.25 y[2] = p*p*r - p*s - q*r + t + 0.75*r + 0.75 y[3] = p*p*s - p*t - q*s + 0.75*s y[4] = p*p*t - q*t + 0.75*t - 0.25 if retI == True: return np.matrix([[interval(-1.5, 2.)],\ [interval(-0.6, 3.)],\ [interval(-1.5, 2.5)],\ [interval(-0.5, 1.9)],\ [interval(-1., 1.)]]) return y
def solve(self, *args, **kw): if len(args) > 1: self.err(''' incorrect number of arguments for solve(), must be at least 1 (solver), other must be keyword arguments''') solver = args[0] if len(args) != 0 else kw.get('solver', self.solver) graph = self.graph # must be networkx instance nodes = graph.nodes() edges = graph.edges() n = len(nodes) node2index = dict([(node, i) for i, node in enumerate(nodes)]) index2node = dict([(i, node) for i, node in enumerate(nodes)]) import FuncDesigner as fd, openopt x = fd.oovars(n, domain=bool) objective = fd.sum(x) startPoint = {x: [0] * n} fixedVars = {} includedNodes = getattr(kw, 'includedNodes', None) if includedNodes is None: includedNodes = getattr(self, 'includedNodes', ()) for node in includedNodes: fixedVars[x[node2index[node]]] = 1 excludedNodes = getattr(kw, 'excludedNodes', None) if excludedNodes is None: excludedNodes = getattr(self, 'excludedNodes', ()) for node in excludedNodes: fixedVars[x[node2index[node]]] = 0 if openopt.oosolver(solver).__name__ == 'interalg': constraints = [ fd.NAND(x[node2index[i]], x[node2index[j]]) for i, j in edges ] P = openopt.GLP else: constraints = [ x[node2index[i]] + x[node2index[j]] <= 1 for i, j in edges ] P = openopt.MILP p = P(objective, startPoint, constraints=constraints, fixedVars=fixedVars, goal='max') for key, val in kw.items(): setattr(p, key, val) r = p.solve(solver, **kw) r.solution = [index2node[i] for i in range(n) if r.xf[x[i]] == 1] r.ff = len(r.solution) return r
def solve(self, *args, **kw): if len(args) > 1: self.err(''' incorrect number of arguments for solve(), must be at least 1 (solver), other must be keyword arguments''') solver = args[0] if len(args) != 0 else kw.get('solver', self.solver) graph = self.graph # must be networkx instance nodes = graph.nodes() edges = graph.edges() n = len(nodes) node2index = dict([(node, i) for i, node in enumerate(nodes)]) index2node = dict([(i, node) for i, node in enumerate(nodes)]) import FuncDesigner as fd, openopt x = fd.oovars(n, domain=bool) objective = fd.sum(x) startPoint = {x:[0]*n} fixedVars = {} includedNodes = getattr(kw, 'includedNodes', None) if includedNodes is None: includedNodes = getattr(self, 'includedNodes', ()) for node in includedNodes: fixedVars[x[node2index[node]]] = 1 excludedNodes = getattr(kw, 'excludedNodes', None) if excludedNodes is None: excludedNodes = getattr(self, 'excludedNodes', ()) for node in excludedNodes: fixedVars[x[node2index[node]]] = 0 if openopt.oosolver(solver).__name__ == 'interalg': constraints = [fd.NAND(x[node2index[i]], x[node2index[j]]) for i, j in edges] P = openopt.GLP else: constraints = [x[node2index[i]]+x[node2index[j]] <=1 for i, j in edges] P = openopt.MILP p = P(objective, startPoint, constraints = constraints, fixedVars = fixedVars, goal = 'max') for key, val in kw.items(): setattr(p, key, val) r = p.solve(solver, **kw) r.solution = [index2node[i] for i in range(n) if r.xf[x[i]] == 1] r.ff = len(r.solution) return r
def GE1(retI = False): """ no = 10: GE1 { -1/(1 + x1) + x2/(1 + x2) = 0 { 1/(1 + x1) - x2/(x1 + x2) = 0 true value = ? """ y = [0.0 for i in range(2)] x[0], x[1] = fd.oovars('x0', 'x1') y[0] = -1./(1. + x[0]) + x[1]/(1. + x[1]) y[1] = 1./(1. + x[0]) - x[1]/(x[0] + x[1]) if retI == True: return np.matrix([[interval(0.01, 100.)], [interval(0.001, 100.)]]) #return np.matrix([[interval(0.1, 10.)], [interval(0.01, 11.)]]) return y
def sincos_function(retI = False): """ no = 4: function including sine and cosine { sin(x1)*cos(x1) - x2 = 0 { x1^2 - 6*x1 + 8 - x2 = 0 true value (x1, x2) = (,), (,) """ y = [0.0 for i in range(2)] x[0], x[1] = fd.oovars('x0', 'x1') y[0] = fd.sin(x[0]) * fd.cos(x[0]) - x[1] y[1] = x[0] * x[0] - 6 * x[0] + 8 - x[1] if retI == True: return np.matrix([[interval(-6.1, 6.)], [interval(-6., 6.)]]) return y
def sample_function_1(retI = False): """ no = 1: sample function 1 { x1^2 - x2 = 0 { (1/2)*x1 - x2 = 0 true value (x1, x2) = (0, 0), (0.5, 0.25) """ y = [0.0 for i in range(2)] x[0], x[1] = fd.oovars('x0', 'x1') y[0] = x[0] * x[0] - x[1] y[1] = 0.5 * x[0] - x[1] if retI == True: return np.matrix([[interval(-2.2, 2.1)], [interval(-1., 2.)]]) return y
def sin_function(retI = False): """ no = 3: function including sin { (pi/2)*sin(x1) - x2 = 0 { x1 - x2 = 0 true value (x1, x2) = (0, 0), (1.57079633.., 1.57079633..), (-1.5709633.., -1.57079633..) """ y = [0.0 for i in range(2)] x[0], x[1] = fd.oovars('x0', 'x1') #y[0] = 1.57079633 * fd.sin(x[0]) - x[1] y[0] = (np.pi/2) * fd.sin(x[0]) - x[1] y[1] = x[0] - x[1] if retI == True: return np.matrix([[interval(-3.1, 3.)], [interval(-2., 2.)]]) return y
def sample_function_2(retI = False): """ no = 2: sample function 2 { x1^2 - x2 = 0 { -x1^2 + 2*x1 - x2 = 0 true value (x1, x2) = (0, 0), (1, 1) """ y = [0.0 for i in range(2)] x[0], x[1] = fd.oovars('x0', 'x1') y[0] = x[0] * x[0] - x[1] y[1] = -x[0] * x[0] + 2 * x[0] - x[1] if retI == True: return np.matrix([[interval(-11., 10.)], [interval(-10., 11.)]]) #return np.matrix([[interval(-10., 10.)], [interval(-10., 10.)]]) return y
def Duffing(retI = False): """ no = 11: Duffing-equation { y(0) = -x(0) + B + 0.1 * x(1) + 0.75 * (x(0)*x(0)*x(0) + x(0) *x(1) * x(1)) { y(1) = - x(1) + 0.1 * x(0) + 0.75 * (x(0)*x(0)*x(1) + x(1)*x(1)*x(1)) true value = 5? """ B = 0. #B = 0.15 y = [0.0 for i in range(2)] x[0], x[1] = fd.oovars('x0', 'x1') y[0] = -1.*x[0] + B + 0.1*x[1] + 0.75*(x[0]*x[0]*x[0] + x[0]*x[1]*x[1]) y[1] = -1.*x[1] + 0.1*x[0] + 0.75*(x[0]*x[0]*x[1] + x[1]*x[1]*x[1]) if retI == True: return np.matrix([[interval(-1e+8-1., 1e+8)], [interval(-1e+8, 1e+8+1.)]]) #return np.matrix([[interval(-1e+5-1., 1e+5)], [interval(-1e+5, 1e+5+1.)]]) return y
def Nosol(retI = False): """ no = 9: No-solutions { x1^2 - x2 = 0 { x1^2 - x2 + param true value (x1, x2) = None """ #param = 0.01 param = 0.001 y = [0.0 for i in range(2)] x[0], x[1] = fd.oovars('x0', 'x1') y[0] = x[0]*x[0] - x[1] y[1] = x[0]*x[0] - x[1] + param if retI == True: return np.matrix([[interval(-1., 1.)], [interval(-1., 1.)]]) return y
def default_function(retI = False): """ no = 0: default function { x1^2 + x2^2 -1 = 0 { x1 - x2 = 0 one true solution which sample function has is below: x1 = x2 = (2^(1/2))/2 (=~ 0.70710678) """ y = [0.0 for i in range(2)] x[0], x[1] = fd.oovars('x0', 'x1') y[0] = x[0] * x[0] + x[1] * x[1] - 1 y[1] = x[0] - x[1] if retI == True: #return np.matrix([[interval(-1.1, 1.)], [interval(-1., 1.)]]) return np.matrix([[interval(-1., 1.)], [interval(-1., 1.)]]) return y
def badCond(retI = False): """ no = 7: BadCond { x1^2 - x2 = 0 { (1 - param) * x1^2 - x2 + param = 0 true value (x1, x2) = (, ), (, ) """ #param = 0.0000001 #param = 0.01 param = 0.001 y = [0.0 for i in range(2)] x[0], x[1] = fd.oovars('x0', 'x1') y[0] = x[0]*x[0] - x[1] y[1] = (1 - param)*x[0]*x[0] - x[1] + param if retI == True: return np.matrix([[interval(-10., 10.)], [interval(-10., 10.)]]) return y
def function_3_dim(retI = False): """ no = 5: function of 3-dimention { x1 + x2 + x3 = 6 { 3*x1 + 2*x2 -2*x3 = 1 { 2*x1 - x2 + 3*x3 = 9 true value (x1, x2, x3) = (1, 2, 3) """ y = [0.0 for i in range(3)] x[0], x[1], x[2] = fd.oovars('x0', 'x1', 'x2') y[0] = x[0] + x[1] + x[2] - 6 y[1] = 3*x[0] + 2*x[1] - 2*x[2] - 1 y[2] = 2*x[0] - x[1] + 3*x[2] - 9 if retI == True: #return np.matrix([[interval(-1.1, 5.)], [interval(-1., 5.)], [interval(-1., 5.1)]]) return np.matrix([[interval(-50.1, 50.)], [interval(-50., 50.)], [interval(-50., 50.1)]]) return y
def Burden(retI = False): """ no = 8: Burden { x1*(4 - 0.0003*x1 - 0.0004*x2) = 0 { x2*(2 - 0.0002*x1 - 0.0001*x2) = 0 true value (x1, x2) = ? """ #param = 0.0001 param = 0.1 y = [0.0 for i in range(2)] x[0], x[1] = fd.oovars('x0', 'x1') y[0] = x[0]*(4. - 3.*param*x[0] - 4.*param*x[1]) y[1] = x[1]*(2. - 2.*param*x[0] - 1.*param*x[1]) if retI == True: #return np.matrix([[interval(0., pow(10., 10))], [interval(0., pow(10., 10))]]) return np.matrix([[interval(-1., pow(10., 10))], [interval(0., pow(10., 10)+1)]]) return y
def function_3_dim_2(retI = False): """ no = 6: function of 3-dimention { x1*x2 - 9 = 0 { x2*x3 - 6 = 0 { x3*x1 - 6 = 0 true value (x1, x2, x3) = (3, 3, 2), (-3, -3, -2) """ y = [0.0 for i in range(3)] x[0], x[1], x[2] = fd.oovars('x0', 'x1', 'x2') y[0] = x[0] * x[1] - 9 y[1] = x[1] * x[2] - 6 y[2] = x[2] * x[0] - 6 if retI == True: #return np.matrix([[interval(-6.1, 5.)], [interval(-5., 6.)], [interval(-6., 7.1)]]) #return np.matrix([[interval(-10.1, 15.)], [interval(-15., 20.)], [interval(-16., 10.1)]]) return np.matrix([[interval(-100, 100.)], [interval(-100., 100.)], [interval(-100., 100.)]]) return y
def automaticdiffertest(): #from FuncDesigner import * a, b, c = fd.oovars('a', 'b', 'c') f1, f2 = fd.sin(a) + fd.cos(b) - fd.log2(c) + fd.sqrt(b), fd.sum(c) + c * fd.cosh(b) / fd.arctan(a) + c[0] * c[1] + c[-1] / (a * c.size) f3 = f1*f2 + 2*a + fd.sin(b) * (1+2*c.size + 3*f2.size) f = 2*a*b*c + f1*f2 + f3 + fd.dot(a+c, b+c) point = {a:1, b:2, c:[3, 4, 5]} # however, you'd better use numpy arrays instead of Python lists print(f(point)) print(f.D(point)) print(f.D(point, a)) print(f.D(point, [b])) print(f.D(point, fixedVars = [a, c]))
def Shinohara2(retI = False): """ no = 13: Shinohara2 { y(0) = p*p*p*p*p - 10.*p*p*p*q*q + 5.*p*q*q*q*q - 3.*p*p*p*p + 18.*p*p*q*q - 3.*q*q*q*q - 2.*p*p*p + 6.*p*q*q + 3.*p*p*q - q*q*q + 12.*p*p - 12.*q*q - 10.*p*q - 8.*p + 8.*q; { y(1) = 5.*p*p*p*p*q - 10.*p*p*q*q*q + q*q*q*q*q - 12.*p*p*p*q + 12.*p*q*q*q - p*p*p + 3.*p*q*q - 6.*p*p*q + 2.*q*q*q + 5.*p*p - 5.*q*q + 24.*p*q - 8.*p - 8.*q + 4.; true value = ? output: 0 = [[[-2.09868411349,-2.09868411345]] [[-0.455089860584,-0.455089860541]]] 1 = [[[0.999999999995,1.0]] [[-4.51311746098e-12,4.51285733701e-12]]] 2 = [[[0.0986841134678,0.0986841134678]] [[0.455089860562,0.455089860562]]] """ y = [0.0 for i in range(2)] x[0], x[1] = fd.oovars('x0', 'x1') p = x[0] q= x[1] y[0] = p*p*p*p*p - 10.*p*p*p*q*q + 5.*p*q*q*q*q\ - 3.*p*p*p*p + 18.*p*p*q*q - 3.*q*q*q*q\ - 2.*p*p*p + 6.*p*q*q + 3.*p*p*q - q*q*q\ + 12.*p*p - 12.*q*q - 10.*p*q - 8.*p + 8.*q y[1] = 5.*p*p*p*p*q - 10.*p*p*q*q*q + q*q*q*q*q\ - 12.*p*p*p*q + 12.*p*q*q*q - p*p*p + 3.*p*q*q\ - 6.*p*p*q + 2.*q*q*q + 5.*p*p - 5.*q*q\ + 24.*p*q - 8.*p - 8.*q + 4. if retI == True: return np.matrix([[interval(-3.1, 3.)], [interval(-3., 3.1)]]) return y
def set_routine(p, *args, **kw): if len(args) > 1: p.err(''' incorrect number of arguments for solve(), must be at least 1 (solver), other must be keyword arguments''') solver = args[0] if len(args) != 0 else kw.get('solver', p.solver) import FuncDesigner as fd, openopt is_interalg = openopt.oosolver(solver).__name__ == 'interalg' graph = p.graph # must be networkx instance nodes = graph.nodes() edges = graph.edges() n = len(nodes) node2index = dict((node, i) for i, node in enumerate(nodes)) index2node = dict((i, node) for i, node in enumerate(nodes)) x = fd.oovars(n, domain=bool) objective = fd.sum(x) startPoint = {x:[0]*n} fixedVars = {} includedNodes = getattr(kw, 'includedNodes', None) if includedNodes is None: includedNodes = getattr(p, 'includedNodes', ()) for node in includedNodes: fixedVars[x[node2index[node]]] = 1 excludedNodes = getattr(kw, 'excludedNodes', None) if excludedNodes is None: excludedNodes = getattr(p, 'excludedNodes', ()) for node in excludedNodes: fixedVars[x[node2index[node]]] = 0 if p.probType == 'DSP': constraints = [] engine = fd.OR if is_interalg else lambda List: fd.sum(List) >= 1 Engine = lambda d, n: engine([x[node2index[k]] for k in (list(d.keys())+[n])]) for node in nodes: adjacent_nodes_dict = graph[node] if len(adjacent_nodes_dict) == 0: fixedVars[x[node2index[node]]] = 1 continue constraints.append(Engine(adjacent_nodes_dict, node)) else: constraints = \ [fd.NAND(x[node2index[i]], x[node2index[j]]) for i, j in edges] \ if is_interalg else \ [x[node2index[i]]+x[node2index[j]] <=1 for i, j in edges] P = openopt.GLP if is_interalg else openopt.MILP goal = 'min' if p.probType == 'DSP' else 'max' p = P(objective, startPoint, constraints = constraints, fixedVars = fixedVars, goal = goal) for key, val in kw.items(): setattr(p, key, val) r = p.solve(solver, **kw) r.solution = [index2node[i] for i in range(n) if r.xf[x[i]] == 1] r.ff = len(r.solution) return r
h = [] for i in range(n): if i == j: h.append(12+n/(i+1.0)) elif i == j + 1: h.append(0) elif j == i + 2: h.append(0) else: h.append(15/((i+1)+0.1*(j+1))) H.append(h) #print H #H = [[15,0,4.83871], # [12.5,13.5,0], # [0,6.52174,13]] #print H x = fd.oovars(n) f = fd.dot(fd.dot(x, H), x) startPoint = {x: np.zeros(n)} constraints = [] constraints.append(x > np.zeros(n)) constraints.append(fd.sum(x) == 1) p = QP(f, startPoint, constraints=constraints) r = p.solve("qlcp") x_opt = r(x) print(math.sqrt(r.ff)) # problem # http://abel.ee.ucla.edu/cvxopt/examples/tutorial/qp.html
def solve(self, *args, **kw): if len(args) > 1: self.err(''' incorrect number of arguments for solve(), must be at least 1 (solver), other must be keyword arguments''') if self.start is None and not self.returnToStart: self.err('for returnToStart=False mode you should provide start, other cases are unimplemented yet') solver = args[0] if len(args) != 0 else kw.get('solver', self.solver) KW = self.__init_kwargs.copy() KW.update(kw) objective = KW.get('objective', self.objective) if isinstance(objective, (list, tuple, set)): nCriteria = len(self.objective) if 3 * nCriteria != np.asarray(self.objective).size: objective = [(objective[3*i], objective[3*i+1], objective[3*i+2]) for i in range(int(round(np.asarray(self.objective).size / 3)))] if len(objective) == 1: KW['fTol'], KW['goal'] = objective[0][1:] else: objective = [(self.objective, KW.get('fTol', getattr(self, 'fTol')), KW.get('goal', getattr(self, 'goal')))] nCriteria = len(objective) isMOP = nCriteria > 1 mainCr = objective[0][0] import FuncDesigner as fd, openopt as oo solverName = solver if type(solver) == str else solver.__name__ is_interalg = solverName == 'interalg' is_glp = solverName == 'sa' if is_glp: assert nCriteria == 1, 'you cannot solve multiobjective tsp by the solver' is_interalg_raw_mode = is_interalg and KW.get('dataHandling', oo.oosolver(solver).dataHandling) in ('auto','raw') KW.pop('objective', None) P = oo.MOP if nCriteria > 1 else oo.GLP if is_interalg else oo.MILP if not is_glp else oo.GLP import networkx as nx graph = self.graph # must be networkx Graph instance init_graph_is_directed = graph.is_directed() init_graph_is_multigraph = graph.is_multigraph() if not init_graph_is_multigraph or not init_graph_is_directed: graph = nx.MultiDiGraph(graph) #if init_graph_is_directed else nx.MultiGraph(graph) nodes = graph.nodes() edges = graph.edges() n = len(nodes) m = len(edges) node2index = dict([(node, i) for i, node in enumerate(nodes)]) # TODO: implement MOP with interalg_gdp mode (requires interpolation interval analysis for non-monotone funcs) interalg_gdp = 1 if not is_interalg:# or isMOP: # !!!!!!!!!!!!! TODO: add handling of MOP with interalg_gdp? interalg_gdp = 0 if interalg_gdp: x = [] edge_ind2x_ind_val = {} else: pass #x = fd.oovars(m, domain=bool) #cr_values = dict([(obj[0], []) for obj in objective]) cr_values = {} constraints = [] EdgesDescriptors, EdgesCoords = [], [] # mb rework it by successors etc? Funcs = {} Cons = KW.pop('constraints', []) if type(Cons) not in (list, tuple): Cons = [Cons] usedValues = getUsedValues(Cons) usedValues.update(getUsedValues([obj[0] for obj in objective])) MainCr = mainCr if type(mainCr) in (str, np.str_) else list(usedValues)[0] isMainCrMin = objective[0][2] in ('min', 'minimum') node_out_edges_num = [] for node in nodes: Edges = graph[node] node_out_edges_num.append(len(Edges)) out_nodes = Edges.keys() if len(out_nodes) == 0: self.err('input graph has node %s that does not lead to any other node; solution is impossible' % node) if init_graph_is_multigraph and not isMOP and type(mainCr) in [str, np.str_]: W = {} for out_node in out_nodes: ww = list(Edges[out_node].values()) for w in ww: tmp = W.get(out_node, None) if tmp is None: W[out_node] = w continue th = tmp[mainCr] w_main_cr_val = w[mainCr] if isMainCrMin == (th > w_main_cr_val): W[out_node] = w Out_nodes, W = np.array(list(W.keys())), np.array(list(W.values())) else: W = np.hstack([list(Edges[out_node].values()) for out_node in out_nodes]) Out_nodes = np.hstack([[out_node] * len(Edges[out_node]) for out_node in out_nodes]) if interalg_gdp: rr = np.array([w[MainCr] for w in W]) if isMainCrMin: rr = -rr elif objective[0][2] not in ('max', 'maximum'): self.err('unimplemented for fixed value goal in TSP yet, only min/max is possible for now') ind = rr.argsort() W = W[ind] Out_nodes = Out_nodes[ind] lc = 0 for i, w in enumerate(W): if interalg_gdp: edge_ind2x_ind_val[len(EdgesCoords)] = (len(x), lc) lc += 1 EdgesCoords.append((node, Out_nodes[i])) EdgesDescriptors.append(w) for key, val in w.items(): # for undirected: #if node2index[key] < node2index[out_node]: continue Val = val if self.returnToStart or node != self.start else 0 if key in cr_values: cr_values[key].append(Val) else: cr_values[key] = [Val] if interalg_gdp: x.append(fd.oovar(domain = np.arange(lc))) m = len(EdgesCoords) # new value if is_glp: if type(mainCr) not in (str, np.str_): self.err('for the solver "sa" only text name objectives are implemented (e.g. "time", "price")') if init_graph_is_multigraph: self.err('the solver "sa" cannot handle multigraphs yet') if len(Cons) != 0: self.err('the solver "sa" cannot handle constrained TSP yet') M = np.empty((n, n)) M.fill(np.nan) Cr_values = np.array(cr_values[mainCr]) isMax = objective[0][-1] in ('max', 'maximum') if isMax: Cr_values = -Cr_values for i, w in enumerate(EdgesDescriptors): node_in, node_out = EdgesCoords[i] M[node_in, node_out] = Cr_values[i] S = np.abs(Cr_values).sum() + 1.0 # TODO: check it M[np.isnan(M)] = S prob = P(lambda x: 0, np.zeros(n), iprint = 1) prob.f = lambda x: np.nan if not hasattr(prob, 'ff') else (prob.ff if isMax else -prob.ff) prob.M = dict([((i, j), M[i, j]) for i in range(n) for j in range(n) if i != j]) r = prob.solve(solver, **KW) xf = [nodes[j] for j in np.array(r.xf, int)] r.nodes = xf#.tolist() if self.start is not None: j = r.nodes.index(self.start) r.nodes = r.nodes[j:] + r.nodes[:j] if self.returnToStart: r.nodes += [r.nodes[0]] r.edges = [(r.nodes[i], r.nodes[i+1]) for i in range(n-1)] r.Edges = [(r.nodes[i], r.nodes[i+1], graph[r.nodes[i]][r.nodes[i+1]][0]) for i in range(n-1)] if self.returnToStart: r.edges.append((r.nodes[-2], r.nodes[0])) print(r.nodes[-1], r.nodes[0], type(r.nodes[-1]), type(r.nodes[0]), graph[2]) r.Edges.append((r.nodes[-2], r.nodes[0], graph[r.nodes[-2]][r.nodes[0]][0])) #r.xf = r.xk = r.nodes # TODO: Edges return r #TODO: fix ooarray lb/ub #u = np.array([1] + [fd.oovar(lb=2, ub=n) for i in range(n-1)]) u = fd.hstack((1, fd.oovars(n-1, lb=2, ub=n))) for i in range(1, u.size): u[i]('u' + str(i)) if is_interalg_raw_mode: for i in range(n-1): u[1+i].domain = np.arange(2, n+1) if interalg_gdp: assert len(x) == n x = fd.ooarray(x) # TODO: remove it when proper enum implementation in FD engine will be done for i in range(n): x[i]._init_domain = x[i].domain constraints.append(x[i]-x[i]._init_domain[-1] <= 0) x[i].domain = np.arange(int(2 ** np.ceil(np.log2(node_out_edges_num[i])))) # for i in range(n-1): # u[1+i]._init_domain = u[1+i].domain # constraints.append(u[1+i]-u[1+i]._init_domain[-1] <= 0) # u[1+i].domain = np.arange(u[1+i]._init_domain[0], u[1+i]._init_domain[0]+int(2 ** np.ceil(np.log2(u[1+i]._init_domain[-1]-u[1+i]._init_domain[0]+1)))) # u[1+i].ub = u[1+i].domain[-1] else: x = fd.oovars(m, domain=bool) # new m value for i in range(x.size): x[i]('x'+str(i)) # if init_graph_is_directed: dictFrom = dict([(node, []) for node in nodes]) dictTo = dict([(node, []) for node in nodes]) for i, edge in enumerate(EdgesCoords): From, To = edge dictFrom[From].append(i) dictTo[To].append(i) engine = fd.XOR # number of outcoming edges = 1 if not interalg_gdp: for node, edges_inds in dictFrom.items(): # !!!!!!!!!! TODO for interalg_raw_mode: and if all edges have sign similar to goal if 1 and is_interalg_raw_mode: c = engine([x[j] for j in edges_inds]) else: nEdges = fd.sum([x[j] for j in edges_inds]) c = nEdges >= 1 if self.allowRevisit else nEdges == 1 constraints.append(c) # number of incoming edges = 1 for node, edges_inds in dictTo.items(): if len(edges_inds) == 0: self.err('input graph has node %s that has no edge from any other node; solution is impossible' % node) if interalg_gdp: x_inds, x_vals = [], [] for elem in edges_inds: x_ind, x_val = edge_ind2x_ind_val[elem] x_inds.append(x_ind) x_vals.append(x_val) c = engine([(x[x_ind] == x_val)(tol = 0.5) for x_ind, x_val in zip(x_inds, x_vals)]) else: if 1 and is_interalg_raw_mode and engine == fd.XOR: c = engine([x[j] for j in edges_inds]) else: nEdges = fd.sum([x[j] for j in edges_inds]) c = nEdges >= 1 if self.allowRevisit else nEdges == 1 constraints.append(c) # MTZ for i, (I, J) in enumerate(EdgesCoords): ii, jj = node2index[I], node2index[J] if ii != 0 and jj != 0: if interalg_gdp: x_ind, x_val = edge_ind2x_ind_val[i] c = fd.ifThen((x[x_ind] == x_val)(tol=0.5), u[ii] - u[jj] <= - 1.0) elif is_interalg_raw_mode: c = fd.ifThen(x[i], u[ii] - u[jj] <= - 1.0)#u[jj] - u[ii] >= 1) else: c = u[ii] - u[jj] + 1 <= (n-1) * (1-x[i]) constraints.append(c) # handling objective(s) FF = [] for optCrName in usedValues: tmp = cr_values.get(optCrName, []) if len(tmp) == 0: self.err('seems like graph edgs have no attribute "%s" to perform optimization on it' % optCrName) elif len(tmp) != m: self.err('for optimization creterion "%s" at least one edge has no this attribute' % optCrName) if interalg_gdp: F = [] lc = 0 for X in x: domain = X._init_domain vals = [tmp[i] for i in range(lc, lc + domain.size)] lc += domain.size #F = sum(x) #F.append(fd.interpolator(domain, vals, k=1, s=0.00000001)(X)) F.append(fd.interpolator(domain, vals, k=1)(X)) #print(domain, vals) F = fd.sum(F) else: F = fd.sum(x*tmp) Funcs[optCrName] = F for obj in objective: FF.append((Funcs[obj[0]] if type(obj[0]) in (str, np.str_) else obj[0](Funcs), obj[1], obj[2])) for c in Cons: tmp = c(Funcs) if type(tmp) in (list, tuple, set): constraints += list(tmp) else: constraints.append(tmp) startPoint = {x:[0]*(m if not interalg_gdp else n)} startPoint.update(dict([(U, i+2) for i, U in enumerate(u[1:])])) p = P(FF if isMOP else FF[0][0], startPoint, constraints = constraints)#, fixedVars = fixedVars) for param in ('start', 'returnToStart'): KW.pop(param, None) r = p.solve(solver, **KW) if P != oo.MOP: r.ff = p.ff if interalg_gdp: x_ind_val2edge_ind = dict([(elem[1], elem[0]) for elem in edge_ind2x_ind_val.items()]) SolutionEdges = [(EdgesCoords[i][0], EdgesCoords[i][1], EdgesDescriptors[i]) for i in [x_ind_val2edge_ind[(ind, x[ind](r))] for ind in range(n)]] else: SolutionEdges = [(EdgesCoords[i][0], EdgesCoords[i][1], EdgesDescriptors[i]) for i in range(m) if r.xf[x[i]] == 1] if len(SolutionEdges) == 0: r.nodes = r.edges = r.Edges = [] return r S = dict([(elem[0], elem) for elem in SolutionEdges]) SE = [SolutionEdges[0]] for i in range(len(SolutionEdges)-1): SE.append(S[SE[-1][1]]) SolutionEdgesCoords = [(elem[0], elem[1]) for elem in SE] nodes = [edge[1] for edge in SolutionEdgesCoords] if self.start is not None: shift_ind = nodes.index(self.start) nodes = nodes[shift_ind:] + nodes[:shift_ind] if self.returnToStart: nodes.append(nodes[0]) edges = SolutionEdgesCoords[1:] + [SolutionEdgesCoords[0]] Edges = SE[1:] + [SE[0]] if self.start is not None: edges, Edges = edges[shift_ind:] + edges[:shift_ind], Edges[shift_ind:] + Edges[:shift_ind] if not self.returnToStart: edges, Edges = edges[:-1], Edges[:-1] r.nodes, r.edges, r.Edges = nodes, edges, Edges else: r.solution = 'for MOP see r.solutions instead of r.solution' tmp_c, tmp_v = r.solutions.coords, r.solutions.values # if interalg_gdp: # x_ind_val2edge_ind = dict([(elem[1], elem[0]) for elem in edge_ind2x_ind_val.items()]) # SolutionEdges = [(EdgesCoords[i][0], EdgesCoords[i][1], EdgesDescriptors[i]) for i in [x_ind_val2edge_ind[(ind, x[ind](r))] for ind in range(n)]] # else: # SolutionEdges = [(EdgesCoords[i][0], EdgesCoords[i][1], EdgesDescriptors[i]) for i in range(m) if r.xf[x[i]] == 1] if interalg_gdp: # default for MOP x_ind_val2edge_ind = dict([(elem[1], elem[0]) for elem in edge_ind2x_ind_val.items()]) r.solutions = MOPsolutions([[(EdgesCoords[i][0], EdgesCoords[i][1], EdgesDescriptors[i]) for i in [x_ind_val2edge_ind[(ind, x[ind](Point))] for ind in range(n)]] for Point in r.solutions]) else:# non-default r.solutions = MOPsolutions([[(EdgesCoords[i][0], EdgesCoords[i][1], EdgesDescriptors[i]) for i in range(m) if Point[x[i]] == 1] for Point in r.solutions]) r.solutions.values = tmp_v return r
def solve(self, *args, **kw): import FuncDesigner as fd, openopt as oo if len(args) > 1: self.err(''' incorrect number of arguments for solve(), must be at least 1 (solver), other must be keyword arguments''') solver = args[0] if len(args) != 0 else kw.get('solver', self.solver) KW = self.__init_kwargs.copy() KW.update(kw) items = self.items n = len(items) objective = KW.get('objective', self.objective) if isinstance(objective, (list, tuple, set)): nCriteria = len(self.objective) if 3 * nCriteria != np.asarray(self.objective).size: objective = [ (objective[3 * i], objective[3 * i + 1], objective[3 * i + 2]) for i in range( int(round(np.asarray(self.objective).size / 3))) ] if len(objective) == 1: KW['fTol'], KW['goal'] = objective[0][1:] else: objective = [(self.objective, KW.get('fTol', getattr(self, 'fTol')), KW.get('goal', getattr(self, 'goal')))] nCriteria = len(objective) isMOP = nCriteria > 1 #mainCr = objective[0][0] solverName = solver if type(solver) == str else solver.__name__ is_interalg = solverName == 'interalg' is_glp = False #solverName == 'sa' if is_glp: assert nCriteria == 1, 'you cannot solve multiobjective KSP by the solver' #is_interalg_raw_mode = is_interalg and KW.get('dataHandling', oo.oosolver(solver).dataHandling) in ('auto','raw') KW.pop('objective', None) P = oo.MOP if nCriteria > 1 else oo.GLP if is_interalg else oo.MILP if not is_glp else oo.GLP x = fd.oovars(n, domain=bool) requireCount = False for i, obj in enumerate(items): if 'n' in obj: x[i].domain = np.arange(obj['n'] + 1) if is_interalg else int x[i].ub = obj['n'] x[i].lb = 0 requireCount = True #cr_values = dict([(obj[0], []) for obj in objective]) constraints = [] Funcs = {} Cons = KW.pop('constraints', []) if type(Cons) not in (list, tuple): Cons = [Cons] usedValues = getUsedValues(Cons) usedValues.update(getUsedValues([obj[0] for obj in objective])) cr_values = {} for val in usedValues: if val == 'nItems': cr_values[val] = 1 else: cr_values[val] = [obj[val] for obj in items] # MainCr = mainCr if type(mainCr) in (str, np.str_) else list(usedValues)[0] # # isMainCrMin = objective[0][2] in ('min', 'minimum') # handling objective(s) FF = [] for optCrName in usedValues: F = fd.sum(x * cr_values[optCrName]) Funcs[optCrName] = F for obj in objective: FF.append((Funcs[obj[0]](obj[0]) if type(obj[0]) in (str, np.str_) else obj[0](Funcs), obj[1], obj[2])) for c in Cons: tmp = c(Funcs) if type(tmp) in (list, tuple, set): constraints += list(tmp) else: constraints.append(tmp) startPoint = {x: [0] * n} p = P(FF if isMOP else FF[0][0], startPoint, constraints=constraints) #, fixedVars = fixedVars) if not isMOP: p.goal = self.goal r = p.solve(solver, **KW) if P != oo.MOP: r.ff = p.ff if isMOP: #assert not requireCount, 'MOP with nItem > 1 is unimplemented yet' r.solution = 'for MOP see r.solutions instead of r.solution' #tmp_c, tmp_v = r.solutions.coords, r.solutions.values if len(r.solutions): S = [] for s in r.solutions: tmp = [((i, int(s[x[i]])) if requireCount else i) for i in range(n) if s[x[i]] >= 1] if 'name' in items[0]: tmp = [ (items[i]['name'], k) for i, k in tmp ] if requireCount else [items[i]['name'] for i in tmp] S.append(dict(tmp) if requireCount else tmp) Vals = dict([(ff[0].name, r.solutions.values[:, i]) for i, ff in enumerate(FF)]) Dicts = [s.copy() for s in S] for v in usedValues: if v != 'nItems': for i, d in enumerate(Dicts): d[v] = Vals[v][i] r.solutions = MOPsolutions(Dicts) r.solutions.coords = S r.solutions.values = Vals else: tmp = [((i, int(r.xf[x[i]])) if requireCount else i) for i in range(n) if r.xf[x[i]] >= 1] if 'name' in items[0]: tmp = [(items[i]['name'], k) for i, k in tmp ] if requireCount else [items[i]['name'] for i in tmp] r.xf = dict(tmp) if requireCount else tmp return r
def solve(self, *args, **kw): if len(args) > 1: self.err(''' incorrect number of arguments for solve(), must be at least 1 (solver), other must be keyword arguments''') if self.start is None and not self.returnToStart: self.err( 'for returnToStart=False mode you should provide start, other cases are unimplemented yet' ) solver = args[0] if len(args) != 0 else kw.get('solver', self.solver) KW = self.__init_kwargs.copy() KW.update(kw) objective = KW.get('objective', self.objective) if isinstance(objective, (list, tuple, set)): nCriteria = len(self.objective) if 3 * nCriteria != np.asarray(self.objective).size: objective = [ (objective[3 * i], objective[3 * i + 1], objective[3 * i + 2]) for i in range( int(round(np.asarray(self.objective).size / 3))) ] if len(objective) == 1: KW['fTol'], KW['goal'] = objective[0][1:] else: objective = [(self.objective, KW.get('fTol', getattr(self, 'fTol')), KW.get('goal', getattr(self, 'goal')))] nCriteria = len(objective) isMOP = nCriteria > 1 mainCr = objective[0][0] import FuncDesigner as fd, openopt as oo solverName = solver if type(solver) == str else solver.__name__ is_interalg = solverName == 'interalg' is_glp = solverName == 'sa' if is_glp: assert nCriteria == 1, 'you cannot solve multiobjective tsp by the solver' is_interalg_raw_mode = is_interalg and KW.get( 'dataHandling', oo.oosolver(solver).dataHandling) in ('auto', 'raw') KW.pop('objective', None) P = oo.MOP if nCriteria > 1 else oo.GLP if is_interalg else oo.MILP if not is_glp else oo.GLP import networkx as nx graph = self.graph # must be networkx Graph instance init_graph_is_directed = graph.is_directed() init_graph_is_multigraph = graph.is_multigraph() if not init_graph_is_multigraph or not init_graph_is_directed: graph = nx.MultiDiGraph( graph) #if init_graph_is_directed else nx.MultiGraph(graph) nodes = graph.nodes() edges = graph.edges() n = len(nodes) m = len(edges) node2index = dict([(node, i) for i, node in enumerate(nodes)]) # TODO: implement MOP with interalg_gdp mode (requires interpolation interval analysis for non-monotone funcs) interalg_gdp = 1 if not is_interalg: # or isMOP: # !!!!!!!!!!!!! TODO: add handling of MOP with interalg_gdp? interalg_gdp = 0 if interalg_gdp: x = [] edge_ind2x_ind_val = {} else: pass #x = fd.oovars(m, domain=bool) #cr_values = dict([(obj[0], []) for obj in objective]) cr_values = {} constraints = [] EdgesDescriptors, EdgesCoords = [], [] # mb rework it by successors etc? Funcs = {} Cons = KW.pop('constraints', []) if type(Cons) not in (list, tuple): Cons = [Cons] usedValues = getUsedValues(Cons) usedValues.update(getUsedValues([obj[0] for obj in objective])) MainCr = mainCr if type(mainCr) in (str, np.str_) else list(usedValues)[0] isMainCrMin = objective[0][2] in ('min', 'minimum') node_out_edges_num = [] for node in nodes: Edges = graph[node] node_out_edges_num.append(len(Edges)) out_nodes = Edges.keys() if len(out_nodes) == 0: self.err( 'input graph has node %s that does not lead to any other node; solution is impossible' % node) if init_graph_is_multigraph and not isMOP and type(mainCr) in [ str, np.str_ ]: W = {} for out_node in out_nodes: ww = list(Edges[out_node].values()) for w in ww: tmp = W.get(out_node, None) if tmp is None: W[out_node] = w continue th = tmp[mainCr] w_main_cr_val = w[mainCr] if isMainCrMin == (th > w_main_cr_val): W[out_node] = w Out_nodes, W = np.array(list(W.keys())), np.array( list(W.values())) else: W = np.hstack( [list(Edges[out_node].values()) for out_node in out_nodes]) Out_nodes = np.hstack([[out_node] * len(Edges[out_node]) for out_node in out_nodes]) if interalg_gdp: rr = np.array([w[MainCr] for w in W]) if isMainCrMin: rr = -rr elif objective[0][2] not in ('max', 'maximum'): self.err( 'unimplemented for fixed value goal in TSP yet, only min/max is possible for now' ) ind = rr.argsort() W = W[ind] Out_nodes = Out_nodes[ind] lc = 0 for i, w in enumerate(W): if interalg_gdp: edge_ind2x_ind_val[len(EdgesCoords)] = (len(x), lc) lc += 1 EdgesCoords.append((node, Out_nodes[i])) EdgesDescriptors.append(w) for key, val in w.items(): # for undirected: #if node2index[key] < node2index[out_node]: continue Val = val if self.returnToStart or node != self.start else 0 if key in cr_values: cr_values[key].append(Val) else: cr_values[key] = [Val] if interalg_gdp: x.append(fd.oovar(domain=np.arange(lc))) m = len(EdgesCoords) # new value if is_glp: if type(mainCr) not in (str, np.str_): self.err( 'for the solver "sa" only text name objectives are implemented (e.g. "time", "price")' ) if init_graph_is_multigraph: self.err('the solver "sa" cannot handle multigraphs yet') if len(Cons) != 0: self.err('the solver "sa" cannot handle constrained TSP yet') M = np.empty((n, n)) M.fill(np.nan) Cr_values = np.array(cr_values[mainCr]) isMax = objective[0][-1] in ('max', 'maximum') if isMax: Cr_values = -Cr_values for i, w in enumerate(EdgesDescriptors): node_in, node_out = EdgesCoords[i] M[node_in, node_out] = Cr_values[i] S = np.abs(Cr_values).sum() + 1.0 # TODO: check it M[np.isnan(M)] = S prob = P(lambda x: 0, np.zeros(n), iprint=1) prob.f = lambda x: np.nan if not hasattr(prob, 'ff') else ( prob.ff if isMax else -prob.ff) prob.M = dict([((i, j), M[i, j]) for i in range(n) for j in range(n) if i != j]) r = prob.solve(solver, **KW) xf = [nodes[j] for j in np.array(r.xf, int)] r.nodes = xf #.tolist() if self.start is not None: j = r.nodes.index(self.start) r.nodes = r.nodes[j:] + r.nodes[:j] if self.returnToStart: r.nodes += [r.nodes[0]] r.edges = [(r.nodes[i], r.nodes[i + 1]) for i in range(n - 1)] r.Edges = [(r.nodes[i], r.nodes[i + 1], graph[r.nodes[i]][r.nodes[i + 1]][0]) for i in range(n - 1)] if self.returnToStart: r.edges.append((r.nodes[-2], r.nodes[0])) print(r.nodes[-1], r.nodes[0], type(r.nodes[-1]), type(r.nodes[0]), graph[2]) r.Edges.append((r.nodes[-2], r.nodes[0], graph[r.nodes[-2]][r.nodes[0]][0])) #r.xf = r.xk = r.nodes # TODO: Edges return r #TODO: fix ooarray lb/ub #u = np.array([1] + [fd.oovar(lb=2, ub=n) for i in range(n-1)]) u = fd.hstack((1, fd.oovars(n - 1, lb=2, ub=n))) for i in range(1, u.size): u[i]('u' + str(i)) if is_interalg_raw_mode: for i in range(n - 1): u[1 + i].domain = np.arange(2, n + 1) if interalg_gdp: assert len(x) == n x = fd.ooarray(x) # TODO: remove it when proper enum implementation in FD engine will be done for i in range(n): x[i]._init_domain = x[i].domain constraints.append(x[i] - x[i]._init_domain[-1] <= 0) x[i].domain = np.arange( int(2**np.ceil(np.log2(node_out_edges_num[i])))) # for i in range(n-1): # u[1+i]._init_domain = u[1+i].domain # constraints.append(u[1+i]-u[1+i]._init_domain[-1] <= 0) # u[1+i].domain = np.arange(u[1+i]._init_domain[0], u[1+i]._init_domain[0]+int(2 ** np.ceil(np.log2(u[1+i]._init_domain[-1]-u[1+i]._init_domain[0]+1)))) # u[1+i].ub = u[1+i].domain[-1] else: x = fd.oovars(m, domain=bool) # new m value for i in range(x.size): x[i]('x' + str(i)) # if init_graph_is_directed: dictFrom = dict([(node, []) for node in nodes]) dictTo = dict([(node, []) for node in nodes]) for i, edge in enumerate(EdgesCoords): From, To = edge dictFrom[From].append(i) dictTo[To].append(i) engine = fd.XOR # number of outcoming edges = 1 if not interalg_gdp: for node, edges_inds in dictFrom.items(): # !!!!!!!!!! TODO for interalg_raw_mode: and if all edges have sign similar to goal if 1 and is_interalg_raw_mode: c = engine([x[j] for j in edges_inds]) else: nEdges = fd.sum([x[j] for j in edges_inds]) c = nEdges >= 1 if self.allowRevisit else nEdges == 1 constraints.append(c) # number of incoming edges = 1 for node, edges_inds in dictTo.items(): if len(edges_inds) == 0: self.err( 'input graph has node %s that has no edge from any other node; solution is impossible' % node) if interalg_gdp: x_inds, x_vals = [], [] for elem in edges_inds: x_ind, x_val = edge_ind2x_ind_val[elem] x_inds.append(x_ind) x_vals.append(x_val) c = engine([(x[x_ind] == x_val)(tol=0.5) for x_ind, x_val in zip(x_inds, x_vals)]) else: if 1 and is_interalg_raw_mode and engine == fd.XOR: c = engine([x[j] for j in edges_inds]) else: nEdges = fd.sum([x[j] for j in edges_inds]) c = nEdges >= 1 if self.allowRevisit else nEdges == 1 constraints.append(c) # MTZ for i, (I, J) in enumerate(EdgesCoords): ii, jj = node2index[I], node2index[J] if ii != 0 and jj != 0: if interalg_gdp: x_ind, x_val = edge_ind2x_ind_val[i] c = fd.ifThen((x[x_ind] == x_val)(tol=0.5), u[ii] - u[jj] <= -1.0) elif is_interalg_raw_mode: c = fd.ifThen(x[i], u[ii] - u[jj] <= -1.0) #u[jj] - u[ii] >= 1) else: c = u[ii] - u[jj] + 1 <= (n - 1) * (1 - x[i]) constraints.append(c) # handling objective(s) FF = [] for optCrName in usedValues: tmp = cr_values.get(optCrName, []) if len(tmp) == 0: self.err( 'seems like graph edgs have no attribute "%s" to perform optimization on it' % optCrName) elif len(tmp) != m: self.err( 'for optimization creterion "%s" at least one edge has no this attribute' % optCrName) if interalg_gdp: F = [] lc = 0 for X in x: domain = X._init_domain vals = [tmp[i] for i in range(lc, lc + domain.size)] lc += domain.size #F = sum(x) #F.append(fd.interpolator(domain, vals, k=1, s=0.00000001)(X)) F.append(fd.interpolator(domain, vals, k=1)(X)) #print(domain, vals) F = fd.sum(F) else: F = fd.sum(x * tmp) Funcs[optCrName] = F for obj in objective: FF.append( (Funcs[obj[0]] if type(obj[0]) in (str, np.str_) else obj[0](Funcs), obj[1], obj[2])) for c in Cons: tmp = c(Funcs) if type(tmp) in (list, tuple, set): constraints += list(tmp) else: constraints.append(tmp) startPoint = {x: [0] * (m if not interalg_gdp else n)} startPoint.update(dict([(U, i + 2) for i, U in enumerate(u[1:])])) p = P(FF if isMOP else FF[0][0], startPoint, constraints=constraints) #, fixedVars = fixedVars) for param in ('start', 'returnToStart'): KW.pop(param, None) r = p.solve(solver, **KW) if P != oo.MOP: r.ff = p.ff if interalg_gdp: x_ind_val2edge_ind = dict([ (elem[1], elem[0]) for elem in edge_ind2x_ind_val.items() ]) SolutionEdges = [ (EdgesCoords[i][0], EdgesCoords[i][1], EdgesDescriptors[i]) for i in [x_ind_val2edge_ind[(ind, x[ind](r))] for ind in range(n)] ] else: SolutionEdges = [(EdgesCoords[i][0], EdgesCoords[i][1], EdgesDescriptors[i]) for i in range(m) if r.xf[x[i]] == 1] if len(SolutionEdges) == 0: r.nodes = r.edges = r.Edges = [] return r S = dict([(elem[0], elem) for elem in SolutionEdges]) SE = [SolutionEdges[0]] for i in range(len(SolutionEdges) - 1): SE.append(S[SE[-1][1]]) SolutionEdgesCoords = [(elem[0], elem[1]) for elem in SE] nodes = [edge[1] for edge in SolutionEdgesCoords] if self.start is not None: shift_ind = nodes.index(self.start) nodes = nodes[shift_ind:] + nodes[:shift_ind] if self.returnToStart: nodes.append(nodes[0]) edges = SolutionEdgesCoords[1:] + [SolutionEdgesCoords[0]] Edges = SE[1:] + [SE[0]] if self.start is not None: edges, Edges = edges[shift_ind:] + edges[:shift_ind], Edges[ shift_ind:] + Edges[:shift_ind] if not self.returnToStart: edges, Edges = edges[:-1], Edges[:-1] r.nodes, r.edges, r.Edges = nodes, edges, Edges else: r.solution = 'for MOP see r.solutions instead of r.solution' tmp_c, tmp_v = r.solutions.coords, r.solutions.values # if interalg_gdp: # x_ind_val2edge_ind = dict([(elem[1], elem[0]) for elem in edge_ind2x_ind_val.items()]) # SolutionEdges = [(EdgesCoords[i][0], EdgesCoords[i][1], EdgesDescriptors[i]) for i in [x_ind_val2edge_ind[(ind, x[ind](r))] for ind in range(n)]] # else: # SolutionEdges = [(EdgesCoords[i][0], EdgesCoords[i][1], EdgesDescriptors[i]) for i in range(m) if r.xf[x[i]] == 1] if interalg_gdp: # default for MOP x_ind_val2edge_ind = dict([ (elem[1], elem[0]) for elem in edge_ind2x_ind_val.items() ]) r.solutions = MOPsolutions([[ (EdgesCoords[i][0], EdgesCoords[i][1], EdgesDescriptors[i]) for i in [ x_ind_val2edge_ind[(ind, x[ind](Point))] for ind in range(n) ] ] for Point in r.solutions]) else: # non-default r.solutions = MOPsolutions([[ (EdgesCoords[i][0], EdgesCoords[i][1], EdgesDescriptors[i]) for i in range(m) if Point[x[i]] == 1 ] for Point in r.solutions]) r.solutions.values = tmp_v return r
def solve(self, *args, **kw): import FuncDesigner as fd, openopt as oo if len(args) > 1: self.err(''' incorrect number of arguments for solve(), must be at least 1 (solver), other must be keyword arguments''') solver = args[0] if len(args) != 0 else kw.get('solver', self.solver) KW = self.__init_kwargs.copy() KW.update(kw) items = self.items n = len(items) objective = KW.get('objective', self.objective) if isinstance(objective, (list, tuple, set)): nCriteria = len(self.objective) if 3 * nCriteria != np.asarray(self.objective).size: objective = [(objective[3*i], objective[3*i+1], objective[3*i+2]) for i in range(int(round(np.asarray(self.objective).size / 3)))] if len(objective) == 1: KW['fTol'], KW['goal'] = objective[0][1:] else: objective = [(self.objective, KW.get('fTol', getattr(self, 'fTol')), KW.get('goal', getattr(self, 'goal')))] nCriteria = len(objective) isMOP = nCriteria > 1 #mainCr = objective[0][0] solverName = solver if type(solver) == str else solver.__name__ is_interalg = solverName == 'interalg' is_glp = False#solverName == 'sa' if is_glp: assert nCriteria == 1, 'you cannot solve multiobjective KSP by the solver' #is_interalg_raw_mode = is_interalg and KW.get('dataHandling', oo.oosolver(solver).dataHandling) in ('auto','raw') KW.pop('objective', None) P = oo.MOP if nCriteria > 1 else oo.GLP if is_interalg else oo.MILP if not is_glp else oo.GLP x = fd.oovars(n, domain=bool) requireCount = False for i, obj in enumerate(items): if 'n' in obj: x[i].domain = np.arange(obj['n']+1) if is_interalg else int x[i].ub = obj['n'] x[i].lb = 0 requireCount = True #cr_values = dict([(obj[0], []) for obj in objective]) constraints = [] Funcs = {} Cons = KW.pop('constraints', []) if type(Cons) not in (list, tuple): Cons = [Cons] usedValues = getUsedValues(Cons) usedValues.update(getUsedValues([obj[0] for obj in objective])) cr_values = {} for val in usedValues: if val == 'nItems': cr_values[val] = 1 else: cr_values[val] = [obj[val] for obj in items] # MainCr = mainCr if type(mainCr) in (str, np.str_) else list(usedValues)[0] # # isMainCrMin = objective[0][2] in ('min', 'minimum') # handling objective(s) FF = [] for optCrName in usedValues: F = fd.sum(x * cr_values[optCrName]) Funcs[optCrName] = F for obj in objective: FF.append((Funcs[obj[0]](obj[0]) if type(obj[0]) in (str, np.str_) else obj[0](Funcs), obj[1], obj[2])) for c in Cons: tmp = c(Funcs) if type(tmp) in (list, tuple, set): constraints += list(tmp) else: constraints.append(tmp) startPoint = {x:[0]*n} p = P(FF if isMOP else FF[0][0], startPoint, constraints = constraints)#, fixedVars = fixedVars) if not isMOP: p.goal=self.goal r = p.solve(solver, **KW) if P != oo.MOP: r.ff = p.ff if isMOP: #assert not requireCount, 'MOP with nItem > 1 is unimplemented yet' r.solution = 'for MOP see r.solutions instead of r.solution' #tmp_c, tmp_v = r.solutions.coords, r.solutions.values if len(r.solutions): S = [] for s in r.solutions: tmp = [((i, int(s[x[i]])) if requireCount else i) for i in range(n) if s[x[i]]>=1] if 'name' in items[0]: tmp = [(items[i]['name'], k) for i, k in tmp] if requireCount else [items[i]['name'] for i in tmp] S.append(dict(tmp) if requireCount else tmp) Vals = dict([(ff[0].name, r.solutions.values[:, i]) for i, ff in enumerate(FF)]) Dicts = [s.copy() for s in S] for v in usedValues: if v != 'nItems': for i, d in enumerate(Dicts): d[v] = Vals[v][i] r.solutions = MOPsolutions(Dicts) r.solutions.coords = S r.solutions.values = Vals else: tmp = [((i, int(r.xf[x[i]])) if requireCount else i) for i in range(n) if r.xf[x[i]]>=1] if 'name' in items[0]: tmp = [(items[i]['name'], k) for i, k in tmp] if requireCount else [items[i]['name'] for i in tmp] r.xf = dict(tmp) if requireCount else tmp return r
def solve(self, *args, **kw): import FuncDesigner as fd, openopt as oo if len(args) > 1: self.err(''' incorrect number of arguments for solve(), must be at least 1 (solver), other must be keyword arguments''') solver = args[0] if len(args) != 0 else kw.get('solver', self.solver) KW = self.__init_kwargs.copy() KW.update(kw) bins, items = self.bins, self.items #n = len(items) # objective = KW.get('objective', self.objective) # if isinstance(objective, (list, tuple, set)): # nCriteria = len(self.objective) # if 3 * nCriteria != np.asarray(self.objective).size: # objective = [(objective[3*i], objective[3*i+1], objective[3*i+2]) for i in range(int(round(np.asarray(self.objective).size / 3)))] # if len(objective) == 1: # KW['fTol'], KW['goal'] = objective[0][1:] # else: # objective = [(self.objective, KW.get('fTol', getattr(self, 'fTol')), KW.get('goal', getattr(self, 'goal')))] nCriteria = 1#len(objective) isMOP = nCriteria > 1 #mainCr = objective[0][0] solverName = solver if type(solver) == str else solver.__name__ is_interalg = solverName == 'interalg' is_glp = False#solverName == 'sa' if is_glp: assert nCriteria == 1, 'you cannot solve multiobjective KSP by the solver' #is_interalg_raw_mode = is_interalg and KW.get('dataHandling', oo.oosolver(solver).dataHandling) in ('auto','raw') KW.pop('objective', None) P = oo.MOP if nCriteria > 1 else oo.GLP if is_interalg else oo.MILP if not is_glp else oo.GLP item_numbers = [item.get('n', 1) for item in items] nItemTypes = len(items) nItems = sum(item_numbers) Cons = KW.pop('constraints', []) if type(Cons) not in (list, tuple): Cons = [Cons] Funcs = {} usedValues = getUsedValues(Cons) bins_keys = set(bins.keys()) for Set in (bins_keys, usedValues): if 'n' in Set: Set.remove('n') UsedValues = usedValues.copy() UsedValues.update(bins_keys) cr_values = {} for val in UsedValues: if val == 'nItems': cr_values[val] = 1 else: cr_values[val] = [obj[val] for obj in items] nBins = bins.get('n', -1) if nBins == -1: if len(UsedValues) == 1 and type(bins) == dict: Tmp_items = sum(list(cr_values.values()[0])) Tmp_bins = bins[list(UsedValues)[0]] approx_n_bins = int(np.ceil((2.0 * Tmp_items) / Tmp_bins)) else: approx_n_bins = nItems nBins = approx_n_bins X = fd.oovars(nBins * nItemTypes, domain=int, lb=0).view(np.ndarray).reshape(nItemTypes, nBins) requireCount = False for item in items: if 'n' in item: # x[i].domain = np.arange(obj['n']+1) if is_interalg else int # x[i].ub = obj['n'] # x[i].lb = 0 requireCount = True break y = fd.oovars(nBins, domain = bool)('y') aux_objective = fd.sum(y) #cr_values = dict([(obj[0], []) for obj in objective]) # MainCr = mainCr if type(mainCr) in (str, np.str_) else list(usedValues)[0] # # isMainCrMin = objective[0][2] in ('min', 'minimum') # handling objective(s) # FF = [] for optCrName in UsedValues: F = [fd.sum(X[:, j].view(fd.ooarray) * cr_values[optCrName]) for j in range(nBins)] Funcs[optCrName] = F FUNCS = [dict((optCrName, Funcs[optCrName][j]) for optCrName in UsedValues) for j in range(nBins)] # for obj in objective: # FF.append((Funcs[obj[0]](obj[0]) if type(obj[0]) in (str, np.str_) else obj[0](Funcs), obj[1], obj[2])) constraints = [] # 1. Constraints from p.constraints for c in Cons: tmp = [c(F) for F in FUNCS] constraints += tmp # 2. Constraints from bins parameters for k, v in bins.items(): if k != 'n': constraints += [fd.sum(X[:, j].view(fd.ooarray) * cr_values[k]) <= v*y[j] for j in range(nBins)] # 3. Number of items of type i from all bins equals to item_numbers[i] constraints += [fd.sum(X[i].view(fd.ooarray)) == item_numbers[i] for i in range(nItemTypes)] startPoint = dict((X[i, j], 0) for i in range(nItemTypes) for j in range(nBins)) startPoint[y] = [0]*nBins p = P(aux_objective, startPoint, constraints = constraints) # p = P(FF if isMOP else FF[0][0], startPoint, constraints = constraints)#, fixedVars = fixedVars) if not isMOP: p.goal=self.goal r = p.solve(solver, **KW) if P != oo.MOP: r.ff = p.ff if isMOP: assert 0, 'unimplemented' # #assert not requireCount, 'MOP with nItem > 1 is unimplemented yet' # r.solution = 'for MOP see r.solutions instead of r.solution' # #tmp_c, tmp_v = r.solutions.coords, r.solutions.values # if len(r.solutions): # S = [] # for s in r.solutions: # tmp = [((i, int(s[x[i]])) if requireCount else i) for i in range(n) if s[x[i]]>=1] # if 'name' in items[0]: # tmp = [(items[i]['name'], k) for i, k in tmp] if requireCount else [items[i]['name'] for i in tmp] # S.append(dict(tmp) if requireCount else tmp) # Vals = dict([(ff[0].name, r.solutions.values[:, i]) for i, ff in enumerate(FF)]) # # Dicts = [s.copy() for s in S] # for v in usedValues: # if v != 'nItems': # for i, d in enumerate(Dicts): # d[v] = Vals[v][i] # r.solutions = MOPsolutions(Dicts) # r.solutions.coords = S # r.solutions.values = Vals else: if requireCount: xf = [dict((item.get('name',i), int(r.xf[X[i, j]])) for i, item in enumerate(items) if r.xf[X[i, j]]>0) for j in range(nBins) if r.xf[y[j]]] else: xf = [tuple(item.get('name',i) for i, item in enumerate(items) if r.xf[X[i, j]]==1) for j in range(nBins) if r.xf[y[j]]] r.values = dict((optCrName, tuple(sum(item[optCrName]*r.xf[X[i, j]] for i, item in enumerate(items)) for j in range(nBins) if r.xf[y[j]])) for optCrName in UsedValues) r.xf = xf # tmp = [((i, int(r.xf[x[i]])) if requireCount else i) for i in range(n) if r.xf[x[i]]>=1] # if 'name' in items[0]: # tmp = [(items[i]['name'], k) for i, k in tmp] if requireCount else [items[i]['name'] for i in tmp] # r.xf = dict(tmp) if requireCount else tmp return r