コード例 #1
0
ファイル: __init__.py プロジェクト: RDCEP/chicagowebdice
    def loop(self, miu=None, deriv=False, scc=True, opt=False):
        """Main loop

        Loop through step function for calculating endogenous variables. This
        method is called by hand, but also during derivative calculations
        when optimizing.

        Kwargs:
            miu (nd.array): values for miu
            deriv (bool): Whether or not to calculate a derivative
            scc (bool): Whether or not to calculate SCC
            opt (bool): Whether or not to optimize the scenario

        Returns:
            DiceDataMatrix: Array of model variables

        """
        _miu = None
        if opt:
            self.eq = LoopOpt(self.params)
            self.eq.set_models(self.params)
            _miu = self.get_ipopt_miu()
            _miu[0] = self.params.miu_2005
        self.eq = Loop(self.params)
        self.eq.set_models(self.params)
        for i in range(self.params.tmax):
            self.step(i, self.vars, _miu, deriv=deriv, opt=opt)
        if scc:
            self.get_scc(_miu)
        return self.vars
コード例 #2
0
ファイル: __init__.py プロジェクト: RDCEP/chicagowebdice
 def __init__(self):
     self.params = DiceParams()
     self.vars = self.params.vars
     self.scc = self.params.scc
     self.eq = Loop(self.params)
     self.eps = 1e-8
     self.dice_version = 2007
     self.opt_vars = 60
     self.opt_x = np.arange(self.opt_vars)
     self.opt_grad_f = None
     self.opt_obj = None
     self.opt_tol = 1e-5
     self.opt_scale = 1e-4
コード例 #3
0
ファイル: __init__.py プロジェクト: RDCEP/chicagowebdice
class Dice(object):
    """Dice object

    Variables, parameters, loop/step, and optimization functions
    for DICE objects.

    Args:
        None

    """
    def __init__(self):
        self.params = DiceParams()
        self.vars = self.params.vars
        self.scc = self.params.scc
        self.eq = Loop(self.params)
        self.eps = 1e-8
        self.dice_version = 2007
        self.opt_vars = 60
        self.opt_x = np.arange(self.opt_vars)
        self.opt_grad_f = None
        self.opt_obj = None
        self.opt_tol = 1e-5
        self.opt_scale = 1e-4

    @property
    def user_params(self):
        """List of parameters

        List of model parameters to be included with output to graphs and CSV.
        This list purposely leaves out model parameters whose names begin with
        an _, as they're assumed to be immutable.

        Args:
            None

        Returns:
            list: List of parameter names (strings)

        """
        u_p = DiceUserParams()
        return [k for k in u_p.__dict__.keys() if k[0] != '_']

    @property
    def model_vars(self):
        """Model variables

        List of model variables to be included with output to graphs and CSV.
        This list purposely leaves out model variables whose names begin with
        an _, though currently (Aug 2014) none exist.

        Args:
            None

        Returns:
            list: List of variable names as strings

        """
        return [k for k, v in self.vars.__dict__.iteritems() if k[0] != '_']

    @property
    def welfare(self):
        """Objective function: ∑(discounted utility)

        Args:
            None

        Returns:
            float: Value of objective function

        """
        return np.sum(self.vars.utility_discounted)

    def step(self, i, df, miu=None, deriv=False, opt=False,
             emissions_shock=0.0):
        """Step function

        Single step for calculating model variables at t. This is called from
        the loop() method.

        Args:
            i (int): index of current step
            df (DiceDataMatrix): numpy array of model variables

        Kwargs:
            miu (nd.array): values for miu
            deriv (bool): Whether or not to calculate a derivative
            opt (bool): Whether or not to optimize the scenario
            emissions_shock (float): Emissions shock for calculating SCC

        Returns:
            DiceDataMatrix: numpy array of model variables

        """

        (
            df.carbon_intensity[i], df.productivity[i], df.capital[i],
            df.backstop_growth[i], df.gross_output[i], df.intensity_decline[i],
            df.population[i],
        ) = self.eq.productivity_model.get_model_values(i, df)
        if i > 0:
            df.productivity[i] *= self.eq.damages_model.get_production_factor(
                df.temp_atmosphere[i - 1]
            ) ** 10
        (
            df.miu[i], df.emissions_ind[i],
            df.emissions_total[i], df.carbon_emitted[i],
            df.tax_rate[i]
        ) = self.eq.emissions_model.get_model_values(
            i, df, miu=miu, emissions_shock=emissions_shock, deriv=deriv,
            opt=opt
        )
        df.mass_atmosphere[i], df.mass_upper[i], df.mass_lower[i] = (
            self.eq.carbon_model.get_model_values(i, df)
        )
        df.forcing[i] = self.eq.carbon_model.forcing(i, df)
        df.temp_atmosphere[i], df.temp_lower[i] = (
            self.eq.temperature_model.get_model_values(i, df)
        )
        df.abatement[i], df.damages[i], df.output[i], df.output_abate[i] = (
            self.eq.damages_model.get_model_values(i, df)
        )
        (df.consumption[i], df.consumption_pc[i], df.consumption_discount[i],
         df.investment[i]) = self.eq.consumption_model.get_model_values(i, df)
        df.utility[i], df.utility_discounted[i] = (
            self.eq.utility_model.get_model_values(i, df)
        )
        return df

    def loop(self, miu=None, deriv=False, scc=True, opt=False):
        """Main loop

        Loop through step function for calculating endogenous variables. This
        method is called by hand, but also during derivative calculations
        when optimizing.

        Kwargs:
            miu (nd.array): values for miu
            deriv (bool): Whether or not to calculate a derivative
            scc (bool): Whether or not to calculate SCC
            opt (bool): Whether or not to optimize the scenario

        Returns:
            DiceDataMatrix: Array of model variables

        """
        _miu = None
        if opt:
            self.eq = LoopOpt(self.params)
            self.eq.set_models(self.params)
            _miu = self.get_ipopt_miu()
            _miu[0] = self.params.miu_2005
        self.eq = Loop(self.params)
        self.eq.set_models(self.params)
        for i in range(self.params.tmax):
            self.step(i, self.vars, _miu, deriv=deriv, opt=opt)
        if scc:
            self.get_scc(_miu)
        return self.vars

    def set_opt_values(self, df):
        """Save current optimal values

        Save last gradient and last objective function. Speeds up optimization
        in the instance that miu (x) is unchanged form one iteration to the
        next.

        Args:
            df (DiceDataMatrix): Array of model variables

        Returns:
            None

        """
        gf = (
            df.utility_discounted[:, :60].sum(axis=0) -
            df.utility_discounted[:, 60].sum()
        ) * self.opt_scale / self.eps
        self.opt_grad_f = gf
        self.opt_obj = (
            df.utility_discounted[:, 60].sum() * self.opt_scale)

    def obj_loop(self, miu):
        """Objective function for optimization

        Calculate objective function. Is called by get_ipopt_miu().
        Calls loop(). Stores and returns result.

        Args:
            miu (nd.array): Array of values for miu, n = Dice().params.tmax

        Returns:
            float: value of objective (utility)

        """
        df = DiceDataMatrix(np.tile(self.vars, (61, 1, 1)).transpose(1, 2, 0))
        for i in xrange(self.params.tmax):
            df.miu[i, :] = miu[i]
            df.miu[i, i] += self.eps
            self.step(i, df, df.miu[i], deriv=True, opt=True)
        self.set_opt_values(df)
        return self.opt_obj

    def grad_loop(self, miu):
        """Gradient function for optimization

        Calculate gradient of objective function using finite differences.
        Is called by get_ipopt_miu(). Calls loop(). Stores and returns result.

        Args:
            miu (nd.array): Array of values for miu, n = Dice().params.tmax

        Returns:
            nd.array: gradient of objective

        """
        df = DiceDataMatrix(np.tile(self.vars, (61, 1, 1)).transpose(1, 2, 0))
        for i in xrange(self.params.tmax):
            df.miu[i, :] = miu[i]
            df.miu[i, i] += self.eps
            self.step(i, df, df.miu[i], deriv=True, opt=True)
        self.set_opt_values(df)
        return self.opt_grad_f

    def get_scc(self, miu):
        """Calculate SCC

        Calculate social cost of carbon. Called automatically from loop().

        Args:
            miu (nd.array): Array of values for miu, n = Dice().params.tmax

        Returns:
            None
        """
        for i in xrange(20):
            th = self.params.scc_horizon
            future = th - i
            self.scc[:] = self.vars[:]
            for j in range(i, th + 1):
                shock = 0
                if j == i:
                    shock = 1.0
                self.step(j, self.scc, miu=miu, emissions_shock=shock)
            diff = (
                self.vars.consumption_pc[i:th] -
                self.scc.consumption_pc[i:th]
            ).clip(0) * self.scc.consumption_discount[:future]
            self.vars.scc[i] = np.sum(diff) * 1000 * 10 * (12 / 44)

    def get_ipopt_miu(self):
        """Optimized miu

        Calculate optimal miu. Called when opt=True is passed to loop().
        ...
        Args:
            None

        Returns
            nd.array: Array of optimal miu, n = params.tmax

        """
        try:
            import pyipopt
        except ImportError:
            pyipopt = None
            print('OPTIMIZATION ERROR: It appears that you do not have '
                  'pyipopt installed. Please install it before running '
                  'optimization.')
        x0 = np.concatenate(
            (np.linspace(0, 1, 40) ** (1 - np.linspace(0, 1, 40)), np.ones(20))
        )
        M = 0
        nnzj = 0
        nnzh = 0
        xl = np.zeros(self.params.tmax)
        xu = np.ones(self.params.tmax)
        xl[0] = .005
        xu[0] = .005
        xl[-20:] = 1
        gl = np.zeros(M)
        gu = np.ones(M) * 4.0
        def eval_f(_x0):
            if (_x0 == self.opt_x).all() and self.opt_obj is not None:
                return self.opt_obj
            else:
                self.opt_x = _x0.copy()
                return self.obj_loop(_x0)
        def eval_grad_f(_x0):
            if (_x0 == self.opt_x).all() and self.opt_grad_f is not None:
                return self.opt_grad_f
            else:
                self.opt_x = _x0.copy()
                return self.grad_loop(_x0)
        def eval_g(x):
            return np.zeros(M)
        def eval_jac_g(x, flag):
            if flag:
                return [], []
            else:
                return np.empty(M)
        pyipopt.set_loglevel(1)
        nlp = pyipopt.create(
            self.opt_vars, xl, xu, M, gl, gu, nnzj, nnzh, eval_f,
            eval_grad_f, eval_g, eval_jac_g,
        )
        nlp.num_option('constr_viol_tol', 8e-7)
        nlp.int_option('max_iter', 30)
        nlp.num_option('max_cpu_time', 60)
        nlp.num_option('tol', self.opt_tol)
        # nlp.num_option('acceptable_tol', 1e-4)
        # nlp.int_option('acceptable_iter', 4)
        nlp.num_option('obj_scaling_factor', -1e+0)
        nlp.int_option('print_level', 0)
        nlp.str_option('linear_solver', 'ma57')
        # nlp.str_option('derivative_test', 'first-order')
        x = nlp.solve(x0)[0]
        nlp.close()
        return x

    def format_output(self):
        """Output as dict()

        Output model variables as dictionary.

        Args:
            None

        Returns:
            dict: Dictionary of model variables with lists of values

        """
        output = dict(parameters=None, data=None)
        output['parameters'] = {
            p: getattr(self.params, p) for p in self.user_params
            if type(getattr(self.params, p)) in [type(10), type(.10)]
        }
        output['data'] = {
            p: list(getattr(self.vars, p)) for p in self.model_vars
        }
        return output