Open cwarny opened 4 months ago
- Is an agent’s
wallet
variable the amount of each currency he carries?
Yes. The wallet of each agent is the current amount of each currency they possess.
- Does the current code assume each agent only produces one good?
Yes. However, every agent's good is unique from that of any other agent. When people buy goods, we allow them to value some higher than others (currently assigned randomly).
- What is an agent’s “demand” for a neighbor? Is it the demand for the one good the neighbor produces?
Yes, this. Specifically, when agents are trying to decide which is their "best vendor", they look at the difference between their demand for that vendor's good and the loss in value in their wallet they incur by paying for the good.
- I’m confused by the
pricing_assessments
variable. Can you explain what it means? Is it the conversion rate of the various currencies into USD? Is it an agent’s internal valuation in USD of each cause? Is it the “vector price” of the one good the agent is selling? If it reflects the price of something, I find the term “assessment” confusing, as it seems to imply that the agent choses prices, but prices typically aren’t chosen by anyone, they are given by the market.
The code currently does not have any way to relate the value of any of the tokens to USD (caused by difficulties not related to this question, happy to explain more if desired). Each agent has a price
variable, and valuations (both kinds) come in units of this price.
I use two different assessment vectors for each agent, one as the actual list of values the agent assigns to every token (inherited_assessments
), and one as the rate at which they are willing to accept each token as payment (pricing_assessments
). These can differ to allow the agent to try to "steal customers" by giving effective discounts with high valuations.
As an example, consider the case with only one currency. A vendor sells a good with a price
of 1. He has an inherited assessment of the currency at 0.33, and a pricing assessment at 0.5. When a buyer pays for the good, they use 2 units of currency to pay for the price of 1. However, the vendor's experienced utility from gaining that currency is only 0.66.
- What is the meaning of
np.dot(customer.wallet, pricing_assessments[neighbor])
(inget_best_vendors
)? My guess:pricing_assessments[neighbor]
is the “vector price” of the one good the vendor is selling and sonp.dot(customer.wallet, pricing_assessments[neighbor])
is the value the customer would get by spending his entire wallet on that one vendor. But then this value is multiplied bycustomer.demand[neighbor] / vendor.price
, which I take to mean the unit value to the customer of the one good the vendor is selling. And I don’t understand the meaning of the result. The code calls isutils_scale
, but it’s unclear what the meaning is.
This idea is close - thinking along the lines of the value the customer would get by spending his entire wallet on that one vendor specifically. We want to compute this quantity for every vendor, and then find the vendor that gives the agent the highest utility. The utility given by this highest vendor is what we choose to use to quantify the value of an index wallet.
However, this function specifically only needs to identify which vendor gives that highest utility. When I wrote it, I instead compare the utility given by the agent spending one unit (magnitude) of their wallet at each vendor. This is the meaning of the util_scale
variable. Since the size of the agent's wallet doesn't change between vendors, this comparison is equivalent.
The pricing_assessments
variable is not quite a vector price. It gives a list of the value the vendor gives to each currency when accepting them as payment. The price of every good is still scalar, given by vendor.price
. Adjusting the pricing_assessments
vector can change the experienced price paid by the agents in two ways.
- What is an agent’s
price
property? This seems to be a scalar. Is it the scalar price of the one good the agent is selling? It’s unclear to me if goods have a scalar price or a vector price.
Goods have a scalar price, given by the price
property. Depending on the composition of the buyer's wallet, and how closely that aligns with the vendor's pricing assessments, a different fraction of the buyer's wallet will need to be transferred to pay this price.
However, the fraction of each currency in the payment is always the same as the same fraction of that currency in the buyer's wallet.
- I don’t understand the profit function:
profit += ( np.dot(customer.wallet, state["inherited_assessments"][node]) / np.dot(customer.wallet, state["pricing_assessments"][node]) / (1 + len(best_vendors[customer_idx])) )
Can you explain how it works? I also don't understand the optimization linked to the profit function.
The optimization is used by a vendor to determine their optimal pricing_assessments
vector. They must balance giving discounts in order to "steal" customers from their competitors with losing profit per customer by giving this discount. This is the same fundamental idea as price setting in a normal economy, but now there is a multidimensional way to change prices (along each of the currencies individually).
This optimization happens in two steps. First, we need to determine which customers are worth selling to (meaning we give enough of a discount to get them to buy from us) and which aren't (meaning we don't give the discounts they need to buy from us). We currently do not have a good way to do this, and brute force search over every possible combination of customers.
The second step is to determine the best assessment for each customer combo. We do this with scipy's optimize library, adding constraints to make sure that our effective prices don't go high enough to prevent any of the customers in the current combo from buying from us. The profit function is the function we are optimizing.
The snippet you quoted here calculates the utility scale the vendor gains from receiving some currency from some customer. In the numerator, the np.dot(customer.wallet, state["inherited_assessments"][node])
term increases the closer the composition of the customers wallet is to the actual value the vendor assigns to each currency. If the vendor gets more of the currencies they value, they experience a greater utility. In the denominator, np.dot(customer.wallet, state["pricing_assessments"][node])
decreases profit with how close the customers wallet is to the value the vendor assigns to each currency as payment. If the vendor lets the customers payment go further, he receives less currency overall. Finally, the (1 + len(best_vendors[customer_idx]))
term in the denominator represents splitting the expected profit among all of the vendors that give the same utility scale to the buyer.
- I don't understand what "inherited assessment" means. What is the difference with pricing assessment?
The idea here is to get a scalar value of an agent's wallet, so we can figure out how muh they actually gain / lose when buying / selling. To do this, we look at how many copies of each good the agent could buy with all of their money for each of their vendors. Then, we multiply these by the demand the buyer has for each vendor's good, and take the maximum. This gives the "value of an index wallet".
We also want to break it down further to get a value the agent assigns to each currency. When an agent is taking a payment, the increase in the value of the wallet can only come from increasing our previous calculation, which happens at a rate proportional to how much more of the best good we can buy. So, to get the utility gained from a payment (i.e. the increase in the value of your wallet) as a single value, we can just dot product the payment with the pricing assessment of the "best vendor" from earlier.
This is what the inherited assessment is. It encodes the actual value an agent receives from each currency. It is called inherited because it comes directly from the valuation of some other node.
This isn't really an issue but I wasn't sure where else to ask my questions. I'm trying to understand the code to maybe see if I could have neural net players play the game with potentially more complex topologies or a larger economy (more goods traded) and see what comes out of it. But I'd like to understand what the current code does, so here are a bunch of questions:
Is an agent’s
wallet
variable the amount of each currency he carries?Does the current code assume each agent only produces one good?
What is an agent’s “demand” for a neighbor? Is it the demand for the one good the neighbor produces?
I’m confused by the
pricing_assessments
variable. Can you explain what it means? Is it the conversion rate of the various currencies into USD? Is it an agent’s internal valuation in USD of each cause? Is it the “vector price” of the one good the agent is selling? If it reflects the price of something, I find the term “assessment” confusing, as it seems to imply that the agent choses prices, but prices typically aren’t chosen by anyone, they are given by the market.What is the meaning of
np.dot(customer.wallet, pricing_assessments[neighbor])
(inget_best_vendors
)? My guess:pricing_assessments[neighbor]
is the “vector price” of the one good the vendor is selling and sonp.dot(customer.wallet, pricing_assessments[neighbor])
is the value the customer would get by spending his entire wallet on that one vendor. But then this value is multiplied bycustomer.demand[neighbor] / vendor.price
, which I take to mean the unit value to the customer of the one good the vendor is selling. And I don’t understand the meaning of the result. The code calls isutils_scale
, but it’s unclear what the meaning is.What is an agent’s
price
property? This seems to be a scalar. Is it the scalar price of the one good the agent is selling? It’s unclear to me if goods have a scalar price or a vector price.I don’t understand the profit function:
Can you explain how it works? I also don't understand the optimization linked to the profit function.
I don't understand what "inherited assessment" means. What is the difference with pricing assessment?