Skip to content
This repository was archived by the owner on Jan 8, 2024. It is now read-only.

Model Description

Austin Drenski edited this page Feb 6, 2017 · 17 revisions

This page describes the organization of an ExPEM-type model. Each model is defined in four components:

  1. Structure
  2. Data
  3. Functions

1. Structure

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 />

2. Data

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>

3. Functions

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.
    }
}

Clone this wiki locally