Example #1
0
        /// <summary>
        /// Computes the profit-maximizing decision (DECT0), given true costs and selling prices.
        /// </summary>
        /// <returns>A [1 x ip.CO] vector of 1's and 0's. 1.0 (0.0) indicates
        /// that the product is (not)included in the profit-maximizing product mix.</returns>
        public RowVector CalcOptimalDecision()
        {
            RowVector pc_b           = CalcTrueProductCosts();
            RowVector productProfits = this.sp - pc_b;
            // Replace each negative (nonnegative) element of productProfits with a 0.0 (1.0)
            var dect0 = productProfits.Map(x => ((x < 0.0) ? 0.0 : 1.0));

            return(new RowVector(dect0));
        }
Example #2
0
        /// <summary>
        /// Assuming the firm implements decision DECF0, this method computes
        /// reported costs for this cost system, which are used to compute the firm's updated decision.
        /// It iterates using the updated decision as the new starting decision until a terminal outcome
        /// (e.g. equilibrium, cycle) is reached.
        /// </summary>
        /// <param name="ip">The current InputParameters object</param>
        /// <param name="DECF0">The starting decision.</param>
        /// <returns>Returns the outcome of iterations and the final decision.</returns>
        public (CostSystemOutcomes stopCode, RowVector DECF1) EquilibriumCheck(InputParameters ip, RowVector DECF0)
        {
            #region Make local copies of firm-level variables

            ColumnVector MXQ = this.firm.MXQ;
            RowVector    SP  = this.firm.SP;

            #endregion

            // The initial vector of production quantities, given
            // starting decision DECF0
            ColumnVector q0 = MXQ.ewMultiply(DECF0);
            // A list of past decisions made during the iteration process.
            // If a decision appears twice on this list, then a cycle exists.
            List <RowVector> pastDecisions = new List <RowVector> {
                DECF0
            };
            // The "next" decision that the firm would make. Assume the firm
            // starts with DECF0, computes resulting resource consumption,
            // and reported costs (through the cost system). Given reported
            // costs, it updates its decision to DECF1.
            RowVector DECF1;

            bool               foundThisDecisionBefore;
            double             MAR_DROP = 1.0 - ip.HYSTERESIS;
            double             MAR_MAKE = 1.0 + ip.HYSTERESIS;
            CostSystemOutcomes stopCode = CostSystemOutcomes.Unassigned;

            bool done;
            do
            {
                RowVector PC_R = CalcReportedCosts(ip, DECF0);

                if (PC_R.Contains(double.NaN))
                {
                    DECF1 = PC_R.Map(x => double.NaN);
                }
                else
                {
                    double[] MAR   = PC_R.Zip(SP, (pc_r, sp) => sp / pc_r).ToArray();
                    var      decf1 = MAR.Zip(q0, (mar, q) =>
                                             (q > 0.0) ? ((mar <= MAR_DROP) ? 0.0 : 1.0) : ((mar > MAR_MAKE) ? 1.0 : 0.0));
                    DECF1 = new RowVector(decf1.ToList());
                }

                ColumnVector q1 = MXQ.ewMultiply(DECF1);
                if (!(foundThisDecisionBefore = pastDecisions.Contains(DECF1)))
                {
                    pastDecisions.Add(DECF1);
                }

                //double ExpectedCosts = PC_R * q1;
                //double TCF0 = this.firm.CalcTotCosts(q1);

                done = true;
                //if (q1 == q0) {
                if (DECF1 == DECF0)
                {
                    stopCode = CostSystemOutcomes.Equilibrium;
                }
                else if (q1.TrueForAll(qty => qty == 0.0))
                {
                    stopCode = CostSystemOutcomes.ZeroMix;
                }
                else if (foundThisDecisionBefore)
                {
                    stopCode = CostSystemOutcomes.Cycle;
                }
                else if (DECF1.Contains(double.NaN))
                {
                    stopCode = CostSystemOutcomes.NaN;
                }
                else
                {
                    done = false;
                }

                if (!done)
                {
                    DECF0 = DECF1;
                    q0    = q1;
                }
            } while (!done);

            return(stopCode, DECF1);
        }
Example #3
0
        /// <summary>
        /// Randomly generates a firm object (production technology and output market parameters).
        /// </summary>
        /// <param name="ip">A pointer to the collection of input parameters.</param>
        /// <param name="FirmID">Unique identifier for this firm (run number)</param>
        public Firm(InputParameters ip, int FirmID)
        {
            // Choose random values for DISP2 (the top DISP1 resources
            // account for DISP2 percent of total resource costs), and
            // density (sparsity) of resource consumption pattern matrix
            this.g = GenRandNumbers.GenUniformDbl(ip.DISP2_MIN, ip.DISP2_MAX);
            this.d = GenRandNumbers.GenUniformDbl(ip.DNS_MIN, ip.DNS_MAX);

            // Generate the true product margins and the true, optimal
            // decision vector. Keep generating new margins until there
            // is at least one product in the optimal mix.
            RowVector MAR, DECT0;

            do
            {
                MAR   = this.GenMargins(ip);
                DECT0 = MAR.Map(x => (x < 1.0) ? 0.0 : 1.0);
            } while (DECT0.TrueForAll(x => x == 0.0));

            // Generate vector of maximum production quantities
            this.mxq = this.GenMXQ(ip);
            // And associated vector of optimal production quantities
            ColumnVector QT = mxq.ewMultiply(DECT0);

            // Flowchart 5.1 - Create resource consumption pattern matrix
            this.res_cons_pat = GenResConsPat(ip);

            // Flowchart 5.2 - Compute TRU
            // Calculate vector of total units of resource
            // consumption, by product
            ColumnVector TRU = this.CalcResConsumption(QT);

            // Flowchart 5.3 - Compute MAXRU
            // Calculate resource consumption under the assumption
            // that all products are produced at maximum quantity
            ColumnVector MAXRU = this.CalcResConsumption(mxq);

            RowVector RCC, PC_B, RCCN;
            double    TCT0;

            #region Flowchart 5.4 - Generate RCC, RCU, and RCCN

            /* -------------------------------- */
            // Flowchart 5.4(a)-(g)

            // Generate vector of total resource costs (RCC)
            RCC = GenRCC(ip);

            /* -------------------------------- */
            // Flowchart 5.4(h)

            // Now generate unit resource costs (RCU) by doing element-wise
            // division of RCC by MAXRU
            this.rcu = RCC.Map((x, i) => x / MAXRU[i]);

            /* -------------------------------- */
            // Flowchart 5.4(i)

            // Compute new RCC vector (RCCN) based on unit resource
            // costs (RCU) and true unit resource consumption (TRU)
            RCCN = this.rcu.ewMultiply(TRU);
            // Check to see if the first resource (RCCN[0]) is the largest.
            // If not, increase RCU[0] by just enough to make it so.
            if (RCCN[0] < RCCN.Skip(1).Max() + 1)
            {
                RCCN[0]     = Math.Ceiling(RCCN.Max()) + 1.0;
                this.rcu[0] = RCCN[0] / TRU[0];
            }

            #endregion

            // Flowchart 5.5 - Calculate PC_B
            // Calculate true unit product costs
            PC_B = this.CalcTrueProductCosts();

            // Flowchart 5.6 - Compute total costs TCT0
            // Compute total costs
            TCT0 = this.CalcTotCosts(QT);

            // Flowchart 5.7 - Rename RCCN to RCC
            RCC         = RCCN;
            initial_rcc = RCC;

            #region Flowchart 5.8 - Calculate SP, TRV0, PROFITT0

            // Calculate product selling prices, total revenue, and profit
            this.sp = PC_B.ewMultiply(MAR);
            double TRV0 = this.sp * QT;
            this.profitt0 = TRV0 - TCT0;

            #endregion

            // 5.9(a) Create RANK vector
            // Note: this method provides a stable sort. It's important to use a stable sort.
            // LOOKUP IN VERSION.TXT WHY IT'S IMPORTANT TO USE A STABLE SORT HERE.
            initial_rank = Enumerable.Range(0, RCC.Dimension).OrderByDescending(i => RCC[i]).ToArray();

            #region Flowchart 5.9(b) - Create RES_CONS_PAT_PRCT

            this.res_cons_pat_prct = new RectangularMatrix(ip.RCP, ip.CO);

            for (int r = 0; r < this.res_cons_pat.RowCount; ++r)
            {
                RowVector rv = this.res_cons_pat.Row(r);
                if (TRU[r] != 0.0)
                {
                    rv = rv.Map((alt_ij, col) => alt_ij * QT[col] / TRU[r]);
                    if (Math.Abs(rv.Sum() - 1.0) > 0.01)
                    {
                        throw new ApplicationException("Sum of row of RES_CONS_PAT_PRCT not equal to 1.");
                    }
                }
                else
                {
                    rv = rv.Map(alt_ij => 0.0);
                }

                this.res_cons_pat_prct.CopyRowInto(rv, r);
            }

            #endregion

            #region Flowchart 5.9(c) - Create correlation matrix
            // Create correlation matrix for rows of RES_CONS_PAT_PRCT
            MultivariateSample mvs = new MultivariateSample(ip.RCP);
            for (int c = 0; c < this.res_cons_pat_prct.ColumnCount; ++c)
            {
                mvs.Add(this.res_cons_pat_prct.Column(c));
            }

            this.pearsoncorr = new SymmetricMatrix(ip.RCP);

            for (int i = 0; i < mvs.Dimension; ++i)
            {
                for (int j = i; j < mvs.Dimension; ++j)
                {
                    //PearsonCorr[i, j] = mvs.PearsonRTest( i, j ).Statistic;
                    this.pearsoncorr[i, j] = mvs.TwoColumns(i, j).PearsonRTest().Statistic;
                }
            }

            #endregion

            // Flowchart 5.10 - Logging true system
            // Note: I'm deliberately passing copies of the fields MXQ, SP, etc.
            Output.LogFirm(
                ip, this, FirmID,
                MAR, DECT0,
                TRV0, TCT0, profitt0,
                RCC);
        }
Example #4
0
        /// <summary>
        /// Generates a resource consumption pattern matrix
        /// </summary>
        /// <param name="ip">The current InputParameters object</param>
        private RectangularMatrix GenResConsPat(InputParameters ip)
        {
            bool throwAway;
            int  numThrows = 0;

            RectangularMatrix outputMatrix;

            do
            {
                throwAway    = false;
                outputMatrix = new RectangularMatrix(ip.RCP, ip.CO);

                // Flowchart 5.1(a): Generate vector X
                RowVector X = GenRandNumbers.GenStdNormalVec(ip.CO);

                // The following code is used in both 5.1(b) and 5.1(c):
                RowVector[] Y = new RowVector[ip.RCP - 1];
                RowVector[] Z = new RowVector[Y.Length];

                for (int i = 0; i < Y.Length; ++i)
                {
                    Y[i] = GenRandNumbers.GenStdNormalVec(ip.CO);
                }

                // Flowchart 5.1(b): Generate (DISP1 - 1) vectors Y
                // Then create Z vectors based on X and Y
                double COR1 =
                    GenRandNumbers.GenUniformDbl(ip.COR1LB, ip.COR1UB);
                double sqrtConstant1 = Math.Sqrt(1 - COR1 * COR1);
                for (int i = 0; i < ip.DISP1 - 1; ++i)
                {
                    Z[i] = (COR1 * X) + (sqrtConstant1 * Y[i]);
                }

                // Flowchart 5.1(c): Generate (RCP - DISP1) vectors Y
                // Then create the remaining Z vectors based on X and Y
                double COR2 =
                    GenRandNumbers.GenUniformDbl(ip.COR2LB, ip.COR2UB);
                double sqrtConstant2 = Math.Sqrt(1 - COR2 * COR2);
                for (int i = ip.DISP1 - 1; i < Z.Length; ++i)
                {
                    Z[i] = (COR2 * X) + (sqrtConstant2 * Y[i]);
                }

                // Flowchart 5.1(d):
                // Take the absolute values of X and the Z's and
                // scale both by 10.0.
                X = X.Map(x => 10.0 * Math.Abs(x));
                for (int i = 0; i < Z.Length; ++i)
                {
                    Z[i] = Z[i].Map(z => 10.0 * Math.Abs(z));
                }

                // Round X and the Z's to integers
                X = X.Map(x => Math.Ceiling(x));
                for (int i = 0; i < Z.Length; ++i)
                {
                    Z[i] = Z[i].Map(z => Math.Ceiling(z));
                }

                // Flowchart 5.1(e):
                // Now punch out values in the Z's at random to make
                // the matrix sparse
                for (int i = 0; i < Z.Length; ++i)
                {
                    Z[i] = Z[i].Map(x => ((GenRandNumbers.GenUniformDbl() < D) ? x : 0.0));
                }

                // Flowchart 5.1(f):
                // Copy X into first row of outputMatrix.
                outputMatrix.CopyRowInto(X, 0);
                // Copy the Z's into the remaining rows of outputMatrix.
                for (int i = 0; i < Z.Length; ++i)
                {
                    outputMatrix.CopyRowInto(Z[i], i + 1);
                }

                // Ensure that the first row has no zeros
                // There is a very small probability of getting a zero with
                // the Ceiling function, but given that there are a finite
                // number of double-precision floating point numbers, it
                // is not impossible to get a 0.0.
                double[] firstRow = outputMatrix.Row(0).ToArray();

                if (Array.Exists(firstRow, x => x == 0.0))
                {
                    throwAway = true;
                    break;
                }

                // Ensure that each *row* has at least one non-zero entry
                for (int i = 0; i < outputMatrix.RowCount; ++i)
                {
                    double[] nextRow = outputMatrix.Row(i).ToArray();

                    if (Array.TrueForAll(nextRow, x => x == 0.0))
                    {
                        throwAway = true;
                        break;
                    }
                }

                // Ensure that each *column* has at least one non-zero entry
                // Technically, this check is redundant, as the first row, X,
                // is not supposed to have any zero entries. But just to be
                // on the safe side...
                for (int j = 0; j < outputMatrix.ColumnCount; ++j)
                {
                    double[] nextCol = outputMatrix.Column(j).ToArray();

                    if (Array.TrueForAll(nextCol, x => x == 0.0))
                    {
                        string s = "There is a column with all zeros. " +
                                   "That should not happen since the first row is " +
                                   "supposed to have no zeros.";
                        throw new ApplicationException(s);
                    }
                }

                if (throwAway)
                {
                    ++numThrows;
                }
            } while (throwAway);

            Console.WriteLine("RES_CONS_PAT: {0} Throw aways\n", numThrows);

            return(outputMatrix);
        }