Revision 3259407b1fa597becb11644b14cd21d3b1cc57a3 authored by Javier Barbero on 28 March 2022, 13:19:02 UTC, committed by GitHub on 28 March 2022, 13:19:02 UTC
1 parent 3e2df08
deaprofitability.jl
# This file contains functions for the Profitability Efficiency DEA model
"""
ProfitabilityDEAModel
An data structure representing a profitability DEA model.
"""
struct ProfitabilityDEAModel <: AbstractProfitabilityDEAModel
n::Int64
m::Int64
s::Int64
alpha::Float64
dmunames::Union{Vector{AbstractString},Nothing}
eff::Vector
lambda::SparseMatrixCSC{Float64, Int64}
crseff::Vector
vrseff::Vector
scaleff::Vector
alloceff::Vector
Xtarget::Matrix
Ytarget::Matrix
end
"""
deaprofitability(X, Y, W, P)
Compute profitability efficiency using data envelopment analysis for
inputs `X`, outputs `Y`, price of inputs `W`, and price of outputs `P`.
# Optional Arguments
- `alpha=0.5`: alpha to use for the generalized distance function.
- `names`: a vector of strings with the names of the decision making units.
"""
function deaprofitability(X::Union{Matrix,Vector}, Y::Union{Matrix,Vector},
W::Union{Matrix,Vector}, P::Union{Matrix,Vector};
alpha::Float64 = 0.5,
names::Union{Vector{<: AbstractString},Nothing} = nothing,
optimizer::Union{DEAOptimizer,Nothing} = nothing)::ProfitabilityDEAModel
# Check parameters
nx, m = size(X, 1), size(X, 2)
ny, s = size(Y, 1), size(Y, 2)
nw, mw = size(W, 1), size(W, 2)
np, sp = size(P, 1), size(P, 2)
if nx != ny
throw(DimensionMismatch("number of rows in X and Y ($nx, $ny) are not equal"));
end
if nw != nx
throw(DimensionMismatch("number of rows in W and X ($nw, $nx) are not equal"));
end
if np != ny
throw(DimensionMismatch("number of rows in P and Y ($np, $ny) are not equal"));
end
if mw != m
throw(DimensionMismatch("number of columns in W and X ($mw, $m) are not equal"));
end
if sp != s
throw(DimensionMismatch("number of columns in P and Y ($sp, $s) are not equal"));
end
# Default optimizer
if optimizer === nothing
optimizer = DEAOptimizer(:NLP)
end
# Compute efficiency for each DMU
n = nx
Xtarget = zeros(n,m)
Ytarget = zeros(n,s)
pefficiency = zeros(n)
plambdaeff = spzeros(n, n)
for i=1:n
# Value of inputs and outputs to evaluate
x0 = X[i,:]
y0 = Y[i,:]
w0 = W[i,:]
p0 = P[i,:]
# Create the optimization model
deamodel = newdeamodel(optimizer)
@variable(deamodel, eff, start = 1.0)
@variable(deamodel, lambda[1:n] >= 0)
@NLobjective(deamodel, Min, eff)
@NLconstraint(deamodel, sum(sum(w0[mi] * X[t,mi] for mi in 1:m) / sum(p0[si] * Y[t,si] for si in 1:s) * lambda[t] for t in 1:n) == eff * sum(w0[j] * x0[j] for j in 1:m ) / sum(p0[j] * y0[j] for j in 1:s))
@constraint(deamodel, sum(lambda) == 1)
# Optimize and return results
JuMP.optimize!(deamodel)
pefficiency[i] = JuMP.objective_value(deamodel)
plambdaeff[i,:] = JuMP.value.(lambda)
Xtarget[i,:] = X[i,:] .* pefficiency[i] ^(1-alpha)
Ytarget[i,:] = Y[i,:] ./ ( pefficiency[i] ^alpha )
# Check termination status
if (termination_status(deamodel) != MOI.OPTIMAL) && (termination_status(deamodel) != MOI.LOCALLY_SOLVED)
@warn ("DMU $i termination status: $(termination_status(deamodel)). Primal status: $(primal_status(deamodel)). Dual status: $(dual_status(deamodel))")
end
end
# Technical, scale and allocative efficiency
crsefficiency = efficiency(deagdf(X, Y, alpha = alpha, rts = :CRS, slack = false, optimizer = optimizer))
vrsefficiency = efficiency(deagdf(X, Y, alpha = alpha, rts = :VRS, slack = false, optimizer = optimizer))
scalefficiency = crsefficiency ./ vrsefficiency
allocefficiency = pefficiency ./ crsefficiency
return ProfitabilityDEAModel(n, m, s, alpha, names, pefficiency, plambdaeff, crsefficiency, vrsefficiency, scalefficiency, allocefficiency, Xtarget, Ytarget)
end
function Base.show(io::IO, x::ProfitabilityDEAModel)
compact = get(io, :compact, false)
n = nobs(x)
m = ninputs(x)
s = noutputs(x)
dmunames = names(x)
eff = efficiency(x)
crseff = efficiency(x, :CRS)
vrseff = efficiency(x, :VRS)
scaleeff = efficiency(x, :Scale)
alloceff = efficiency(x, :Allocative)
if !compact
print(io, "Profitability DEA Model \n")
print(io, "DMUs = ", n)
print(io, "; Inputs = ", m)
print(io, "; Outputs = ", s)
print(io, "\n")
print(io, "alpha = ", x.alpha)
print(io, "; Returns to Scale = VRS")
print(io, "\n")
show(io, CoefTable(hcat(eff, crseff, vrseff, scaleeff, alloceff), ["Profitability", "CRS", "VRS", "Scale", "Allocative"], dmunames))
end
end
Computing file changes ...