def get_mutable(exp): """ Returns a mutable copy of the given expression if it is immutable Parameters ---------- exp : :class:`Variable` or :class:`Expression` Object to be wrapped Returns ------- r : :class:`Expression` Mutable copy of the expression, if the original is immutable """ if isinstance(exp, sasoptpy.Variable): r = sasoptpy.Expression(exp) r._abstract = exp._abstract elif isinstance(exp, sasoptpy.SetIterator): r = wrap_expression(exp) return r elif isinstance(exp, sasoptpy.Expression): r = exp else: r = sasoptpy.core.Expression(exp) return r
def concat(self, other): r = sasoptpy.Expression() key = (id(self), id(other), '||') ref = [self, other] val = 1 op = '||' r.set_member(key=key, ref=ref, val=val, op=op) return r
def wrap_expression(e, abstract=False): """ Wraps expression inside another expression """ wrapper = sasoptpy.Expression() if hasattr(e, 'get_name') and e.get_name() is not None: name = e.get_name() else: name = get_next_name() if sasoptpy.core.util.is_expression(e): wrapper.set_member(key=name, ref=e, val=1) wrapper._abstract = e._abstract or abstract elif isinstance(e, dict): wrapper._linCoef[name] = {**e} elif isinstance(e, str): wrapper = sasoptpy.Auxiliary(base=e) elif np.isinstance(type(e), np.number): wrapper += e return wrapper
def test(cas_conn): m = so.Model(name='nlpse01', session=cas_conn) x = m.add_variables(range(1, 9), lb=0.1, ub=10, name='x') f = so.Expression(0.4 * (x[1] / x[7])**0.67 + 0.4 * (x[2] / x[8])**0.67 + 10 - x[1] - x[2], name='f') m.set_objective(f, sense=so.MIN, name='f1') m.add_constraint(1 - 0.0588 * x[5] * x[7] - 0.1 * x[1] >= 0, name='c1') m.add_constraint(1 - 0.0588 * x[6] * x[8] - 0.1 * x[1] - 0.1 * x[2] >= 0, name='c2') m.add_constraint(1 - 4 * x[3] / x[5] - 2 / (x[3]**0.71 * x[5]) - 0.0588 * (x[7] / x[3]**1.3) >= 0, name='c3') m.add_constraint(1 - 4 * x[4] / x[6] - 2 / (x[4]**0.71 * x[6]) - 0.0588 * (x[8] / x[4]**1.3) >= 0, name='c4') m.add_constraint(f == [0.1, 4.2], name='frange') x[1].set_init(6) x[2].set_init(3) x[3].set_init(0.4) x[4].set_init(0.2) x[5].set_init(6) x[6].set_init(6) x[7].set_init(1) x[8].set_init(0.5) m.solve(verbose=True, options={'with': 'nlp', 'algorithm': 'activeset'}) print(m.get_problem_summary()) print(m.get_solution_summary()) if m.get_session_type() == 'CAS': print(m.get_solution()[['var', 'value']]) return m.get_objective_value()
def test(cas_conn, sols=False): # Upload data to server first xy_raw = pd.DataFrame([ [0.0, 1.0], [0.5, 0.9], [1.0, 0.7], [1.5, 1.5], [1.9, 2.0], [2.5, 2.4], [3.0, 3.2], [3.5, 2.0], [4.0, 2.7], [4.5, 3.5], [5.0, 1.0], [5.5, 4.0], [6.0, 3.6], [6.6, 2.7], [7.0, 5.7], [7.6, 4.6], [8.5, 6.0], [9.0, 6.8], [10.0, 7.3] ], columns=['x', 'y']) xy_data = cas_conn.upload_frame(xy_raw, casout={'name': 'xy_data', 'replace': True}) # Read observations POINTS, (x, y), xy_table_ref = so.read_table(xy_data, columns=['x', 'y']) # Parameters and variables order = so.Parameter(name='order') beta = so.VariableGroup(so.exp_range(0, order), name='beta') estimate = so.ImplicitVar( (beta[0] + so.quick_sum(beta[k] * x[i] ** k for k in so.exp_range(1, order)) for i in POINTS), name='estimate') surplus = so.VariableGroup(POINTS, name='surplus', lb=0) slack = so.VariableGroup(POINTS, name='slack', lb=0) objective1 = so.Expression( so.quick_sum(surplus[i] + slack[i] for i in POINTS), name='objective1') abs_dev_con = so.ConstraintGroup( (estimate[i] - surplus[i] + slack[i] == y[i] for i in POINTS), name='abs_dev_con') minmax = so.Variable(name='minmax') objective2 = so.Expression(minmax + 0.0, name='objective2') minmax_con = so.ConstraintGroup( (minmax >= surplus[i] + slack[i] for i in POINTS), name='minmax_con') order.set_init(1) L1 = so.Model(name='L1', session=cas_conn) L1.set_objective(objective1, sense=so.MIN) L1.include(POINTS, x, y, xy_table_ref) L1.include(order, beta, estimate, surplus, slack, abs_dev_con) L1.add_statement('print x y estimate surplus slack;', after_solve=True) L1.solve(verbose=True) sol_data1 = L1.response['Print3.PrintTable'].sort_values('x') print(so.get_solution_table(beta)) print(sol_data1.to_string()) Linf = so.Model(name='Linf', session=cas_conn) Linf.include(L1, minmax, minmax_con) Linf.set_objective(objective2, sense=so.MIN) Linf.solve() sol_data2 = Linf.response['Print3.PrintTable'].sort_values('x') print(so.get_solution_table(beta)) print(sol_data2.to_string()) order.set_init(2) L1.solve() sol_data3 = L1.response['Print3.PrintTable'].sort_values('x') print(so.get_solution_table(beta)) print(sol_data3.to_string()) Linf.solve() sol_data4 = Linf.response['Print3.PrintTable'].sort_values('x') print(so.get_solution_table(beta)) print(sol_data4.to_string()) if sols: return (sol_data1, sol_data2, sol_data3, sol_data4) else: return Linf.get_objective_value()
def test(cas_conn): # Input data demand_data = pd.DataFrame([ [0, 2000, 1500, 1000], [1, 1000, 1400, 1000], [2, 500, 2000, 1500], [3, 0, 2500, 2000] ], columns=['period', 'unskilled', 'semiskilled', 'skilled'])\ .set_index(['period']) worker_data = pd.DataFrame( [['unskilled', 0.25, 0.10, 500, 200, 1500, 50, 500], ['semiskilled', 0.20, 0.05, 800, 500, 2000, 50, 400], ['skilled', 0.10, 0.05, 500, 500, 3000, 50, 400]], columns=[ 'worker', 'waste_new', 'waste_old', 'recruit_ub', 'redundancy_cost', 'overmanning_cost', 'shorttime_ub', 'shorttime_cost' ]).set_index(['worker']) retrain_data = pd.DataFrame([ ['unskilled', 'semiskilled', 200, 400], ['semiskilled', 'skilled', math.inf, 500], ], columns=['worker1', 'worker2', 'retrain_ub', 'retrain_cost']).\ set_index(['worker1', 'worker2']) downgrade_data = pd.DataFrame( [['semiskilled', 'unskilled'], ['skilled', 'semiskilled'], ['skilled', 'unskilled']], columns=['worker1', 'worker2']) semiskill_retrain_frac_ub = 0.25 downgrade_leave_frac = 0.5 overmanning_ub = 150 shorttime_frac = 0.5 # Sets WORKERS = worker_data.index.tolist() PERIODS0 = demand_data.index.tolist() PERIODS = PERIODS0[1:] RETRAIN_PAIRS = [i for i, _ in retrain_data.iterrows()] DOWNGRADE_PAIRS = [(row['worker1'], row['worker2']) for _, row in downgrade_data.iterrows()] waste_old = worker_data['waste_old'] waste_new = worker_data['waste_new'] redundancy_cost = worker_data['redundancy_cost'] overmanning_cost = worker_data['overmanning_cost'] shorttime_cost = worker_data['shorttime_cost'] retrain_cost = retrain_data['retrain_cost'].unstack(level=-1) # Initialization m = so.Model(name='manpower_planning', session=cas_conn) # Variables numWorkers = m.add_variables(WORKERS, PERIODS0, name='numWorkers', lb=0) demand0 = demand_data.loc[0] for w in WORKERS: numWorkers[w, 0].set_bounds(lb=demand0[w], ub=demand0[w]) numRecruits = m.add_variables(WORKERS, PERIODS, name='numRecruits', lb=0) worker_ub = worker_data['recruit_ub'] for w in WORKERS: for p in PERIODS: numRecruits[w, p].set_bounds(ub=worker_ub[w]) numRedundant = m.add_variables(WORKERS, PERIODS, name='numRedundant', lb=0) numShortTime = m.add_variables(WORKERS, PERIODS, name='numShortTime', lb=0) shorttime_ub = worker_data['shorttime_ub'] for w in WORKERS: for p in PERIODS: numShortTime.set_bounds(ub=shorttime_ub[w]) numExcess = m.add_variables(WORKERS, PERIODS, name='numExcess', lb=0) retrain_ub = pd.DataFrame() for i in PERIODS: retrain_ub[i] = retrain_data['retrain_ub'] numRetrain = m.add_variables(RETRAIN_PAIRS, PERIODS, name='numRetrain', lb=0, ub=retrain_ub) numDowngrade = m.add_variables(DOWNGRADE_PAIRS, PERIODS, name='numDowngrade', lb=0) # Constraints m.add_constraints( (numWorkers[w, p] - (1 - shorttime_frac) * numShortTime[w, p] - numExcess[w, p] == demand_data.loc[p, w] for w in WORKERS for p in PERIODS), name='demand') m.add_constraints( (numWorkers[w, p] == (1 - waste_old[w]) * numWorkers[w, p - 1] + (1 - waste_new[w]) * numRecruits[w, p] + (1 - waste_old[w]) * numRetrain.sum('*', w, p) + (1 - downgrade_leave_frac) * numDowngrade.sum('*', w, p) - numRetrain.sum(w, '*', p) - numDowngrade.sum(w, '*', p) - numRedundant[w, p] for w in WORKERS for p in PERIODS), name='flow_balance') m.add_constraints((numRetrain['semiskilled', 'skilled', p] <= semiskill_retrain_frac_ub * numWorkers['skilled', p] for p in PERIODS), name='semiskill_retrain') m.add_constraints( (numExcess.sum('*', p) <= overmanning_ub for p in PERIODS), name='overmanning') # Objectives redundancy = so.Expression(numRedundant.sum('*', '*'), name='redundancy') cost = so.Expression( so.expr_sum(redundancy_cost[w] * numRedundant[w, p] + shorttime_cost[w] * numShortTime[w, p] + overmanning_cost[w] * numExcess[w, p] for w in WORKERS for p in PERIODS) + so.expr_sum(retrain_cost.loc[i, j] * numRetrain[i, j, p] for i, j in RETRAIN_PAIRS for p in PERIODS), name='cost') m.set_objective(redundancy, sense=so.MIN, name='redundancy_obj') res = m.solve() if res is not None: print('Redundancy:', redundancy.get_value()) print('Cost:', cost.get_value()) print( so.get_solution_table(numWorkers, numRecruits, numRedundant, numShortTime, numExcess)) print(so.get_solution_table(numRetrain)) print(so.get_solution_table(numDowngrade)) m.set_objective(cost, sense=so.MIN, name='cost_obj') res = m.solve() if res is not None: print('Redundancy:', redundancy.get_value()) print('Cost:', cost.get_value()) print( so.get_solution_table(numWorkers, numRecruits, numRedundant, numShortTime, numExcess)) print(so.get_solution_table(numRetrain)) print(so.get_solution_table(numDowngrade)) return m.get_objective_value()