def __init__(self, *args, **kwargs):
        # if inputting as a function
        self.problem = args[0]

        # Lets replace some commonly used strings in problem statement
        # to a standard string

        # min, Min, Minimize, MINIMIZE etc -> MIN
        replace_mins = re.compile('min\.|minimize|min', re.IGNORECASE)
        self.problem = replace_mins.sub('MIN', self.problem)

        # max, Max, Maximize, MAXIMIZE etc -> MAX
        replace_maxs = re.compile('max\.|maximize|max', re.IGNORECASE)
        self.problem = replace_maxs.sub('MAX', self.problem)

        # subject to, such that, sub. to, s.t., sub to etc -> SUB TO
        replace_sub_to = re.compile(
            's\.t\.|sub\.|sub to|subject to|such that|st', re.IGNORECASE)
        self.problem = replace_sub_to.sub('SUB TO', self.problem)

        self.original_variable = []
        debug(LOCAL_LEVEL, 'PROBLEM: ', self.problem)
        # get the constraints from problem separately in raw format
        self.constraints = filter(
            None,
            self.problem.replace('SUB TO', '\t').split('\t'))[1:]
        debug(LOCAL_LEVEL, "constraints: ", self.constraints)
        # by default assume non-negative variables, this will be changed later if needed
        self.variable_sign_needed = False
	def __init__(self, *args, **kwargs):
		# if inputting as a function
		self.problem = args[0]

		# Lets replace some commonly used strings in problem statement
		# to a standard string

		# min, Min, Minimize, MINIMIZE etc -> MIN
		replace_mins = re.compile('min\.|minimize|min', re.IGNORECASE)
		self.problem = replace_mins.sub('MIN', self.problem)

		# max, Max, Maximize, MAXIMIZE etc -> MAX
		replace_maxs = re.compile('max\.|maximize|max', re.IGNORECASE)
		self.problem = replace_maxs.sub('MAX', self.problem)

		# subject to, such that, sub. to, s.t., sub to etc -> SUB TO
		replace_sub_to = re.compile('s\.t\.|sub\.|sub to|subject to|such that|st', re.IGNORECASE)
		self.problem = replace_sub_to.sub('SUB TO', self.problem)

		self.original_variable = []
		debug(LOCAL_LEVEL, 'PROBLEM: ', self.problem)
		# get the constraints from problem separately in raw format
		self.constraints = filter(None, self.problem.replace('SUB TO', '\t').split('\t'))[1:]
		debug(LOCAL_LEVEL, "constraints: ", self.constraints)
		# by default assume non-negative variables, this will be changed later if needed
		self.variable_sign_needed = False
	def parse_variables(self):
		# figure out how many variables are there and get all of them
		problem_str = "+".join(self.problem.split('\\'))
		# remove unnecessary words, lets focus on variables
		problem_split = ' '.join(re.split('\+|\-|MIN|SUB TO|=|<=|>=', problem_str)).replace('MIN', '').replace('MAX', '').replace('SUB TO', '').strip()
		# get variables : they can be of form x, x1, X, X1
		self.original_variable = re.findall('([A-Z]\\b|[A-Z][0-9]*|[a-z]\\b|[a-z][0-9]*\\b)', problem_split)
		# remove any duplicate entry and sort them alphabatically - this doesn't matter but looks good
		self.original_variable = list(set(filter(None, self.original_variable)))
		self.original_variable.sort()
		debug(LEVEL, "Original variables: ", self.original_variable)
 def parse_variables(self):
     # figure out how many variables are there and get all of them
     problem_str = "+".join(self.problem.split('\\'))
     # remove unnecessary words, lets focus on variables
     problem_split = ' '.join(
         re.split('\+|\-|MIN|SUB TO|=|<=|>=', problem_str)).replace(
             'MIN', '').replace('MAX', '').replace('SUB TO', '').strip()
     # get variables : they can be of form x, x1, X, X1
     self.original_variable = re.findall(
         '([A-Z]\\b|[A-Z][0-9]*|[a-z]\\b|[a-z][0-9]*\\b)', problem_split)
     # remove any duplicate entry and sort them alphabatically - this doesn't matter but looks good
     self.original_variable = list(set(filter(None,
                                              self.original_variable)))
     self.original_variable.sort()
     debug(LEVEL, "Original variables: ", self.original_variable)
 def get_standardized_coeff_matrix(self, constraints, coeff_matrix, b):
     # take the original coefficient matrix and
     # add slack variables to convert it to standard form
     # make sure there isn't any negative b
     is_two_phase_required = False
     coeff_matrix_with_slack = coeff_matrix
     b_positive = b
     # add positive slack with <= and negative slack with >= constraints
     # if all constraints are <= then we don't need Two Phase otherwise we do
     # if any of the b is negative we'll use Two Phase, in some cases we don't have to but
     # efforts to single out those cases are not worth the time
     for constraint in constraints:
         index = constraints.index(constraint)
         if '<=' in constraint:
             slack_column = np.eye(1, len(constraints), index).transpose()
             coeff_matrix_with_slack = np.append(coeff_matrix_with_slack,
                                                 slack_column, 1)
             if b[index] < 0.:
                 coeff_matrix_with_slack[
                     index] = -1 * coeff_matrix_with_slack[index]
                 b_positive[index] = -1 * b_positive[index]
                 is_two_phase_required = True
         elif '>=' in constraint:
             slack_column = -1 * np.eye(1, len(constraints),
                                        index).transpose()
             coeff_matrix_with_slack = np.append(coeff_matrix_with_slack,
                                                 slack_column, 1)
             if b[index] < 0:
                 coeff_matrix_with_slack[
                     index] = -1 * coeff_matrix_with_slack[index]
                 b_positive[index] = -1 * b_positive[index]
             else:
                 is_two_phase_required = True
         elif '=' in constraint:
             if b[index] < 0:
                 coeff_matrix_with_slack[
                     index] = -1 * coeff_matrix_with_slack[index]
                 b_positive[index] = -1 * b_positive[index]
             is_two_phase_required = True
     coeff_matrix_with_slack += 0.
     debug(LEVEL, "standardized coeff matrix: \n", coeff_matrix_with_slack,
           "\nb_positive: \n", b_positive, "\nis_two_phase_required: ",
           is_two_phase_required)
     return is_two_phase_required, coeff_matrix_with_slack, b_positive
	def get_coeff(self, str_line, var):
		# get coefficient of var from str_line
		debug(LOCAL_LEVEL, "str_line ", str_line, " var ", var)
		# search for coefficient only if a variable is there in search str otherwise return 0
		search_str = re.search(var+'\\b', ''.join(str_line.split()))
		if(search_str):
			# get the coefficient of the form 123, +123, -123, -12.3, 2/3, -2/3 (.12 is invalid use 0.12 instead)
			# Regex! Oh Regex! what would I do without thou!
			coeff = re.findall('(\-?\d+\.*\d*|\-?\d+\/\.*\d*)('+var+'\\b)', ''.join(str_line.split()))
			# coeff = re.findall('(\-?\d+\.*\d*)('+var+'\\b)', ''.join(str_line.split()))
			# if there is no coefficient then its either +1 and -1 decide based on sign
			if len(coeff) == 0:
				sign = re.findall('(\-)('+var+'\\b)', ''.join(str_line.split()))
				if(len(sign) != 0 and sign[0][0] == '-'):
					coeff = [('-1', var)]
				else:
					coeff = [('1', var)]
			debug(LOCAL_LEVEL, "coeff of variable ", var, " in ", " constraint ", str_line, " is ", coeff)
			return float(Fraction(coeff[0][0]))
		else:
			return 0.
	def get_standardized_coeff_matrix(self, constraints, coeff_matrix, b):
		# take the original coefficient matrix and
		# add slack variables to convert it to standard form
		# make sure there isn't any negative b
		is_two_phase_required = False
		coeff_matrix_with_slack = coeff_matrix
		b_positive = b
		# add positive slack with <= and negative slack with >= constraints
		# if all constraints are <= then we don't need Two Phase otherwise we do
		# if any of the b is negative we'll use Two Phase, in some cases we don't have to but
		# efforts to single out those cases are not worth the time
		for constraint in constraints:
			index = constraints.index(constraint)
			if '<=' in constraint:
				slack_column = np.eye(1, len(constraints), index).transpose()
				coeff_matrix_with_slack = np.append(coeff_matrix_with_slack, slack_column, 1)
				if b[index] < 0.:
					coeff_matrix_with_slack[index] = -1 * coeff_matrix_with_slack[index]
					b_positive[index] = -1 * b_positive[index]
					is_two_phase_required = True
			elif '>=' in constraint:
				slack_column = -1 * np.eye(1, len(constraints), index).transpose()
				coeff_matrix_with_slack = np.append(coeff_matrix_with_slack, slack_column, 1)
				if b[index] < 0:
					coeff_matrix_with_slack[index] = -1 * coeff_matrix_with_slack[index]
					b_positive[index] = -1 * b_positive[index]
				else:
					is_two_phase_required = True
			elif '=' in constraint:
				if b[index] < 0:
					coeff_matrix_with_slack[index] = -1 * coeff_matrix_with_slack[index]
					b_positive[index] = -1 * b_positive[index]
				is_two_phase_required = True
		coeff_matrix_with_slack += 0.
		debug(LEVEL, "standardized coeff matrix: \n", coeff_matrix_with_slack, "\nb_positive: \n", b_positive, "\nis_two_phase_required: ", is_two_phase_required)
		return is_two_phase_required, coeff_matrix_with_slack, b_positive
 def get_coeff(self, str_line, var):
     # get coefficient of var from str_line
     debug(LOCAL_LEVEL, "str_line ", str_line, " var ", var)
     # search for coefficient only if a variable is there in search str otherwise return 0
     search_str = re.search(var + '\\b', ''.join(str_line.split()))
     if (search_str):
         # get the coefficient of the form 123, +123, -123, -12.3, 2/3, -2/3 (.12 is invalid use 0.12 instead)
         # Regex! Oh Regex! what would I do without thou!
         coeff = re.findall('(\-?\d+\.*\d*|\-?\d+\/\.*\d*)(' + var + '\\b)',
                            ''.join(str_line.split()))
         # coeff = re.findall('(\-?\d+\.*\d*)('+var+'\\b)', ''.join(str_line.split()))
         # if there is no coefficient then its either +1 and -1 decide based on sign
         if len(coeff) == 0:
             sign = re.findall('(\-)(' + var + '\\b)',
                               ''.join(str_line.split()))
             if (len(sign) != 0 and sign[0][0] == '-'):
                 coeff = [('-1', var)]
             else:
                 coeff = [('1', var)]
         debug(LOCAL_LEVEL, "coeff of variable ", var, " in ",
               " constraint ", str_line, " is ", coeff)
         return float(Fraction(coeff[0][0]))
     else:
         return 0.
 def get_variable_sign(self):
     # tell others that they need to consider variable sign into the account
     self.variable_sign_needed = True
     # warn humans that they are asking you to do too much so just check their intention
     print '\033[91m' + "Make sure you know what you are doing." + '\033[0m'
     print "You chose assume_non_negative_variable = False."
     print "This means that any variable that is not explicitly mentioned in problem file will be trated as free variable."
     self.non_negative_variables = []
     self.negative_variables = []
     self.free_variables = []
     self.constraints_for_sign = []
     # we'll determine the sign based on the non-negativity (negativity) constraint
     # x>=0 or x<=0 will be matched and others will be assumed to be free
     # we'll also mark these constraints to remove them later
     for variable in self.original_variable:
         variable_sign = False
         for constraint in self.constraints:
             stripped_constraint = ''.join(constraint.split())
             debug(LOCAL_LEVEL, "constraint: ", stripped_constraint)
             positive_constraint = variable + '>=0'
             negative_constraint = variable + '<=0'
             if not variable_sign:
                 if positive_constraint == stripped_constraint:
                     self.non_negative_variables.append(variable)
                     variable_sign = True
                     debug(LOCAL_LEVEL, "positive ", variable, " ",
                           stripped_constraint)
                     self.constraints_for_sign.append(
                         self.constraints.index(constraint))
                 elif negative_constraint == stripped_constraint:
                     self.negative_variables.append(variable)
                     variable_sign = True
                     debug(LOCAL_LEVEL, "negative ", variable, " ",
                           stripped_constraint)
                     self.constraints_for_sign.append(
                         self.constraints.index(constraint))
         if not variable_sign:
             self.free_variables.append(variable)
             variable_sign = True
             debug(LOCAL_LEVEL, "free ", variable)
     print " positive variables: ", self.non_negative_variables
     print " negative variables: ", self.negative_variables
     print " free variables: ", self.free_variables
     self.constraints_for_sign.sort()
     self.constraints_for_sign.reverse()
示例#10
0
def get_entering_variable(c):
	# get the indices where cost coefficient is greater than 0
	entering_var_index_valid = np.where(c > np.finfo(np.float32).eps)
	debug(LOCAL_LEVEL, " entering_var_index_valid: ", entering_var_index_valid)
	enter_var_index = entering_var_index_valid[0]
	debug(LOCAL_LEVEL, "length of entering_var_index: ", len(enter_var_index))
	# if we don't get any entering variable tell that we are at optimum
	if len(enter_var_index) == 0:
		return '', True
	# return the entering variable index otherwise and tell that we are not yet optimum
	debug(LOCAL_LEVEL, " entering_var_index: ", enter_var_index[0])
	# if len(enter_var_index)>1:
	return enter_var_index[0], False
示例#11
0
	def get_variable_sign(self):
		# tell others that they need to consider variable sign into the account
		self.variable_sign_needed = True
		# warn humans that they are asking you to do too much so just check their intention
		print '\033[91m' + "Make sure you know what you are doing." + '\033[0m'
		print "You chose assume_non_negative_variable = False."
		print "This means that any variable that is not explicitly mentioned in problem file will be trated as free variable."
		self.non_negative_variables = []
		self.negative_variables = []
		self.free_variables = []
		self.constraints_for_sign = []
		# we'll determine the sign based on the non-negativity (negativity) constraint
		# x>=0 or x<=0 will be matched and others will be assumed to be free
		# we'll also mark these constraints to remove them later
		for variable in self.original_variable:
			variable_sign = False
			for constraint in self.constraints:
				stripped_constraint = ''.join(constraint.split())
				debug(LOCAL_LEVEL, "constraint: ", stripped_constraint)
				positive_constraint = variable+'>=0'
				negative_constraint = variable+'<=0'
				if not variable_sign:
					if positive_constraint == stripped_constraint:
						self.non_negative_variables.append(variable)
						variable_sign = True
						debug(LOCAL_LEVEL, "positive ", variable, " ", stripped_constraint)
						self.constraints_for_sign.append(self.constraints.index(constraint))
					elif negative_constraint == stripped_constraint:
						self.negative_variables.append(variable)
						variable_sign = True
						debug(LOCAL_LEVEL, "negative ", variable, " ", stripped_constraint)
						self.constraints_for_sign.append(self.constraints.index(constraint))
			if not variable_sign:
				self.free_variables.append(variable)
				variable_sign = True
				debug(LOCAL_LEVEL, "free ", variable)
		print " positive variables: ", self.non_negative_variables
		print " negative variables: ", self.negative_variables
		print " free variables: ", self.free_variables
		self.constraints_for_sign.sort()
		self.constraints_for_sign.reverse()
示例#12
0
def minimum_ratio_test(y, b, basic_variable):
	# do ratio test only if y>0
	valid_index = np.where(y > np.finfo(np.float32).eps)
	debug(LEVEL, " current b: \n", b)
	debug(LOCAL_LEVEL, "Ratio Test: \n", b[valid_index]/y[valid_index])
	# get the minimum ratio and return it for pivoting
	min_ratio = min(b[valid_index]/y[valid_index])
	# also get leaving variable which has minimum ratio
	# leaving variable will be one with minimum index in case of tie - Bland's rule
	debug(LOCAL_LEVEL, " tied mininimum valid_index ", np.where(b[valid_index]/y[valid_index] == min_ratio))
	debug(LOCAL_LEVEL, " basic_vairable ", basic_variable)
	# Lets get all indexes for tied minimum ratio
	min_ratio_possible_index = valid_index[0][np.where(b[valid_index]/y[valid_index] == min_ratio)[0]]
	debug(LOCAL_LEVEL, "min_ratio_possible_index ", min_ratio_possible_index)
	# take the one which has minimum index in basic variables
	min_ratio_index = basic_variable.index(min(basic_variable[i] for i in min_ratio_possible_index))
	debug(LOCAL_LEVEL, "valid leaving index: ", valid_index, "\nmin_ratio: ", min_ratio, "\nleaving variable index: ", min_ratio_index)
	return min_ratio_index, min_ratio
示例#13
0
    def get_coeff_matrix(self):
        # get coefficient matrix A and also get RHS b
        self.coeff_matrix = np.zeros(
            (len(self.constraints), len(self.original_variable)))
        self.b = np.zeros((len(self.constraints), 1))
        # b would be anything that is after <=, >= or =
        for i in range(len(self.constraints)):
            self.b[i, 0] = float(
                Fraction(re.split('<=|>=|=', self.constraints[i])[-1]))
        # generate coefficient matrix using get_coeff with constraints
        j_index = 0
        for var in self.original_variable:
            for i in range(len(self.constraints)):
                self.coeff_matrix[i, j_index] = self.get_coeff(
                    self.constraints[i], var)
                debug(LOCAL_LEVEL, self.constraints[i], " ", var, " ",
                      self.coeff_matrix[i, j_index])
            j_index = j_index + 1
        debug(LEVEL, "Coefficient Matrix: \n", self.coeff_matrix, "\n b: \n",
              self.b)

        # Lets change it in case we need to take variable sign in account
        if self.variable_sign_needed:
            self.signed_variable = self.original_variable[:]
            debug(LEVEL, " self.signed_variable ", self.signed_variable)
            # as before -1* coefficients for negative variables
            for var in self.negative_variables:
                var_index = self.signed_variable.index(var)
                self.coeff_matrix[:,
                                  var_index] = -1 * self.coeff_matrix[:,
                                                                      var_index]
                self.signed_variable[var_index] = var + '-'
                debug(LOCAL_LEVEL, " var_index ", var_index,
                      " signed_variable: ", self.signed_variable, " var: ",
                      var)
            # replace free variables with x+ - x-, this essentially means adding extra column to coefficient matrix
            for var in self.free_variables:
                var_index = self.signed_variable.index(var)
                self.coeff_matrix = np.insert(self.coeff_matrix,
                                              var_index + 1,
                                              -1 *
                                              self.coeff_matrix[:, var_index],
                                              axis=1)
                debug(LOCAL_LEVEL, " var_index ", var_index,
                      " signed_variable: ", self.signed_variable, " var: ",
                      var)
                self.signed_variable[var_index] = var + '+'
                debug(LOCAL_LEVEL, " var_index ", var_index,
                      " signed_variable: ", self.signed_variable, " var: ",
                      var)
                self.signed_variable.insert(var_index + 1, var + '-')
                debug(LOCAL_LEVEL, " var_index ", var_index,
                      " signed_variable: ", self.signed_variable, " var: ",
                      var)

            debug(LEVEL, " self.coeff_matrix after sign adjustments \n",
                  self.coeff_matrix)
            # now that we have taken variable signs in account, lets delete non_negativity constraints
            for i in self.constraints_for_sign:
                self.coeff_matrix = np.delete(self.coeff_matrix, i, 0)
                self.constraints.remove(self.constraints[i])
                self.b = np.delete(self.b, i, 0)
            debug(
                LEVEL,
                " self.coeff_matrix after sign adjustments and deleting additional rows\n",
                self.coeff_matrix)
        return self.constraints, self.coeff_matrix, self.b
示例#14
0
    def get_original_cost_coeff(self):
        # get cost coefficient in an array
        # the array would correspond to original variables - makes sense!
        # we'll worry about slacks while we input them to main simplex routine, they'll be 0 anyway
        self.cost_coeff = np.zeros((1, len(self.original_variable)))
        # get objective function
        self.obj_function = self.problem.strip().split('\t')[0]
        debug(LEVEL, "Objective function: ", self.obj_function)
        # don't need unencessary words, chuck them out
        obj_function_strip = self.obj_function.replace('MIN',
                                                       '').replace('MAX',
                                                                   '').strip()
        # get coefficients using get_coeff function - check it out for detail
        variable_index = 0
        for variable in self.original_variable:
            self.cost_coeff[0, variable_index] = -1 * self.get_coeff(
                obj_function_strip, variable)
            debug(LOCAL_LEVEL, "variable_index ", variable_index)
            variable_index = variable_index + 1

        # if problem is maximization then cost coefficients will be negative
        self.is_min_problem = "MIN" in self.obj_function
        if self.is_min_problem is False:
            self.cost_coeff = -1. * self.cost_coeff
        debug(LEVEL, "cost coeff:", self.cost_coeff)

        # Lets change it in case we need to take variable sign in account
        if self.variable_sign_needed:
            self.signed_variable = self.original_variable[:]
            debug(LEVEL, " self.signed_variable ", self.signed_variable)
            # -1 * coefficient for negative variables
            for var in self.negative_variables:
                var_index = self.signed_variable.index(var)
                self.cost_coeff[0,
                                var_index] = -1 * self.cost_coeff[0, var_index]
                self.signed_variable[var_index] = var + '-'
                debug(LOCAL_LEVEL, " var_index ", var_index,
                      " signed_variable: ", self.signed_variable, " var: ",
                      var)
            # for free variables replace them by x+ - x-
            for var in self.free_variables:
                var_index = self.signed_variable.index(var)
                self.cost_coeff = np.insert(self.cost_coeff,
                                            var_index + 1,
                                            -1 * self.cost_coeff[0, var_index],
                                            axis=1)
                debug(LOCAL_LEVEL, " var_index ", var_index,
                      " signed_variable: ", self.signed_variable, " var: ",
                      var)
                self.signed_variable[var_index] = var + '+'
                debug(LOCAL_LEVEL, " var_index ", var_index,
                      " signed_variable: ", self.signed_variable, " var: ",
                      var)
                self.signed_variable.insert(var_index + 1, var + '-')
                debug(LOCAL_LEVEL, " var_index ", var_index,
                      " signed_variable: ", self.signed_variable, " var: ",
                      var)

            debug(LEVEL, "signed variable ", self.signed_variable)
示例#15
0
	def get_coeff_matrix(self):
		# get coefficient matrix A and also get RHS b
		self.coeff_matrix = np.zeros((len(self.constraints), len(self.original_variable)))
		self.b = np.zeros((len(self.constraints), 1))
		# b would be anything that is after <=, >= or =
		for i in range(len(self.constraints)):
			self.b[i, 0] = float(Fraction(re.split('<=|>=|=', self.constraints[i])[-1]))
		# generate coefficient matrix using get_coeff with constraints
		j_index = 0
		for var in self.original_variable:
			for i in range(len(self.constraints)):
				self.coeff_matrix[i, j_index] = self.get_coeff(self.constraints[i], var)
				debug(LOCAL_LEVEL, self.constraints[i], " ", var, " ", self.coeff_matrix[i, j_index])
			j_index = j_index+1
		debug(LEVEL, "Coefficient Matrix: \n", self.coeff_matrix, "\n b: \n", self.b)

		# Lets change it in case we need to take variable sign in account
		if self.variable_sign_needed:
			self.signed_variable = self.original_variable[:]
			debug(LEVEL, " self.signed_variable ", self.signed_variable)
			# as before -1* coefficients for negative variables
			for var in self.negative_variables:
				var_index = self.signed_variable.index(var)
				self.coeff_matrix[:, var_index] = -1 * self.coeff_matrix[:, var_index]
				self.signed_variable[var_index] = var+'-'
				debug(LOCAL_LEVEL, " var_index ", var_index, " signed_variable: ", self.signed_variable, " var: ", var)
			# replace free variables with x+ - x-, this essentially means adding extra column to coefficient matrix
			for var in self.free_variables:
				var_index = self.signed_variable.index(var)
				self.coeff_matrix = np.insert(self.coeff_matrix, var_index+1, -1 * self.coeff_matrix[:, var_index], axis=1)
				debug(LOCAL_LEVEL, " var_index ", var_index, " signed_variable: ", self.signed_variable, " var: ", var)
				self.signed_variable[var_index] = var+'+'
				debug(LOCAL_LEVEL, " var_index ", var_index, " signed_variable: ", self.signed_variable, " var: ", var)
				self.signed_variable.insert(var_index+1, var+'-')
				debug(LOCAL_LEVEL, " var_index ", var_index, " signed_variable: ", self.signed_variable, " var: ", var)

			debug(LEVEL, " self.coeff_matrix after sign adjustments \n", self.coeff_matrix)
			# now that we have taken variable signs in account, lets delete non_negativity constraints
			for i in self.constraints_for_sign:
				self.coeff_matrix = np.delete(self.coeff_matrix, i, 0)
				self.constraints.remove(self.constraints[i])
				self.b = np.delete(self.b, i, 0)
			debug(LEVEL, " self.coeff_matrix after sign adjustments and deleting additional rows\n", self.coeff_matrix)
		return self.constraints, self.coeff_matrix, self.b
示例#16
0
	def get_original_cost_coeff(self):
		# get cost coefficient in an array
		# the array would correspond to original variables - makes sense!
		# we'll worry about slacks while we input them to main simplex routine, they'll be 0 anyway
		self.cost_coeff = np.zeros((1, len(self.original_variable)))
		# get objective function
		self.obj_function = self.problem.strip().split('\t')[0]
		debug(LEVEL, "Objective function: ", self.obj_function)
		# don't need unencessary words, chuck them out
		obj_function_strip = self.obj_function.replace('MIN', '').replace('MAX', '').strip()
		# get coefficients using get_coeff function - check it out for detail
		variable_index = 0
		for variable in self.original_variable:
			self.cost_coeff[0, variable_index] = -1 * self.get_coeff(obj_function_strip, variable)
			debug(LOCAL_LEVEL, "variable_index ", variable_index)
			variable_index = variable_index+1

		# if problem is maximization then cost coefficients will be negative
		self.is_min_problem = "MIN" in self.obj_function
		if self.is_min_problem is False:
			self.cost_coeff = -1. * self.cost_coeff
		debug(LEVEL, "cost coeff:", self.cost_coeff)

		# Lets change it in case we need to take variable sign in account
		if self.variable_sign_needed:
			self.signed_variable = self.original_variable[:]
			debug(LEVEL, " self.signed_variable ", self.signed_variable)
			# -1 * coefficient for negative variables
			for var in self.negative_variables:
				var_index = self.signed_variable.index(var)
				self.cost_coeff[0, var_index] = -1 * self.cost_coeff[0, var_index]
				self.signed_variable[var_index] = var+'-'
				debug(LOCAL_LEVEL, " var_index ", var_index, " signed_variable: ", self.signed_variable, " var: ", var)
			# for free variables replace them by x+ - x-
			for var in self.free_variables:
				var_index = self.signed_variable.index(var)
				self.cost_coeff = np.insert(self.cost_coeff, var_index+1, -1 * self.cost_coeff[0, var_index], axis=1)
				debug(LOCAL_LEVEL, " var_index ", var_index, " signed_variable: ", self.signed_variable, " var: ", var)
				self.signed_variable[var_index] = var+'+'
				debug(LOCAL_LEVEL, " var_index ", var_index, " signed_variable: ", self.signed_variable, " var: ", var)
				self.signed_variable.insert(var_index+1, var+'-')
				debug(LOCAL_LEVEL, " var_index ", var_index, " signed_variable: ", self.signed_variable, " var: ", var)

			debug(LEVEL, "signed variable ", self.signed_variable)
示例#17
0
def simplex_solve(coeff_matrix, basic_var_index, b, c, phase, initial_obj_value, should_print_tableau=False):
	# do some sanity testing
	# see if matrix dimensions match before proceeding
	if coeff_matrix.shape[1] is not c.shape[1]:
		print " Coefficient matrix(", coeff_matrix.shape[1], ") and cost coefficient(", c.shape[1], ") must have same number of columns."
		sys.exit()
	if len(coeff_matrix) is not len(b):
		print " Coefficient matrix(", len(coeff_matrix), ") and RHS(", len(b), ") must have same number of rows."
		sys.exit()

	if should_print_tableau:
		LEVEL = 2
	else:
		LEVEL = 0
	# create initial simplex tableau, add cost coefficients and RHS to coefficient matrix
	simplex_tableau = np.append(coeff_matrix, c, 0)
	debug(LOCAL_LEVEL, "Initial Objective Value: ", initial_obj_value)
	b_simplex = np.append(b, np.array([[initial_obj_value]]), 0)
	simplex_tableau = np.append(simplex_tableau, b_simplex, 1)
	debug(LEVEL, "Phase ", phase, " Initial Simplex Tableau:\n", simplex_tableau)

	# assume initial tableau is not optimum
	is_optimum = False
	# get the entering variable, tableau is optimum if we can't get entering variable
	# we use Bland's rule to avoid cycling, check get_entering_variable for more details
	entering_var_index, is_optimum = get_entering_variable(simplex_tableau[-1, :-1])

	# if initial tableau is optimum
	if is_optimum:
		debug(LOCAL_LEVEL, "Optimal achieved and optimum is: ", simplex_tableau[-1, -1])
		return simplex_tableau, basic_var_index

	# start the loop if initial tableau is not optimum
	while not is_optimum:
		# get entering variables column (y) so that we can do minimum ratio test
		# remember to remove row/s for cost coefficients depending on Phase 1 or Phase 2
		y = simplex_tableau[:-1 if phase == 2 else -2, entering_var_index]
		y = y.reshape(len(y), 1)
		debug(LEVEL, "Phase ", phase, " Entering Variable: ", entering_var_index)
		debug(LOCAL_LEVEL, "Phase: ", phase, " Entering Variable: ", entering_var_index, "\nSimplex Tableau:\n", simplex_tableau, "\n y :\n", y)
		# if each element of y is negative then we conclude that problem is unbounded
		# if it happens in Phase 1 then original problem is infeasible
		# if it happens in Phase 2 then we get the extreme direction
		if not (True in (y > 0)):
			if phase == 1:
				print "Problem is infeasible because Phase 1 is unbounded."
				sys.exit()
			elif phase == 2:
				direction = np.zeros((simplex_tableau.shape[1]-1, 1))
				direction[entering_var_index, 0] = 1.
				direction[basic_var_index] = -1*y
				print "Problem is unbounded with one of the direction: \n", direction + 0.
				sys.exit()
		# get current b to do minimum ratio test
		current_b = simplex_tableau[:-1 if phase == 2 else -2, -1].reshape(y.shape)
		# do the ratio test and get leaving variable
		# we use Bland's rule to break the tie, check minimum_ratio_test function for more details
		leaving_var_index, minimum_ratio = minimum_ratio_test(y, current_b, basic_var_index)
		debug(LEVEL, "Phase ", phase, " Leaving Variable: ", basic_var_index[leaving_var_index])
		# update basic variable for next iteration
		basic_var_index[leaving_var_index] = entering_var_index

		# Lets do pivoting and row operations here so that we get simplex tableau for next iteration
		simplex_tableau[leaving_var_index, :] = simplex_tableau[leaving_var_index, :]/simplex_tableau[leaving_var_index, entering_var_index]
		for i in range(len(simplex_tableau)):
			if i != leaving_var_index:
				simplex_tableau[i] = simplex_tableau[i] - simplex_tableau[i, entering_var_index] * simplex_tableau[leaving_var_index]
		debug(LEVEL, "Phase ", phase, " Simplex Tableau: \n", simplex_tableau)
		entering_var_index, is_optimum = get_entering_variable(simplex_tableau[-1, :-1])

	debug(LOCAL_LEVEL, "We have hit optimum folks!\nOptimum Value is: ", simplex_tableau[-1, -1])
	return simplex_tableau, basic_var_index
from SimplexMain import simplex_solve
import numpy as np

# Debug level : 0 - None, 1 - Some, 2 - All (Red) debug statements will be printed
LEVEL = 0
LOCAL_LEVEL = 0

# Config file
# Searches for file named "config" in working directory
# Reads configuration from there
# Read the file named "config" in to understand each configuration
config = ConfigParser.ConfigParser()
if (len(config.read('config')) == 0):
    print "config file is missing from current directory."
    sys.exit()
debug(LOCAL_LEVEL, config.sections())

# Which input method to choose
use_human_readable_config = 'True' in config.get('DEFAULT_CONFIG',
                                                 'use_human_readable_config')
use_standard_form_config = 'True' in config.get('DEFAULT_CONFIG',
                                                'use_standard_form_config')

should_print_tableau = 'True' in config.get('DEFAULT_CONFIG',
                                            'should_print_tableau')

if use_human_readable_config and use_standard_form_config:
    print "Can't use both configuration simultaneously."
    sys.exit()

if not use_human_readable_config and not use_standard_form_config:
from SimplexMain import simplex_solve
import numpy as np

# Debug level : 0 - None, 1 - Some, 2 - All (Red) debug statements will be printed
LEVEL = 0
LOCAL_LEVEL = 0

# Config file
# Searches for file named "config" in working directory
# Reads configuration from there
# Read the file named "config" in to understand each configuration
config = ConfigParser.ConfigParser()
if(len(config.read('config')) == 0):
	print "config file is missing from current directory."
	sys.exit()
debug(LOCAL_LEVEL, config.sections())

# Which input method to choose
use_human_readable_config = 'True' in config.get('DEFAULT_CONFIG', 'use_human_readable_config')
use_standard_form_config = 'True' in config.get('DEFAULT_CONFIG', 'use_standard_form_config')

should_print_tableau = 'True' in config.get('DEFAULT_CONFIG', 'should_print_tableau')

if use_human_readable_config and use_standard_form_config:
	print "Can't use both configuration simultaneously."
	sys.exit()

if not use_human_readable_config and not use_standard_form_config:
	print "Choose atleast one input method."
	sys.exit()