-
Notifications
You must be signed in to change notification settings - Fork 1
Model Description
This page describes the organization of an ExPEM-type model. Each model is defined in four components:
The structure of an ExPEM-type model is described by an XML tree. For example, a model with one downstream sector made up of three upstream sectors would be defined as:
<!--- ModelStructure.xml --->
<?xml version="1.0" encoding="UTF-8"?>
<downstream1>
<upstream1 />
<upstream2 />
<upstream3 />
</downstream1>If each upstream sector was itself made up of two upstream sectors, then:
<!--- ModelStructure.xml --->
<?xml version="1.0" encoding="UTF-8"?>
<Downstream1>
<Upstream1 />
<SecondUpstream1 />
<SecondUpstream2 />
<Upstream2 />
<SecondUpstream1 />
<SecondUpstream2 />
<Upstream3 />
<SecondUpstream1 />
<SecondUpstream2 />
</Downstream1>These models are parsed in document-order, meaning:
1. <Downstream1 />
2. <Upstream1 />
3. <SecondUpstream1 />
4. <SecondUpstream2 />
5. <Upstream2 />
6. <SecondUpstream1 />
7. <SecondUpstream2 />
8. <Upstream3 />
9. <SecondUpstream1 />
10. <SecondUpstream2 />Data is read into the model from a delimited file that (1) contains a header row, and (2) follows the document-order described above. A data file containing prices and market shares would be formatted as:
ModelData.csv
Price,MarketShare
1.0,1.00
1.0,0.25
1.0,0.50
1.0,0.50
1.0,0.25
1.0,0.50
1.0,0.50
1.0,0.50
1.0,0.50
1.0,0.50
ModelData.csv will be read into the model using:
AD.PartialEquilibriumApi.DefineAttributeData(this XElement, DelimitedFilePath)Generating:
<!--- ModelStructure.xml + ModelData.xsv --->
<?xml version="1.0" encoding="UTF-8"?>
<Downstream1 Price="1.0" MarketShare="1.00" >
<Upstream1 Price="1.0" MarketShare="0.25" />
<SecondUpstream1 Price="1.0" MarketShare="0.50" />
<SecondUpstream2 Price="1.0" MarketShare="0.50" />
<Upstream2 Price="1.0" MarketShare="0.25" />
<SecondUpstream1 Price="1.0" MarketShare="0.50" />
<SecondUpstream2 Price="1.0" MarketShare="0.50" />
<Upstream3 Price="1.0" MarketShare="0.50" />
<SecondUpstream1 Price="1.0" MarketShare="0.50" />
<SecondUpstream2 Price="1.0" MarketShare="0.50" />
</Downstream1>The equations defining a model will vary with application. The AD.PartialEquilibriumApi defines basic functions for aggregating a model similar to the example.
public static class Program
{
public static void Main(string[] args)
{
// Define files from command line arguments
XmlFilePath structureFile = args[0];
DelimitedFilePath dataFile = args[1];
// Read the model description and data into an XElement
XElement model = XElement.Load(structureFile)
.DefineAttributeData(dataFile);
// Define a function that calculates something from the model
Func<double[], double> function =
x =>
{
XElement[] items = model.Elements().ToArray();
for (int i = 0; i < items.Length; i++)
{
items[i].SetAttributeValue("Price", x[i]);
}
return model.Elements()
.Select(y => (double) y.Attribute("Price")
*
(double) y.Attribute("MarketShare"))
.Select(y => y * y)
.Sum();
};
// Define simplex
Simplex simplex =
new Simplex(
numberOfSolutions: 9,
dimensions: 9,
lowerBound: 0,
upperBound: 1,
maximumIterations: 1000,
objectiveFunction: function
);
// Solve simplex
Solution result = simplex.Solve();
Console.WriteLine($"result.Value == {result.Value}");
// result.Value == 0.032317945744046984
// This result does not have an interpretation. The simplex is instructed to
// repeatedly pass a price vector populated with numbers strictly greater than
// 0.0 and strictly less than 1.0 to the function, and attempt to minimize the
// sum of the product of the prices and market shares.
// In a real model, the function might instead calculate a price for each
// element, each nest, and each sector. Then return some aggregation of those
// prices to the simplex. The takeaway is that any method call can be embedded
// inside of the Func<double[], double>, allowing for complicated LINQ queries
// to traverse the model for specific values.
}
}