def save_constraint_analysis(cfp_m, utility, delta_util_x, delta_cons=0.01, prefix=None): from tools import write_columns_csv utility_given_delta_con = utility.adjusted_utility( cfp_m, first_period_consadj=delta_cons) delta_util_c = utility_given_delta_con - utility.utility(cfp_m) delta_con = find_bec(cfp_m, utility, delta_util_x) marginal_benefit = (delta_util_x / delta_util_c ) * delta_con * utility.cost.cons_per_ton / delta_cons delta_cons_billions = delta_con * utility.cost.cons_per_ton * utility.damage.bau.emit_level[ 0] delta_emission_gton = delta_cons * utility.damage.bau.emit_level[0] deadweight = delta_con * utility.cost.cons_per_ton / delta_cons if prefix is not None: prefix += "_" else: prefix = "" write_columns_csv([ delta_util_x, delta_util_c, [delta_con], marginal_benefit, [delta_cons_billions], [delta_emission_gton], [deadweight] ], prefix + "constraint_output", header=[ "Delta Utility Mitigation", "Delta Utility Consumption", "Delta Consumption", "Marginal Benefit", "Delta Consumption Billions", "Delta Emission GTon", "Deadweight" ])
def write_columns(self, file_name, header, start_year=2015, delimiter=";"): """Save values in `tree` as columns into file `file_name` in the 'data' directory in the current working directory. If there is no 'data' directory, one is created. +------------+------------+-----------+ | Year | Node | header | +============+============+===========+ | start_year | 0 | val0 | +------------+------------+-----------+ | .. | .. | .. | +------------+------------+-----------+ Parameters ---------- file_name : str name of saved file header : str description of values in tree start_year : int, optional start year of analysis delimiter : str, optional delimiter in file """ from tools import write_columns_csv, file_exists if file_exists(file_name): self.write_columns_existing(file_name, header) else: real_times = self.decision_times[:-1] years = [] nodes = [] output_lst = [] k = 0 for t in real_times: for n in range(len(self.tree[t])): years.append(t + start_year) nodes.append(k) output_lst.append(self.tree[t][n]) k += 1 write_columns_csv(lst=[output_lst], file_name=file_name, header=["Year", "Node", header], index=[years, nodes], delimiter=delimiter)
def write_columns(self, file_name, header, start_year): from tools import write_columns_csv, file_exists if file_exists(file_name): self.write_columns_existing(file_name, header) else: real_times = self.decision_times[:-1] years = [] nodes = [] output_lst = [] k = 0 for t in real_times: for n in range(len(self.tree[t])): years.append(t + start_year) nodes.append(k) output_lst.append(self.tree[t][n]) k += 1 write_columns_csv([output_lst], file_name, ["Year", "Node", header], [years, nodes])
def save_sensitivity_analysis(m, utility, utility_tree, cons_tree, cost_tree, ce_tree, prefix=None, return_delta_utility=False): """Calculate and save sensitivity analysis based on the optimal mitigation. For every sub-period, i.e. the periods given by the utility calculations, the function calculates and saves: * discount prices * net expected damages * expected damages * risk premium * expected SDF * cross SDF & damages * discounted expected damages * cov term * scaled net expected damages * scaled risk premiums into the file `prefix` + 'sensitivity_output' in the 'data' directory in the current working directory. Furthermore, for every node the function calculates and saves: * SDF * delta consumption * forward marginal utility * up-node marginal utility * down-node marginal utility into the file `prefix` + 'tree' in the 'data' directory in the current working directory. If there is no 'data' directory, one is created. Parameters ---------- m : ndarray or list array of mitigation utility : `Utility` object object of utility class utility_tree : `BigStorageTree` object utility values from optimal mitigation values cons_tree : `BigStorageTree` object consumption values from optimal mitigation values cost_tree : `SmallStorageTree` object cost values from optimal mitigation values ce_tree : `BigStorageTree` object certain equivalence values from optimal mitigation values prefix : str, optional prefix to be added to file_name """ from tools import write_columns_csv, append_to_existing sdf_tree = BigStorageTree(utility.period_len, utility.decision_times) sdf_tree.set_value(0, np.array([1.0])) discount_prices = np.zeros(len(sdf_tree)) net_expected_damages = np.zeros(len(sdf_tree)) expected_damages = np.zeros(len(sdf_tree)) risk_premiums = np.zeros(len(sdf_tree)) expected_sdf = np.zeros(len(sdf_tree)) cross_sdf_damages = np.zeros(len(sdf_tree)) discounted_expected_damages = np.zeros(len(sdf_tree)) net_discount_damages = np.zeros(len(sdf_tree)) cov_term = np.zeros(len(sdf_tree)) discount_prices[0] = 1.0 cost_sum = 0 end_price = find_term_structure(m, utility, 0.01) perp_yield = perpetuity_yield(end_price, sdf_tree.periods[-2]) delta_cons_tree, delta_cost_array, delta_utility = delta_consumption( m, utility, cons_tree, cost_tree, 0.01) mu_0, mu_1, mu_2 = utility.marginal_utility(m, utility_tree, cons_tree, cost_tree, ce_tree) sub_len = sdf_tree.subinterval_len i = 1 for period in sdf_tree.periods[1:]: node_period = sdf_tree.decision_interval(period) period_probs = utility.tree.get_probs_in_period(node_period) expected_damage = np.dot(delta_cons_tree[period], period_probs) expected_damages[i] = expected_damage if sdf_tree.is_information_period(period - sdf_tree.subinterval_len): total_probs = period_probs[::2] + period_probs[1::2] mu_temp = np.zeros(2 * len(mu_1[period - sub_len])) mu_temp[::2] = mu_1[period - sub_len] mu_temp[1::2] = mu_2[period - sub_len] sdf = (np.repeat(total_probs, 2) / period_probs) * ( mu_temp / np.repeat(mu_0[period - sub_len], 2)) period_sdf = np.repeat(sdf_tree.tree[period - sub_len], 2) * sdf else: sdf = mu_1[period - sub_len] / mu_0[period - sub_len] period_sdf = sdf_tree[period - sub_len] * sdf expected_sdf[i] = np.dot(period_sdf, period_probs) cross_sdf_damages[i] = np.dot(period_sdf, delta_cons_tree[period] * period_probs) cov_term[i] = cross_sdf_damages[i] - expected_sdf[i] * expected_damage discount_prices[i] = expected_sdf[i] sdf_tree.set_value(period, period_sdf) if i < len(delta_cost_array): net_discount_damages[i] = -(expected_damage + delta_cost_array[ i, 1]) * expected_sdf[i] / delta_cons_tree[0] cost_sum += -delta_cost_array[ i, 1] * expected_sdf[i] / delta_cons_tree[0] else: net_discount_damages[ i] = -expected_damage * expected_sdf[i] / delta_cons_tree[0] risk_premiums[i] = -cov_term[i] / delta_cons_tree[0] discounted_expected_damages[ i] = -expected_damage * expected_sdf[i] / delta_cons_tree[0] i += 1 damage_scale = utility.cost.price( 0, m[0], 0) / (net_discount_damages.sum() + risk_premiums.sum()) scaled_discounted_ed = net_discount_damages * damage_scale scaled_risk_premiums = risk_premiums * damage_scale if prefix is not None: prefix += "_" else: prefix = "" write_columns_csv([ discount_prices, net_discount_damages, expected_damages, risk_premiums, expected_sdf, cross_sdf_damages, discounted_expected_damages, cov_term, scaled_discounted_ed, scaled_risk_premiums ], prefix + "sensitivity_output", [ "Year", "Discount Prices", "Net Expected Damages", "Expected Damages", "Risk Premium", "Expected SDF", "Cross SDF & Damages", "Discounted Expected Damages", "Cov Term", "Scaled Net Expected Damages", "Scaled Risk Premiums" ], [sdf_tree.periods.astype(int) + 2015]) append_to_existing( [[end_price], [perp_yield], [scaled_discounted_ed.sum()], [scaled_risk_premiums.sum()], [utility.cost.price(0, m[0], 0)], cost_sum], prefix + "sensitivity_output", header=[ "Zero Bound Price", "Perp Yield", "Expected Damages", "Risk Premium", "SCC", "Sum Delta Cost" ], start_char='\n') store_trees(prefix=prefix, SDF=sdf_tree, DeltaConsumption=delta_cons_tree, MU_0=mu_0, MU_1=mu_1, MU_2=mu_2) if return_delta_utility: return delta_utility
def save_output(m, utility, utility_tree, cons_tree, cost_tree, ce_tree, prefix=None): """Save the result of optimization and calculated values based on optimal mitigation. For every node the function calculates and saves: * average mitigation * average emission * GHG level * SCC into the file `prefix` + 'node_period_output' in the 'data' directory in the current working directory. For every period the function calculates and appends: * expected SCC/price * expected mitigation * expected emission into the file `prefix` + 'node_period_output' in the 'data' directory in the current working directory. The function also saves the values stored in the `BaseStorageTree` object parameters to a file called `prefix` + 'tree' in the 'data' directory in the current working directory. If there is no 'data' directory, one is created. Parameters ---------- m : ndarray or list array of mitigation utility : `Utility` object object of utility class utility_tree : `BigStorageTree` object utility values from optimal mitigation values cons_tree : `BigStorageTree` object consumption values from optimal mitigation values cost_tree : `SmallStorageTree` object cost values from optimal mitigation values ce_tree : `BigStorageTree` object certain equivalence values from optimal mitigation values prefix : str, optional prefix to be added to file_name """ from tools import write_columns_csv, append_to_existing bau = utility.damage.bau tree = utility.tree periods = tree.num_periods prices = np.zeros(len(m)) ave_mitigations = np.zeros(len(m)) ave_emissions = np.zeros(len(m)) expected_period_price = np.zeros(periods) expected_period_mitigation = np.zeros(periods) expected_period_emissions = np.zeros(periods) additional_emissions = additional_ghg_emission(m, utility) ghg_levels = utility.damage.ghg_level(m) periods = tree.num_periods for period in range(0, periods): years = tree.decision_times[period] period_years = tree.decision_times[period + 1] - tree.decision_times[period] nodes = tree.get_nodes_in_period(period) num_nodes_period = 1 + nodes[1] - nodes[0] period_lens = tree.decision_times[:period + 1] for node in range(nodes[0], nodes[1] + 1): path = np.array(tree.get_path(node, period)) new_m = m[path] mean_mitigation = np.dot(new_m, period_lens) / years price = utility.cost.price(years, m[node], mean_mitigation) prices[node] = price ave_mitigations[node] = utility.damage.average_mitigation_node( m, node, period) ave_emissions[node] = additional_emissions[node] / ( period_years * bau.emission_to_bau) probs = tree.get_probs_in_period(period) expected_period_price[period] = np.dot(prices[nodes[0]:nodes[1] + 1], probs) expected_period_mitigation[period] = np.dot( ave_mitigations[nodes[0]:nodes[1] + 1], probs) expected_period_emissions[period] = np.dot( ave_emissions[nodes[0]:nodes[1] + 1], probs) if prefix is not None: prefix += "_" else: prefix = "" write_columns_csv([m, prices, ave_mitigations, ave_emissions, ghg_levels], prefix + "node_period_output", [ "Node", "Mitigation", "Prices", "Average Mitigation", "Average Emission", "GHG Level" ], [range(len(m))]) append_to_existing([ expected_period_price, expected_period_mitigation, expected_period_emissions ], prefix + "node_period_output", header=[ "Period", "Expected Price", "Expected Mitigation", "Expected Emission" ], index=[range(periods)], start_char='\n') store_trees(prefix=prefix, Utility=utility_tree, Consumption=cons_tree, Cost=cost_tree, CertainEquivalence=ce_tree)
def save_sensitivity_analysis(m, utility, utility_tree, cons_tree, cost_tree, ce_tree, new_cons_tree, cost_array, start_filename): """ create_output in dlw_optimization. Maybe we only want to use gradient desecent here""" from tools import write_columns_csv sdf_tree = BigStorageTree(utility.period_len, utility.decision_times) sdf_tree.set_value(0, np.array([1.0])) discount_prices = np.zeros(len(sdf_tree)) net_expected_damages = np.zeros(len(sdf_tree)) expected_damages = np.zeros(len(sdf_tree)) risk_premiums = np.zeros(len(sdf_tree)) expected_sdf = np.zeros(len(sdf_tree)) cross_sdf_damages = np.zeros(len(sdf_tree)) discounted_expected_damages = np.zeros(len(sdf_tree)) net_discount_damages = np.zeros(len(sdf_tree)) cov_term = np.zeros(len(sdf_tree)) discount_prices[0] = 1.0 cost_sum = 0 end_price = find_term_structure(m, utility, len(utility_tree), 0.01) perp_yield = perpetuity_yield(end_price, sdf_tree.periods[-2]) print("Zero coupon bond maturing in {} has price {} and yield {}".format( sdf_tree.periods[-2], end_price, perp_yield)) #grad = utility.numerical_gradient(m) #years_to_maturity = utility_tree.last_period - utility_tree.subinterval_len mu_0, mu_1, mu_2 = utility.marginal_utility(m, utility_tree, cons_tree, cost_tree, ce_tree) sub_len = sdf_tree.subinterval_len i = 1 for period in sdf_tree.periods[1:]: node_period = sdf_tree.decision_interval(period) period_probs = utility.tree.get_probs_in_period(node_period) expected_damage = np.dot(new_cons_tree[period], period_probs) expected_damages[i] = expected_damage if sdf_tree.is_information_period(period - sdf_tree.subinterval_len): total_probs = period_probs[::2] + period_probs[1::2] mu_temp = np.zeros(2 * len(mu_1[period - sub_len])) mu_temp[::2] = mu_1[period - sub_len] mu_temp[1::2] = mu_2[period - sub_len] sdf = (np.repeat(total_probs, 2) / period_probs) * ( mu_temp / np.repeat(mu_0[period - sub_len], 2)) period_sdf = np.repeat(sdf_tree.tree[period - sub_len], 2) * sdf else: sdf = mu_1[period - sub_len] / mu_0[period - sub_len] period_sdf = sdf_tree[period - sub_len] * sdf expected_sdf[i] = np.dot(period_sdf, period_probs) cross_sdf_damages[i] = np.dot(period_sdf, new_cons_tree[period] * period_probs) cov_term[i] = cross_sdf_damages[i] - expected_sdf[i] * expected_damage discount_prices[i] = expected_sdf[i] sdf_tree.set_value(period, period_sdf) if i < len(cost_array): net_discount_damages[i] = -(expected_damage + cost_array[ i, 1]) * expected_sdf[i] / new_cons_tree.tree[0] cost_sum += -cost_array[ i, 1] * expected_sdf[i] / new_cons_tree.tree[0] else: net_discount_damages[ i] = -expected_damage * expected_sdf[i] / new_cons_tree.tree[0] risk_premiums[i] = -cov_term[i] / new_cons_tree.tree[0] discounted_expected_damages[ i] = -expected_damage * expected_sdf[i] / new_cons_tree.tree[0] i += 1 damage_scale = utility.cost.price( 0, m[0], 0) / (net_discount_damages.sum() + risk_premiums.sum()) scaled_discounted_ed = net_discount_damages * damage_scale scaled_risk_premiums = risk_premiums * damage_scale write_columns_csv([ discount_prices, net_discount_damages, expected_damages, risk_premiums, expected_sdf, cross_sdf_damages, discounted_expected_damages, cov_term, scaled_discounted_ed, scaled_risk_premiums ], start_filename + "sensitivity_output", [ "Year", "Discount Prices", "Net Expected Damages", "Expected Damages", "Risk Premium", "Expected SDF", "Cross SDF & Damages", "Discounted Expected Damages", "Cov Term", "Scaled Net Expected Damages", "Scaled Risk Premiums" ], [sdf_tree.periods.astype(int) + 2015]) store_trees(prefix=start_filename, SDF=sdf_tree, DeltaConsumption=new_cons_tree, MU_0=mu_0, MU_1=mu_1, MU_2=mu_2)
def save_output(m, utility, utility_tree, cons_tree, cost_tree, ce_tree, delta_cons_analysis=True, constraint_first_period=True, directory=None, prefix=None): from tools import write_columns_csv, append_to_existing import os bau = utility.damage.bau tree = utility.tree periods = tree.num_periods prices = np.zeros(len(m)) ave_mitigations = np.zeros(len(m)) ave_emissions = np.zeros(len(m)) expected_period_price = np.zeros(periods) expected_period_mitigation = np.zeros(periods) expected_period_emissions = np.zeros(periods) additional_emissions = additional_ghg_emission(m, utility) ghg_levels = ghg_level(utility, additional_emissions) periods = tree.num_periods for period in range(0, periods): years = tree.decision_times[period] nodes = tree.get_nodes_in_period(period) num_nodes_period = 1 + nodes[1] - nodes[0] period_lens = tree.decision_times[:period + 1] for node in range(nodes[0], nodes[1] + 1): path = np.array(tree.get_path(node, period)) new_m = m[path] mean_mitigation = np.dot(new_m, period_lens) / years price = utility.cost.price(years, m[node], mean_mitigation) prices[node] = price ave_mitigations[node] = utility.damage.average_mitigation_node( m, node, period) ave_emissions[node] = additional_emissions[node] / ( num_nodes_period * bau.emission_to_bau) probs = tree.get_probs_in_period(period) expected_period_price[period] = np.dot(prices[nodes[0]:nodes[1] + 1], probs) expected_period_mitigation[period] = np.dot( ave_mitigations[nodes[0]:nodes[1] + 1], probs) expected_period_emissions[period] = np.dot( ave_emissions[nodes[0]:nodes[1] + 1], probs) if directory is not None: start_filename = directory + os.path.sep else: start_filename = "" if prefix is not None: prefix += "_" else: prefix = "" write_columns_csv([prices, m, ave_mitigations, ave_emissions, ghg_levels], start_filename + prefix + "node_period_output", [ "Node", "Mitigation", "Prices", "Average Mitigation", "Average Emission", "GHG Level" ], [range(len(m))]) append_to_existing([ expected_period_price, expected_period_mitigation, expected_period_emissions ], start_filename + prefix + "node_period_output", header=[ "Period", "Expected Price", "Expected Mitigation", "Expected Emission" ], index=[range(periods)]) store_trees(prefix=start_filename + prefix, Utility=utility_tree, Consumption=cons_tree, Cost=cost_tree, CertainEquivalence=ce_tree)
def _write_to_file(self): filename = "simulated_damages" write_columns_csv(self.d[0].T, filename) for arr in self.d[1:]: append_to_existing(arr.T, filename, start_char='#')