Source code for Pyfrontier.domain.result

import abc
from dataclasses import dataclass
from typing import List, Literal

import numpy as np

from Pyfrontier.domain import DMU


[docs] @dataclass(frozen=True) class BaseResult(abc.ABC): score: float id: int dmu: DMU
[docs] @dataclass(frozen=True) class EnvelopResult(BaseResult): """ - score: efficiency - id: - dmu: - weight: - x_slack: - y_slack: - orientation: "in" for input-oriented, "out" for output-oriented """ score: float id: int dmu: DMU weights: List[float] x_slack: List[float] y_slack: List[float] orientation: Literal["in", "out"] def __post_init__(self): pass @property def is_efficient(self) -> bool: if self.score == 1: return not self.has_slack else: return False @property def has_slack(self) -> bool: if np.sum(self.x_slack) + np.sum(self.y_slack) > 0: return True else: return False @property def virtual_dmu(self) -> DMU: """ Returns the virtual DMU (projection onto the efficient frontier). The virtual DMU represents the target values that an inefficient DMU should achieve to become efficient, based on DEA theory. For input-oriented models: - projected_input = score * original_input - input_slack - projected_output = original_output + output_slack For output-oriented models: - projected_input = original_input - input_slack - projected_output = score * original_output + output_slack Returns: DMU: A new DMU object with projected input and output values """ if self.orientation == "in": projected_input = self.score * self.dmu.input - np.array(self.x_slack) projected_output = self.dmu.output + np.array(self.y_slack) else: # "out" projected_input = self.dmu.input - np.array(self.x_slack) projected_output = self.score * self.dmu.output + np.array(self.y_slack) return DMU( input=projected_input, output=projected_output, id=self.dmu.id, )
[docs] @dataclass(frozen=True) class MultipleResult(BaseResult): """ - score: efficiency - id: - dmu: - x_weight: - y_weight: - bias: """ score: float id: int dmu: DMU x_weight: List[float] y_weight: List[float] bias: float def __post_init__(self): pass @property def is_efficient(self) -> bool: if self.score == 1: return True else: return False
[docs] @dataclass(frozen=True) class AdditiveResult(BaseResult): """ - score: efficiency - id: - dmu: - x_slack: - y_slack: - weights: lambda """ score: float id: int dmu: DMU x_slack: List[float] y_slack: List[float] weights: List[float] @property def is_efficient(self) -> bool: if np.sum(self.x_slack) + np.sum(self.y_slack) > 0: return False else: return True