Пример #1
0
def test_pypower(verbose=False):
    """Run all PYPOWER tests.

    Prints the details of the individual tests if verbose is true.

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    tests = []

    ## PYPOWER base test
    tests.append('t_loadcase')
    # tests.append('t_ext2int2ext')
    tests.append('t_jacobian')
    tests.append('t_hessian')
    tests.append('t_totcost')
    tests.append('t_modcost')
    tests.append('t_hasPQcap')

    # tests.append('t_pips')

    # tests.append('t_qps_pypower')
    # tests.append('t_pf')

    if have_fcn('gurobipy'):
        tests.append('t_opf_dc_gurobi')

    # tests.append('t_opf_pips')
    # tests.append('t_opf_pips_sc')

    if have_fcn('pyipopt'):
        tests.append('t_opf_ipopt')
        tests.append('t_opf_dc_ipopt')

    # tests.append('t_opf_dc_pips')
    # tests.append('t_opf_dc_pips_sc')

    if have_fcn('mosek'):
        tests.append('t_opf_dc_mosek')

    # tests.append('t_opf_userfcns')
    # tests.append('t_runopf_w_res')
    # tests.append('t_dcline')
    # tests.append('t_makePTDF')
    # tests.append('t_makeLODF')
    # tests.append('t_total_load')
    # tests.append('t_scale_load')

    ## smartmarket tests


#    tests.append('t_off2case')
#    tests.append('t_auction_mips')
#    tests.append('t_runmarket')

    t_run_tests(tests, verbose)
Пример #2
0
def test_pypower(verbose=False):
    """Run all PYPOWER tests.

    Prints the details of the individual tests if verbose is true.

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    tests = []

    ## PYPOWER base test
    tests.append('t_loadcase')
    tests.append('t_ext2int2ext')
    tests.append('t_jacobian')
    tests.append('t_hessian')
    tests.append('t_totcost')
    tests.append('t_modcost')
    tests.append('t_hasPQcap')

    tests.append('t_pips')

    tests.append('t_qps_pypower')
    tests.append('t_pf')

    if have_fcn('gurobipy'):
        tests.append('t_opf_dc_gurobi')

    tests.append('t_opf_pips')
    tests.append('t_opf_pips_sc')

    if have_fcn('pyipopt'):
        tests.append('t_opf_ipopt')
        tests.append('t_opf_dc_ipopt')

    tests.append('t_opf_dc_pips')
    tests.append('t_opf_dc_pips_sc')

    if have_fcn('mosek'):
        tests.append('t_opf_dc_mosek')

    tests.append('t_opf_userfcns')
    tests.append('t_runopf_w_res')
    tests.append('t_dcline')
    tests.append('t_makePTDF')
    tests.append('t_makeLODF')
    tests.append('t_total_load')
    tests.append('t_scale_load')

    ## smartmarket tests
#    tests.append('t_off2case')
#    tests.append('t_auction_mips')
#    tests.append('t_runmarket')

    t_run_tests(tests, verbose)
Пример #3
0
def test_opf(verbose=False, *others):
    tests = []

    tests.append('t_loadcase')
    tests.append('t_ext2int2ext')
    tests.append('t_hessian')
    tests.append('t_totcost')
    tests.append('t_modcost')
    tests.append('t_hasPQcap')

    tests.append('t_qps_pypower')

    if have_fcn('gurobipy'):
        tests.append('t_opf_dc_gurobi')

    tests.append('t_opf_dc_pips')
    tests.append('t_opf_dc_pips_sc')

    tests.append('t_pips')

    tests.append('t_opf_pips')
    tests.append('t_opf_pips_sc')

    if have_fcn('pyipopt'):
        tests.append('t_opf_ipopt')
        tests.append('t_opf_dc_ipopt')

    if have_fcn('mosek'):
        tests.append('t_opf_dc_mosek')

    tests.append('t_runopf_w_res')

    tests.append('t_makePTDF')
    tests.append('t_makeLODF')
    tests.append('t_total_load')
    tests.append('t_scale_load')

    tests.extend(others)

    return t_run_tests(tests, verbose)
Пример #4
0
def test_opf(verbose=False, *others):
    tests = []

    tests.append('t_loadcase')
    tests.append('t_ext2int2ext')
    tests.append('t_hessian')
    tests.append('t_totcost')
    tests.append('t_modcost')
    tests.append('t_hasPQcap')

    tests.append('t_qps_pypower')

    if have_fcn('gurobipy'):
        tests.append('t_opf_dc_gurobi')

    tests.append('t_opf_dc_pips')
    tests.append('t_opf_dc_pips_sc')

    tests.append('t_pips')

    tests.append('t_opf_pips')
    tests.append('t_opf_pips_sc')

    if have_fcn('pyipopt'):
        tests.append('t_opf_ipopt')
        tests.append('t_opf_dc_ipopt')

    if have_fcn('mosek'):
        tests.append('t_opf_dc_mosek')

    tests.append('t_runopf_w_res')

    tests.append('t_makePTDF')
    tests.append('t_makeLODF')
    tests.append('t_total_load')
    tests.append('t_scale_load')

    tests.extend(others)

    return t_run_tests(tests, verbose)
Пример #5
0
def test_opf(verbose=False, *others):
    tests = []

    tests.append("t_loadcase")
    tests.append("t_ext2int2ext")
    tests.append("t_hessian")
    tests.append("t_totcost")
    tests.append("t_modcost")
    tests.append("t_hasPQcap")

    tests.append("t_qps_pypower")

    if have_fcn("gurobipy"):
        tests.append("t_opf_dc_gurobi")

    tests.append("t_opf_dc_pips")
    tests.append("t_opf_dc_pips_sc")

    tests.append("t_pips")

    tests.append("t_opf_pips")
    tests.append("t_opf_pips_sc")

    if have_fcn("pyipopt"):
        tests.append("t_opf_ipopt")
        tests.append("t_opf_dc_ipopt")

    if have_fcn("mosek"):
        tests.append("t_opf_dc_mosek")

    tests.append("t_runopf_w_res")

    tests.append("t_makePTDF")
    tests.append("t_makeLODF")
    tests.append("t_total_load")
    tests.append("t_scale_load")

    tests.extend(others)

    return t_run_tests(tests, verbose)
Пример #6
0
def t_qps_pypower(quiet=False):
    """Tests of C{qps_pypower} QP solvers.

    @author: Ray Zimmerman (PSERC Cornell)
    """
    algs = [200, 250, 400, 500, 600, 700]
    names = ['PIPS', 'sc-PIPS', 'IPOPT', 'CPLEX', 'MOSEK', 'Gurobi']
    check = [None, None, 'ipopt', 'cplex', 'mosek', 'gurobipy']

    n = 36
    t_begin(n * len(algs), quiet)

    for k in range(len(algs)):
        if check[k] is not None and not have_fcn(check[k]):
            t_skip(n, '%s not installed' % names[k])
        else:
            opt = {'verbose': 0, 'alg': algs[k]}

            if names[k] == 'PIPS' or names[k] == 'sc-PIPS':
                opt['pips_opt'] = {}
                opt['pips_opt']['comptol'] = 1e-8
            if names[k] == 'CPLEX':
#               alg = 0        ## default uses barrier method with NaN bug in lower lim multipliers
                alg = 2        ## use dual simplex
                ppopt = ppoption(CPLEX_LPMETHOD = alg, CPLEX_QPMETHOD = min([4, alg]))
                opt['cplex_opt'] = cplex_options([], ppopt)

            if names[k] == 'MOSEK':
#                alg = 5        ## use dual simplex
                ppopt = ppoption()
#                ppopt = ppoption(ppopt, MOSEK_LP_ALG = alg)
                ppopt = ppoption(ppopt, MOSEK_GAP_TOL=1e-9)
                opt['mosek_opt'] = mosek_options([], ppopt)

            t = '%s - 3-d LP : ' % names[k]
            ## example from 'doc linprog'
            c = array([-5, -4, -6], float)
            A = sparse([[1, -1,  1],
                        [3,  2,  4],
                        [3,  2,  0]], dtype=float)
            l = None
            u = array([20, 42, 30], float)
            xmin = array([0, 0, 0], float)
            x0 = None
            x, f, s, _, lam = qps_pypower(None, c, A, l, u, xmin, None, None, opt)
            t_is(s, 1, 12, [t, 'success'])
            t_is(x, [0, 15, 3], 6, [t, 'x'])
            t_is(f, -78, 6, [t, 'f'])
            t_is(lam['mu_l'], [0, 0, 0], 13, [t, 'lam.mu_l'])
            t_is(lam['mu_u'], [0, 1.5, 0.5], 9, [t, 'lam.mu_u'])
            t_is(lam['lower'], [1, 0, 0], 9, [t, 'lam.lower'])
            t_is(lam['upper'], zeros(shape(x)), 13, [t, 'lam.upper'])

            t = '%s - unconstrained 3-d quadratic : ' % names[k]
            ## from http://www.akiti.ca/QuadProgEx0Constr.html
            H = sparse([
                [ 5, -2, -1],
                [-2,  4,  3],
                [-1,  3,  5]
            ], dtype=float)
            c = array([2, -35, -47], float)
            x0 = array([0, 0, 0], float)
            x, f, s, _, lam = qps_pypower(H, c, opt=opt)
            t_is(s, 1, 12, [t, 'success'])
            t_is(x, [3, 5, 7], 8, [t, 'x'])
            t_is(f, -249, 13, [t, 'f'])
            t_ok(len(lam['mu_l']) == 0, [t, 'lam.mu_l'])
            t_ok(len(lam['mu_u']) == 0, [t, 'lam.mu_u'])
            t_is(lam['lower'], zeros(shape(x)), 13, [t, 'lam.lower'])
            t_is(lam['upper'], zeros(shape(x)), 13, [t, 'lam.upper'])

            t = '%s - constrained 2-d QP : ' % names[k]
            ## example from 'doc quadprog'
            H = sparse([[ 1, -1],
                        [-1,  2]], dtype=float)
            c = array([-2, -6], float)
            A = sparse([[ 1, 1],
                        [-1, 2],
                        [ 2, 1]], dtype=float)
            l = None
            u = array([2, 2, 3], float)
            xmin = array([0, 0])
            x0 = None
            x, f, s, _, lam = qps_pypower(H, c, A, l, u, xmin, None, x0, opt)
            t_is(s, 1, 12, [t, 'success'])
            t_is(x, array([2., 4.]) / 3, 7, [t, 'x'])
            t_is(f, -74. / 9, 6, [t, 'f'])
            t_is(lam['mu_l'], [0., 0., 0.], 13, [t, 'lam.mu_l'])
            t_is(lam['mu_u'], array([28., 4., 0.]) / 9, 7, [t, 'lam.mu_u'])
            t_is(lam['lower'], zeros(shape(x)), 8, [t, 'lam.lower'])
            t_is(lam['upper'], zeros(shape(x)), 13, [t, 'lam.upper'])

            t = '%s - constrained 4-d QP : ' % names[k]
            ## from http://www.jmu.edu/docs/sasdoc/sashtml/iml/chap8/sect12.htm
            H = sparse([[1003.1,  4.3,     6.3,     5.9],
                        [4.3,     2.2,     2.1,     3.9],
                        [6.3,     2.1,     3.5,     4.8],
                        [5.9,     3.9,     4.8,    10.0]])
            c = zeros(4)
            A = sparse([[   1,       1,       1,       1],
                        [0.17,    0.11,    0.10,    0.18]])
            l = array([1, 0.10])
            u = array([1, Inf])
            xmin = zeros(4)
            x0 = array([1, 0, 0, 1], float)
            x, f, s, _, lam = qps_pypower(H, c, A, l, u, xmin, None, x0, opt)
            t_is(s, 1, 12, [t, 'success'])
            t_is(x, array([0, 2.8, 0.2, 0]) / 3, 5, [t, 'x'])
            t_is(f, 3.29 / 3, 6, [t, 'f'])
            t_is(lam['mu_l'], array([6.58, 0]) / 3, 6, [t, 'lam.mu_l'])
            t_is(lam['mu_u'], [0, 0], 13, [t, 'lam.mu_u'])
            t_is(lam['lower'], [2.24, 0, 0, 1.7667], 4, [t, 'lam.lower'])
            t_is(lam['upper'], zeros(shape(x)), 13, [t, 'lam.upper'])

            t = '%s - (dict) constrained 4-d QP : ' % names[k]
            p = {'H': H, 'A': A, 'l': l, 'u': u, 'xmin': xmin, 'x0': x0, 'opt': opt}
            x, f, s, _, lam = qps_pypower(p)
            t_is(s, 1, 12, [t, 'success'])
            t_is(x, array([0, 2.8, 0.2, 0]) / 3, 5, [t, 'x'])
            t_is(f, 3.29 / 3, 6, [t, 'f'])
            t_is(lam['mu_l'], array([6.58, 0]) / 3, 6, [t, 'lam.mu_l'])
            t_is(lam['mu_u'], [0, 0], 13, [t, 'lam.mu_u'])
            t_is(lam['lower'], [2.24, 0, 0, 1.7667], 4, [t, 'lam.lower'])
            t_is(lam['upper'], zeros(shape(x)), 13, [t, 'lam.upper'])

            t = '%s - infeasible LP : ' % names[k]
            p = {'A': sparse([1, 1]), 'c': array([1, 1]), 'u': array([-1]),
                 'xmin': array([0, 0]), 'opt': opt}
            x, f, s, _, lam = qps_pypower(p)
            t_ok(s <= 0, [t, 'no success'])

    t_end()
Пример #7
0
def dcopf_solver(om, ppopt, out_opt=None):
    """Solves a DC optimal power flow.

    Inputs are an OPF model object, a PYPOWER options dict and
    a dict containing fields (can be empty) for each of the desired
    optional output fields.

    Outputs are a C{results} dict, C{success} flag and C{raw} output dict.

    C{results} is a PYPOWER case dict (ppc) with the usual baseMVA, bus
    branch, gen, gencost fields, along with the following additional
    fields:
        - C{order}      see 'help ext2int' for details of this field
        - C{x}          final value of optimization variables (internal order)
        - C{f}          final objective function value
        - C{mu}         shadow prices on ...
            - C{var}
                - C{l}  lower bounds on variables
                - C{u}  upper bounds on variables
            - C{lin}
                - C{l}  lower bounds on linear constraints
                - C{u}  upper bounds on linear constraints
        - C{g}          (optional) constraint values
        - C{dg}         (optional) constraint 1st derivatives
        - C{df}         (optional) obj fun 1st derivatives (not yet implemented)
        - C{d2f}        (optional) obj fun 2nd derivatives (not yet implemented)

    C{success} is C{True} if solver converged successfully, C{False} otherwise.

    C{raw} is a raw output dict in form returned by MINOS
        - C{xr}     final value of optimization variables
        - C{pimul}  constraint multipliers
        - C{info}   solver specific termination code
        - C{output} solver specific output information

    @see: L{opf}, L{qps_pypower}

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
    Autonoma de Manizales)
    @author: Richard Lincoln
    """
    if out_opt is None:
        out_opt = {}

    ## options
    verbose = ppopt['VERBOSE']
    alg = ppopt['OPF_ALG_DC']

    if alg == 0:
        if have_fcn('cplex'):  ## use CPLEX by default, if available
            alg = 500
        elif have_fcn('mosek'):  ## if not, then MOSEK, if available
            alg = 600
        elif have_fcn('gurobi'):  ## if not, then Gurobi, if available
            alg = 700
        else:  ## otherwise PIPS
            alg = 200

    ## unpack data
    ppc = om.get_ppc()
    baseMVA, bus, gen, branch, gencost = \
        ppc["baseMVA"], ppc["bus"], ppc["gen"], ppc["branch"], ppc["gencost"]
    cp = om.get_cost_params()
    N, H, Cw = cp["N"], cp["H"], cp["Cw"]
    fparm = array(c_[cp["dd"], cp["rh"], cp["kk"], cp["mm"]])
    Bf = om.userdata('Bf')
    Pfinj = om.userdata('Pfinj')
    vv, ll, _, _ = om.get_idx()

    ## problem dimensions
    ipol = find(gencost[:, MODEL] == POLYNOMIAL)  ## polynomial costs
    ipwl = find(gencost[:, MODEL] == PW_LINEAR)  ## piece-wise linear costs
    nb = bus.shape[0]  ## number of buses
    nl = branch.shape[0]  ## number of branches
    nw = N.shape[0]  ## number of general cost vars, w
    ny = om.getN('var', 'y')  ## number of piece-wise linear costs
    nxyz = om.getN('var')  ## total number of control vars of all types

    ## linear constraints & variable bounds
    A, l, u = om.linear_constraints()
    x0, xmin, xmax = om.getv()

    ## set up objective function of the form: f = 1/2 * X'*HH*X + CC'*X
    ## where X = [x;y;z]. First set up as quadratic function of w,
    ## f = 1/2 * w'*HHw*w + CCw'*w, where w = diag(M) * (N*X - Rhat). We
    ## will be building on the (optionally present) user supplied parameters.

    ## piece-wise linear costs
    any_pwl = int(ny > 0)
    if any_pwl:
        # Sum of y vars.
        Npwl = sparse(
            (ones(ny), (zeros(ny), arange(vv["i1"]["y"], vv["iN"]["y"]))),
            (1, nxyz))
        Hpwl = sparse((1, 1))
        Cpwl = array([1])
        fparm_pwl = array([[1, 0, 0, 1]])
    else:
        Npwl = None  #zeros((0, nxyz))
        Hpwl = None  #array([])
        Cpwl = array([])
        fparm_pwl = zeros((0, 4))

    ## quadratic costs
    npol = len(ipol)
    if any(find(gencost[ipol, NCOST] > 3)):
        stderr.write('DC opf cannot handle polynomial costs with higher '
                     'than quadratic order.\n')
    iqdr = find(gencost[ipol, NCOST] == 3)
    ilin = find(gencost[ipol, NCOST] == 2)
    polycf = zeros((npol, 3))  ## quadratic coeffs for Pg
    if len(iqdr) > 0:
        polycf[iqdr, :] = gencost[ipol[iqdr], COST:COST + 3]
    if npol:
        polycf[ilin, 1:3] = gencost[ipol[ilin], COST:COST + 2]
    polycf = dot(polycf, diag([baseMVA**2, baseMVA, 1]))  ## convert to p.u.
    if npol:
        Npol = sparse((ones(npol), (arange(npol), vv["i1"]["Pg"] + ipol)),
                      (npol, nxyz))  # Pg vars
        Hpol = sparse((2 * polycf[:, 0], (arange(npol), arange(npol))),
                      (npol, npol))
    else:
        Npol = None
        Hpol = None
    Cpol = polycf[:, 1]
    fparm_pol = ones((npol, 1)) * array([[1, 0, 0, 1]])

    ## combine with user costs
    NN = vstack(
        [n for n in [Npwl, Npol, N] if n is not None and n.shape[0] > 0],
        "csr")
    # FIXME: Zero dimension sparse matrices.
    if (Hpwl is not None) and any_pwl and (npol + nw):
        Hpwl = hstack([Hpwl, sparse((any_pwl, npol + nw))])
    if Hpol is not None:
        if any_pwl and npol:
            Hpol = hstack([sparse((npol, any_pwl)), Hpol])
        if npol and nw:
            Hpol = hstack([Hpol, sparse((npol, nw))])
    if (H is not None) and nw and (any_pwl + npol):
        H = hstack([sparse((nw, any_pwl + npol)), H])
    HHw = vstack(
        [h for h in [Hpwl, Hpol, H] if h is not None and h.shape[0] > 0],
        "csr")
    CCw = r_[Cpwl, Cpol, Cw]
    ffparm = r_[fparm_pwl, fparm_pol, fparm]

    ## transform quadratic coefficients for w into coefficients for X
    nnw = any_pwl + npol + nw
    M = sparse((ffparm[:, 3], (range(nnw), range(nnw))))
    MR = M * ffparm[:, 1]
    HMR = HHw * MR
    MN = M * NN
    HH = MN.T * HHw * MN
    CC = MN.T * (CCw - HMR)
    C0 = 0.5 * dot(MR, HMR) + sum(polycf[:, 2])  # Constant term of cost.

    ## set up input for QP solver
    opt = {'alg': alg, 'verbose': verbose}
    if (alg == 200) or (alg == 250):
        ## try to select an interior initial point
        Varefs = bus[bus[:, BUS_TYPE] == REF, VA] * (pi / 180.0)

        lb, ub = xmin.copy(), xmax.copy()
        lb[xmin == -Inf] = -1e10  ## replace Inf with numerical proxies
        ub[xmax == Inf] = 1e10
        x0 = (lb + ub) / 2
        # angles set to first reference angle
        x0[vv["i1"]["Va"]:vv["iN"]["Va"]] = Varefs[0]
        if ny > 0:
            ipwl = find(gencost[:, MODEL] == PW_LINEAR)
            # largest y-value in CCV data
            c = gencost.flatten('F')[sub2ind(gencost.shape, ipwl,
                                             NCOST + 2 * gencost[ipwl, NCOST])]
            x0[vv["i1"]["y"]:vv["iN"]["y"]] = max(c) + 0.1 * abs(max(c))

        ## set up options
        feastol = ppopt['PDIPM_FEASTOL']
        gradtol = ppopt['PDIPM_GRADTOL']
        comptol = ppopt['PDIPM_COMPTOL']
        costtol = ppopt['PDIPM_COSTTOL']
        max_it = ppopt['PDIPM_MAX_IT']
        max_red = ppopt['SCPDIPM_RED_IT']
        if feastol == 0:
            feastol = ppopt['OPF_VIOLATION']  ## = OPF_VIOLATION by default
        opt["pips_opt"] = {
            'feastol': feastol,
            'gradtol': gradtol,
            'comptol': comptol,
            'costtol': costtol,
            'max_it': max_it,
            'max_red': max_red,
            'cost_mult': 1
        }
    elif alg == 400:
        opt['ipopt_opt'] = ipopt_options([], ppopt)
    elif alg == 500:
        opt['cplex_opt'] = cplex_options([], ppopt)
    elif alg == 600:
        opt['mosek_opt'] = mosek_options([], ppopt)
    elif alg == 700:
        opt['grb_opt'] = gurobi_options([], ppopt)
    else:
        raise ValueError("Unrecognised solver [%d]." % alg)

    ##-----  run opf  -----
    x, f, info, output, lmbda = \
            qps_pypower(HH, CC, A, l, u, xmin, xmax, x0, opt)
    success = (info == 1)

    ##-----  calculate return values  -----
    if not any(isnan(x)):
        ## update solution data
        Va = x[vv["i1"]["Va"]:vv["iN"]["Va"]]
        Pg = x[vv["i1"]["Pg"]:vv["iN"]["Pg"]]
        f = f + C0

        ## update voltages & generator outputs
        bus[:, VA] = Va * 180 / pi
        gen[:, PG] = Pg * baseMVA

        ## compute branch flows
        branch[:, [QF, QT]] = zeros((nl, 2))
        branch[:, PF] = (Bf * Va + Pfinj) * baseMVA
        branch[:, PT] = -branch[:, PF]

    ## package up results
    mu_l = lmbda["mu_l"]
    mu_u = lmbda["mu_u"]
    muLB = lmbda["lower"]
    muUB = lmbda["upper"]

    ## update Lagrange multipliers
    il = find((branch[:, RATE_A] != 0) & (branch[:, RATE_A] < 1e10))
    bus[:, [LAM_P, LAM_Q, MU_VMIN, MU_VMAX]] = zeros((nb, 4))
    gen[:, [MU_PMIN, MU_PMAX, MU_QMIN, MU_QMAX]] = zeros((gen.shape[0], 4))
    branch[:, [MU_SF, MU_ST]] = zeros((nl, 2))
    bus[:, LAM_P] = (mu_u[ll["i1"]["Pmis"]:ll["iN"]["Pmis"]] -
                     mu_l[ll["i1"]["Pmis"]:ll["iN"]["Pmis"]]) / baseMVA
    branch[il, MU_SF] = mu_u[ll["i1"]["Pf"]:ll["iN"]["Pf"]] / baseMVA
    branch[il, MU_ST] = mu_u[ll["i1"]["Pt"]:ll["iN"]["Pt"]] / baseMVA
    gen[:, MU_PMIN] = muLB[vv["i1"]["Pg"]:vv["iN"]["Pg"]] / baseMVA
    gen[:, MU_PMAX] = muUB[vv["i1"]["Pg"]:vv["iN"]["Pg"]] / baseMVA

    pimul = r_[mu_l - mu_u, -ones(
        (ny > 0)),  ## dummy entry corresponding to linear cost row in A
               muLB - muUB]

    mu = {'var': {'l': muLB, 'u': muUB}, 'lin': {'l': mu_l, 'u': mu_u}}

    results = deepcopy(ppc)
    results["bus"], results["branch"], results["gen"], \
        results["om"], results["x"], results["mu"], results["f"] = \
            bus, branch, gen, om, x, mu, f

    raw = {'xr': x, 'pimul': pimul, 'info': info, 'output': output}

    return results, success, raw
Пример #8
0
def qps_pypower(H, c=None, A=None, l=None, u=None, xmin=None, xmax=None,
                x0=None, opt=None):
    """Quadratic Program Solver for PYPOWER.

    A common wrapper function for various QP solvers.
    Solves the following QP (quadratic programming) problem::

        min 1/2 x'*H*x + c'*x
         x

    subject to::

        l <= A*x <= u       (linear constraints)
        xmin <= x <= xmax   (variable bounds)

    Inputs (all optional except C{H}, C{c}, C{A} and C{l}):
        - C{H} : matrix (possibly sparse) of quadratic cost coefficients
        - C{c} : vector of linear cost coefficients
        - C{A, l, u} : define the optional linear constraints. Default
        values for the elements of C{l} and C{u} are -Inf and Inf,
        respectively.
        - C{xmin}, C{xmax} : optional lower and upper bounds on the
        C{x} variables, defaults are -Inf and Inf, respectively.
        - C{x0} : optional starting value of optimization vector C{x}
        - C{opt} : optional options structure with the following fields,
        all of which are also optional (default values shown in parentheses)
            - C{alg} (0) - determines which solver to use
                -   0 = automatic, first available of BPMPD_MEX, CPLEX,
                        Gurobi, PIPS
                - 100 = BPMPD_MEX
                - 200 = PIPS, Python Interior Point Solver
                pure Python implementation of a primal-dual
                interior point method
                - 250 = PIPS-sc, a step controlled variant of PIPS
                - 300 = Optimization Toolbox, QUADPROG or LINPROG
                - 400 = IPOPT
                - 500 = CPLEX
                - 600 = MOSEK
                - 700 = Gurobi
            - C{verbose} (0) - controls level of progress output displayed
                - 0 = no progress output
                - 1 = some progress output
                - 2 = verbose progress output
            - C{max_it} (0) - maximum number of iterations allowed
                - 0 = use algorithm default
            - C{bp_opt} - options vector for BP
            - C{cplex_opt} - options dict for CPLEX
            - C{grb_opt}   - options dict for gurobipy
            - C{ipopt_opt} - options dict for IPOPT
            - C{pips_opt}  - options dict for L{qps_pips}
            - C{mosek_opt} - options dict for MOSEK
            - C{ot_opt}    - options dict for QUADPROG/LINPROG
        - C{problem} : The inputs can alternatively be supplied in a single
        C{problem} dict with fields corresponding to the input arguments
        described above: C{H, c, A, l, u, xmin, xmax, x0, opt}

    Outputs:
        - C{x} : solution vector
        - C{f} : final objective function value
        - C{exitflag} : exit flag
            - 1 = converged
            - 0 or negative values = algorithm specific failure codes
        - C{output} : output struct with the following fields:
            - C{alg} - algorithm code of solver used
            - (others) - algorithm specific fields
        - C{lmbda} : dict containing the Langrange and Kuhn-Tucker
        multipliers on the constraints, with fields:
            - C{mu_l} - lower (left-hand) limit on linear constraints
            - C{mu_u} - upper (right-hand) limit on linear constraints
            - C{lower} - lower bound on optimization variables
            - C{upper} - upper bound on optimization variables


    Example from U{http://www.uc.edu/sashtml/iml/chap8/sect12.htm}:

        >>> from numpy import array, zeros, Inf
        >>> from scipy.sparse import csr_matrix
        >>> H = csr_matrix(array([[1003.1,  4.3,     6.3,     5.9],
        ...                       [4.3,     2.2,     2.1,     3.9],
        ...                       [6.3,     2.1,     3.5,     4.8],
        ...                       [5.9,     3.9,     4.8,     10 ]]))
        >>> c = zeros(4)
        >>> A = csr_matrix(array([[1,       1,       1,       1   ],
        ...                       [0.17,    0.11,    0.10,    0.18]]))
        >>> l = array([1, 0.10])
        >>> u = array([1, Inf])
        >>> xmin = zeros(4)
        >>> xmax = None
        >>> x0 = array([1, 0, 0, 1])
        >>> solution = qps_pips(H, c, A, l, u, xmin, xmax, x0)
        >>> round(solution["f"], 11) == 1.09666678128
        True
        >>> solution["converged"]
        True
        >>> solution["output"]["iterations"]
        10

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    ##----- input argument handling  -----
    ## gather inputs
    if isinstance(H, dict):       ## problem struct
        p = H
        if 'opt' in p: opt = p['opt']
        if 'x0' in p: x0 = p['x0']
        if 'xmax' in p: xmax = p['xmax']
        if 'xmin' in p: xmin = p['xmin']
        if 'u' in p: u = p['u']
        if 'l' in p: l = p['l']
        if 'A' in p: A = p['A']
        if 'c' in p: c = p['c']
        if 'H' in p: H = p['H']
    else:                         ## individual args
#        assert H is not None  zero dimensional sparse matrices not supported
        assert c is not None
#        assert A is not None  zero dimensional sparse matrices not supported
#        assert l is not None  no lower bounds indicated by None

    if opt is None:
        opt = {}
#    if x0 is None:
#        x0 = array([])
#    if xmax is None:
#        xmax = array([])
#    if xmin is None:
#        xmin = array([])

    ## default options
    if 'alg' in opt:
        alg = opt['alg']
    else:
        alg = 0

    if 'verbose' in opt:
        verbose = opt['verbose']
    else:
        verbose = 0

    if alg == 0:
        if have_fcn('cplex'):        ## use CPLEX by default, if available
            alg = 500
        elif have_fcn('mosek'):      ## if not, then MOSEK, if available
            alg = 600
        elif have_fcn('gurobipy'):   ## if not, then Gurobi, if available
            alg = 700
        else:                        ## otherwise PIPS
            alg = 200

    ##----- call the appropriate solver  -----
    if alg == 200 or alg == 250:    ## use MIPS or sc-MIPS
        ## set up options
        if 'pips_opt' in opt:
            pips_opt = opt['pips_opt']
        else:
            pips_opt = {}

        if 'max_it' in opt:
            pips_opt['max_it'] = opt['max_it']

        if alg == 200:
            pips_opt['step_control'] = False
        else:
            pips_opt['step_control'] = True

        pips_opt['verbose'] = verbose

        ## call solver
        x, f, eflag, output, lmbda = \
            qps_pips(H, c, A, l, u, xmin, xmax, x0, pips_opt)
    elif alg == 400:                    ## use IPOPT
        x, f, eflag, output, lmbda = \
            qps_ipopt(H, c, A, l, u, xmin, xmax, x0, opt)
    elif alg == 500:                    ## use CPLEX
        x, f, eflag, output, lmbda = \
            qps_cplex(H, c, A, l, u, xmin, xmax, x0, opt)
    elif alg == 600:                    ## use MOSEK
        x, f, eflag, output, lmbda = \
            qps_mosek(H, c, A, l, u, xmin, xmax, x0, opt)
    elif 700:                           ## use Gurobi
        x, f, eflag, output, lmbda = \
            qps_gurobi(H, c, A, l, u, xmin, xmax, x0, opt)
    else:
        sys.stderr.write('qps_pypower: %d is not a valid algorithm code\n', alg)

    if 'alg' not in output:
        output['alg'] = alg

    return x, f, eflag, output, lmbda
Пример #9
0
def dcopf_solver(om, ppopt, out_opt=None):
    """Solves a DC optimal power flow.

    Inputs are an OPF model object, a PYPOWER options dict and
    a dict containing fields (can be empty) for each of the desired
    optional output fields.

    Outputs are a C{results} dict, C{success} flag and C{raw} output dict.

    C{results} is a PYPOWER case dict (ppc) with the usual baseMVA, bus
    branch, gen, gencost fields, along with the following additional
    fields:
        - C{order}      see 'help ext2int' for details of this field
        - C{x}          final value of optimization variables (internal order)
        - C{f}          final objective function value
        - C{mu}         shadow prices on ...
            - C{var}
                - C{l}  lower bounds on variables
                - C{u}  upper bounds on variables
            - C{lin}
                - C{l}  lower bounds on linear constraints
                - C{u}  upper bounds on linear constraints
        - C{g}          (optional) constraint values
        - C{dg}         (optional) constraint 1st derivatives
        - C{df}         (optional) obj fun 1st derivatives (not yet implemented)
        - C{d2f}        (optional) obj fun 2nd derivatives (not yet implemented)

    C{success} is C{True} if solver converged successfully, C{False} otherwise.

    C{raw} is a raw output dict in form returned by MINOS
        - C{xr}     final value of optimization variables
        - C{pimul}  constraint multipliers
        - C{info}   solver specific termination code
        - C{output} solver specific output information

    @see: L{opf}, L{qps_pypower}

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
    Autonoma de Manizales)
    """
    if out_opt is None:
        out_opt = {}

    ## options
    verbose = ppopt['VERBOSE']
    alg     = ppopt['OPF_ALG_DC']

    if alg == 0:
        if have_fcn('cplex'):        ## use CPLEX by default, if available
            alg = 500
        elif have_fcn('mosek'):      ## if not, then MOSEK, if available
            alg = 600
        elif have_fcn('gurobi'):     ## if not, then Gurobi, if available
            alg = 700
        else:                        ## otherwise PIPS
            alg = 200

    ## unpack data
    ppc = om.get_ppc()
    baseMVA, bus, gen, branch, gencost = \
        ppc["baseMVA"], ppc["bus"], ppc["gen"], ppc["branch"], ppc["gencost"]
    cp = om.get_cost_params()
    N, H, Cw = cp["N"], cp["H"], cp["Cw"]
    fparm = array(c_[cp["dd"], cp["rh"], cp["kk"], cp["mm"]])
    Bf = om.userdata('Bf')
    Pfinj = om.userdata('Pfinj')
    vv, ll, _, _ = om.get_idx()

    ## problem dimensions
    ipol = find(gencost[:, MODEL] == POLYNOMIAL) ## polynomial costs
    ipwl = find(gencost[:, MODEL] == PW_LINEAR)  ## piece-wise linear costs
    nb = bus.shape[0]              ## number of buses
    nl = branch.shape[0]           ## number of branches
    nw = N.shape[0]                ## number of general cost vars, w
    ny = om.getN('var', 'y')       ## number of piece-wise linear costs
    nxyz = om.getN('var')          ## total number of control vars of all types

    ## linear constraints & variable bounds
    A, l, u = om.linear_constraints()
    x0, xmin, xmax = om.getv()

    ## set up objective function of the form: f = 1/2 * X'*HH*X + CC'*X
    ## where X = [x;y;z]. First set up as quadratic function of w,
    ## f = 1/2 * w'*HHw*w + CCw'*w, where w = diag(M) * (N*X - Rhat). We
    ## will be building on the (optionally present) user supplied parameters.

    ## piece-wise linear costs
    any_pwl = int(ny > 0)
    if any_pwl:
        # Sum of y vars.
        Npwl = sparse((ones(ny), (zeros(ny), arange(vv["i1"]["y"], vv["iN"]["y"]))), (1, nxyz))
        Hpwl = sparse((1, 1))
        Cpwl = array([1])
        fparm_pwl = array([[1, 0, 0, 1]])
    else:
        Npwl = None#zeros((0, nxyz))
        Hpwl = None#array([])
        Cpwl = array([])
        fparm_pwl = zeros((0, 4))

    ## quadratic costs
    npol = len(ipol)
    if any(find(gencost[ipol, NCOST] > 3)):
        stderr.write('DC opf cannot handle polynomial costs with higher '
                     'than quadratic order.\n')
    iqdr = find(gencost[ipol, NCOST] == 3)
    ilin = find(gencost[ipol, NCOST] == 2)
    polycf = zeros((npol, 3))         ## quadratic coeffs for Pg
    if len(iqdr) > 0:
        polycf[iqdr, :] = gencost[ipol[iqdr], COST:COST + 3]
    if npol:
        polycf[ilin, 1:3] = gencost[ipol[ilin], COST:COST + 2]
    polycf = dot(polycf, diag([ baseMVA**2, baseMVA, 1]))     ## convert to p.u.
    if npol:
        Npol = sparse((ones(npol), (arange(npol), vv["i1"]["Pg"] + ipol)),
                      (npol, nxyz))  # Pg vars
        Hpol = sparse((2 * polycf[:, 0], (arange(npol), arange(npol))),
                      (npol, npol))
    else:
        Npol = None
        Hpol = None
    Cpol = polycf[:, 1]
    fparm_pol = ones((npol, 1)) * array([[1, 0, 0, 1]])

    ## combine with user costs
    NN = vstack([n for n in [Npwl, Npol, N] if n is not None and n.shape[0] > 0], "csr")
    # FIXME: Zero dimension sparse matrices.
    if (Hpwl is not None) and any_pwl and (npol + nw):
        Hpwl = hstack([Hpwl, sparse((any_pwl, npol + nw))])
    if Hpol is not None:
        if any_pwl and npol:
            Hpol = hstack([sparse((npol, any_pwl)), Hpol])
        if npol and nw:
            Hpol = hstack([Hpol, sparse((npol, nw))])
    if (H is not None) and nw and (any_pwl + npol):
        H = hstack([sparse((nw, any_pwl + npol)), H])
    HHw = vstack([h for h in [Hpwl, Hpol, H] if h is not None and h.shape[0] > 0], "csr")
    CCw = r_[Cpwl, Cpol, Cw]
    ffparm = r_[fparm_pwl, fparm_pol, fparm]

    ## transform quadratic coefficients for w into coefficients for X
    nnw = any_pwl + npol + nw
    M = sparse((ffparm[:, 3], (range(nnw), range(nnw))))
    MR = M * ffparm[:, 1]
    HMR = HHw * MR
    MN = M * NN
    HH = MN.T * HHw * MN
    CC = MN.T * (CCw - HMR)
    C0 = 0.5 * dot(MR, HMR) + sum(polycf[:, 2])  # Constant term of cost.

    ## set up input for QP solver
    opt = {'alg': alg, 'verbose': verbose}
    if (alg == 200) or (alg == 250):
        ## try to select an interior initial point
        Varefs = bus[bus[:, BUS_TYPE] == REF, VA] * (pi / 180.0)

        lb, ub = xmin.copy(), xmax.copy()
        lb[xmin == -Inf] = -1e10   ## replace Inf with numerical proxies
        ub[xmax ==  Inf] =  1e10
        x0 = (lb + ub) / 2;
        # angles set to first reference angle
        x0[vv["i1"]["Va"]:vv["iN"]["Va"]] = Varefs[0]
        if ny > 0:
            ipwl = find(gencost[:, MODEL] == PW_LINEAR)
            # largest y-value in CCV data
            c = gencost.flatten('F')[sub2ind(gencost.shape, ipwl,
                                NCOST + 2 * gencost[ipwl, NCOST])]
            x0[vv["i1"]["y"]:vv["iN"]["y"]] = max(c) + 0.1 * abs(max(c))

        ## set up options
        feastol = ppopt['PDIPM_FEASTOL']
        gradtol = ppopt['PDIPM_GRADTOL']
        comptol = ppopt['PDIPM_COMPTOL']
        costtol = ppopt['PDIPM_COSTTOL']
        max_it  = ppopt['PDIPM_MAX_IT']
        max_red = ppopt['SCPDIPM_RED_IT']
        if feastol == 0:
            feastol = ppopt['OPF_VIOLATION']    ## = OPF_VIOLATION by default
        opt["pips_opt"] = {  'feastol': feastol,
                             'gradtol': gradtol,
                             'comptol': comptol,
                             'costtol': costtol,
                             'max_it':  max_it,
                             'max_red': max_red,
                             'cost_mult': 1  }
    elif alg == 400:
        opt['ipopt_opt'] = ipopt_options([], ppopt)
    elif alg == 500:
        opt['cplex_opt'] = cplex_options([], ppopt)
    elif alg == 600:
        opt['mosek_opt'] = mosek_options([], ppopt)
    elif alg == 700:
        opt['grb_opt'] = gurobi_options([], ppopt)
    else:
        raise ValueError("Unrecognised solver [%d]." % alg)

    ##-----  run opf  -----
    x, f, info, output, lmbda = \
            qps_pypower(HH, CC, A, l, u, xmin, xmax, x0, opt)
    success = (info == 1)

    ##-----  calculate return values  -----
    if not any(isnan(x)):
        ## update solution data
        Va = x[vv["i1"]["Va"]:vv["iN"]["Va"]]
        Pg = x[vv["i1"]["Pg"]:vv["iN"]["Pg"]]
        f = f + C0

        ## update voltages & generator outputs
        bus[:, VA] = Va * 180 / pi
        gen[:, PG] = Pg * baseMVA

        ## compute branch flows
        branch[:, [QF, QT]] = zeros((nl, 2))
        branch[:, PF] = (Bf * Va + Pfinj) * baseMVA
        branch[:, PT] = -branch[:, PF]

    ## package up results
    mu_l = lmbda["mu_l"]
    mu_u = lmbda["mu_u"]
    muLB = lmbda["lower"]
    muUB = lmbda["upper"]

    ## update Lagrange multipliers
    il = find((branch[:, RATE_A] != 0) & (branch[:, RATE_A] < 1e10))
    bus[:, [LAM_P, LAM_Q, MU_VMIN, MU_VMAX]] = zeros((nb, 4))
    gen[:, [MU_PMIN, MU_PMAX, MU_QMIN, MU_QMAX]] = zeros((gen.shape[0], 4))
    branch[:, [MU_SF, MU_ST]] = zeros((nl, 2))
    bus[:, LAM_P]       = (mu_u[ll["i1"]["Pmis"]:ll["iN"]["Pmis"]] -
                           mu_l[ll["i1"]["Pmis"]:ll["iN"]["Pmis"]]) / baseMVA
    branch[il, MU_SF]   = mu_u[ll["i1"]["Pf"]:ll["iN"]["Pf"]] / baseMVA
    branch[il, MU_ST]   = mu_u[ll["i1"]["Pt"]:ll["iN"]["Pt"]] / baseMVA
    gen[:, MU_PMIN]     = muLB[vv["i1"]["Pg"]:vv["iN"]["Pg"]] / baseMVA
    gen[:, MU_PMAX]     = muUB[vv["i1"]["Pg"]:vv["iN"]["Pg"]] / baseMVA

    pimul = r_[
      mu_l - mu_u,
     -ones(int(ny > 0)), ## dummy entry corresponding to linear cost row in A
      muLB - muUB
    ]

    mu = { 'var': {'l': muLB, 'u': muUB},
           'lin': {'l': mu_l, 'u': mu_u} }

    results = deepcopy(ppc)
    results["bus"], results["branch"], results["gen"], \
        results["om"], results["x"], results["mu"], results["f"] = \
            bus, branch, gen, om, x, mu, f

    raw = {'xr': x, 'pimul': pimul, 'info': info, 'output': output}

    return results, success, raw
Пример #10
0
def t_opf_dc_gurobi(quiet=False):
    """Tests for DC optimal power flow using Gurobi solver.
    """
    algs = [0, 1, 2, 3, 4]
    num_tests = 23 * len(algs)

    t_begin(num_tests, quiet)

    tdir = dirname(__file__)
    casefile = join(tdir, 't_case9_opf')
    if quiet:
        verbose = False
    else:
        verbose = False

    ppopt = ppoption('OUT_ALL', 0, 'VERBOSE', verbose)
    ppopt = ppoption(ppopt, 'OPF_ALG_DC', 700)

    ## run DC OPF
    if have_fcn('gurobipy'):
        for k in range(len(algs)):
            ppopt = ppoption(ppopt, 'GRB_METHOD', algs[k])
            methods = [
                'automatic',
                'primal simplex',
                'dual simplex',
                'barrier',
                'concurrent',
                'deterministic concurrent',
            ]
            t0 = 'DC OPF (Gurobi %s): ' % methods[k]

            ## set up indices
            ib_data = r_[arange(BUS_AREA + 1), arange(BASE_KV, VMIN + 1)]
            ib_voltage = arange(VM, VA + 1)
            ib_lam = arange(LAM_P, LAM_Q + 1)
            ib_mu = arange(MU_VMAX, MU_VMIN + 1)
            ig_data = r_[[GEN_BUS, QMAX, QMIN], arange(MBASE, APF + 1)]
            ig_disp = array([PG, QG, VG])
            ig_mu = arange(MU_PMAX, MU_QMIN + 1)
            ibr_data = arange(ANGMAX + 1)
            ibr_flow = arange(PF, QT + 1)
            ibr_mu = array([MU_SF, MU_ST])
            #ibr_angmu   = array([MU_ANGMIN, MU_ANGMAX])

            ## get solved DC power flow case from MAT-file
            ## defines bus_soln, gen_soln, branch_soln, f_soln
            soln9_dcopf = loadmat(join(tdir, 'soln9_dcopf.mat'),
                                  struct_as_record=True)
            bus_soln, gen_soln, branch_soln, f_soln = \
                    soln9_dcopf['bus_soln'], soln9_dcopf['gen_soln'], \
                    soln9_dcopf['branch_soln'], soln9_dcopf['f_soln']

            ## run OPF
            t = t0
            r = rundcopf(casefile, ppopt)
            bus, gen, branch, f, success = \
                    r['bus'], r['gen'], r['branch'], r['f'], r['success']
            t_ok(success, [t, 'success'])
            t_is(f, f_soln, 3, [t, 'f'])
            t_is(bus[:, ib_data], bus_soln[:, ib_data], 10, [t, 'bus data'])
            t_is(bus[:, ib_voltage], bus_soln[:, ib_voltage], 3,
                 [t, 'bus voltage'])
            t_is(bus[:, ib_lam], bus_soln[:, ib_lam], 3, [t, 'bus lambda'])
            t_is(bus[:, ib_mu], bus_soln[:, ib_mu], 2, [t, 'bus mu'])
            t_is(gen[:, ig_data], gen_soln[:, ig_data], 10, [t, 'gen data'])
            t_is(gen[:, ig_disp], gen_soln[:, ig_disp], 3, [t, 'gen dispatch'])
            t_is(gen[:, ig_mu], gen_soln[:, ig_mu], 3, [t, 'gen mu'])
            t_is(branch[:, ibr_data], branch_soln[:, ibr_data], 10,
                 [t, 'branch data'])
            t_is(branch[:, ibr_flow], branch_soln[:, ibr_flow], 3,
                 [t, 'branch flow'])
            t_is(branch[:, ibr_mu], branch_soln[:, ibr_mu], 2,
                 [t, 'branch mu'])

            ##-----  run OPF with extra linear user constraints & costs  -----
            ## two new z variables
            ##      0 <= z1, P2 - P1 <= z1
            ##      0 <= z2, P2 - P3 <= z2
            ## with A and N sized for DC opf
            ppc = loadcase(casefile)
            row = [0, 0, 0, 1, 1, 1]
            col = [9, 10, 12, 10, 11, 13]
            ppc['A'] = sparse(([-1, 1, -1, 1, -1, -1], (row, col)), (2, 14))
            ppc['u'] = array([0, 0])
            ppc['l'] = array([-Inf, -Inf])
            ppc['zl'] = array([0, 0])

            ppc['N'] = sparse(([1, 1], ([0, 1], [12, 13])),
                              (2, 14))  ## new z variables only
            ppc['fparm'] = ones((2, 1)) * array([[1, 0, 0, 1]])  ## w = r = z
            ppc['H'] = sparse((2, 2))  ## no quadratic term
            ppc['Cw'] = array([1000, 1])

            t = ''.join([t0, 'w/extra constraints & costs 1 : '])
            r = rundcopf(ppc, ppopt)
            t_ok(r['success'], [t, 'success'])
            t_is(r['gen'][0, PG], 116.15974, 4, [t, 'Pg1 = 116.15974'])
            t_is(r['gen'][1, PG], 116.15974, 4, [t, 'Pg2 = 116.15974'])
            t_is(r['var']['val']['z'], [0, 0.3348], 4, [t, 'user vars'])
            t_is(r['cost']['usr'], 0.3348, 3, [t, 'user costs'])

            ## with A and N sized for AC opf
            ppc = loadcase(casefile)
            row = [0, 0, 0, 1, 1, 1]
            col = [18, 19, 24, 19, 20, 25]
            ppc['A'] = sparse(([-1, 1, -1, 1, -1, -1], (row, col)), (2, 26))
            ppc['u'] = array([0, 0])
            ppc['l'] = array([-Inf, -Inf])
            ppc['zl'] = array([0, 0])

            ppc['N'] = sparse(([1, 1], ([0, 1], [24, 25])),
                              (2, 26))  ## new z variables only
            ppc['fparm'] = ones((2, 1)) * array([[1, 0, 0, 1]])  ## w = r = z
            ppc['H'] = sparse((2, 2))  ## no quadratic term
            ppc['Cw'] = array([1000, 1])

            t = ''.join([t0, 'w/extra constraints & costs 2 : '])
            r = rundcopf(ppc, ppopt)
            t_ok(r['success'], [t, 'success'])
            t_is(r['gen'][0, PG], 116.15974, 4, [t, 'Pg1 = 116.15974'])
            t_is(r['gen'][1, PG], 116.15974, 4, [t, 'Pg2 = 116.15974'])
            t_is(r['var']['val']['z'], [0, 0.3348], 4, [t, 'user vars'])
            t_is(r['cost']['usr'], 0.3348, 3, [t, 'user costs'])

            t = ''.join([t0, 'infeasible : '])
            ## with A and N sized for DC opf
            ppc = loadcase(casefile)
            ppc['A'] = sparse(([1, 1], ([0, 0], [9, 10])),
                              (1, 14))  ## Pg1 + Pg2
            ppc['u'] = array([Inf])
            ppc['l'] = array([600])
            r = rundcopf(ppc, ppopt)
            t_ok(not r['success'], [t, 'no success'])
    else:
        t_skip(num_tests, 'Gurobi not available')

    t_end()
def t_opf_dc_gurobi(quiet=False):
    """Tests for DC optimal power flow using Gurobi solver.
    """
    algs = [0, 1, 2, 3, 4]
    num_tests = 23 * len(algs)

    t_begin(num_tests, quiet)

    tdir = dirname(__file__)
    casefile = join(tdir, 't_case9_opf')
    if quiet:
        verbose = False
    else:
        verbose = False

    ppopt = ppoption('OUT_ALL', 0, 'VERBOSE', verbose);
    ppopt = ppoption(ppopt, 'OPF_ALG_DC', 700);

    ## run DC OPF
    if have_fcn('gurobipy'):
        for k in range(len(algs)):
            ppopt = ppoption(ppopt, 'GRB_METHOD', algs[k])
            methods = [
                'automatic',
                'primal simplex',
                'dual simplex',
                'barrier',
                'concurrent',
                'deterministic concurrent',
            ]
            t0 = 'DC OPF (Gurobi %s): ' % methods[k]

            ## set up indices
            ib_data     = r_[arange(BUS_AREA + 1), arange(BASE_KV, VMIN + 1)]
            ib_voltage  = arange(VM, VA + 1)
            ib_lam      = arange(LAM_P, LAM_Q + 1)
            ib_mu       = arange(MU_VMAX, MU_VMIN + 1)
            ig_data     = r_[[GEN_BUS, QMAX, QMIN], arange(MBASE, APF + 1)]
            ig_disp     = array([PG, QG, VG])
            ig_mu       = arange(MU_PMAX, MU_QMIN + 1)
            ibr_data    = arange(ANGMAX + 1)
            ibr_flow    = arange(PF, QT + 1)
            ibr_mu      = array([MU_SF, MU_ST])
            #ibr_angmu   = array([MU_ANGMIN, MU_ANGMAX])

            ## get solved DC power flow case from MAT-file
            ## defines bus_soln, gen_soln, branch_soln, f_soln
            soln9_dcopf = loadmat(join(tdir, 'soln9_dcopf.mat'),
                    struct_as_record=True)
            bus_soln, gen_soln, branch_soln, f_soln = \
                    soln9_dcopf['bus_soln'], soln9_dcopf['gen_soln'], \
                    soln9_dcopf['branch_soln'], soln9_dcopf['f_soln']

            ## run OPF
            t = t0
            r = rundcopf(casefile, ppopt)
            bus, gen, branch, f, success = \
                    r['bus'], r['gen'], r['branch'], r['f'], r['success']
            t_ok(success, [t, 'success'])
            t_is(f, f_soln, 3, [t, 'f'])
            t_is(   bus[:, ib_data   ],    bus_soln[:, ib_data   ], 10, [t, 'bus data'])
            t_is(   bus[:, ib_voltage],    bus_soln[:, ib_voltage],  3, [t, 'bus voltage'])
            t_is(   bus[:, ib_lam    ],    bus_soln[:, ib_lam    ],  3, [t, 'bus lambda'])
            t_is(   bus[:, ib_mu     ],    bus_soln[:, ib_mu     ],  2, [t, 'bus mu'])
            t_is(   gen[:, ig_data   ],    gen_soln[:, ig_data   ], 10, [t, 'gen data'])
            t_is(   gen[:, ig_disp   ],    gen_soln[:, ig_disp   ],  3, [t, 'gen dispatch'])
            t_is(   gen[:, ig_mu     ],    gen_soln[:, ig_mu     ],  3, [t, 'gen mu'])
            t_is(branch[:, ibr_data  ], branch_soln[:, ibr_data  ], 10, [t, 'branch data'])
            t_is(branch[:, ibr_flow  ], branch_soln[:, ibr_flow  ],  3, [t, 'branch flow'])
            t_is(branch[:, ibr_mu    ], branch_soln[:, ibr_mu    ],  2, [t, 'branch mu'])

            ##-----  run OPF with extra linear user constraints & costs  -----
            ## two new z variables
            ##      0 <= z1, P2 - P1 <= z1
            ##      0 <= z2, P2 - P3 <= z2
            ## with A and N sized for DC opf
            ppc = loadcase(casefile)
            row = [0, 0, 0, 1, 1, 1]
            col = [9, 10, 12, 10, 11, 13]
            ppc['A'] = sparse(([-1, 1, -1, 1, -1, -1], (row, col)), (2, 14))
            ppc['u'] = array([0, 0])
            ppc['l'] = array([-Inf, -Inf])
            ppc['zl'] = array([0, 0])

            ppc['N'] = sparse(([1, 1], ([0, 1], [12, 13])), (2, 14))  ## new z variables only
            ppc['fparm'] = ones((2, 1)) * array([[1, 0, 0, 1]])       ## w = r = z
            ppc['H'] = sparse((2, 2))                            ## no quadratic term
            ppc['Cw'] = array([1000, 1])

            t = ''.join([t0, 'w/extra constraints & costs 1 : '])
            r = rundcopf(ppc, ppopt)
            t_ok(r['success'], [t, 'success'])
            t_is(r['gen'][0, PG], 116.15974, 4, [t, 'Pg1 = 116.15974'])
            t_is(r['gen'][1, PG], 116.15974, 4, [t, 'Pg2 = 116.15974'])
            t_is(r['var']['val']['z'], [0, 0.3348], 4, [t, 'user vars'])
            t_is(r['cost']['usr'], 0.3348, 3, [t, 'user costs'])

            ## with A and N sized for AC opf
            ppc = loadcase(casefile)
            row = [0, 0, 0, 1, 1, 1]
            col = [18, 19, 24, 19, 20, 25]
            ppc['A'] = sparse(([-1, 1, -1, 1, -1, -1], (row, col)), (2, 26))
            ppc['u'] = array([0, 0])
            ppc['l'] = array([-Inf, -Inf])
            ppc['zl'] = array([0, 0])

            ppc['N'] = sparse(([1, 1], ([0, 1], [24, 25])), (2, 26))   ## new z variables only
            ppc['fparm'] = ones((2, 1)) * array([[1, 0, 0, 1]])        ## w = r = z
            ppc['H'] = sparse((2, 2))                            ## no quadratic term
            ppc['Cw'] = array([1000, 1])

            t = ''.join([t0, 'w/extra constraints & costs 2 : '])
            r = rundcopf(ppc, ppopt)
            t_ok(r['success'], [t, 'success'])
            t_is(r['gen'][0, PG], 116.15974, 4, [t, 'Pg1 = 116.15974'])
            t_is(r['gen'][1, PG], 116.15974, 4, [t, 'Pg2 = 116.15974'])
            t_is(r['var']['val']['z'], [0, 0.3348], 4, [t, 'user vars'])
            t_is(r['cost']['usr'], 0.3348, 3, [t, 'user costs'])

            t = ''.join([t0, 'infeasible : '])
            ## with A and N sized for DC opf
            ppc = loadcase(casefile)
            ppc['A'] = sparse(([1, 1], ([0, 0], [9, 10])), (1, 14))   ## Pg1 + Pg2
            ppc['u'] = array([Inf])
            ppc['l'] = array([600])
            r = rundcopf(ppc, ppopt)
            t_ok(not r['success'], [t, 'no success'])
    else:
        t_skip(num_tests, 'Gurobi not available')

    t_end()
Пример #12
0
def t_qps_pypower(quiet=False):
    """Tests of C{qps_pypower} QP solvers.

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    algs = [200, 250, 400, 500, 600, 700]
    names = ['PIPS', 'sc-PIPS', 'IPOPT', 'CPLEX', 'MOSEK', 'Gurobi']
    check = [None, None, 'ipopt', 'cplex', 'mosek', 'gurobipy']

    n = 36
    t_begin(n * len(algs), quiet)

    for k in range(len(algs)):
        if check[k] is not None and not have_fcn(check[k]):
            t_skip(n, '%s not installed' % names[k])
        else:
            opt = {'verbose': 0, 'alg': algs[k]}

            if names[k] == 'PIPS' or names[k] == 'sc-PIPS':
                opt['pips_opt'] = {}
                opt['pips_opt']['comptol'] = 1e-8
            if names[k] == 'CPLEX':
                #               alg = 0        ## default uses barrier method with NaN bug in lower lim multipliers
                alg = 2  ## use dual simplex
                ppopt = ppoption(CPLEX_LPMETHOD=alg,
                                 CPLEX_QPMETHOD=min([4, alg]))
                opt['cplex_opt'] = cplex_options([], ppopt)

            if names[k] == 'MOSEK':
                #                alg = 5        ## use dual simplex
                ppopt = ppoption()
                #                ppopt = ppoption(ppopt, MOSEK_LP_ALG = alg)
                ppopt = ppoption(ppopt, MOSEK_GAP_TOL=1e-9)
                opt['mosek_opt'] = mosek_options([], ppopt)

            t = '%s - 3-d LP : ' % names[k]
            ## example from 'doc linprog'
            c = array([-5, -4, -6], float)
            A = sparse([[1, -1, 1], [3, 2, 4], [3, 2, 0]], dtype=float)
            l = None
            u = array([20, 42, 30], float)
            xmin = array([0, 0, 0], float)
            x0 = None
            x, f, s, _, lam = qps_pypower(None, c, A, l, u, xmin, None, None,
                                          opt)
            t_is(s, 1, 12, [t, 'success'])
            t_is(x, [0, 15, 3], 6, [t, 'x'])
            t_is(f, -78, 6, [t, 'f'])
            t_is(lam['mu_l'], [0, 0, 0], 13, [t, 'lam.mu_l'])
            t_is(lam['mu_u'], [0, 1.5, 0.5], 9, [t, 'lam.mu_u'])
            t_is(lam['lower'], [1, 0, 0], 9, [t, 'lam.lower'])
            t_is(lam['upper'], zeros(shape(x)), 13, [t, 'lam.upper'])

            t = '%s - unconstrained 3-d quadratic : ' % names[k]
            ## from http://www.akiti.ca/QuadProgEx0Constr.html
            H = sparse([[5, -2, -1], [-2, 4, 3], [-1, 3, 5]], dtype=float)
            c = array([2, -35, -47], float)
            x0 = array([0, 0, 0], float)
            x, f, s, _, lam = qps_pypower(H, c, opt=opt)
            t_is(s, 1, 12, [t, 'success'])
            t_is(x, [3, 5, 7], 8, [t, 'x'])
            t_is(f, -249, 13, [t, 'f'])
            t_ok(len(lam['mu_l']) == 0, [t, 'lam.mu_l'])
            t_ok(len(lam['mu_u']) == 0, [t, 'lam.mu_u'])
            t_is(lam['lower'], zeros(shape(x)), 13, [t, 'lam.lower'])
            t_is(lam['upper'], zeros(shape(x)), 13, [t, 'lam.upper'])

            t = '%s - constrained 2-d QP : ' % names[k]
            ## example from 'doc quadprog'
            H = sparse([[1, -1], [-1, 2]], dtype=float)
            c = array([-2, -6], float)
            A = sparse([[1, 1], [-1, 2], [2, 1]], dtype=float)
            l = None
            u = array([2, 2, 3], float)
            xmin = array([0, 0])
            x0 = None
            x, f, s, _, lam = qps_pypower(H, c, A, l, u, xmin, None, x0, opt)
            t_is(s, 1, 12, [t, 'success'])
            t_is(x, array([2., 4.]) / 3, 7, [t, 'x'])
            t_is(f, -74. / 9, 6, [t, 'f'])
            t_is(lam['mu_l'], [0., 0., 0.], 13, [t, 'lam.mu_l'])
            t_is(lam['mu_u'], array([28., 4., 0.]) / 9, 7, [t, 'lam.mu_u'])
            t_is(lam['lower'], zeros(shape(x)), 8, [t, 'lam.lower'])
            t_is(lam['upper'], zeros(shape(x)), 13, [t, 'lam.upper'])

            t = '%s - constrained 4-d QP : ' % names[k]
            ## from http://www.jmu.edu/docs/sasdoc/sashtml/iml/chap8/sect12.htm
            H = sparse([[1003.1, 4.3, 6.3, 5.9], [4.3, 2.2, 2.1, 3.9],
                        [6.3, 2.1, 3.5, 4.8], [5.9, 3.9, 4.8, 10.0]])
            c = zeros(4)
            A = sparse([[1, 1, 1, 1], [0.17, 0.11, 0.10, 0.18]])
            l = array([1, 0.10])
            u = array([1, Inf])
            xmin = zeros(4)
            x0 = array([1, 0, 0, 1], float)
            x, f, s, _, lam = qps_pypower(H, c, A, l, u, xmin, None, x0, opt)
            t_is(s, 1, 12, [t, 'success'])
            t_is(x, array([0, 2.8, 0.2, 0]) / 3, 5, [t, 'x'])
            t_is(f, 3.29 / 3, 6, [t, 'f'])
            t_is(lam['mu_l'], array([6.58, 0]) / 3, 6, [t, 'lam.mu_l'])
            t_is(lam['mu_u'], [0, 0], 13, [t, 'lam.mu_u'])
            t_is(lam['lower'], [2.24, 0, 0, 1.7667], 4, [t, 'lam.lower'])
            t_is(lam['upper'], zeros(shape(x)), 13, [t, 'lam.upper'])

            t = '%s - (dict) constrained 4-d QP : ' % names[k]
            p = {
                'H': H,
                'A': A,
                'l': l,
                'u': u,
                'xmin': xmin,
                'x0': x0,
                'opt': opt
            }
            x, f, s, _, lam = qps_pypower(p)
            t_is(s, 1, 12, [t, 'success'])
            t_is(x, array([0, 2.8, 0.2, 0]) / 3, 5, [t, 'x'])
            t_is(f, 3.29 / 3, 6, [t, 'f'])
            t_is(lam['mu_l'], array([6.58, 0]) / 3, 6, [t, 'lam.mu_l'])
            t_is(lam['mu_u'], [0, 0], 13, [t, 'lam.mu_u'])
            t_is(lam['lower'], [2.24, 0, 0, 1.7667], 4, [t, 'lam.lower'])
            t_is(lam['upper'], zeros(shape(x)), 13, [t, 'lam.upper'])

            t = '%s - infeasible LP : ' % names[k]
            p = {
                'A': sparse([1, 1]),
                'c': array([1, 1]),
                'u': array([-1]),
                'xmin': array([0, 0]),
                'opt': opt
            }
            x, f, s, _, lam = qps_pypower(p)
            t_ok(s <= 0, [t, 'no success'])

    t_end()
Пример #13
0
def qps_pypower(H,
                c=None,
                A=None,
                l=None,
                u=None,
                xmin=None,
                xmax=None,
                x0=None,
                opt=None):
    """Quadratic Program Solver for PYPOWER.

    A common wrapper function for various QP solvers.
    Solves the following QP (quadratic programming) problem::

        min 1/2 x'*H*x + c'*x
         x

    subject to::

        l <= A*x <= u       (linear constraints)
        xmin <= x <= xmax   (variable bounds)

    Inputs (all optional except C{H}, C{c}, C{A} and C{l}):
        - C{H} : matrix (possibly sparse) of quadratic cost coefficients
        - C{c} : vector of linear cost coefficients
        - C{A, l, u} : define the optional linear constraints. Default
        values for the elements of C{l} and C{u} are -Inf and Inf,
        respectively.
        - C{xmin}, C{xmax} : optional lower and upper bounds on the
        C{x} variables, defaults are -Inf and Inf, respectively.
        - C{x0} : optional starting value of optimization vector C{x}
        - C{opt} : optional options structure with the following fields,
        all of which are also optional (default values shown in parentheses)
            - C{alg} (0) - determines which solver to use
                -   0 = automatic, first available of BPMPD_MEX, CPLEX,
                        Gurobi, PIPS
                - 100 = BPMPD_MEX
                - 200 = PIPS, Python Interior Point Solver
                pure Python implementation of a primal-dual
                interior point method
                - 250 = PIPS-sc, a step controlled variant of PIPS
                - 300 = Optimization Toolbox, QUADPROG or LINPROG
                - 400 = IPOPT
                - 500 = CPLEX
                - 600 = MOSEK
                - 700 = Gurobi
            - C{verbose} (0) - controls level of progress output displayed
                - 0 = no progress output
                - 1 = some progress output
                - 2 = verbose progress output
            - C{max_it} (0) - maximum number of iterations allowed
                - 0 = use algorithm default
            - C{bp_opt} - options vector for BP
            - C{cplex_opt} - options dict for CPLEX
            - C{grb_opt}   - options dict for gurobipy
            - C{ipopt_opt} - options dict for IPOPT
            - C{pips_opt}  - options dict for L{qps_pips}
            - C{mosek_opt} - options dict for MOSEK
            - C{ot_opt}    - options dict for QUADPROG/LINPROG
        - C{problem} : The inputs can alternatively be supplied in a single
        C{problem} dict with fields corresponding to the input arguments
        described above: C{H, c, A, l, u, xmin, xmax, x0, opt}

    Outputs:
        - C{x} : solution vector
        - C{f} : final objective function value
        - C{exitflag} : exit flag
            - 1 = converged
            - 0 or negative values = algorithm specific failure codes
        - C{output} : output struct with the following fields:
            - C{alg} - algorithm code of solver used
            - (others) - algorithm specific fields
        - C{lmbda} : dict containing the Langrange and Kuhn-Tucker
        multipliers on the constraints, with fields:
            - C{mu_l} - lower (left-hand) limit on linear constraints
            - C{mu_u} - upper (right-hand) limit on linear constraints
            - C{lower} - lower bound on optimization variables
            - C{upper} - upper bound on optimization variables


    Example from U{http://www.uc.edu/sashtml/iml/chap8/sect12.htm}:

        >>> from numpy import array, zeros, Inf
        >>> from scipy.sparse import csr_matrix
        >>> H = csr_matrix(array([[1003.1,  4.3,     6.3,     5.9],
        ...                       [4.3,     2.2,     2.1,     3.9],
        ...                       [6.3,     2.1,     3.5,     4.8],
        ...                       [5.9,     3.9,     4.8,     10 ]]))
        >>> c = zeros(4)
        >>> A = csr_matrix(array([[1,       1,       1,       1   ],
        ...                       [0.17,    0.11,    0.10,    0.18]]))
        >>> l = array([1, 0.10])
        >>> u = array([1, Inf])
        >>> xmin = zeros(4)
        >>> xmax = None
        >>> x0 = array([1, 0, 0, 1])
        >>> solution = qps_pips(H, c, A, l, u, xmin, xmax, x0)
        >>> round(solution["f"], 11) == 1.09666678128
        True
        >>> solution["converged"]
        True
        >>> solution["output"]["iterations"]
        10

    @author: Ray Zimmerman (PSERC Cornell)
    """
    ##----- input argument handling  -----
    ## gather inputs
    if isinstance(H, dict):  ## problem struct
        p = H
        if 'opt' in p: opt = p['opt']
        if 'x0' in p: x0 = p['x0']
        if 'xmax' in p: xmax = p['xmax']
        if 'xmin' in p: xmin = p['xmin']
        if 'u' in p: u = p['u']
        if 'l' in p: l = p['l']
        if 'A' in p: A = p['A']
        if 'c' in p: c = p['c']
        if 'H' in p: H = p['H']
    else:  ## individual args
        #        assert H is not None  zero dimensional sparse matrices not supported
        assert c is not None
#        assert A is not None  zero dimensional sparse matrices not supported
#        assert l is not None  no lower bounds indicated by None

    if opt is None:
        opt = {}


#    if x0 is None:
#        x0 = array([])
#    if xmax is None:
#        xmax = array([])
#    if xmin is None:
#        xmin = array([])

## default options
    if 'alg' in opt:
        alg = opt['alg']
    else:
        alg = 0

    if 'verbose' in opt:
        verbose = opt['verbose']
    else:
        verbose = 0

    if alg == 0:
        if have_fcn('cplex'):  ## use CPLEX by default, if available
            alg = 500
        elif have_fcn('mosek'):  ## if not, then MOSEK, if available
            alg = 600
        elif have_fcn('gurobipy'):  ## if not, then Gurobi, if available
            alg = 700
        else:  ## otherwise PIPS
            alg = 200

    ##----- call the appropriate solver  -----
    if alg == 200 or alg == 250:  ## use MIPS or sc-MIPS
        ## set up options
        if 'pips_opt' in opt:
            pips_opt = opt['pips_opt']
        else:
            pips_opt = {}

        if 'max_it' in opt:
            pips_opt['max_it'] = opt['max_it']

        if alg == 200:
            pips_opt['step_control'] = False
        else:
            pips_opt['step_control'] = True

        pips_opt['verbose'] = verbose

        ## call solver
        x, f, eflag, output, lmbda = \
            qps_pips(H, c, A, l, u, xmin, xmax, x0, pips_opt)
    elif alg == 400:  ## use IPOPT
        x, f, eflag, output, lmbda = \
            qps_ipopt(H, c, A, l, u, xmin, xmax, x0, opt)
    elif alg == 500:  ## use CPLEX
        x, f, eflag, output, lmbda = \
            qps_cplex(H, c, A, l, u, xmin, xmax, x0, opt)
    elif alg == 600:  ## use MOSEK
        x, f, eflag, output, lmbda = \
            qps_mosek(H, c, A, l, u, xmin, xmax, x0, opt)
    elif 700:  ## use Gurobi
        x, f, eflag, output, lmbda = \
            qps_gurobi(H, c, A, l, u, xmin, xmax, x0, opt)
    else:
        sys.stderr.write('qps_pypower: %d is not a valid algorithm code\n',
                         alg)

    if 'alg' not in output:
        output['alg'] = alg

    return x, f, eflag, output, lmbda