Source code for pycirk.fundamental_operations

# -*- coding: utf-8 -*-
"""
Created on Wed Nov 2 12:05:08 2016

Description: Class to perform SUT and IOT transformations and balancing

Scope: Modelling circular economy policies in EEIOA

@author:Franco Donati
@institution:Leiden University CML
"""
import numpy as np
from numpy import linalg as ln


[docs]class Operations: """ Contains all basic operations to transform SUTs into IOTs and verify them It contains two subclasses defining two different trasformation methods PxP ITA Market share and Technical Coefficient methods note: It should be expanded to other transformation methods in the future """
[docs] def inv(x): """ Returns inverse by dividing by 1 and eliminating inf and nan values """ mask = (x == 0) x[~mask] = 1/x[~mask] return x
[docs] def delta_Y(Y, Yalt): """ method to calculate difference in Y Y = final demand baseline Yalt = final demand scenario """ return Y - Yalt
[docs] def delta_x(L, Lalt, y): """ method to calculate difference in q L = Leontief of baseline Lalt = Leontief of scenario """ return (L-Lalt) @ y
[docs] def verifyIOT(S, Y, W): x_out = np.sum(np.array(S), axis=1) + np.sum(np.array(Y), axis=1) x_in = np.sum(S, axis=0) + np.sum(W[:9], axis=0) with np.errstate(divide="ignore", invalid="ignore"): ver = x_out/x_in * 100 return np.nan_to_num(ver)
[docs] class PxP_ITA_TC: """ Model with Transformation Coefficients ProdxProd Industry Technology assumption """
[docs] def T(V, inv_diag_g): """ Transformation matrix T = inv(diag(g)) * V """ # V.transpose because it's in MAKE table instead of SUPPLY return inv_diag_g @ V.transpose()
[docs] def L(U, T, inv_diag_q): """ Input coefficients intermediates A = U * T * inv[diag (q)] Multiplier matrix L = (I-A)^-1 """ A = U @ T @ inv_diag_q # technical coefficient matrix A = np.nan_to_num(A) IA = np.identity(len(A)) - A return ln.inv(IA)
[docs] def B(R, T, inv_diag_q): """ Calculates extension intensity """ RT = R @ T return RT @ inv_diag_q # Input coefficients
[docs] def R(B, diag_q): """ Calculates absolute extensions """ return B @ diag_q
[docs] def Z(T, U): """ Intemediates Z = U * T """ return U @ T
[docs] class PxP_ITA_MSC: """ Model with Market Share Coef. Prod x Prod Industry Technology assumption """ # new update of numpy broke consistency of @ operator # where the exceptional behaviour appeared I substituted # @ with np.matmul(), this is to be changed in the future
[docs] def S(U, inv_diag_g): """ Intermediate coefficients Input requirements Z = U * inv(diag(g)) """ return U @ inv_diag_g
[docs] def D(V, inv_diag_q): """ Market share coefficients D = V * inv(diag(q)) """ # V.transpose because it's in MAKE table instead of SUPPLY return V.transpose() @ inv_diag_q
[docs] def A(inter_coef, D): """ Total requirement multipliers A = Z * D """ return np.matmul(inter_coef, D)
[docs] def L(A): """ Leontief inverse L = (I-A)^-1 """ IA = np.identity(len(A)) - A return ln.inv(IA)
[docs] def B(R, D, inv_diag_g): """ Calculates extensions intensities """ B_ = R @ inv_diag_g return np.matmul(B_, D)
[docs] def R(B, diag_q): """ Calculates absolute extensions """ return B @ diag_q
[docs] def Z(inter_coef, D, diag_q): """ Intermediates Z = inter_coef * D * diag(q) """ return np.matmul(inter_coef, D) @ diag_q
[docs] class IOT: """ General IOT operations subclass some methods repeat from other subclasses but it's good to have them divided for clarity """
[docs] def x(Z, Y): """ total product output s the sum of Si and y """ return np.sum(np.array(Z), axis=1) + np.sum(np.array(Y), axis=1)
[docs] def B(R, inv_diag_x): """ Calculates extensions intensities """ return R @ inv_diag_x
[docs] def R(B, diag_x): """ Calculates absolute extensions """ return B @ diag_x
[docs] def x_IAy(L, y): """ Total product ouput x = inv(I - A) * yi """ return np.dot(L, y)
[docs] def Z(A, diag_x): """ Total product ouput Z = A * diag_x """ return A @ diag_x
[docs] def A(Z, inv_diag_x): """ Technical coefficient matrix A = Z * inv(diag(x)) """ return Z @ inv_diag_x
[docs] def L(A): """ Leontief inverse L = (I-A)^-1 """ IA = np.identity(len(A)) - A return ln.inv(IA)
[docs] def bY(RY, inv_diag_yj): """ Calculates intensities of extensions in final demand Method for transformation matrix of bY (e.g. final demand emissions) """ return RY @ inv_diag_yj
[docs] def RY(bY, diag_yj): """ Caclculates absolute extensions in final demand """ return bY @ diag_yj
# is this function really needed?
[docs] def IOT(Z, Y, W, E, R, M): """ IOT """ x = Operations.IOT.x(Z, Y) # total product output diag_x = np.diag(x) inv_diag_x = Operations.inv(diag_x) y = np.sum(Y, axis=1) A = Operations.IOT.A(Z, inv_diag_x) # technical coefficient matrix L = Operations.IOT.L(A) # leontief inverse w = Operations.IOT.B(W, inv_diag_x) # primary inputs coef W = Operations.IOT.R(w, diag_x) e = Operations.IOT.B(E, inv_diag_x) # Be coefficient matrix E = Operations.IOT.R(e, diag_x) # environmental extensions r = Operations.IOT.B(R, inv_diag_x) # Br coefficient matrix R = Operations.IOT.R(r, diag_x) # resource extensions m = Operations.IOT.B(M, inv_diag_x) # Bm coefficient matrix M = Operations.IOT.R(m, diag_x) # Material extension Z = Operations.IOT.Z(A, diag_x) # intermediates x = Operations.IOT.x_IAy(L, y) ver_base = Operations.verifyIOT(Z, Y, E) return {"A": A, "Z": Z, "L": L, "Z": Z, "Y": Y, "w": w, "W": W, "x": x, "E": E, "e": e, "R": R, "r": r, "M": M, "m": m, "ver_base": ver_base }
[docs] def calculate_characterized(data): data.Cr_E = data.Cr_E_k @ np.array(data.E) data.Cr_M = data.Cr_M_k @ np.array(data.M) data.Cr_R = data.Cr_R_k @ np.array(data.R) data.Cr_W = data.Cr_W_k @ np.array(data.W) data.Cr_EY = data.Cr_E_k @ np.array(data.EY) data.Cr_MY = data.Cr_M_k @ np.array(data.MY) data.Cr_RY = data.Cr_R_k @ np.array(data.RY) data.Cr_tot_E = data.Cr_E.sum(axis=1) + data.Cr_EY.sum(axis=1) data.Cr_tot_M = data.Cr_M.sum(axis=1) + data.Cr_MY.sum(axis=1) data.Cr_tot_R = data.Cr_R.sum(axis=1) + data.Cr_RY.sum(axis=1) return data