Beispiel #1
0
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
Beispiel #2
0
 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
Beispiel #3
0
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
Beispiel #4
0
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()
Beispiel #5
0
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()