📄 auction.m
字号:
function [co, cb] = auction(offers, bids, auction_type, limit_prc, gtee_prc)%AUCTION Clear auction based on OPF results (qty's and lambdas).% [co, cb] = auction(offers, bids, auction_type, limit_prc, gtee_prc)% Clears a set of bids and offers based on the results of an OPF, where the% pricing is adjusted for network losses and binding constraints.% The arguments offers and bids are structs with the following fields:% qty - m x n, offer/bid quantities, m offers/bids, n blocks% prc - m x n, offer/bid prices% lam - m x n, corresponding lambdas% total_qty - m x 1, total quantity cleared for each offer/bid%% There are 8 types of auctions implemented, specified by auction_type.%% 0 - discriminative pricing (price equal to offer or bid)% 1 - last accepted offer auction% 2 - first rejected offer auction% 3 - last accepted bid auction% 4 - first rejected bid auction% 5 - first price auction (marginal unit, offer or bid, sets the price)% 6 - second price auction (if offer is marginal, price set by% min(FRO,LAB), else max(FRB,LAO)% 7 - split the difference pricing (set by last accepted offer & bid)% 8 - LAO sets seller price, LAB sets buyer price%% Whether or not cleared offer (bid) prices are guaranteed to be greater% (less) than or equal to the corresponding offer (bid) price is specified by% a flag gtee_prc.offer (gtee_prc.bid). The default is value true.% % Offer/bid and cleared offer/bid min and max prices are specified in the% limit_prc struct with the following fields:% max_offer% min_bid% max_cleared_offer% min_cleared_bid% Offers (bids) above (below) max_offer (min_bid) are treated as withheld% and cleared offer (bid) prices above (below) max_cleared_offer% (min_cleared_bid) are clipped to max_cleared offer (min_cleared_bid) if% given. All of these limit prices are ignored if the field is missing% or is empty.% MATPOWER% $Id: auction.m,v 1.15 2005/10/17 22:21:01 ray Exp $% by Ray Zimmerman, PSERC Cornell% Copyright (c) 1996-2005 by Power System Engineering Research Center (PSERC)% See http://www.pserc.cornell.edu/matpower/ for more info.%%----- initialization -----%% define named indices into data matrices[PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ... VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;[GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ... MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ... QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;[AREA_I, PRICE_REF_BUS] = idx_area;%% initialize some stuffif have_fcn('minopf') zero_tol = 1e-5;else zero_tol = 0.1; %% fmincon is SO bad with prices that it isend %% NOT recommended for use with auction.mbig_num = 1e6;if isempty(bids) bids = struct( 'qty', [], ... 'prc', [], ... 'lam', [], ... 'total_qty', [] );endif nargin < 4 | isempty(limit_prc) limit_prc = struct( 'max_offer', [], 'min_bid', [], ... 'max_cleared_offer', [], 'min_cleared_bid', [] );else if ~isfield(limit_prc, 'max_offer'), limit_prc.max_offer = []; end if ~isfield(limit_prc, 'min_bid'), limit_prc.min_bid = []; end if ~isfield(limit_prc, 'max_cleared_offer'), limit_prc.max_cleared_offer = []; end if ~isfield(limit_prc, 'min_cleared_bid'), limit_prc.min_cleared_bid = []; endendif nargin < 5 | isempty(gtee_prc) gtee_prc = struct( 'offer', 1, 'bid', 1 );else if ~isfield(gtee_prc, 'offer'), gtee_prc.offer = 1; end if ~isfield(gtee_prc, 'bid'), gtee_prc.bid = 1; endend[nro, nco] = size(offers.qty);[nrb, ncb] = size(bids.qty);%% determine cleared quantitiesif isempty(limit_prc.max_offer) [co.qty, o.on, o.off] = clear_qty(offers.qty, offers.total_qty);else mask = offers.prc <= limit_prc.max_offer; [co.qty, o.on, o.off] = clear_qty(offers.qty, offers.total_qty, mask);endif isempty(limit_prc.min_bid) [cb.qty, b.on, b.off] = clear_qty(bids.qty, bids.total_qty);else mask = bids.prc <= limit_prc.min_bid; [cb.qty, b.on, b.off] = clear_qty(bids.qty, bids.total_qty, mask);end%% initialize cleared pricesco.prc = zeros(nro, nco); %% cleared offer pricescb.prc = zeros(nrb, ncb); %% cleared bid prices%%----- compute shift values to add to lam to get desired pricing -----%% The locationally adjusted offer/bid price, when normalized to an arbitrary%% reference location where lambda is equal to ref_lam, is:%% norm_prc = prc + (ref_lam - lam)%% Then we can define the difference between the normalized offer/bid prices%% and the ref_lam as:%% diff = norm_prc - ref_lam = prc - lam%% This diff represents the gap between the marginal unit (setting lambda)%% and the offer/bid price in question.offer_diff = offers.prc - offers.lam;bid_diff = bids.prc - bids.lam;%% shift.LAO + lambda is equal to the last accepted offershift.LAO = o.on .* offer_diff - o.off * big_num;shift.LAO( find(shift.LAO(:) > zero_tol) ) = -big_num; %% don't let gens @ Pmin set priceshift.LAO = max( shift.LAO(:) );%% shift.FRO + lambda is equal to the first rejected offershift.FRO = o.off .* offer_diff + o.on * big_num;shift.FRO = min( shift.FRO(:) );if nrb %% shift.LAB + lambda is equal to the last accepted bid shift.LAB = b.on .* bid_diff + b.off * big_num; shift.LAB = min( shift.LAB(:) ); %% shift.FRB + lambda is equal to the first rejected bid shift.FRB = b.off .* bid_diff - b.on * big_num; shift.FRB = max( shift.FRB(:) );else shift.LAB = big_num; shift.FRB = shift.LAB;end%% cleared offer/bid prices for different auction typesif auction_type == 0 %% discriminative co.prc = offers.prc; cb.prc = bids.prc;elseif auction_type == 1 %% LAO co.prc = offers.lam + shift.LAO; cb.prc = bids.lam + shift.LAO;elseif auction_type == 2 %% FRO co.prc = offers.lam + shift.FRO; cb.prc = bids.lam + shift.FRO;elseif auction_type == 3 %% LAB co.prc = offers.lam + shift.LAB; cb.prc = bids.lam + shift.LAB;elseif auction_type == 4 %% FRB co.prc = offers.lam + shift.FRB; cb.prc = bids.lam + shift.FRB;elseif auction_type == 5 %% 1st price co.prc = offers.lam; cb.prc = bids.lam;elseif auction_type == 6 %% 2nd price if abs(shift.LAO) < zero_tol co.prc = offers.lam + min(shift.FRO,shift.LAB); cb.prc = bids.lam + min(shift.FRO,shift.LAB); else co.prc = offers.lam + max(shift.LAO,shift.FRB); cb.prc = bids.lam + max(shift.LAO,shift.FRB); endelseif auction_type == 7 %% split the difference co.prc = offers.lam + (shift.LAO + shift.LAB) / 2; cb.prc = bids.lam + (shift.LAO + shift.LAB) / 2;elseif auction_type == 8 %% LAO seller, LAB buyer co.prc = offers.lam + shift.LAO; cb.prc = bids.lam + shift.LAB;end%% guarantee that cleared offer prices are >= offersif gtee_prc.offer clip = o.on .* (offers.prc - co.prc); co.prc = co.prc + (clip > zero_tol) .* clip;end%% guarantee that cleared bid prices are >= bidsif gtee_prc.bid clip = b.on .* (bids.prc - cb.prc); cb.prc = cb.prc + (clip < -zero_tol) .* clip;end%% clip cleared offer prices by limit_prc.max_cleared_offerif ~isempty(limit_prc.max_cleared_offer) co.prc = co.prc + (co.prc > limit_prc.max_cleared_offer) .* ... (limit_prc.max_cleared_offer - co.prc);end%% clip cleared bid prices by limit_prc.min_cleared_bidif ~isempty(limit_prc.min_cleared_bid) cb.prc = cb.prc + (cb.prc < limit_prc.min_cleared_bid) .* ... (limit_prc.min_cleared_bid - co.prc);end%% make prices uniform after clipping (except for discrim auction)%% since clipping may only affect a single block of a multi-block generatorif auction_type ~= 0 %% equal to largest price in row if nco > 1 co.prc = diag(max(co.prc')) * ones(nro,nco); end if ncb > 1 cb.prc = diag(min(cb.prc')) * ones(nrb,ncb); endendreturn;function [cqty, on, off] = clear_qty(qty, total_cqty, mask)%CLEAR_QTY Computed cleared offer/bid quantities from totals.% Inputs:% qty - m x n, offer/bid quantities, m offers/bids, n blocks% total_cqty - m x 1, total cleared quantity for each offer/bid% mask - m x n, boolean indicating which offers/bids are valid (not withheld)% Outputs:% cqty - m x n, cleared offer/bid quantities, m offers/bids, n blocks% on - m x n, 1 if partially or fully accepted, 0 if rejected% off - m x n, 1 if rejected, 0 if partially or fully accepted[nr, nc] = size(qty);accept = zeros(nr,nc);cqty = zeros(nr,nc);for i = 1:nr %% offer/bid i for j = 1:nc %% block j if qty(i, j) %% ignore zero quantity offers/bids %% compute fraction of the block accepted ... accept(i, j) = (total_cqty(i) - sum(qty(i, 1:j-1))) / qty(i, j); %% ... clipped to the range [0, 1] (i.e. 0-100%) if accept(i, j) > 1 accept(i, j) = 1; elseif accept(i, j) < 1.0e-5 accept(i, j) = 0; end cqty(i, j) = qty(i, j) * accept(i, j); end endendif nargin == 3 accept = mask .* accept;endon = (accept > 0);off = (accept == 0);return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -