示例#1
0
def subproblem(xhat):
    '''子问题求解

    '''
    # 初始化问题
    r = xp.problem()

    # 定义变量
    y = [xp.var() for i in range(n2)]
    z = [xp.var(lb=-xp.infinity) for i in range(n1)]
    epsilon = xp.var(lb=-xp.infinity)
    r.addVariable(y, z, epsilon)

    # 定义约束
    dummy1 = [z[i] == xhat[i] for i in range(n1)]
    dummy2 = epsilon == 1
    constr=[xp.Sum(A1[ii][jj]*z[jj] for jj in range(n1)) +                     \
            xp.Sum(A2[ii][jj]*y[jj] for jj in range(n2))                       \
            - epsilon*b[ii]<=0 for ii in range(m)]
    r.addConstraint(constr, dummy1, dummy2)

    # 定义目标函数
    r.setObjective(xp.Sum(c2[jj] * y[jj] for jj in range(n2)),
                   sense=xp.minimize)
    r.setControl({"presolve": 0})

    # 解该问题
    r.setControl('outputlog', 0)
    r.solve()

    # 寻找切片
    xind1 = [r.getIndex(dummy1[ii]) for ii in range(n1)]

    # 根据自问题的解的情况判断下一步
    if r.getProbStatus() == xp.lp_optimal:
        # 获得了最优解
        print("Optimal Subproblem")
        dualmult = r.getDual()
        lamb = [dualmult[ii] for ii in xind1]
        beta = r.getObjVal()
        return (lamb, beta, 'Optimal')
    elif r.getProbStatus() == xp.lp_infeas:
        # 子问题不可行
        print("Infeasible Subproblem")
        if not r.hasdualray():
            print("Could not retrieve a dual ray, return no good cut instead:")
            xhatones = set(ii for ii in range(n1) if xhat[ii] >= 0.5)
            lamb = [2 * xhat[ii] - 1 for ii in range(n1)]
            beta = -sum(xhat) + 1
        else:
            # 求解对偶
            dray = []
            r.getdualray(dray)
            print("Dual Ray:", dray)
            lamb = [dray[ii] for ii in xind1]
            beta = dray[r.getIndex(dummy2)]
        return (lamb, beta, 'Infeasible')
    else:
        print("ERROR: Subproblem not optimal or infeasible. Terminating.")
        sys.exit()
示例#2
0
    def set_variables(self):
        self.x = np.array([[xp.var(vartype=xp.binary) for j in self.slots]
                           for i in self.slots])

        self.c = np.array([xp.var(vartype=xp.binary) for i in self.matches])
        # print(self.x.shape)
        print(self.c.shape)
        self.m.addVariable(self.x, self.c)
def standard_linearization(quad, lhs_constraints=True, **kwargs):
	"""
	Apply the standard linearization to a QP and return resulting model

	param lhs_constraints: can choose to include optional lower bound constraints (or upper bound if mixed_sign)
	"""
	n = quad.n
	c = quad.c
	C = quad.C
	a = quad.a
	b = quad.b

	# create model and add variables
	m = xp.problem(name='standard_linearization')
	x = np.array([xp.var(vartype=xp.binary) for i in range(n)])
	w = np.array([[xp.var(vartype=xp.continuous) for i in range(n)] for i in range(n)])
	m.addVariable(x,w)

	if type(quad) is Knapsack:  # HSP and UQP don't have cap constraint
		# add capacity constraint(s)
		for k in range(quad.m):
			m.addConstraint(xp.Sum(x[i]*a[k][i] for i in range(n)) <= b[k])

	#k_item constraint if necessary (if KQKP or HSP)
	if quad.num_items > 0:
		m.addConstraint(xp.Sum(x[i] for i in range(n)) == quad.num_items)

	# add auxiliary constraints
	for i in range(n):
		for j in range(i+1, n):
			if lhs_constraints:
				if C[i,j]+C[j,i] > 0:
					m.addConstraint(w[i,j] <= x[i])
					m.addConstraint(w[i,j] <= x[j])
				else:
					m.addConstraint(x[i]+x[j]-1 <= w[i,j])
					m.addConstraint(w[i,j] >= 0)
			else:
				m.addConstraint(w[i,j] <= x[i])
				m.addConstraint(w[i,j] <= x[j])
				m.addConstraint(x[i]+x[j]-1 <= w[i,j])
				m.addConstraint(w[i,j] >= 0)

	#compute quadratic values contirbution to obj
	quadratic_values = 0
	for i in range(n):
		for j in range(i+1, n):
			quadratic_values = quadratic_values + (w[i, j]*(C[i, j]+C[j, i]))
	# set objective function
	linear_values = sum(x[i]*c[i] for i in range(n))
	m.setObjective(linear_values + quadratic_values, sense=xp.maximize)

	# return model + setup time
	return [m, 0]
示例#4
0
    def __init__(self, accs, intervals):
        self.accs = accs
        self.accsNum = len(accs)
        self.intervals = intervals
        self.intNum = len(intervals)
        self.matches = np.array(list(combinations(self.accs, 2)))

        self.p = xp.problem()
        self.x = np.array([[[xp.var(vartype=xp.binary) for _ in intervals] for _ in accs] for _ in self.accs])
        self.m = np.array([xp.var(vartype=xp.binary) for _ in self.matches])

        self.p.addVariable(self.x, self.m)
def qsap_ss(qsap, **kwargs):
	"""
	Sherali-Smith Linear Formulation for the quadratic semi-assignment problem
	"""
	n = qsap.n
	m = qsap.m
	e = qsap.e
	c = qsap.c

	#create model and add variables
	mdl = xp.problem(name='qsap_ss')
	x = np.array([[xp.var(vartype=xp.binary) for i in range(n)]for j in range(m)])
	s = np.array([[xp.var(vartype=xp.continuous) for i in range(n)]for j in range(m)])
	y = np.array([[xp.var(vartype=xp.continuous) for i in range(n)]for j in range(m)])
	mdl.addVariable(x,s,y)
	mdl.addConstraint((sum(x[i,k] for k in range(n)) == 1) for i in range(m))

	start = timer()
	U = np.zeros((m,n))
	L = np.zeros((m,n))
	bound_mdl = xp.problem(name='upper_bound_model')
	bound_mdl.setlogfile("xpress.log")
	bound_x = np.array([xp.var(vartype=xp.continuous, lb=0, ub=1) for i in range(m) for j in range(n)]).reshape(m,n)
	bound_mdl.addVariable(bound_x)
	bound_mdl.addConstraint((sum(bound_x[i,k] for k in range(n)) == 1) for i in range(m))
	for i in range(m-1):
		for k in range(n):
			bound_mdl.setObjective(sum(sum(c[i,k,j,l]*bound_x[j,l] for l in range(n)) for j in range(i+1,m)), sense=xp.maximize)
			bound_mdl.solve()
			U[i,k] = bound_mdl.getObjVal()

			bound_mdl.setObjective(sum(sum(c[i,k,j,l]*bound_x[j,l] for l in range(n)) for j in range(i+1,m)), sense=xp.minimize)
			bound_mdl.solve()
			L[i,k] = bound_mdl.getObjVal()
	end = timer()
	setup_time = end-start

	#add auxiliary constraints
	for i in range(m-1):
		for k in range(n):
			mdl.addConstraint(sum(sum(c[i,k,j,l]*x[j,l] for j in range(i+1,m)) for l in range(n))-s[i,k]-L[i,k]==y[i,k])
			mdl.addConstraint(y[i,k] <= (U[i,k]-L[i,k])*(1-x[i,k]))
			mdl.addConstraint(s[i,k] <= (U[i,k]-L[i,k])*x[i,k])
			mdl.addConstraint(y[i,k] >= 0)
			mdl.addConstraint(s[i,k] >= 0)

	#set objective function
	linear_values = sum(sum(e[i,k]*x[i,k] for i in range(m)) for k in range(n))
	mdl.setObjective(linear_values + sum(sum(s[i,k]+x[i,k]*(L[i,k]) for i in range(m-1)) for k in range(n)), sense=xp.maximize)

	#return model + setup time
	return [mdl, setup_time]
def extended_linear_formulation(quad, **kwargs):
	"""
	Apply the extended linear formulation to a QP and return resulting model
	"""
	start = timer()
	n = quad.n
	c = quad.c
	C = quad.C
	a = quad.a
	b = quad.b

	#create model and add variables
	m = xp.problem(name='extended_linear_formulation')
	x = np.array([xp.var(vartype=xp.binary) for i in range(n)])
	z = np.array([[[xp.var(vartype=xp.continuous, lb=-xp.infinity) for i in range(n)] for j in range(n)] for k in range(n)])
	m.addVariable(x,z)

	if type(quad) is Knapsack: #HSP and UQP don't have cap constraint
		#add capacity constraint(s)
		for k in range(quad.m):
			m.addConstraint(xp.Sum(x[i]*a[k][i] for i in range(n)) <= b[k])

	#k_item constraint if necessary (if KQKP or HSP)
	if quad.num_items > 0:
		m.addConstraint(xp.Sum(x[i] for i in range(n)) == quad.num_items)

	#add auxiliary constraints
	for i in range(n):
		for j in range(i+1,n):
			m.addConstraint(z[i,i,j]+z[j,i,j] <= 1)
			if C[i,j] < 0:
				m.addConstraint(x[i] + z[i,i,j] <= 1)
				m.addConstraint(x[j] + z[j,i,j] <= 1)
			elif C[i,j] > 0:
				m.addConstraint(x[i] + z[i,i,j] + z[j,i,j] >= 1)
				m.addConstraint(x[j] + z[i,i,j] + z[j,i,j] >= 1)

	#compute quadratic values contirbution to obj
	constant = 0
	quadratic_values = 0
	for i in range(n):
		for j in range(i+1,n):
			constant = constant + C[i,j]
			quadratic_values = quadratic_values + (C[i,j]*(z[i,i,j]+z[j,i,j]))
	#set objective function
	linear_values = xp.Sum(x[i]*c[i] for i in range(n))
	m.setObjective(linear_values + constant - quadratic_values, sense=xp.maximize)

	end = timer()
	setup_time = end-start
	#return model + setup time
	return [m, setup_time]
def qsap_standard(qsap, **kwargs):
	"""
	standard linearization for the quadratic semi-assignment problem
	"""
	n = qsap.n
	m = qsap.m
	e = qsap.e
	c = qsap.c

	#create model and add variables
	mdl = xp.problem(name='qsap_standard_linearization')
	x = np.array([[xp.var(vartype=xp.binary) for i in range(n)]for j in range(m)])
	w = np.array([[[[xp.var(vartype=xp.continuous) for i in range(n)]for j in range(m)]
						for k in range(n)]for l in range(m)])
	mdl.addVariable(x,w)
	mdl.addConstraint((sum(x[i,k] for k in range(n)) == 1) for i in range(m))

	#add auxiliary constraints
	for i in range(m-1):
		for k in range(n):
			for j in range(i+1,m):
				for l in range(n):
					if lhs_constraints:
						if c[i,k,j,l]+c[j,l,i,k] > 0:
							mdl.add_constraint(w[i,k,j,l] <= x[i,k])
							mdl.add_constraint(w[i,k,j,l] <= x[j,l])
						else:
							mdl.add_constraint(x[i,k] + x[j,l] - 1 <= w[i,k,j,l])
							mdl.add_constraint(w[i,k,j,l] >= 0)
					else:
						mdl.add_constraint(w[i,k,j,l] <= x[i,k])
						mdl.add_constraint(w[i,k,j,l] <= x[j,l])
						mdl.add_constraint(x[i,k] + x[j,l] - 1 <= w[i,k,j,l])
						mdl.add_constraint(w[i,k,j,l] >= 0)

	#compute quadratic values contirbution to obj
	quadratic_values = 0
	for i in range(m-1):
		for j in range(i+1,m):
			for k in range(n):
				for l in range(n):
					quadratic_values = quadratic_values + (c[i,k,j,l]*(w[i,k,j,l]))

	linear_values = sum(x[i,k]*e[i,k] for k in range(n) for i in range(m))
	mdl.setObjective(linear_values + quadratic_values, sense=xp.maximize)

	#return model. no setup time for std
	return [mdl, 0]
def no_linearization(quad, **kwargs):
	"""
	Solve a problem using the solver's default approach to quadratics (for cplex, this is the std linearization)
	"""
	start = timer()
	n = quad.n
	c = quad.c
	m = xp.problem(name='no_linearization')
	x = np.array([xp.var(vartype=xp.binary) for i in range(n)])
	m.addVariable(x)

	if type(quad) is Knapsack: #HSP and UQP don't have cap constraint
		#add capacity constraint(s)
		for k in range(quad.m):
			m.addConstraint(xp.Sum(x[i]*quad.a[k][i] for i in range(n)) <= quad.b[k])

	#k_item constraint if necessary (if KQKP or HSP)
	if quad.num_items > 0:
		m.addConstraint(xp.Sum(x[i] for i in range(n)) == quad.num_items)

	#compute quadratic values contirbution to obj
	quadratic_values = 0
	for i in range(n):
		for j in range(i+1,n):
			quadratic_values = quadratic_values + (x[i]*x[j]*quad.C[i,j])
	#set objective function
	linear_values = xp.Sum(x[i]*c[i] for i in range(n))
	m.setObjective(linear_values + quadratic_values, sense=xp.maximize)

	end = timer()
	setup_time = end-start
	return [m, setup_time]
示例#9
0
 def define_placement_variables(self, placements):
     self.x = {
         p: xp.var(vartype=xp.binary,
                   name=f'x_{p.doctor.name}, {p.shift}, {p.hospital}')
         for p in placements
     }
     self.model.addVariable(self.x)
示例#10
0
 def define_auxiliary_variables_for_doctors(self, doctors):
     self.t = {
         d: xp.var(vartype=xp.continuous,
                   lb=0,
                   name=f'Auxiliary for doctor {d.name}')
         for d in doctors
     }
     self.model.addVariable(self.t)
示例#11
0
    def __init__(self, areas_list, periods):
        self._areasList = areas_list
        self._periods = periods
        self._matches = np.array(list(combinations(self._areasList, 2)))

        self.p = xp.problem()

        self.e = np.array([[xp.var(vartype=xp.integer) for _ in self._periods]
                           for _ in areas_list])
        self.y = np.array(
            [[[xp.var(vartype=xp.integer) for _ in self._periods]
              for _ in areas_list] for _ in areas_list])
        self.m = np.array([xp.var(vartype=xp.binary) for _ in self._matches])
        self.p.addVariable(self.e, self.y, self.m)

        self.flow = None
        self.solutionMatches = None
示例#12
0
 def define_nightshift_change(self, nightshifts):
     self.y = {
         n: xp.var(vartype=xp.integer,
                   lb=-1,
                   ub=1,
                   name=f'y_{n.doctor.name},{n.day}')
         for n in nightshifts
     }
     self.model.addVariable(self.y)
def qsap_elf(qsap, **kwargs):
	"""
	extended linear formulation for the quadratic semi-assignment problem
	"""
	n = qsap.n
	m = qsap.m
	e = qsap.e
	c = qsap.c
	mdl = xp.problem(name='qsap_elf')
	x = np.array([[xp.var(vartype=xp.binary) for i in range(n)]for j in range(m)])
	z = np.array([[[[[[xp.var(vartype=xp.continuous, lb=-xp.infinity) for i in range(n)]
		for j in range(m)] for k in range(n)] for l in range(m)] for r in range(n)] for s in range(m)])
	mdl.addVariable(x, z)

	cons = [xp.constraint(sum(x[i,k] for k in range(n)) == 1) for i in range(m)]
	mdl.addConstraint(cons)

	#add auxiliary constraints
	for i in range(m-1):
		for j in range(i+1,m):
			for k in range(n):
				for l in range(n):
					mdl.addConstraint(z[i,k,i,k,j,l] + z[j,l,i,k,j,l] <= 1)
					mdl.addConstraint(x[i,k] + z[i,k,i,k,j,l] <= 1)
					mdl.addConstraint(x[j,l] + z[j,l,i,k,j,l] <= 1)
					mdl.addConstraint(x[i,k] + z[i,k,i,k,j,l] + z[j,l,i,k,j,l] >= 1)
					mdl.addConstraint(x[j,l] + z[i,k,i,k,j,l] + z[j,l,i,k,j,l] >= 1)

	#compute quadratic values contirbution to obj
	constant = 0
	quadratic_values = 0
	for i in range(m-1):
		for j in range(i+1,m):
			for k in range(n):
				for l in range(n):
					constant = constant + c[i,k,j,l]
					quadratic_values = quadratic_values + (c[i,k,j,l]*(z[i,k,i,k,j,l]+z[j,l,i,k,j,l]))

	linear_values = sum(x[i,k]*e[i,k] for k in range(n) for i in range(m))
	mdl.setObjective(linear_values + constant - quadratic_values, sense=xp.maximize)

	#return model + setup time
	return [mdl, 0]
示例#14
0
 def add_var(self, lb=0, ub=float("inf"), type="continuous", name=""):
     """
     Add a variable to the model.
     :param lb: The lower bound of the variable.
     :param ub: The upper bound of the variable.
     :param type: either 'binary' or 'continuous'
     :param name: The name of the variable. (Ignored if falsey).
     :return: The variable object associated with the model_type engine API
     """
     verify(type in ["continuous", "binary"],
            "type needs to be 'continuous' or 'binary'")
     verify(
         utils.numericish(lb) and utils.numericish(ub),
         "lb, ub need to be numbers")
     verify(ub >= lb, "lb cannot be bigger than ub")
     verify(lb < float("inf"), "lb cannot be positive infinity")
     verify(ub > -float("inf"), "ub cannot be negative infinity")
     if type == "binary":
         ub = 1 if ub == float("inf") else ub
         verify(lb in [0, 1] and ub in [0, 1],
                "lb,ub need to be 0 or 1 when type = 'binary'")
     name_dict = {"name": name} if name else {}
     if self.model_type == "gurobi":
         vtype = {
             "continuous": gurobi.GRB.CONTINUOUS,
             "binary": gurobi.GRB.BINARY
         }[type]
         rtn = self.core_model.addVar(lb=lb,
                                      ub=ub,
                                      vtype=vtype,
                                      **name_dict)
         return rtn
     if self.model_type == "cplex":
         if type == "continuous":
             return self.core_model.continuous_var(lb=lb,
                                                   ub=ub,
                                                   **name_dict)
         rtn = self.core_model.binary_var(**name_dict)
         rhs = ub if ub == 0 else (lb if lb == 1 else None)
         if utils.numericish(rhs):
             self.core_model.add_constraint(rtn == rhs)
         return rtn
     if self.model_type == "xpress":
         vtype = {
             "continuous": xpress.continuous,
             "binary": xpress.binary
         }[type]
         rtn = xpress.var(lb=lb, ub=ub, vartype=vtype, **name_dict)
         self.core_model.addVariable(rtn)
         return rtn
示例#15
0
def bb(A, b):

    pb = xp.problem()
    x_lp = np.array([xp.var(vartype=xp.continuous) for _ in range(A.shape[1])])
    pb.addVariable(x_lp)
    pb.addConstraint(xp.Dot(A, x_lp) <= b)
    pb.setObjective(xp.Dot(c, x_lp), sense=xp.maximize)

    lb_node = Node(xp.problem(), -1)

    root_node = Node(pb)

    is_integer, is_infeasible = root_node.solve()

    show_tree(root_node)

    if is_integer:
        return root_node.pb.getObjVal(), root_node.pb.getSolution()
    elif is_infeasible:
        return False, False

    l_node, r_node = root_node.make_sub_problems()

    active_nodes = [l_node, r_node]

    while True:
        show_tree(root_node)
        not_pruned_nodes = []
        for node in active_nodes:
            is_integer, is_infeasible = node.solve()
            if is_integer:
                if node.objVal > lb_node.objVal:
                    lb_node = node
            elif not is_infeasible and node.objVal > lb_node.objVal:
                not_pruned_nodes.append(node)
            else:
                node.is_pruned = True
            # # inp = input()

        if is_optimal(lb_node, not_pruned_nodes):
            lb_node.is_optimal = True
            show_tree(root_node)
            return lb_node.pb.getObjVal(), lb_node.pb.getSolution()

        active_nodes = []
        for node in not_pruned_nodes:
            l_node, r_node = node.make_sub_problems()
            active_nodes.append(l_node)
            active_nodes.append(r_node)
示例#16
0
    def _add_var(self, var):
        varname = self._symbol_map.getSymbol(var, self._labeler)
        vartype = self._xpress_vartype_from_var(var)
        lb, ub = self._xpress_lb_ub_from_var(var)

        xpress_var = xpress.var(name=varname, lb=lb, ub=ub, vartype=vartype)
        self._solver_model.addVariable(xpress_var)

        ## bounds on binary variables don't seem to be set correctly
        ## by the method above
        if vartype == xpress.binary:
            if lb == ub:
                self._solver_model.chgbounds([xpress_var], ['B'], [lb])
            else:
                self._solver_model.chgbounds([xpress_var, xpress_var], ['L', 'U'], [lb,ub])

        self._pyomo_var_to_solver_var_map[var] = xpress_var
        self._solver_var_to_pyomo_var_map[xpress_var] = var
        self._referenced_variables[var] = 0
示例#17
0
def UDPPlocalOpt(airline: air.UDPPairline,
                 slots: List[sl.Slot],
                 xp_problem=None):

    if xp_problem is None:
        m = xp.problem()
    else:
        m = xp_problem

    x = np.array([[xp.var(vartype=xp.binary) for j in slots]
                  for i in airline.flights])

    m.addVariable(x)

    flight: fl.UDPPflight

    for k in range(airline.numFlights):
        #one x max for slot
        m.addConstraint(
            xp.Sum(x[flight.localNum, k] for flight in airline.flights) == 1)

    for flight in airline.flights:
        # flight assignment
        m.addConstraint(
            xp.Sum(x[flight.localNum, k]
                   for k in range(eta_limit_slot(flight, airline.AUslots),
                                  airline.numFlights)) == 1)

    m.setObjective(
        xp.Sum(
            x[flight.localNum][k] * flight.costFun(flight, airline.AUslots[k])
            for flight in airline.flights for k in range(airline.numFlights)))

    m.solve()
    # print("airline ",airline)
    for flight in airline.flights:

        for k in range(airline.numFlights):
            if m.getSolution(x[flight.localNum, k]) > 0.5:
                flight.newSlot = airline.flights[k].slot
                flight.priorityNumber = k
                flight.priorityValue = "N"
示例#18
0
    def solve(self, X):
        """
            Implementation of the dual of SVDD problem
            
            Params:
                - X, the dataset without labels
            Returns:
                None
        """

        m = X.shape[0]

        # Define Variables of the problem
        alphas = [xp.var(lb=0, ub=self.C) for i in range(m)]
        self.p.addVariable(alphas)

        # Define Constraints
        # constr1 = [alpha <= C for alpha in alphas]
        # p.addConstraint(constr1)
        # already defined in the definition of the variable as a upper bound

        # Define objective function
        obj1 = xp.Sum(alphas[i] * np.sum(
            self.kernel(X[i].reshape(1, -1), X[i].reshape(1, -1))[0][0])
                      for i in range(m))
        obj2 = xp.Sum(alphas[i] * alphas[j] * np.sum(
            self.kernel(X[i].reshape(1, -1), X[j].reshape(1, -1))[0][0])
                      for i in range(m) for j in range(m))

        obj = obj1 - obj2
        self.p.setObjective(obj, sense=xp.maximize)  #set maximization problem
        # solve the problem
        self.p.solve()

        self.opt = np.array(
            self.p.getSolution(alphas))  #save the values of alphas
        self.c0 = np.sum(self.opt.reshape(-1, 1) * X, axis=0)

        indices_support_vectors = self.select_support_vectors(
        )  #choose a point as support vector
        self.support_vectors = X[indices_support_vectors]
示例#19
0
# Problem: given n, find the n-sided polygon of largest area inscribed
# in the unit circle.
#
# While it is natural to prove that all vertices of a global optimum
# reside on the unit circle, here we formulate the problem so that
# every vertex i is at distance rho[i] from the center and at angle
# theta[i]. We would certainly expect that the local optimum found has
# all rho's are equal to 1.

N = 9

Vertices = range(N)

# Declare variables
rho = [xp.var(name='rho_{}'.format(i), lb=1e-5, ub=1.0) for i in Vertices]
theta = [
    xp.var(name='theta_{}'.format(i), lb=-math.pi, ub=math.pi)
    for i in Vertices
]

p = xp.problem()

p.addVariable(rho, theta)

# The objective function is the total area of the polygon. Considering
# the segment S[i] joining the center to the i-th vertex and A(i,j)
# the area of the triangle defined by the two segments S[i] and S[j],
# the objective function is
#
# A[0,1] + A[1,2] + ... + A[N-1,0]
示例#20
0
    def solve(self):

        ### Params ###
        self.n_plyrs_per_game = [
            self.game_list[i][1] for i in range(len(self.game_list))
        ]
        req_plyrs_per_round = sum([ct * 2 for ct in self.n_plyrs_per_game])

        if self.trim_gms & (req_plyrs_per_round > self.n_plyrs):
            if self.debug:
                st.text("Removing games to fit the number of passed players")
            while req_plyrs_per_round > self.n_plyrs:
                self.game_list = self.game_list[:-1]
                self.n_plyrs_per_game = [
                    self.game_list[i][1] for i in range(len(self.game_list))
                ]
                req_plyrs_per_round = sum(
                    [ct * 2 for ct in self.n_plyrs_per_game])
            print(req_plyrs_per_round, self.n_plyrs)
            # max number of times a player can play a given game
            self.max_gm_plays = max(
                2,
                math.ceil(req_plyrs_per_round * self.n_rounds / self.n_plyrs))
        st.text(f'Final game list: {self.game_list}')
        if not self.max_gm_plays_soft:
            st.text(
                f'Max times a player is allowed to play same game: {self.max_gm_plays}'
            )
        self.n_games = len(self.game_list)

        ## Instantiate problem ##
        self.model = xp.problem()

        #################
        ### Variables ###
        #################
        # Player-game-round-team
        plyrs = {}
        for p in range(self.n_plyrs):
            plyrs[p] = {}
            for g in range(self.n_games):
                plyrs[p][g] = {}
                for r in range(self.n_rounds):
                    plyr_var_list = [
                        xp.var(name=f"p{p}_g{g}_r{r}_t{t}", vartype=xp.binary)
                        for t in range(self.n_tms)
                    ]
                    plyrs[p][g][r] = plyr_var_list
                    self.model.addVariable(plyr_var_list)

        # Team assignments
        tms = {}
        for t in range(self.n_tms):
            tm_var_list = [
                xp.var(name=f"p{p}_tm{t}", vartype=xp.binary)
                for p in range(self.n_plyrs)
            ]
            tms[t] = tm_var_list
            self.model.addVariable(tm_var_list)

        # Variable set greater_than/equal_to game_played count for all players for all games - this quantity is minimized
        max_gm_plays_global = xp.var(name='max_gm_plays_global', lb=0)
        self.model.addVariable(max_gm_plays_global)

        ###################
        ### Constraints ###
        ###################
        # Correct number of plyrs per game per team
        ## Why need both less/greater than and not equal to?
        for g in range(self.n_games):
            for r in range(self.n_rounds):
                for t in range(self.n_tms):
                    suff_plyrs_tm_1 = xp.Sum(plyrs[p][g][r][t] for p in range(
                        self.n_plyrs)) >= self.n_plyrs_per_game[g]
                    suff_plyrs_tm_2 = xp.Sum(plyrs[p][g][r][t] for p in range(
                        self.n_plyrs)) <= self.n_plyrs_per_game[g]
                    self.model.addConstraint(
                        xp.constraint(suff_plyrs_tm_1,
                                      name=f'gteq_plyrs_tm{t}_rnd{r}_gm{g}'))
                    self.model.addConstraint(
                        xp.constraint(suff_plyrs_tm_2,
                                      name=f'lteq_plyrs_tm{t}_rnd{r}_gm{g}'))

        # One game per time per player
        for p in range(self.n_plyrs):
            for r in range(self.n_rounds):
                for t in range(self.n_tms):
                    one_game_per_round_per_plyr = xp.Sum(
                        plyrs[p][g][r][t] for g in range(self.n_games)) <= 1
                    self.model.addConstraint(
                        xp.constraint(
                            one_game_per_round_per_plyr,
                            name=f"one_gm_in_rnd{r}_for_plyr{p}_tm{t}"))

        # Team assignment constraints
        for p in range(self.n_plyrs):
            # One team per player
            tm_lb = xp.Sum(tms[t][p] for t in range(self.n_tms)) <= 1
            tm_ub = xp.Sum(tms[t][p] for t in range(self.n_tms)) >= 1
            self.model.addConstraint(
                xp.constraint(tm_lb, name=f'plyr{p}_lteq_1_tm'))
            self.model.addConstraint(
                xp.constraint(tm_ub, name=f'plyr{p}_gteq_1_tm'))
            for t in range(self.n_tms):
                # Forcing tm variables to be flipped when player selected
                tm_enforce = xp.Sum(
                    plyrs[p][g][r][t] for g in range(self.n_games)
                    for r in range(self.n_rounds)) <= tms[t][p] * self.n_rounds
                self.model.addConstraint(
                    xp.constraint(tm_enforce, name=f'plyr{p}_tm{t}_enforce'))

        # Teams evenly split
        tms_even_1 = xp.Sum(tms[0][p] for p in range(self.n_plyrs)) - xp.Sum(
            tms[1][p] for p in range(self.n_plyrs)) <= 1
        tms_even_2 = xp.Sum(tms[1][p] for p in range(self.n_plyrs)) - xp.Sum(
            tms[0][p] for p in range(self.n_plyrs)) <= 1
        self.model.addConstraint(tms_even_1)
        self.model.addConstraint(tms_even_2)

        # Each player plays each game at most 'self.max_gm_plays'
        for p in range(self.n_plyrs):
            for g in range(self.n_games):
                for t in range(self.n_tms):
                    max_rds_per_game_per_plyr = xp.Sum(
                        plyrs[p][g][r][t] for r in range(self.n_rounds))
                    if not self.max_gm_plays_soft:
                        self.model.addConstraint(
                            xp.constraint(
                                max_rds_per_game_per_plyr <= self.max_gm_plays,
                                name=
                                f"plyr{p}_plays_gm{g}_max_{self.max_gm_plays}_times_tm{t}"
                            ))
                    self.model.addConstraint(
                        xp.constraint(
                            max_gm_plays_global >= max_rds_per_game_per_plyr,
                            name=f'max_gm_plays_global_gteq_p{p}_g{g}_t{t}'))

        # Each player plays at most once more than every other player
        for p1 in range(self.n_plyrs):
            n_plays = xp.Sum(plyrs[p1][g][r][t] for g in range(self.n_games)
                             for r in range(self.n_rounds)
                             for t in range(self.n_tms))
            for p2 in range(p1 + 1, self.n_plyrs):
                n_plays_ = xp.Sum(plyrs[p2][g][r][t]
                                  for g in range(self.n_games)
                                  for r in range(self.n_rounds)
                                  for t in range(self.n_tms))
                self.model.addConstraint(
                    (n_plays - n_plays_) <= self.max_gm_gap)
                self.model.addConstraint(
                    (n_plays_ - n_plays) <= self.max_gm_gap)

        # Objective
        self.model.setObjective(max_gm_plays_global, sense=xp.minimize)
        self.model.solve()
        self.check_model_feasibility()
        return plyrs, tms
示例#21
0
def create_variable(problem, edge, prefix="x", var_args=None):
    """ Create a single xpress variable and return it """

    name = mip_utils.name_variable(edge, prefix=prefix)
    return xp.var(name=name, **var_args)
示例#22
0
#
# Example: changing an optimization problem
#          using the Xpress Python interface
#

import xpress as xp

x = xp.var()
y = xp.var()

cons1 = x + y >= 2
upperlim = 2 * x + y <= 3

p = xp.problem()

p.addVariable(x, y)
p.setObjective((x - 4)**2 + (y - 1)**2)
p.addConstraint(cons1, upperlim)

p.write('original', 'lp')

p.chgcoef(cons1, x, 3)  # coefficient of x in cons1    becomes 3
p.chgcoef(1, 0, 4)  # coefficient of y in upperlim becomes 4

p.write('changed', 'lp')
示例#23
0
from __future__ import print_function

import xpress as xp

#
# Construct a problem using addVariable and addConstraint, then use
# the Xpress API routines to amend the problem with rows and quadratic
# terms.
#

p = xp.problem ()

N = 5
S = range (N)

x = [xp.var (vartype = xp.binary) for i in S]

p.addVariable (x)

# vectors can be used whole or addressed with their index

c0 = xp.Sum (x) <= 10
cc = [x[i]/1.1 <= x[i+1]*2 for i in range (N-1)]

p.addConstraint (c0, cc)

p.setObjective (3 - x[0])

mysol = [0, 0, 1, 1, 1, 1.4]

# add a variable with its coefficients
示例#24
0
p = xp.problem ()

# fill in a problem with three variables and four constraints

p.loadproblem ("",                                            # probname
               ['G','G','E', 'L'],                            # qrtypes
               [-2.4, -3, 4, 5],                              # rhs
               None,                                          # range
               [3,4,5],                                       # obj
               [0,2,4,8],                                     # mstart
               None,                                          # mnel
               [0,1,2,3,0,1,2,3],                             # mrwind
               [1,1,1,1,1,1,1,1],                             # dmatval
               [-1,-1,-1],                                    # lb
               [3,5,8],                                       # ub
               colnames = ['x1','x2','x3'],                   # column names
               rownames = ['row1','row2','row3','constr_04']) # row    names

p.write ("loadlp", "lp")
p.solve ()

# Create another variable and add it, then modify the objective
# function. Note that the objective function is replaced by, not
# amended with, the new objective

x = xp.var()
p.addVariable (x)
p.setObjective (x**2 + 2*x + 444)
p.solve()
p.write ("updated", "lp")
示例#25
0
    def solve_via_data(self,
                       data,
                       warm_start,
                       verbose,
                       solver_opts,
                       solver_cache=None):
        import xpress

        if 'no_qp_reduction' in solver_opts.keys(
        ) and solver_opts['no_qp_reduction'] is True:
            self.translate_back_QP_ = True

        c = data[s.C]  # objective coefficients

        dims = dims_to_solver_dict(
            data[s.DIMS])  # contains number of columns, rows, etc.

        nrowsEQ = dims[s.EQ_DIM]
        nrowsLEQ = dims[s.LEQ_DIM]
        nrows = nrowsEQ + nrowsLEQ

        # linear constraints
        b = data[s.B][:nrows]  # right-hand side
        A = data[s.A][:nrows]  # coefficient matrix

        # Problem
        self.prob_ = xpress.problem()

        mstart = makeMstart(A, len(c), 1)

        varGroups = {
        }  # If origprob is passed, used to tie IIS to original constraints
        transf2Orig = {
        }  # Ties transformation constraints to originals via varGroups
        nOrigVar = len(c)

        # Uses flat naming. Warning: this mixes
        # original with auxiliary variables.

        varnames = ['x_{0:05d}'.format(i) for i in range(len(c))]
        linRownames = ['lc_{0:05d}'.format(i) for i in range(len(b))]

        self.prob_.loadproblem(
            "CVXproblem",
            ['E'] * nrowsEQ + ['L'] * nrowsLEQ,  # qrtypes
            None,  # range
            c,  # obj coeff
            mstart,  # mstart
            None,  # mnel
            A.indices,  # row indices
            A.data,  # coefficients
            [-xpress.infinity] * len(c),  # lower bound
            [xpress.infinity] * len(c),  # upper bound
            colnames=varnames,  # column names
            rownames=linRownames)  # row    names

        x = np.array(self.prob_.getVariable())  # get whole variable vector

        # Set variable types for discrete variables
        self.prob_.chgcoltype(
            data[s.BOOL_IDX] + data[s.INT_IDX],
            'B' * len(data[s.BOOL_IDX]) + 'I' * len(data[s.INT_IDX]))

        currow = nrows

        iCone = 0

        auxVars = set(range(nOrigVar, len(c)))

        # Conic constraints
        #
        # Quadratic objective and constraints fall in this category,
        # as all quadratic stuff is converted into a cone via a linear transformation
        for k in dims[s.SOC_DIM]:

            # k is the size of the i-th cone, where i is the index
            # within dims [s.SOC_DIM]. The cone variables in
            # CVXOPT, apparently, are separate variables that are
            # marked as conic but not shown in a cone explicitly.

            A = data[s.A][currow:currow + k].tocsr()
            b = data[s.B][currow:currow + k]
            currow += k

            if self.translate_back_QP_:

                # Conic problem passed by CVXPY is translated back
                # into a QP problem. The problem is passed to us
                # as follows:
                #
                # min c'x
                # s.t. Ax <>= b
                #      y[i] = P[i]' * x + b[i]
                #      ||y[i][1:]||_2 <= y[i][0]
                #
                # where P[i] is a matrix, b[i] is a vector. Get
                # rid of the y variables by explicitly rewriting
                # the conic constraint as quadratic:
                #
                # y[i][1:]' * y[i][1:] <= y[i][0]^2
                #
                # and hence
                #
                # (P[i][1:]' * x + b[i][1:])^2 <= (P[i][0]' * x + b[i][0])^2

                Plhs = A[1:]
                Prhs = A[0]

                indRowL, indColL = Plhs.nonzero()
                indRowR, indColR = Prhs.nonzero()

                coeL = Plhs.data
                coeR = Prhs.data

                lhs = list(b[1:])
                rhs = b[0]

                for i in range(len(coeL)):
                    lhs[indRowL[i]] -= coeL[i] * x[indColL[i]]

                for i in range(len(coeR)):
                    rhs -= coeR[i] * x[indColR[i]]

                self.prob_.addConstraint(
                    xpress.Sum([lhs[i]**2 for i in range(len(lhs))]) <= rhs**2)

            else:

                # Create new (cone) variables and add them to the problem
                conevar = np.array([
                    xpress.var(name='cX{0:d}_{1:d}'.format(iCone, i),
                               lb=-xpress.infinity if i > 0 else 0)
                    for i in range(k)
                ])

                self.prob_.addVariable(conevar)

                initrow = self.prob_.attributes.rows

                mstart = makeMstart(A, k, 0)

                trNames = [
                    'linT_qc{0:d}_{1:d}'.format(iCone, i) for i in range(k)
                ]

                # Linear transformation for cone variables <--> original variables
                self.prob_.addrows(
                    ['E'] * k,  # qrtypes
                    b,  # rhs
                    mstart,  # mstart
                    A.indices,  # ind
                    A.data,  # dmatval
                    names=trNames)  # row names

                self.prob_.chgmcoef([initrow + i for i in range(k)], conevar,
                                    [1] * k)

                conename = 'cone_qc{0:d}'.format(iCone)
                # Real cone on the cone variables (if k == 1 there's no
                # need for this constraint as y**2 >= 0 is redundant)
                if k > 1:
                    self.prob_.addConstraint(
                        xpress.constraint(constraint=xpress.Sum(
                            conevar[i]**2
                            for i in range(1, k)) <= conevar[0]**2,
                                          name=conename))

                auxInd = list(set(A.indices) & auxVars)

                if len(auxInd) > 0:
                    group = varGroups[varnames[auxInd[0]]]
                    for i in trNames:
                        transf2Orig[i] = group
                    transf2Orig[conename] = group

            iCone += 1

        # Objective. Minimize is by default both here and in CVXOPT
        self.prob_.setObjective(xpress.Sum(c[i] * x[i] for i in range(len(c))))

        # End of the conditional (warm-start vs. no warm-start) code,
        # set options, solve, and report.

        # Set options
        #
        # The parameter solver_opts is a dictionary that contains only
        # one key, 'solver_opt', and its value is a dictionary
        # {'control': value}, matching perfectly the format used by
        # the Xpress Python interface.

        if verbose:
            self.prob_.controls.miplog = 2
            self.prob_.controls.lplog = 1
            self.prob_.controls.outputlog = 1
        else:
            self.prob_.controls.miplog = 0
            self.prob_.controls.lplog = 0
            self.prob_.controls.outputlog = 0

        if 'solver_opts' in solver_opts.keys():
            self.prob_.setControl(solver_opts['solver_opts'])

        self.prob_.setControl({
            i: solver_opts[i]
            for i in solver_opts.keys()
            if i in xpress.controls.__dict__.keys()
        })

        # Solve
        self.prob_.solve()

        results_dict = {
            'problem': self.prob_,
            'status': self.prob_.getProbStatus(),
            'obj_value': self.prob_.getObjVal(),
        }

        status_map_lp, status_map_mip = self.get_status_maps()

        if self.is_mip(data):
            status = status_map_mip[results_dict['status']]
        else:
            status = status_map_lp[results_dict['status']]

        results_dict[s.XPRESS_TROW] = transf2Orig

        results_dict[
            s.XPRESS_IIS] = None  # Return no IIS if problem is feasible

        if status in s.SOLUTION_PRESENT:
            results_dict['x'] = self.prob_.getSolution()
            if not (data[s.BOOL_IDX] or data[s.INT_IDX]):
                results_dict['y'] = self.prob_.getDual()

        elif status == s.INFEASIBLE:

            # Retrieve all IIS. For LPs there can be more than one,
            # but for QCQPs there is only support for one IIS.

            iisIndex = 0

            self.prob_.iisfirst(0)  # compute all IIS

            row, col, rtype, btype, duals, rdcs, isrows, icols = [], [], [], [], [], [], [], []

            self.prob_.getiisdata(0, row, col, rtype, btype, duals, rdcs,
                                  isrows, icols)

            origrow = []
            for iRow in row:
                if iRow.name in transf2Orig.keys():
                    name = transf2Orig[iRow.name]
                else:
                    name = iRow.name

                if name not in origrow:
                    origrow.append(name)

            results_dict[s.XPRESS_IIS] = [{
                'orig_row': origrow,
                'row': row,
                'col': col,
                'rtype': rtype,
                'btype': btype,
                'duals': duals,
                'redcost': rdcs,
                'isolrow': isrows,
                'isolcol': icols
            }]

            while self.prob_.iisnext() == 0:
                iisIndex += 1
                self.prob_.getiisdata(iisIndex, row, col, rtype, btype, duals,
                                      rdcs, isrows, icols)
                results_dict[s.XPRESS_IIS].append(
                    (row, col, rtype, btype, duals, rdcs, isrows, icols))

        # Generate solution.
        solution = {}

        if results_dict["status"] != s.SOLVER_ERROR:

            self.prob_ = results_dict['problem']

            vartypes = []
            self.prob_.getcoltype(vartypes, 0, len(data[s.C]) - 1)

        status_map_lp, status_map_mip = self.get_status_maps()

        if data[s.BOOL_IDX] or data[s.INT_IDX]:
            solution[s.STATUS] = status_map_mip[results_dict['status']]
        else:
            solution[s.STATUS] = status_map_lp[results_dict['status']]

        if solution[s.STATUS] in s.SOLUTION_PRESENT:

            solution[s.PRIMAL] = results_dict['x']
            solution[s.VALUE] = results_dict['obj_value']

            if not (data[s.BOOL_IDX] or data[s.INT_IDX]):
                solution[s.EQ_DUAL] = [-v for v in results_dict['y']]

        solution[s.XPRESS_IIS] = results_dict[s.XPRESS_IIS]
        solution[s.XPRESS_TROW] = results_dict[s.XPRESS_TROW]

        return solution
示例#26
0
def max_flow():
    global graph
    global vertices_no
    global vertices
    global weight

    thres = 0.4  # density of network
    thresdem = 0.8  # density of demand mesh

    dem = []

    for i in range(vertices_no):
        for j in range(vertices_no):
            if i != j and np.random.random() < thresdem:
                dem.append((vertices[i], vertices[j],
                            math.ceil(200 * np.random.random())))
    print("This is a random demand for each node", dem)

    for i in range(vertices_no):
        for j in range(vertices_no):
            if graph[i][j] != 0:
                pair = vertices[i], vertices[j]
                print(pair)

    #***********************************************************************************************************************
    #flow variables
    f = {(i, j, d):
         xp.var(name='f_{0}_{1}_{2}_{3}'.format(i, j, dem[d][0], dem[d][1]))
         for (i, j) in pair for d in range(len(dem))}

    # capacity variables
    x = {(i, j): xp.var(vartype=xp.integer, name='cap_{0}_{1}'.format(i, j))
         for (i, j) in pair}
    print("this is x", x)

    p = xp.problem('network flow')
    p.addVariable(f, x)

    def demand(i, d):
        if dem[d][0] == i:  # source
            return 1
        elif dem[d][1] == i:  # destination
            return -1
        else:
            return 0

    # Flow conservation constraints: total flow balance at node i for each demand d
    # must be 0 if i is an intermediate node, 1 if i is the source of demand d, and
    # -1 if i is the destination.

    flow = {(i, d): xp.constraint(
        constraint=xp.Sum(f[vertices[i], vertices[j], d]
                          for j in range(vertices_no)
                          if (vertices[i], vertices[j]) in weight) -
        xp.Sum(f[vertices[j], vertices[i], d] for j in range(vertices_no)
               if (vertices[j], vertices[i]) in weight) == demand(
                   vertices[i], d),
        name='cons_{0}_{1}_{2}'.format(i, dem[d][0], dem[d][1]))
            for d in range(len(dem)) for i in range(vertices_no)}

    # Capacity constraints: weighted sum of flow variables must be contained in the
    # total capacity installed on the arc (i, j)
    capacity = {
        (i, j):
        xp.constraint(constraint=xp.Sum(
            dem[d][2] * f[vertices[i], vertices[j], d]
            for d in range(len(dem))) <= x[vertices[i], vertices[j]],
                      name='capacity_{0}_{1}'.format(vertices[i], vertices[j]))
        for (i, j) in weight
    }

    p.addConstraint(flow, capacity)

    p.setObjective(xp.Sum(x[i, j] for (i, j) in weight))
    p.solve()

    p.getSolution()
示例#27
0
#!/bin/env python

# Test problem on a dot product between matrices of scalars and/or of
# variables. Note that the problem cannot be solved by the Optimizer
# as it is nonconvex.

from __future__ import print_function

import xpress as xp
import numpy as np

a = 0.1 + np.arange(21).reshape(3, 7)
y = np.array([xp.var() for i in range(21)]).reshape(3, 7)
x = np.array([xp.var() for i in range(35)]).reshape(7, 5)

p = xp.problem()
p.addVariable(x, y)

p.addConstraint(xp.Dot(y, x) <= 0)
p.addConstraint(xp.Dot(a, x) == 1)

p.setObjective(x[0][0])

p.write("test6-nonconv", "lp")
p.solve()
示例#28
0
# Q and a point x0, minimize the quadratic function
#
# x' (Q + alpha I) x
#
# subject to the linear system Q (x - x0) = 1 and nonnegativity on all
# variables. Report solution if available

from __future__ import print_function

import xpress as xp
import numpy as np

N = 10

Q = np.arange(1, N**2 + 1).reshape(N, N)
x = np.array([xp.var() for i in range(N)])
x0 = np.random.random(N)

p = xp.problem()

p.addVariable(x)

# c1 and c2 are two systems of constraints of size N each written as
#
# (x-x0)' Q = 1
#
# Qx >= 0

c1 = -xp.Dot((x - x0), Q) == 1
c2 = xp.Dot(Q, x) >= 0
示例#29
0
    def solve(self, objective, constraints, cached_data,
              warm_start, verbose, solver_opts):

        """Returns the result of the call to the solver.

        Parameters
        ----------
        objective : LinOp
            The canonicalized objective.
        constraints : list
            The list of canonicalized cosntraints.
        cached_data : dict
            A map of solver name to cached problem data.
        warm_start : bool
            Should the previous solver result be used to warm_start?
        verbose : bool
            Should the solver print output?
        solver_opts : dict
            Additional arguments for the solver.

        Returns
        -------
        tuple
            (status, optimal value, primal, equality dual, inequality dual)
        """

        import xpress

        verbose = True

        # Get problem data
        data = super(XPRESS, self).get_problem_data(objective, constraints, cached_data)

        origprob = None

        if 'original_problem' in solver_opts.keys():
            origprob = solver_opts['original_problem']

        if 'no_qp_reduction' in solver_opts.keys() and solver_opts['no_qp_reduction'] is True:
            self.translate_back_QP_ = True

        c = data[s.C]  # objective coefficients

        dims = data[s.DIMS]  # contains number of columns, rows, etc.

        nrowsEQ = dims[s.EQ_DIM]
        nrowsLEQ = dims[s.LEQ_DIM]
        nrows = nrowsEQ + nrowsLEQ

        # linear constraints
        b = data[s.B][:nrows]  # right-hand side
        A = data[s.A][:nrows]  # coefficient matrix

        n = c.shape[0]  # number of variables

        solver_cache = cached_data[self.name()]

        ###########################################################################################

        # Allow warm start if all dimensions match, i.e., if the
        # modified problem has the same number of rows/column and the
        # same list of cone sizes. Failing that, we can just take the
        # standard route and build the problem from scratch.

        if warm_start and \
           solver_cache.prev_result is not None and \
           n == len(solver_cache.prev_result['obj']) and \
           nrows == len(solver_cache.prev_result['rhs']) and \
           data[s.DIMS][s.SOC_DIM] == solver_cache.prev_result['cone_ind']:

            # We are re-solving a problem that was previously solved

            # Initialize the problem as the same as the previous solve
            self.prob_ = solver_cache.prev_result['problem']

            c0 = solver_cache.prev_result['obj']
            A0 = solver_cache.prev_result['mat']
            b0 = solver_cache.prev_result['rhs']

            vartype0 = solver_cache.prev_result['vartype']

            # If there is a parameter in the objective, it may have changed.
            if len(linutils.get_expr_params(objective)) > 0:
                dci = numpy.where(c != c0)[0]
                self.prob_.chgobj(dci, c[dci])

            # Get equality and inequality constraints.
            sym_data = self.get_sym_data(objective, constraints, cached_data)
            all_constrs, _, _ = self.split_constr(sym_data.constr_map)

            # If there is a parameter in the constraints,
            # A or b may have changed.

            if any(len(linutils.get_expr_params(con.expr)) > 0 for con in constraints):

                dAi = (A != A0).tocoo()  # retrieves row/col nonzeros as a tuple of two arrays
                dbi = numpy.where(b != b0)[0]

                if dAi.getnnz() > 0:
                    self.prob_.chgmcoef(dAi.row, dAi.col,
                                        [A[i, j] for (i, j) in list(zip(dAi.row, dAi.col))])

                if len(dbi) > 0:
                    self.prob_.chgrhs(dbi, b[dbi])

            vartype = []
            self.prob_.getcoltype(vartype, 0, len(data[s.C]) - 1)

            vti = (numpy.array(vartype) != numpy.array(vartype0))

            if any(vti):
                self.prob_.chgcoltype(numpy.arange(len(c))[vti], vartype[vti])

        ############################################################################################

        else:

            # No warm start, create problem from scratch

            # Problem
            self.prob_ = xpress.problem()

            mstart = makeMstart(A, len(c), 1)

            varGroups = {}  # If origprob is passed, used to tie IIS to original constraints
            transf2Orig = {}  # Ties transformation constraints to originals via varGroups
            nOrigVar = len(c)

            # From a summary knowledge of origprob.constraints() and
            # the constraints list, the following seems to hold:
            #
            # 1) origprob.constraints is the list as generated by the
            #    user. origprob.constraints[i].size returns the number
            #    of actual rows in each constraint, while .constr_id
            #    returns its id (not necessarily numbered from 0).
            #
            # 2) constraints is also a list whose every element
            #    contains fields size and constr_id. These correspond
            #    to the items in origprob.constraints, though the list
            #    is in not in order of constr_id. Also, given that it
            #    refers to the transformed problem, it contains extra
            #    constraints deriving from the cone transformations,
            #    all with a constr_id and a size.
            #
            # Given this information, attempt to set names in varnames
            # and linRownames so that they can be easily identified

            # Load linear part of the problem.

            if origprob is not None:

                # The original problem was passed, we can take a
                # better guess at the constraints and variable names.

                nOrigVar = 0
                orig_id = [i.id for i in origprob.constraints]

                varnames = []
                for v in origprob.variables():
                    nOrigVar += v.size[0]
                    if v.size[0] == 1:
                        varnames.append('{0}'. format(v.var_id))
                    else:
                        varnames.extend(['{0}_{1:d}'. format(v.var_id, j)
                                         for j in range(v.size[0])])

                varnames.extend(['aux_{0:d}'.format(i) for i in range(len(varnames), len(c))])

                # Construct constraint name list by checking constr_id for each

                linRownames = []

                for con in constraints:
                    if con.constr_id in orig_id:

                        prefix = ''

                        if type(con.constr_id) == int:
                            prefix = 'row_'

                        if con.size[0] == 1:
                            name = '{0}{1}'.format(prefix, con.constr_id)
                            linRownames.append(name)
                            transf2Orig[name] = con.constr_id

                        else:
                            names = ['{0}{1}_{2:d}'.format(prefix, con.constr_id, j)
                                     for j in range(con.size[0])]
                            linRownames.extend(names)
                            for i in names:
                                transf2Orig[i] = con.constr_id

                # Tie auxiliary variables to constraints. Scan all
                # auxiliary variables in the objective function and in
                # the corresponding columns of A.indices

                iObjQuad = 0  # keeps track of quadratic quantities in the objective

                for i in range(nOrigVar, len(c)):

                    if c[i] != 0:
                        varGroups[varnames[i]] = 'objF_{0}'.format(iObjQuad)
                        iObjQuad += 1

                    if len(A.indices[mstart[i]:mstart[i+1]]) > 0:
                        varGroups[varnames[i]] = linRownames[min(A.indices[mstart[i]:mstart[i+1]])]

            else:

                # fall back to flat naming. Warning: this mixes
                # original with auxiliary variables.

                varnames = ['x_{0:05d}'. format(i) for i in range(len(c))]
                linRownames = ['lc_{0:05d}'.format(i) for i in range(len(b))]

            self.prob_.loadproblem("CVXproblem",
                                   ['E'] * nrowsEQ + ['L'] * nrowsLEQ,  # qrtypes
                                   b,                                   # rhs
                                   None,                                # range
                                   c,                                   # obj coeff
                                   mstart,                              # mstart
                                   None,                                # mnel
                                   A.indices,                           # row indices
                                   A.data,                              # coefficients
                                   [-xpress.infinity] * len(c),         # lower bound
                                   [xpress.infinity] * len(c),          # upper bound
                                   colnames=varnames,                   # column names
                                   rownames=linRownames)                # row    names

            x = numpy.array(self.prob_.getVariable())  # get whole variable vector

            # Set variable types for discrete variables
            self.prob_.chgcoltype(data[s.BOOL_IDX] + data[s.INT_IDX],
                                  'B' * len(data[s.BOOL_IDX]) + 'I' * len(data[s.INT_IDX]))

            currow = nrows

            iCone = 0

            auxVars = set(range(nOrigVar, len(c)))

            # Conic constraints
            #
            # Quadratic objective and constraints fall in this category,
            # as all quadratic stuff is converted into a cone via a linear transformation
            for k in dims[s.SOC_DIM]:

                # k is the size of the i-th cone, where i is the index
                # within dims [s.SOC_DIM]. The cone variables in
                # CVXOPT, apparently, are separate variables that are
                # marked as conic but not shown in a cone explicitly.

                A = data[s.A][currow: currow + k].tocsr()
                b = data[s.B][currow: currow + k]
                currow += k

                if self.translate_back_QP_:

                    # Conic problem passed by CVXPY is translated back
                    # into a QP problem. The problem is passed to us
                    # as follows:
                    #
                    # min c'x
                    # s.t. Ax <>= b
                    #      y[i] = P[i]' * x + b[i]
                    #      ||y[i][1:]||_2 <= y[i][0]
                    #
                    # where P[i] is a matrix, b[i] is a vector. Get
                    # rid of the y variables by explicitly rewriting
                    # the conic constraint as quadratic:
                    #
                    # y[i][1:]' * y[i][1:] <= y[i][0]^2
                    #
                    # and hence
                    #
                    # (P[i][1:]' * x + b[i][1:])^2 <= (P[i][0]' * x + b[i][0])^2

                    Plhs = A[1:]
                    Prhs = A[0]

                    indRowL, indColL = Plhs.nonzero()
                    indRowR, indColR = Prhs.nonzero()

                    coeL = Plhs.data
                    coeR = Prhs.data

                    lhs = list(b[1:])
                    rhs = b[0]

                    for i in range(len(coeL)):
                        lhs[indRowL[i]] -= coeL[i] * x[indColL[i]]

                    for i in range(len(coeR)):
                        rhs -= coeR[i] * x[indColR[i]]

                    self.prob_.addConstraint(xpress.Sum([lhs[i]**2 for i in range(len(lhs))])
                                             <= rhs**2)

                else:

                    # Create new (cone) variables and add them to the problem
                    conevar = numpy.array([xpress.var(name='cX{0:d}_{1:d}'.format(iCone, i),
                                                      lb=-xpress.infinity if i > 0 else 0)
                                           for i in range(k)])

                    self.prob_.addVariable(conevar)

                    initrow = self.prob_.attributes.rows

                    mstart = makeMstart(A, k, 0)

                    trNames = ['linT_qc{0:d}_{1:d}'.format(iCone, i) for i in range(k)]

                    # Linear transformation for cone variables <--> original variables
                    self.prob_.addrows(['E'] * k,        # qrtypes
                                       b,                # rhs
                                       mstart,           # mstart
                                       A.indices,        # ind
                                       A.data,           # dmatval
                                       names=trNames)  # row names

                    self.prob_.chgmcoef([initrow + i for i in range(k)],
                                        conevar, [1] * k)

                    conename = 'cone_qc{0:d}'.format(iCone)
                    # Real cone on the cone variables (if k == 1 there's no
                    # need for this constraint as y**2 >= 0 is redundant)
                    if k > 1:
                        self.prob_.addConstraint(
                            xpress.constraint(constraint=xpress.Sum
                                              (conevar[i]**2 for i in range(1, k))
                                              <= conevar[0] ** 2,
                                              name=conename))

                    auxInd = list(set(A.indices) & auxVars)

                    if len(auxInd) > 0:
                        group = varGroups[varnames[auxInd[0]]]
                        for i in trNames:
                            transf2Orig[i] = group
                        transf2Orig[conename] = group

                iCone += 1

            # Objective. Minimize is by default both here and in CVXOPT
            self.prob_.setObjective(xpress.Sum(c[i] * x[i] for i in range(len(c))))

        # End of the conditional (warm-start vs. no warm-start) code,
        # set options, solve, and report.

        # Set options
        #
        # The parameter solver_opts is a dictionary that contains only
        # one key, 'solver_opt', and its value is a dictionary
        # {'control': value}, matching perfectly the format used by
        # the Xpress Python interface.

        if verbose:
            self.prob_.controls.miplog = 2
            self.prob_.controls.lplog = 1
            self.prob_.controls.outputlog = 1
        else:
            self.prob_.controls.miplog = 0
            self.prob_.controls.lplog = 0
            self.prob_.controls.outputlog = 0

        if 'solver_opts' in solver_opts.keys():
            self.prob_.setControl(solver_opts['solver_opts'])

        self.prob_.setControl({i: solver_opts[i] for i in solver_opts.keys()
                               if i in xpress.controls.__dict__.keys()})

        # Solve
        self.prob_.solve()

        results_dict = {

            'problem':   self.prob_,
            'status':    self.prob_.getProbStatus(),
            'obj_value': self.prob_.getObjVal(),
        }

        status_map_lp, status_map_mip = self.get_status_maps()

        if self.is_mip(data):
            status = status_map_mip[results_dict['status']]
        else:
            status = status_map_lp[results_dict['status']]

        results_dict[s.XPRESS_TROW] = transf2Orig

        results_dict[s.XPRESS_IIS] = None  # Return no IIS if problem is feasible

        if status in s.SOLUTION_PRESENT:
            results_dict['x'] = self.prob_.getSolution()
            if not self.is_mip(data):
                results_dict['y'] = self.prob_.getDual()

        elif status == s.INFEASIBLE:

            # Retrieve all IIS. For LPs there can be more than one,
            # but for QCQPs there is only support for one IIS.

            iisIndex = 0

            self.prob_.iisfirst(0)  # compute all IIS

            row, col, rtype, btype, duals, rdcs, isrows, icols = [], [], [], [], [], [], [], []

            self.prob_.getiisdata(0, row, col, rtype, btype, duals, rdcs, isrows, icols)

            origrow = []
            for iRow in row:
                if iRow.name in transf2Orig.keys():
                    name = transf2Orig[iRow.name]
                else:
                    name = iRow.name

                if name not in origrow:
                    origrow.append(name)

            results_dict[s.XPRESS_IIS] = [{'orig_row': origrow,
                                           'row':      row,
                                           'col':      col,
                                           'rtype':    rtype,
                                           'btype':    btype,
                                           'duals':    duals,
                                           'redcost':  rdcs,
                                           'isolrow':  isrows,
                                           'isolcol':  icols}]

            while self.prob_.iisnext() == 0:
                iisIndex += 1
                self.prob_.getiisdata(iisIndex,
                                      row, col, rtype, btype, duals, rdcs, isrows, icols)
                results_dict[s.XPRESS_IIS].append((
                    row, col, rtype, btype, duals, rdcs, isrows, icols))

        return self.format_results(results_dict, data, cached_data)
#
# The n queens: place n queens on an nxn chessboard so that none of
# them can be eaten in one move.
#

from __future__ import print_function

import xpress as xp

n = 8  # the size of the chessboard
N = range(n)

# Create a "dictionary" of variables, i.e. a mapping from all tuples
# (i,j) to a variable.

x = {(i, j): xp.var(vartype=xp.binary, name='q{0}_{1}'.format(i, j))
     for i in N for j in N}

vertical = [xp.Sum(x[i, j] for i in N) <= 1 for j in N]
horizontal = [xp.Sum(x[i, j] for j in N) <= 1 for i in N]

diagonal1 = [
    xp.Sum(x[k - j, j] for j in range(max(0, k - n + 1), min(k + 1, n))) <= 1
    for k in range(1, 2 * n - 2)
]
diagonal2 = [
    xp.Sum(x[k + j, j] for j in range(max(0, -k), min(n - k, n))) <= 1
    for k in range(2 - n, n - 1)
]

p = xp.problem()
示例#31
0
#!/bin/env python

#
# Demonstrate how variables, or arrays thereof, and constraints, or
# arrays of constraints, can be added into a problem. Prints the
# solution and all attributes/controls of the problem.
#

from __future__ import print_function

import xpress as xp

N = 4
S = range(N)
v = [xp.var(name="y{0}".format(i)) for i in S]  # set name of a variable as

m = xp.problem()

v1 = xp.var(name="v1", lb=0, ub=10, threshold=5, vartype=xp.continuous)
v2 = xp.var(name="v2", lb=1, ub=7, threshold=3, vartype=xp.continuous)
vb = xp.var(name="vb", vartype=xp.binary)

v = [xp.var(name="y{0}".format(i), lb=0, ub=2 * N)
     for i in S]  # set name of a variable as

m.addVariable(
    vb, v, v1, v2
)  # adds both v, a vector (list) of variables, and v1 and v2, two scalar variables.

c1 = v1 + v2 >= 5