Chapter 7 Producer
import requests
response = requests.get("https://www.dropbox.com/s/cyp43ve6wyqnof1/consumers.py?dl=1")
output_file_object = open("consumers.py", "w")
output_file_object.writelines(response.text)
output_file_object.close()
from pathlib import Path
currentPath = Path()
if currentPath.cwd() not in sys.path:
sys.path.append(currentPath.cwd())
import consumers as cs
from numpy.random import default_rng
rng_alpha = default_rng(2020)
rng_beta = default_rng(3892)
size = 500
consumers500 = [
cs.Consumer(alpha, beta) for alpha, beta in zip(rng_alpha.uniform(300,500,size), rng_beta.uniform(5,30,size))
]- It is wise to close a file object when necessary operations are finished.
7.1 Monopoly
Suppose a monopoly has a constant marginal cost (mc) with no fixed cost. The producer sees market demand (i.e. aggregate demand, Qd), and decides market price. The quantity he can sell at a given price level is Qd(p)
class Monopoly:
def __init__(self, mc, Qd):
self.mc=mc
self.Qd=Qd
def cost(self, p):
return self.mc*self.Qd(p)
def revenue(self, p):
return p*self.Qd(p)
def profit(self, p):
return p*self.Qd(p) - self.mc *self.Qd(p)- A monopoly not only knows his own cost of production, but also knows exactly market demend (Qd).
7.1.1 Market demand
import numpy as np
def Qd(p):
return np.maximum(np.zeros(len(p)),100-2*p)
# np.zeros: generate array of zeros
# np.maximum: compare two arrays elementwise and choose the maximal one
prices = np.arange(1,101)
Qd(prices)Qdmaps 1-D array to
from scipy import optimize
monopoly=Monopoly(2, Qd)
monopoly.cost(np.array([3]))
monopoly.revenue(np.array([3]))
monopoly.profit(np.array([3]))7.1.2 Profit maximization
def negative_conversion(fn):
def neg_fun(p):
return -1*fn(p)
return neg_funobjective_negative=negative_conversion(monopoly.profit)optimize.minimize(
fun=negative_conversion(monopoly.profit),
x0=np.array([3])
)def monopoly_optim(x0=3):
optim = optimize.minimize(
fun=negative_conversion(monopoly.profit),
x0=np.array([x0])
)
return optimoptim = monopoly_optim()
optim.x
monopoly.Qd(optim.x)7.1.3 Class
class Monopoly:
def __init__(self, mc, Qd):
self.mc=mc
self.Qd=Qd
def cost(self, p):
return self.mc*self.Qd(p)
def revenue(self, p):
return p*self.Qd(p)
def profit(self, p):
return p*self.Qd(p) - self.mc *self.Qd(p)
def optimize(self, x0=3):
optim = optimize.minimize(
fun=negative_conversion(self.profit),
x0=np.array([x0])
)
self.optim_p = optim.x
self.optim_q = self.Qd(self.optim_p)
return optimmonopoly = Monopoly(5, Qd)
monopoly.Qd
monopoly.mcmonopoly.optimize()
monopoly.optim_p
monopoly.optim_q
monopoly.profit(monopoly.optim_p)7.2 Class variable
7.2.1 Class: Market Demand
class MarketDemand:
def __init__(self, intercept, slope):
self.intercept = intercept
self.slope = slope
def Qd(self, p):
return self.intercept - self.slope * pmarketDemand = MarketDemand(500, 7)
Qd = marketDemand.Qd
monopoly = Monopoly(10, Qd)
monopoly.optimize()
monopoly.optim_p
monopoly.optim_q7.2.2 Change of demand
marketDemand2 = MarketDemand(380, 5)
Qd = marketDemand2.Qd
# optimization will give the same result
monopoly.optimize()
monopoly.optim_p
monopoly.optim_q7.2.3 Class variable
import numpy as np
from scipy import optimize
class Monopoly:
intercept=100
slope=2
def __init__(self, mc):
self.mc=mc
def cost(self, p):
return self.mc*self.__class__.Qd(p)
def revenue(self, p):
return p*self.__class__.Qd(p)
def profit(self, p):
return p*self.__class__.Qd(p) - self.mc *self.__class__.Qd(p)
def optimize(self, x0=3):
optim_res = optimize.minimize(
fun=negative_conversion(self.profit),
x0=np.array([x0])
)
self.optim_p = optim_res.x
self.optim_q = self.__class__.Qd(self.optim_p)
return optim_res
@classmethod
def Qd(cls, p):
return cls.intercept - cls.slope*p
# helper
def negative_conversion(fn):
def neg_fun(p):
return -1*fn(p)
return neg_fun\[Qd(p)=100-2p\]
monopoly = Monopoly(5)
monopoly.Qd(3)\[Qd(p)=300-7p\]
Monopoly.intercept = 300
Monopoly.slope = 7
monopoly.Qd(3)Note that once class variables are changed. It stay that way until next change
monopoly2 = Monopoly(5) # will not go back to original Monopoly definition
monopoly2.Qd(3)Monopoly.intercept = 300
Monopoly.slope = 7
monopoly.optimize()
monopoly.optim_p
monopoly.optim_qMonopoly.intercept = 100
Monopoly.slope = 3
monopoly.optimize()
monopoly.optim_p
monopoly.optim_q7.3 Ex-Post Manipulation
Class variables and instance variables can be manipulated ex post – including adding and deletion.
class Apple:
pass # do nothing apple1 = Apple()
apple2 = Apple()# An instance variable
apple1.color = "red"
apple2.color = "green"
# A class variable
Apple.type = "fruit"# type is a class variable to all instances
apple1.__class__.type
apple2.__class__.type
# class variable can be accessed as it is an instance variables
# except all instances share the same value (common knowledge)
apple1.type
apple2.type
# instance variables
apple1.color
apple2.colorIf there is also an instance variable called type such as:
apple1.type = "animal" # instance variable creationThen apple1.type represents the instance variable instead of the class variable:
apple1.type
apple1.__class__.type # you still can access class variable (type) this wayDeletion:
del Apple.type
del apple1.color
del apple2.color
del apple1del can be used to delete any object in the environment:
del Apple7.4 Common knowledge
7.4.1 Market structure narrative
In a country where demand is always linear, any demand is an instance of LinearDemand class via:
class LinearDemand:
def __init__(self, intercept, slope):
self.intercept=intercept
self.slope=slope
demand = LinearDemand(intercept=300, slope=0.2)
demand.intercept
demand.slopeThere are three producers to serve the market: mono, duo, and trio. They are instances of the same Producer class.
How can we model the common knowledge demand for these three instances so that:
mono.demand
duo.demand
trio.demand
# all are aware of the SAME demandIn addition, whenever something changes to demand, such as:
demand.intercept=500all instance.demands changes as well.
7.4.2 Common in id
=: identical assignment
The first approach is to feed demand as instance variable when each instance is created. Consider the following class constructor:
class Producer:
def __init__(self, demand):
self.demand = demand
mono = Producer(demand)
duo = Producer(demand)- The design ensures that demand is in mono and duo’s knowledge domain (as an instance variable).
The above construction has:
print(id(demand))
print(id(mono.demand))
print(id(duo.demand))the same.
Change one will change all:
demand.slope += 2
demand.slope
mono.demand.slope
duo.demand.slopeHowever, the above common knowledge structure works only under the same ID source of instance variable. It can be breached easily when users accidentally create another new instance source and feed it into a new instance, such as:
import copy
demand = copy.deepcopy(demand)
trio = Producer(demand)
print(id(mono.demand))
print(id(duo.demand))
print(id(trio.demand)) # different from the other two
print(id(demand)) # same as trio, different from the other two
# change to demand
demand.intercept += 50
demand.intercept
# changes
trio.demand.intercept
# but not
mono.demand.intercept
duo.demand.intercept7.4.3 Common as class variables
If you want to ensure mono, duo, trio share the common knowledge of demand, you ought to make demand a class variable.
class Producer:
pass
mono = Producer()
duo = Producer()demand = LinearDemand(intercept=300, slope=0.2)
Producer.demand = demand
print(id(mono.demand))
print(id(duo.demand))
# create a new copy
demand = copy.deepcopy(demand)
print(id(demand))
# Attach new copy to Producer
Producer.demand = demand
# will immediately change each instance's knowledge
print(id(mono.demand))
print(id(duo.demand))- This is because the common knowledge ID comes from the class Producer – not from its own instance variable. This ensures each instance access the same source of demand knowledge.
Always model common knowledge across instances as their class variable.
7.5 Examples
7.5.1 Consumers
In an economy, there are many consumers with Cobb-Douglass utility: \[U(x_1, x_2)=x_1^\alpha x_2^{1-\alpha},\] with given prices \((p_1,p_2)\) and income \(I\). Optimal consumptions will be: \[x_1^*=\alpha*I/p_1,\ x_2^*=(1-\alpha)*I/p_2.\] Suppose there are 30 consumers randomly drawn from \(\alpha\sim uniform(0.2, 0.8)\) and \(I\sim uniform(500,1000)\)
from numpy.random import default_rng
alpha_s = default_rng(2038).uniform(0.2,0.8, size=30)
I_s = default_rng(2033).uniform(500,100, size=30)
class Consumer:
def __init__(self, alpha, I):
self.alpha = alpha
self.I = I
def optimise(self):
p1, p2 = self.__class__.p
self.x1 = self.alpha * self.I/p1
self.x2 = (1-self.alpha) * self.I/p2
consumers = [
Consumer(alpha, I) for alpha, I in zip(alpha_s, I_s)
]- note that class variable p is not assigned yet.
# Given p1=1, p2=1
p = (1, 1)
# Assign it as common knowledge for all consumers
Consumer.p = pOnce consumers share the common knowledge, they know how much they want to consume:
for i in range(len(consumers)):
consumers[i].optimise()
# check their decisions
consumers[0].x1
consumers[0].x2
consumers[22].x1
consumers[22].x2You can also:
for consumer_i in consumers:
consumer_i.optimise()
# check their decisions
consumers[0].x1
consumers[0].x2
consumers[22].x1
consumers[22].x2- The iterates from the iterable object are representing its element identically (i.e. sharing the same memory address).
7.5.2 Producers
An economy has many log production function producers. Each has production function: \[q(x)=\sqrt x,\] where \(x\) is some intermediate input quantity (such as labor). Assume intermediate input has a constant unit price \(w\) so that hiring \(x\) units of intermediate input will incur \(wx\) total cost while generating \(q(x)\) units of output and \(p q(x)\) total revenue. This means the producer’s total profit function is: \[\pi(x)=p\sqrt x-wx.\]
There are 10 producers in the economy whose \(w\) is randomly drawn from \(w\sim uniform(2, 5)\). They take market price \(p\) as their common knowledge. They are price taker. Optimal production of output will have: \[x^*=(p/w)^2/4,\ q^*=(p/w)/2\]
rng_w = default_rng(2033).uniform(2,5, size=10)
class Producer:
def __init__(self, w):
self.w=w
def optimise(self):
p = self.__class__.p
self.x = (p/self.w)**2 /4
self.q = (p/self.w)/2
producers = [
Producer(w) for w in rng_w
]- note that class variable p is not assignment yet.
# Given
p = 1
# Assign it as common knowledge for all producers
Producer.p = pOnce producers share the common knowledge, they know how many they want to produce:
for i in range(len(producers)):
producers[i].optimise()
# check their decisions
producers[0].x
producers[0].q
producers[7].x
producers[7].q7.5.3 Competitive markets
A (perfect) competition market consists of market demand, marke supply and an equilibrium condition that requires demand equal to supply to determine equilibrium price and quantity.
import numpy as np
from scipy.optimize import root
class Competitive_market:
def equilibrium(self):
excess_demand = lambda x: self.Qd(x) - self.Qs(x)
result = root(excess_demand, x0=np.array([1]))
self.P = result.x
self.Q = self.Qd(self.P)def excess_demand(x):
return Qd(x) - Qs(x)market = Competitive_market()
def Qd(p):
return max(0, 3-p)
def Qs(p):
return max(0, 0+2*p)
# supply Qd and Qs
market.Qd = Qd
market.Qs = Qs
market.equilibrium()
market.P
market.QWe can change Qd and Qs instance variables, and reuse optimise instance method:
def Qd(p):
Consumer.p = (p, 1)
total = 0
for consumer_i in consumers:
consumer_i.optimise()
total += consumer_i.x1
return total
def Qs(p):
Producer.p = p
total = 0
for producer_i in producers:
producer_i.optimise()
total += producer_i.q
return total
market.Qd = Qd
market.Qs = Qs
market.equilibrium()
market.P
market.Q7.6 綜合練習
1. Consumers
In an economy, there are many Cobb-Douglas preference consumers. Each faces a utility function \(U(\bf{x})\): \[U({\bf x})=x_1^{\alpha}x_2^{1-\alpha},\] where \({\bf x}=[x_1, x_2]\) is a vector representing the consumption of \((x_1, x_2)\) bundle.
For any consumer, say consumer \(i\), he faces a budget constraint: \[p_1x_1+p_2x_2\leq I_i,\] Assume that the market prices are \((p_1=2, p_2=5)\) at the current moment. We can give birth to a \((\alpha=0.3, I_i=200)\) consumer via:
alpha = 0.3
I = 200
consumer_i = Consumer(alpha, I)Once he is born, he:
# is aware of his budget constraint
consumer_i.describe_budget_constraint() # will generate his budget constraint at the following instance variable
consumer_i.budget_constraint # shows a dictionary object that represents the nonnegative budget constraint description as restriction optimization procedure requires
# knows his preference
consumer_i.U([2,3]) # shows utility of x1=2, x2=3 consumption
# is able to optimize
consumer_i.optimize() # generate consumer_i.x1 consumer_i.x2 to show the optimized x1, x2 consumption bundle.We describe the market prices change to \((p_1=2.5, p_2=4)\) via:
Consumer.p1=2.5
Consumer.p2=4Once the change is done, consumer_i can:
# re-optimize
consumer_i.optimize()
# which gives you a new optimal consumption bundle
consumer_i.x1
consumer_i.x2We can play God to give birth to 300 consumers via
from numpy.random import default_rng
rng_alpha = default_rng(2020)
rng_I = default_rng(2020)
world_alpha = rng_alpha.uniform(0.01, 0.99, size=300)
world_I = rng_I.uniform(500, 1000, size=300)
world_consumers = [Consumer(alpha, I) for alpha, I in zip(world_alpha, world_I)]Not only does world_consumers keep track of these 300 consumers, so does the class object Consumer keep the record as well, which can be checked via:
Consumer.world_consumersIn addition, whenever God is not happy, it can destroy all consumers via:
Consumer.destroy()which will turn Consumer.world_consumers into an empty list.
Design the Consumer class.
2. Market demand function
Given the Consumer from question 1, run the following code to generate 30 consumers:
from numpy.random import default_rng
rng_alpha = default_rng(2020)
rng_I = default_rng(2020)
world_alpha = rng_alpha.uniform(0.2, 0.8, size=30)
world_I = rng_I.uniform(500, 1000, size=30)
Consumer.destroy()
for alpha, I in zip(world_alpha, world_I):
Consumer(alpha, I)Complete the design of the following market demand function for \(x1\)
def Qd(class_consumer, p1):
....Given the construction of 30 consumers earlier,
Qd(Consumer, 3) # You can use a **class** as an input argument.will return the quantity of market demand at a price of p1=3 (which is around 4718), given the default value of Consumer.p2=5.
3. Cocky producer
Continue from the setting of question 1. There is only one producer Cocky who produces \(x_1\) (think it as chocolate cake). Cocky thinks his product is extremely unique so that the other commodity \(x_2\) (think it as bubble tea) is completely different and won’t affect Cocky’s profit – at least Cocky thinks so. At the current moment \(p_2=5\), Cocky think this price will continue to be that way no matter what price \(p_1\) he sets for \(x_1\).
Cocky is generated by a Producer1 class via:
cocky = Producer1(5, Consumer)where 5 is his marginal cost of production, and Consumer is the class Consumer you design earlier.
Cocky:
# knows his market quantity demanded at price p1=3 via:
cocky.Qd(3)
# Other than that, he can calculate his cost of production at price =3
cocky.cost(3)
# his revenue of production at price=3
cocky.revenue(3)
# his profit of production at price=3
cocky.profit(3)Cocky think the bubble tea will continue to charge at \(p_2=5\) as fixed via:
Consumer.p2 = 5Given that perception, Cocky chooses a price \(p_1\) to maximize his profit via:
cocky.optimize()
# his optimal price and output will show up at
cocky.p1 # around 9.99
cocky.x1 # around 1415You can play around with your simulated economy at different \(p_2\) price scenarios and see how Cocky would respond with his optimal \(p_1\). From the exercise, you can think about the following question:
Is there truly a pure monopoly in reality ?
同場加映(中間會有一首非常有名的曲子):
3. Prudent producer
Prue is the unique producer of \(x_2\). She grows up with Cocky; therefore, she know everything about Cocky. To model such an information structure, assume Prue is a instance generated by:
Prue = Producer2(2, Consumer, cocky)Different from Cocky, whenever Prue thinks of her market demand, she thinks of the ability of the influence of her price \(p_2\) on \(p_1\) as an instance method, prue.p1, which tells Prue what optimal p1 will be charge by Cocky. For example, to know how much Cocky will charge when Prue charges \(p_1=5\), he can:
prue.p1(5) # tell us what p1 will be when Prue set a price of 5Prue has two different types of market demands. One that take \(p_1\) as constant: \[\text{Qd_typeA} = Qd(p_2, p_1),\] the other takes \(p_1\) as an influced price of Prue’s \(p_2\), i.e. \[\text{Qd_typeB} = Qd(p_2, p_1^*(p_2)),\] where \(p_1^*(p_2)\) means the optimized price setting of \(p_1\) from Cocky given \(p_2\).
knitr::opts_chunk$set(message=F, eval=F)
klippy::klippy(lang=c("r","python"))