/// <summary>
        /// This example shows a simple AMPL iterative procedure implemented in AMPL.
        /// Must be executed with a solver supporting the suffix dunbdd
        /// </summary>
        /// <param name="args">
        /// The first string, if present, should point to the models directory
        /// </param>
        public static int Main(string[] args)
        {
            string modelDirectory = ((args != null) && (args.Length > 0)) ? args[0]
         : "../../models";

            /*
             * // If the AMPL installation directory is not in the system search path:
             * ampl.Environment env = new ampl.Environment(
             * "full path to the AMPL installation directory");
             * // Create an AMPL instance
             * using (AMPL a = new AMPL(env)) {}
             */

            // Create an AMPL instance
            using (AMPL ampl = new AMPL())
            {
                // Must be solved with a solver supporting the suffix dunbdd
                ampl.SetOption("solver", "cplex");

                modelDirectory += "/locationtransportation";
                ampl.SetOption("presolve", false);
                ampl.SetOption("omit_zero_rows", true);

                // Read the model.
                ampl.Read(modelDirectory + "/trnloc2.mod");
                ampl.ReadData(modelDirectory + "/trnloc.dat"); // TODO: set data
                                                               // programmatically

                // Get references to AMPL's model entities for easy access.
                Objective  shipCost    = ampl.GetObjective("Ship_Cost");
                Variable   maxShipCost = ampl.GetVariable("Max_Ship_Cost");
                Variable   buildVar    = ampl.GetVariable("Build");
                Constraint supply      = ampl.GetConstraint("Supply");
                Constraint demand      = ampl.GetConstraint("Demand");
                Parameter  numCutParam = ampl.GetParameter("nCUT");
                Parameter  cutType     = ampl.GetParameter("cut_type");
                Parameter  buildParam  = ampl.GetParameter("build");
                Parameter  supplyPrice = ampl.GetParameter("supply_price");
                Parameter  demandPrice = ampl.GetParameter("demand_price");

                numCutParam.Set(0);
                maxShipCost.Value = 0;
                double[] initialBuild = new double[ampl.GetSet("ORIG").Size];
                for (int i = 0; i < initialBuild.Length; i++)
                {
                    initialBuild[i] = 1;
                }
                buildParam.SetValues(initialBuild);
                int numCuts;
                for (numCuts = 1; ; numCuts++)
                {
                    Console.WriteLine("Iteration {0}", numCuts);
                    ampl.Display("build");
                    // Solve the subproblem.
                    ampl.Eval("solve Sub;");
                    string result = shipCost.Result;

                    if (result.Equals("infeasible"))
                    {
                        // Add a feasibility cut.
                        numCutParam.Set(numCuts);
                        cutType.Set(new ampl.Tuple(numCuts), "ray");
                        DataFrame dunbdd = supply.GetValues("dunbdd");
                        foreach (var row in dunbdd)
                        {
                            supplyPrice.Set(new ampl.Tuple(row[0], numCuts), row[1].Dbl);
                        }
                        dunbdd = demand.GetValues("dunbdd");
                        foreach (var row in dunbdd)
                        {
                            demandPrice.Set(new ampl.Tuple(row[0], numCuts), row[1].Dbl);
                        }
                    }
                    else if (shipCost.Value > maxShipCost.Value + 0.00001)
                    {
                        // Add an optimality cut.
                        numCutParam.Set(numCuts);
                        cutType.Set(new ampl.Tuple(numCuts), "point");
                        ampl.Display("Ship");
                        DataFrame duals = supply.GetValues();
                        foreach (var row in duals)
                        {
                            supplyPrice.Set(new ampl.Tuple(row[0], numCuts), row[1].Dbl);
                        }
                        duals = demand.GetValues();
                        foreach (var row in duals)
                        {
                            demandPrice.Set(new ampl.Tuple(row[0], numCuts), row[1].Dbl);
                        }
                    }
                    else
                    {
                        break;
                    }

                    // Re-solve the master problem.
                    Console.WriteLine("RE-SOLVING MASTER PROBLEM");
                    ampl.Eval("solve Master;");

                    // Copy the data from the Build variable used in the master problem
                    // to the build parameter used in the subproblem.
                    DataFrame data = buildVar.GetValues();
                    buildParam.SetValues(data);
                }
                ampl.Display("Ship");
            }
            return(0);
        }