Source code for pyanp.prioritizer

'''
A prioritizer is the root class of all things that prioritize objects (e.g. Pairwise and AHPTree).
'''

from enum import Enum
from copy import deepcopy
import numpy as np
import pandas

[docs]class PriorityType(Enum): ''' An enumeration telling how to normalize priorities for a calculation ''' RAW = 1 """Leave the priorities unchanged.""" NORMALIZE = 2 """Divide priorities by sum, so that they sum to 1.""" IDEALIZE = 3 """Divide priorities by max, so that the largest is 1."""
[docs] def apply(self, vals): ''' Returns a copy of the parameter vals that has been adjusted as this PriorityType would. :param vals: A list-like object of values. We return a copy that is adjusted. :return: A list-like of the same type as 'vals' that has been normalized as this PriorityType would do. ''' rval = copy_array_as_float(vals) if self == PriorityType.RAW: return rval elif self == PriorityType.NORMALIZE: s = np.sum(np.abs(vals)) if s != 0: for i in range(len(rval)): rval[i] /= float(s) return rval elif self == PriorityType.IDEALIZE: s = max(np.abs(vals)) if s != 0: for i in range(len(rval)): rval[i] /= s return rval else: raise ValueError("Unknown PriorityType "+str(self))
def priority_type_default(): return PriorityType.RAW def copy_array_as_float(src): if isinstance(src, (list, tuple)): return deepcopy(src) elif hasattr(src, "dtype"): rval = src.astype(float) return rval else: return deepcopy(src)
[docs]class Prioritizer: ''' This class is the abstract representation of anything that prioritizes a list of items. Examples include :py:class:`pyanp.pairwise.Pairwise` for doing group pairwise comparisons and :py:class:`pyanp.ahptree.AHPTree` for doing group AHP tree models. '''
[docs] def add_alt(self, alt_name:str, ignore_existing=True)->None: ''' Add an alternative to the prioritizer. This should be overriden by the implementing class. :param alt_name: The name of the alternative to add. :return: Nothing ''' raise ValueError("Should be overriden in subclass")
[docs] def priority(self, username=None, ptype:PriorityType=None) -> pandas.Series: ''' Calculates the alternative priorities. Should be overriden by the implementing class. :param user_name: The name/names of the users to calculate the priority of. If None, we get the priority of the group average. If it is a string, we get the priority of that user. If it is a list of users, we get the priority of the group average for that list of users. :param ptype: How should we normalize the resulting priorities (if at all). :return: A pandas.Series whose indices are the alternative names and whose values are the priorities of those alternatives. ''' raise ValueError("Should be over riden in subclass")
[docs] def nalts(self): ''' :return: The number of alternatives (things you are pairwise comparing) in this group pairwise comparison object. ''' return len(self.alt_names())
[docs] def add_user(self, uname): ''' Adds a user to this prioritizer object. :param user_name: The name of the user to add :return: Nothing :raises ValueError: If the user already existed. ''' raise ValueError("Should be overriden in subclass")
[docs] def user_names(self): ''' :return: A list of the users in this prioritizer object. ''' raise ValueError("Should be overriden in subclass")
def _repr_html(self, tab="\t"): raise ValueError("Should override in subclass")
[docs] def alt_names(self): ''' :return: A list of the alts in this prioritizer object. ''' raise ValueError("Should be overriden in subclass")
[docs] def data_names(self, append_to=None, post_pend="")->str: ''' Return string of newline separated names for the data that this prioritizer needs for each user. :param append_to: If not none, elements are appended here, otherwise a new list is created. :param post_pend: A string to post_pend to each name :return: List of strings of names. ''' raise ValueError("Should be overriden in subclass")
[docs] def priority_df(self, user_infos=None)->pandas.DataFrame: """ Returns the priority scores dataframe for all users and the group :param user_infos: A list of users to do this for, if None is a part of this list, it means group average. If None, it defaults to None plus all users. :return: pandas.DataFrame rows are alternatives, cols are users. """ if user_infos is None: user_infos = list(self.user_names()) user_infos.insert(0, None) rval = pandas.DataFrame() for user in user_infos: if user is None: uname = "Group Average" else: uname = user rval[uname] = self.priority(user) return rval