diff --git a/deepcomp/env/entities/user.py b/deepcomp/env/entities/user.py index a595aed..4445a77 100644 --- a/deepcomp/env/entities/user.py +++ b/deepcomp/env/entities/user.py @@ -5,7 +5,7 @@ import matplotlib.pyplot as plt from matplotlib import cm -from deepcomp.env.util.utility import log_utility, step_utility +from deepcomp.env.util.utility import log_utility, step_utility, linear_clipped_utility from deepcomp.util.constants import MIN_UTILITY, MAX_UTILITY, SUPPORTED_UTILITIES @@ -86,6 +86,8 @@ def dr_to_utility(self, dr): return log_utility(dr) if self.util_func == 'step': return step_utility(dr, self.dr_req) + if self.util_func == 'linear': + return linear_clipped_utility(dr) # unknown utility not implemented raise NotImplementedError(f"Utility function {self.util_func} not implemented!") diff --git a/deepcomp/env/util/utility.py b/deepcomp/env/util/utility.py index 3fa926e..3931019 100644 --- a/deepcomp/env/util/utility.py +++ b/deepcomp/env/util/utility.py @@ -7,6 +7,19 @@ from deepcomp.util.constants import MIN_UTILITY, MAX_UTILITY +def linear_clipped_utility(curr_dr, max_dr=MAX_UTILITY): + """ + Utility that directly equals the data rate, increasing linearly up to a given maximum. + + :param max_dr: Maximum data rate at which the utility does not increase further + :return: Utility + """ + assert curr_dr >= 0 and max_dr >= 0 + assert MIN_UTILITY == 0 and MAX_UTILITY == max_dr, \ + f"The chosen linear utility requires MIN_UTILITY=0 and sensible MAX_UTILITY. Set sensible values manually!" + return np.clip(curr_dr, MIN_UTILITY, MAX_UTILITY) + + def step_utility(curr_dr, req_dr): """ Flat negative utility as long as the required data rate is not met; then positive. Nothing in between. diff --git a/deepcomp/util/cli.py b/deepcomp/util/cli.py index ba1e806..2715e1c 100644 --- a/deepcomp/util/cli.py +++ b/deepcomp/util/cli.py @@ -3,7 +3,8 @@ import structlog from deepcomp.util.constants import SUPPORTED_ALGS, SUPPORTED_ENVS, SUPPORTED_AGENTS, SUPPORTED_RENDER, \ - SUPPORTED_SHARING, SUPPORTED_REWARDS, CENTRAL_ALGS, MULTI_ALGS, SUPPORTED_UE_ARRIVAL, SUPPORTED_UTILITIES + SUPPORTED_SHARING, SUPPORTED_REWARDS, CENTRAL_ALGS, MULTI_ALGS, SUPPORTED_UE_ARRIVAL, SUPPORTED_UTILITIES, \ + MIN_UTILITY, MAX_UTILITY log = structlog.get_logger() @@ -117,6 +118,11 @@ def setup_cli(): log.warning('Algorithm only supports multi-agent. Switching to multi-agent.', alg=args.alg) args.agent = 'multi' + # warn for linear utility; can't change this automatically in code + if args.util == 'linear': + log.warning('Make sure to set MIN_UTILITY and MAX_UTILITY to sensible values manually!', + util_func=args.util, min_utility=MIN_UTILITY, max_utility=MAX_UTILITY, suggestion=(0, 1000)) + # render settings if (args.dashboard or args.ue_details) and args.video is None: log.warning("--dashboard and --ue-details have no effect without --video.") diff --git a/deepcomp/util/constants.py b/deepcomp/util/constants.py index aac5524..a5eb78a 100644 --- a/deepcomp/util/constants.py +++ b/deepcomp/util/constants.py @@ -22,7 +22,7 @@ SUPPORTED_RENDER = {'html', 'gif', 'both', None} SUPPORTED_SHARING = {'max-cap', 'resource-fair', 'rate-fair', 'proportional-fair'} SUPPORTED_REWARDS = {'min', 'sum'} -SUPPORTED_UTILITIES = {'log', 'step'} +SUPPORTED_UTILITIES = {'log', 'step', 'linear'} # small epsilon used in denominator to avoid division by zero EPSILON = 1e-16 @@ -36,8 +36,9 @@ # upper and lower bound for utility # affects reward clipping, normalization, plotting, etc.; change for different utility function -MIN_UTILITY = -20 -MAX_UTILITY = 20 +# TODO: manually adjust for different utility functions. more elegant solution? +MIN_UTILITY = 0 +MAX_UTILITY = 1000 # constants regarding result files