Exemple #1
0
    internal static void PopulateByNonzero(IMPModeler model,
                                           INumVar[][] var,
                                           IRange[][] rng)
    {
        double[]  lb = { 0.0, 0.0, 0.0 };
        double[]  ub = { 40.0, System.Double.MaxValue, System.Double.MaxValue };
        INumVar[] x  = model.NumVarArray(3, lb, ub);
        var[0] = x;

        double[] objvals = { 1.0, 2.0, 3.0 };
        model.Add(model.Maximize(model.ScalProd(x, objvals)));

        rng[0]    = new IRange[2];
        rng[0][0] = model.AddRange(-System.Double.MaxValue, 20.0);
        rng[0][1] = model.AddRange(-System.Double.MaxValue, 30.0);

        rng[0][0].Expr = model.Sum(model.Prod(-1.0, x[0]),
                                   model.Prod(1.0, x[1]),
                                   model.Prod(1.0, x[2]));
        rng[0][1].Expr = model.Sum(model.Prod(1.0, x[0]),
                                   model.Prod(-3.0, x[1]),
                                   model.Prod(1.0, x[2]));
        x[0].Name = "x1";
        x[1].Name = "x2";
        x[2].Name = "x3";

        rng[0][0].Name = "c1";
        rng[0][0].Name = "c2";
    }
Exemple #2
0
    internal static void PopulateByColumn(IMPModeler model,
                                          INumVar[][] var,
                                          IRange[][] rng)
    {
        IObjective obj = model.AddMaximize();

        rng[0]    = new IRange[2];
        rng[0][0] = model.AddRange(-System.Double.MaxValue, 20.0, "c1");
        rng[0][1] = model.AddRange(-System.Double.MaxValue, 30.0, "c2");

        IRange r0 = rng[0][0];
        IRange r1 = rng[0][1];

        var[0]    = new INumVar[3];
        var[0][0] = model.NumVar(model.Column(obj, 1.0).And(
                                     model.Column(r0, -1.0).And(
                                         model.Column(r1, 1.0))),
                                 0.0, 40.0, "x1");
        var[0][1] = model.NumVar(model.Column(obj, 2.0).And(
                                     model.Column(r0, 1.0).And(
                                         model.Column(r1, -3.0))),
                                 0.0, System.Double.MaxValue, "x2");
        var[0][2] = model.NumVar(model.Column(obj, 3.0).And(
                                     model.Column(r0, 1.0).And(
                                         model.Column(r1, 1.0))),
                                 0.0, System.Double.MaxValue, "x3");
    }
Exemple #3
0
    internal static INumVar[] populateByRow(IMPModeler model,
                                            IRange[]     row)
    {
        double[]  lb = { 0.0, 0.0, 0.0 };
        double[]  ub = { 40.0, System.Double.MaxValue, System.Double.MaxValue };
        INumVar[] x  = model.NumVarArray(3, lb, ub);

        // - x0 +   x1 + x2 <= 20
        //   x0 - 3*x1 + x2 <= 30
        double[][] val = { new double[] { -1.0,  1.0, 1.0 },
                           new double[] {  1.0, -3.0, 1.0 } };
        row[0] = model.AddLe(model.ScalProd(val[0], x), 20.0);
        row[1] = model.AddLe(model.ScalProd(val[1], x), 30.0);

        // x0*x0 + x1*x1 + x2*x2 <= 1.0
        row[2] = model.AddLe(model.Sum(model.Prod(x[0], x[0]),
                                       model.Prod(x[1], x[1]),
                                       model.Prod(x[2], x[2])), 1.0);

        // Q = 0.5 ( 33*x0*x0 + 22*x1*x1 + 11*x2*x2 - 12*x0*x1 - 23*x1*x2 )
        INumExpr x00 = model.Prod(33.0, x[0], x[0]);
        INumExpr x11 = model.Prod(22.0, x[1], x[1]);
        INumExpr x22 = model.Prod(11.0, x[2], x[2]);
        INumExpr x01 = model.Prod(-12.0, x[0], x[1]);
        INumExpr x12 = model.Prod(-23.0, x[1], x[2]);
        INumExpr Q   = model.Prod(0.5, model.Sum(x00, x11, x22, x01, x12));

        // maximize x0 + 2*x1 + 3*x2 + Q
        double[] objvals = { 1.0, 2.0, 3.0 };
        model.Add(model.Maximize(model.Diff(model.ScalProd(x, objvals), Q)));

        return(x);
    }
Exemple #4
0
    internal static ILPMatrix PopulateByRow(IMPModeler model)
    {
        ILPMatrix lp = model.AddLPMatrix();

        double[]  lb = { 0.0, 0.0, 0.0 };
        double[]  ub = { 40.0, System.Double.MaxValue, System.Double.MaxValue };
        INumVar[] x  = model.NumVarArray(model.ColumnArray(lp, 3), lb, ub);

        // - x0 +   x1 + x2 <= 20
        //   x0 - 3*x1 + x2 <= 30
        double[]   lhs = { -System.Double.MaxValue, -System.Double.MaxValue };
        double[]   rhs = { 20.0, 30.0 };
        double[][] val = { new double[] { -1.0,  1.0, 1.0 },
                           new double[] {  1.0, -3.0, 1.0 } };
        int[][]    ind = { new int[] { 0, 1, 2 },
                           new int[] { 0, 1, 2 } };
        lp.AddRows(lhs, rhs, ind, val);

        // Q = 0.5 ( 33*x0*x0 + 22*x1*x1 + 11*x2*x2 - 12*x0*x1 - 23*x1*x2 )
        INumExpr x00 = model.Prod(33.0, model.Square(x[0]));
        INumExpr x11 = model.Prod(22.0, model.Square(x[1]));
        INumExpr x22 = model.Prod(11.0, model.Square(x[2]));
        INumExpr x01 = model.Prod(-12.0, model.Prod(x[0], x[1]));
        INumExpr x12 = model.Prod(-23.0, model.Prod(x[1], x[2]));
        INumExpr Q   = model.Prod(0.5, model.Sum(x00, x11, x22, x01, x12));

        // maximize x0 + 2*x1 + 3*x2 + Q
        double[] objvals = { 1.0, 2.0, 3.0 };
        model.Add(model.Maximize(model.Diff(model.ScalProd(x, objvals), Q)));

        return(lp);
    }
Exemple #5
0
    // To populate by row, we first create the variables, and then use them to
    // create the range constraints and objective.  The model we create is:
    //
    // Minimize
    //  obj:   - 0.5 (-3 * xˆ2 - 3 * yˆ2 - 1 * x * y)
    // Subject To
    //  c1: -x + y >= 0
    //  c2:  x + y >= 0
    // Bounds
    //  -1 <= x <= 1
    //   0 <= y <= 1
    // End

    internal static ILPMatrix PopulateByRow(IMPModeler model)
    {
        ILPMatrix lp = model.AddLPMatrix();

        double[]  lb = { -1.0, 0.0 };
        double[]  ub = { 1.0, 1.0 };
        INumVar[] x  = model.NumVarArray(model.ColumnArray(lp, 2), lb, ub);

        double[]   lhs = { 0.0, 0.0 };
        double[]   rhs = { System.Double.MaxValue, System.Double.MaxValue };
        double[][] val = { new double[] { -1.0, 1.0 },
                           new double[] {  1.0, 1.0 } };
        int[][]    ind = { new int[] { 0, 1 },
                           new int[] { 0, 1 } };
        lp.AddRows(lhs, rhs, ind, val);

        INumExpr x00 = model.Prod(-3.0, x[0], x[0]);
        INumExpr x11 = model.Prod(-3.0, x[1], x[1]);
        INumExpr x01 = model.Prod(-1.0, x[0], x[1]);
        INumExpr Q   = model.Prod(0.5, model.Sum(x00, x11, x01));

        model.Add(model.Minimize(Q));

        return(lp);
    }
Exemple #6
0
    // To populate by row, we first create the variables, and then use them to
    // create the range constraints and objective.  The model we create is:
    //
    // Minimize
    //  obj:   - 0.5 (-3 * xˆ2 - 3 * yˆ2 - 1 * x * y)
    // Subject To
    //  c1: -x + y >= 0
    //  c2:  x + y >= 0
    // Bounds
    //  -1 <= x <= 1
    //   0 <= y <= 1
    // End
    internal static ILPMatrix PopulateByRow(IMPModeler model)
    {
        ILPMatrix lp = model.AddLPMatrix();

          double[]    lb = {-1.0, 0.0};
          double[]    ub = { 1.0, 1.0};
          INumVar[] x  = model.NumVarArray(model.ColumnArray(lp, 2), lb, ub);

          double[]   lhs = {0.0, 0.0};
          double[]   rhs = {System.Double.MaxValue, System.Double.MaxValue};
          double[][] val = {new double[] {-1.0, 1.0},
                        new double[] { 1.0, 1.0}};
          int[][]    ind = {new int[] {0, 1},
                        new int[] {0, 1}};
          lp.AddRows(lhs, rhs, ind, val);

          INumExpr x00 = model.Prod(-3.0, x[0], x[0]);
          INumExpr x11 = model.Prod(-3.0, x[1], x[1]);
          INumExpr x01 = model.Prod(-1.0, x[0], x[1]);
          INumExpr Q   = model.Prod(0.5, model.Sum(x00, x11, x01));

          model.Add(model.Minimize(Q));

          return (lp);
    }
Exemple #7
0
    internal static void PopulateByRow(IMPModeler model,
                                       INumVar[][] var,
                                       IRange[][]  rng)
    {
        //  First define the variables, three continuous and one integer
        double[]     xlb = { 0.0, 0.0, 0.0, 2.0 };
        double[]     xub = { 40.0,                      System.Double.MaxValue,
                             System.Double.MaxValue, 3.0 };
        NumVarType[] xt = { NumVarType.Float, NumVarType.Float,
                            NumVarType.Float, NumVarType.Int };
        INumVar[]    x = model.NumVarArray(4, xlb, xub, xt);
        var[0] = x;

        // Objective Function:  maximize x0 + 2*x1 + 3*x2 + x3
        double[] objvals = { 1.0, 2.0, 3.0, 1.0 };
        model.AddMaximize(model.ScalProd(x, objvals));

        // Three constraints
        rng[0] = new IRange[3];
        // - x0 + x1 + x2 + 10*x3 <= 20
        rng[0][0] = model.AddLe(model.Sum(model.Prod(-1.0, x[0]),
                                          model.Prod(1.0, x[1]),
                                          model.Prod(1.0, x[2]),
                                          model.Prod(10.0, x[3])), 20.0);
        // x0 - 3*x1 + x2 <= 30
        rng[0][1] = model.AddLe(model.Sum(model.Prod(1.0, x[0]),
                                          model.Prod(-3.0, x[1]),
                                          model.Prod(1.0, x[2])), 30.0);
        // x1 - 3.5*x3 = 0
        rng[0][2] = model.AddEq(model.Sum(model.Prod(1.0, x[1]),
                                          model.Prod(-3.5, x[3])), 0.0);
    }
Exemple #8
0
   internal static void PopulateByRow (IMPModeler  model,
                                       INumVar[][] var,
                                       IRange[][]  rng) {
      //  First define the variables, three continuous and one integer
      double[]        xlb = {0.0, 0.0, 0.0, 2.0};
      double[]        xub = {40.0, System.Double.MaxValue,
                                   System.Double.MaxValue, 3.0};
      NumVarType[] xt  = {NumVarType.Float, NumVarType.Float,
                          NumVarType.Float, NumVarType.Int};
      INumVar[]     x  = model.NumVarArray(4, xlb, xub, xt);
      var[0] = x;

      // Objective Function:  maximize x0 + 2*x1 + 3*x2 + x3
      double[] objvals = {1.0, 2.0, 3.0, 1.0};
      model.AddMaximize(model.ScalProd(x, objvals));

      // Three constraints
      rng[0] = new IRange[3];
      // - x0 + x1 + x2 + 10*x3 <= 20
      rng[0][0] = model.AddLe(model.Sum(model.Prod(-1.0, x[0]),
                                        model.Prod( 1.0, x[1]),
                                        model.Prod( 1.0, x[2]),
                                        model.Prod(10.0, x[3])), 20.0);
      // x0 - 3*x1 + x2 <= 30
      rng[0][1] = model.AddLe(model.Sum(model.Prod( 1.0, x[0]),
                                        model.Prod(-3.0, x[1]),
                                        model.Prod( 1.0, x[2])), 30.0);
      // x1 - 3.5*x3 = 0
      rng[0][2] = model.AddEq(model.Sum(model.Prod( 1.0, x[1]),
                                        model.Prod(-3.5, x[3])), 0.0);
   }
Exemple #9
0
    internal static ILPMatrix PopulateByRow(IMPModeler model)
    {
        ILPMatrix lp = model.AddLPMatrix();

          double[]    lb = {0.0, 0.0, 0.0};
          double[]    ub = {40.0, System.Double.MaxValue, System.Double.MaxValue};
          INumVar[]   x  = model.NumVarArray(model.ColumnArray(lp, 3), lb, ub);

          // - x0 +   x1 + x2 <= 20
          //   x0 - 3*x1 + x2 <= 30
          double[]   lhs = {-System.Double.MaxValue, -System.Double.MaxValue};
          double[]   rhs = {20.0, 30.0};
          double[][] val = { new double[] {-1.0,  1.0,  1.0},
                         new double[] { 1.0, -3.0,  1.0} };
          int[][]    ind = { new int[] {0, 1, 2},
                         new int[] {0, 1, 2} };
          lp.AddRows(lhs, rhs, ind, val);

          // Q = 0.5 ( 33*x0*x0 + 22*x1*x1 + 11*x2*x2 - 12*x0*x1 - 23*x1*x2 )
          INumExpr x00 = model.Prod( 33.0, model.Square(x[0]));
          INumExpr x11 = model.Prod( 22.0, model.Square(x[1]));
          INumExpr x22 = model.Prod( 11.0, model.Square(x[2]));
          INumExpr x01 = model.Prod(-12.0, model.Prod(x[0], x[1]));
          INumExpr x12 = model.Prod(-23.0, model.Prod(x[1], x[2]));
          INumExpr Q   = model.Prod(0.5, model.Sum(x00, x11, x22, x01, x12));

          // maximize x0 + 2*x1 + 3*x2 + Q
          double[] objvals = {1.0, 2.0, 3.0};
          model.Add(model.Maximize(model.Diff(model.ScalProd(x, objvals), Q)));

          return (lp);
    }
Exemple #10
0
    internal static void BuildModelByColumn(IMPModeler model,
                                            Data data,
                                            INumVar[]  Buy,
                                            NumVarType type)
    {
        int nFoods = data.nFoods;
        int nNutrs = data.nNutrs;

        IObjective cost = model.AddMinimize();

        IRange[] constraint = new IRange[nNutrs];

        for (int i = 0; i < nNutrs; i++)
        {
            constraint[i] = model.AddRange(data.nutrMin[i], data.nutrMax[i]);
        }

        for (int j = 0; j < nFoods; j++)
        {
            Column col = model.Column(cost, data.foodCost[j]);
            for (int i = 0; i < nNutrs; i++)
            {
                col = col.And(model.Column(constraint[i], data.nutrPerFood[i][j]));
            }
            Buy[j] = model.NumVar(col, data.foodMin[j], data.foodMax[j], type);
        }
    }
Exemple #11
0
    internal static INumVar[] populateByRow(IMPModeler model,
                                           IRange[]     row)
    {
        double[]  lb = {0.0, 0.0, 0.0};
          double[]  ub = {40.0, System.Double.MaxValue, System.Double.MaxValue};
          INumVar[] x  = model.NumVarArray(3, lb, ub);

          // - x0 +   x1 + x2 <= 20
          //   x0 - 3*x1 + x2 <= 30
          double[][] val = {new double[]{-1.0,  1.0,  1.0},
                        new double[]{ 1.0, -3.0,  1.0}};
          row[0] = model.AddLe(model.ScalProd(val[0], x), 20.0);
          row[1] = model.AddLe(model.ScalProd(val[1], x), 30.0);

          // x0*x0 + x1*x1 + x2*x2 <= 1.0
          row[2] = model.AddLe(model.Sum(model.Prod(x[0], x[0]),
                                     model.Prod(x[1], x[1]),
                                     model.Prod(x[2], x[2])), 1.0);

          // Q = 0.5 ( 33*x0*x0 + 22*x1*x1 + 11*x2*x2 - 12*x0*x1 - 23*x1*x2 )
          INumExpr x00 = model.Prod( 33.0, x[0], x[0]);
          INumExpr x11 = model.Prod( 22.0, x[1], x[1]);
          INumExpr x22 = model.Prod( 11.0, x[2], x[2]);
          INumExpr x01 = model.Prod(-12.0, x[0], x[1]);
          INumExpr x12 = model.Prod(-23.0, x[1], x[2]);
          INumExpr Q   = model.Prod(0.5, model.Sum(x00, x11, x22, x01, x12));

          // maximize x0 + 2*x1 + 3*x2 + Q
          double[] objvals = {1.0, 2.0, 3.0};
          model.Add(model.Maximize(model.Diff(model.ScalProd(x, objvals), Q)));

          return x;
    }
        internal static ILinearNumExpr[] ComputeAreaExpr(IMPModeler model, IIntVar[][] x, CPatch[] aCph)
        {
            int intCpgCount = aCph.GetLength(0);

            ILinearNumExpr[] aAreaExpr = new ILinearNumExpr[intCpgCount];
            for (int i = 0; i < intCpgCount; i++)  //i is the index of a center
            {
                aAreaExpr[i] = model.LinearNumExpr();
                for (int j = 0; j < intCpgCount; j++)
                {
                    aAreaExpr[i].AddTerm(x[j][i], aCph[j].dblArea);
                }
            }

            return(aAreaExpr);
        }
Exemple #13
0
 internal static void PopulateByRow(IMPModeler  model,
                                    INumVar[][] var,
                                    IRange[][]  rng) {
    double[] lb = {0.0, 0.0, 0.0};
    double[] ub = {40.0, System.Double.MaxValue, System.Double.MaxValue};
    var[0] = model.NumVarArray(3, lb, ub);
  
    double[] objvals = {1.0, 2.0, 3.0};
    model.AddMaximize(model.ScalProd(var[0], objvals));
  
    rng[0] = new IRange[2];
    rng[0][0] = model.AddLe(model.Sum(model.Prod(-1.0, var[0][0]),
                                      model.Prod( 1.0, var[0][1]),
                                      model.Prod( 1.0, var[0][2])), 20.0);
    rng[0][1] = model.AddLe(model.Sum(model.Prod( 1.0, var[0][0]),
                                      model.Prod(-3.0, var[0][1]),
                                      model.Prod( 1.0, var[0][2])), 30.0);
 }
Exemple #14
0
    // Creating a simple QP problem
    internal static ILPMatrix CreateQPModel(IMPModeler model)
    {
        ILPMatrix lp = model.AddLPMatrix();

        double[]  lb    = { 0.0, 0.0, 0.0 };
        double[]  ub    = { 40.0, System.Double.MaxValue, System.Double.MaxValue };
        INumVar[] x     = model.NumVarArray(model.ColumnArray(lp, 3), lb, ub);
        int       nvars = x.Length;

        for (int j = 0; j < nvars; ++j)
        {
            x[j].Name = "x" + j;
        }

        // - x0 +   x1 + x2 <= 20
        //   x0 - 3*x1 + x2 <= 30
        double[]   lhs = { -System.Double.MaxValue, -System.Double.MaxValue };
        double[]   rhs = { 20.0, 30.0 };
        double[][] val = { new double[] { -1.0,  1.0, 1.0 },
                           new double[] {  1.0, -3.0, 1.0 } };
        int[][]    ind = { new int[] { 0, 1, 2 },
                           new int[]    { 0, 1, 2 } };
        lp.AddRows(lhs, rhs, ind, val);

        // minimize - x0 - x1 - x2 + x0*x0 + x1*x1 + x0*x1 + x1*x0
        ILQNumExpr objExpr = model.LqNumExpr();

        for (int i = 0; i < nvars; ++i)
        {
            objExpr.AddTerm(-1.0, x[i]);
            for (int j = 0; j < nvars; ++j)
            {
                objExpr.AddTerm(1.0, x[i], x[j]);
            }
        }
        IObjective obj = model.Minimize(objExpr);

        model.Add(obj);

        // Print out the objective function
        PrintObjective(obj);

        return(lp);
    }
Exemple #15
0
    internal static void PopulateByRow(IMPModeler model,
                                       INumVar[][] var,
                                       IRange[][]  rng)
    {
        double[] lb = { 0.0, 0.0, 0.0 };
        double[] ub = { 40.0, System.Double.MaxValue, System.Double.MaxValue };
        var[0] = model.NumVarArray(3, lb, ub);

        double[] objvals = { 1.0, 2.0, 3.0 };
        model.AddMaximize(model.ScalProd(var[0], objvals));

        rng[0]    = new IRange[2];
        rng[0][0] = model.AddLe(model.Sum(model.Prod(-1.0, var[0][0]),
                                          model.Prod(1.0, var[0][1]),
                                          model.Prod(1.0, var[0][2])), 20.0);
        rng[0][1] = model.AddLe(model.Sum(model.Prod(1.0, var[0][0]),
                                          model.Prod(-3.0, var[0][1]),
                                          model.Prod(1.0, var[0][2])), 30.0);
    }
Exemple #16
0
    internal static ILPMatrix PopulateByRow(IMPModeler model)
    {
        ILPMatrix lp = model.AddLPMatrix();

          double[]  lb = {0.0, 0.0, 0.0};
          double[]  ub = {40.0, System.Double.MaxValue, System.Double.MaxValue};
          INumVar[] x  = model.NumVarArray(model.ColumnArray(lp, 3), lb, ub);

          double[]   lhs = {-System.Double.MaxValue, -System.Double.MaxValue};
          double[]   rhs = {20.0, 30.0};
          double[][] val = {new double[] {-1.0,  1.0,  1.0},
                        new double[] { 1.0, -3.0,  1.0}};
          int[][]    ind = {new int[] {0, 1, 2},
                        new int[] {0, 1, 2}};
          lp.AddRows(lhs, rhs, ind, val);

          double[] objvals = {1.0, 2.0, 3.0};
          model.AddMaximize(model.ScalProd(x, objvals));

          return (lp);
    }
Exemple #17
0
    // The following methods all populate the problem with data for the following
    // linear program:
    //
    //    Maximize
    //     x1 + 2 x2 + 3 x3
    //    Subject To
    //     - x1 + x2 + x3 <= 20
    //     x1 - 3 x2 + x3 <= 30
    //    Bounds
    //     0 <= x1 <= 40
    //    End
    //
    // using the IMPModeler API

    internal static void PopulateByRow(IMPModeler model,
                                       INumVar[][] var,
                                       IRange[][] rng)
    {
        double[]  lb      = { 0.0, 0.0, 0.0 };
        double[]  ub      = { 40.0, System.Double.MaxValue, System.Double.MaxValue };
        string[]  varname = { "x1", "x2", "x3" };
        INumVar[] x       = model.NumVarArray(3, lb, ub, varname);
        var[0] = x;

        double[] objvals = { 1.0, 2.0, 3.0 };
        model.AddMaximize(model.ScalProd(x, objvals));

        rng[0]    = new IRange[2];
        rng[0][0] = model.AddLe(model.Sum(model.Prod(-1.0, x[0]),
                                          model.Prod(1.0, x[1]),
                                          model.Prod(1.0, x[2])), 20.0, "c1");
        rng[0][1] = model.AddLe(model.Sum(model.Prod(1.0, x[0]),
                                          model.Prod(-3.0, x[1]),
                                          model.Prod(1.0, x[2])), 30.0, "c2");
    }
Exemple #18
0
    internal static ILPMatrix PopulateByRow(IMPModeler model)
    {
        ILPMatrix lp = model.AddLPMatrix();

        double[]  lb = { 0.0, 0.0, 0.0 };
        double[]  ub = { 40.0, System.Double.MaxValue, System.Double.MaxValue };
        INumVar[] x  = model.NumVarArray(model.ColumnArray(lp, 3), lb, ub);

        double[]   lhs = { -System.Double.MaxValue, -System.Double.MaxValue };
        double[]   rhs = { 20.0, 30.0 };
        double[][] val = { new double[] { -1.0,  1.0, 1.0 },
                           new double[] {  1.0, -3.0, 1.0 } };
        int[][]    ind = { new int[] { 0, 1, 2 },
                           new int[] { 0, 1, 2 } };
        lp.AddRows(lhs, rhs, ind, val);

        double[] objvals = { 1.0, 2.0, 3.0 };
        model.AddMaximize(model.ScalProd(x, objvals));

        return(lp);
    }
Exemple #19
0
   internal static void PopulateByRow (IMPModeler  model,
                                       INumVar[][] var,
                                       IRange[][]  rng) {

      // Define the variables one-by-one
      INumVar[] x = new INumVar[4];
      x[0] = model.NumVar(0.0, 40.0, "x0");
      x[1] = model.IntVar(0, System.Int32.MaxValue, "x1");
      x[2] = model.IntVar(0, System.Int32.MaxValue, "x2");
      x[3] = model.IntVar(2, 3, "x3");
      var[0] = x;
    
      // Objective Function
      model.AddMaximize(model.Sum(model.Prod( 1.0, x[0]),
                                  model.Prod( 2.0, x[1]),
                                  model.Prod( 3.0, x[2]),
                                  model.Prod( 1.0, x[3])));
    
      // Define three constraints one-by-one 
      rng[0] = new IRange[3];
      rng[0][0] = model.AddLe(model.Sum(model.Prod(-1.0, x[0]),
                                        model.Prod( 1.0, x[1]),
                                        model.Prod( 1.0, x[2]),
                                        model.Prod(10.0, x[3])),
                              20.0, "rng0");
      rng[0][1] = model.AddLe(model.Sum(model.Prod( 1.0, x[0]),
                                        model.Prod(-3.0, x[1]),
                                        model.Prod( 1.0, x[2])),
                              30.0, "rng1");
      rng[0][2] = model.AddEq(model.Sum(model.Prod( 1.0, x[1]),
                                        model.Prod(-3.5, x[3])),
                              0, "rng2");
    
      // add special ordered set of type 1
      INumVar[] sosvars    = {x[2], x[3]};
      double[]  sosweights = {25.0, 18.0};
      model.AddSOS1(sosvars, sosweights);
   }
Exemple #20
0
    internal static void PopulateByRow(IMPModeler model,
                                       INumVar[][] var,
                                       IRange[][]  rng)
    {
        // Define the variables one-by-one
        INumVar[] x = new INumVar[4];
        x[0]   = model.NumVar(0.0, 40.0, "x0");
        x[1]   = model.IntVar(0, System.Int32.MaxValue, "x1");
        x[2]   = model.IntVar(0, System.Int32.MaxValue, "x2");
        x[3]   = model.IntVar(2, 3, "x3");
        var[0] = x;

        // Objective Function
        model.AddMaximize(model.Sum(model.Prod(1.0, x[0]),
                                    model.Prod(2.0, x[1]),
                                    model.Prod(3.0, x[2]),
                                    model.Prod(1.0, x[3])));

        // Define three constraints one-by-one
        rng[0]    = new IRange[3];
        rng[0][0] = model.AddLe(model.Sum(model.Prod(-1.0, x[0]),
                                          model.Prod(1.0, x[1]),
                                          model.Prod(1.0, x[2]),
                                          model.Prod(10.0, x[3])),
                                20.0, "rng0");
        rng[0][1] = model.AddLe(model.Sum(model.Prod(1.0, x[0]),
                                          model.Prod(-3.0, x[1]),
                                          model.Prod(1.0, x[2])),
                                30.0, "rng1");
        rng[0][2] = model.AddEq(model.Sum(model.Prod(1.0, x[1]),
                                          model.Prod(-3.5, x[3])),
                                0, "rng2");

        // add special ordered set of type 1
        INumVar[] sosvars    = { x[2], x[3] };
        double[]  sosweights = { 25.0, 18.0 };
        model.AddSOS1(sosvars, sosweights);
    }
Exemple #21
0
    // Creating a simple QP problem
    internal static ILPMatrix CreateQPModel(IMPModeler model)
    {
        ILPMatrix lp = model.AddLPMatrix();

          double[]    lb = {0.0, 0.0, 0.0};
          double[]    ub = {40.0, System.Double.MaxValue, System.Double.MaxValue};
          INumVar[] x  = model.NumVarArray(model.ColumnArray(lp, 3), lb, ub);
          int nvars = x.Length;
          for (int j = 0; j < nvars; ++j)
         x[j].Name = "x" +j;

          // - x0 +   x1 + x2 <= 20
          //   x0 - 3*x1 + x2 <= 30
          double[] lhs = { -System.Double.MaxValue, -System.Double.MaxValue };
          double[] rhs = { 20.0, 30.0 };
          double[][] val = { new double[] {-1.0,  1.0,  1.0},
                         new double[] { 1.0, -3.0,  1.0} };
          int[][] ind = { new int[] {0, 1, 2},
                         new int[] {0, 1, 2} };
          lp.AddRows(lhs, rhs, ind, val);

          // minimize - x0 - x1 - x2 + x0*x0 + x1*x1 + x0*x1 + x1*x0
          ILQNumExpr objExpr = model.LqNumExpr();
          for (int i = 0; i < nvars; ++i) {
         objExpr.AddTerm(-1.0, x[i]);
         for (int j = 0; j < nvars; ++j) {
            objExpr.AddTerm(1.0, x[i], x[j]);
         }
          }
          IObjective obj = model.Minimize(objExpr);
          model.Add(obj);

          // Print out the objective function
          PrintObjective(obj);

          return lp;
    }
        internal static IIntVar[][][][] Generate4DNumVar(IMPModeler model,
                                                         int intCount1, int intCount2, int intCount3, int intCount4)
        {
            if (intCount1 < 0)
            {
                intCount1 = 0;
            }

            IIntVar[][][][] x = new IIntVar[intCount1][][][];
            for (int i = 0; i < intCount1; i++)
            {
                x[i] = new IIntVar[intCount2][][];
                for (int j = 0; j < intCount2; j++)
                {
                    x[i][j] = new IIntVar[intCount3][];
                    for (int k = 0; k < intCount3; k++)
                    {
                        x[i][j][k] = model.BoolVarArray(intCount4);
                    }
                }
            }

            return(x);
        }
        // Step 4 *****************************************************************************************************
        // Step 4 *****************************************************************************************************
        internal static void PopulateByRow(IMPModeler model, out IIntVar[][][] var2, out IIntVar[][][][] var3,
                                           out IIntVar[][][][][] var4, out IRange[][] rng,
                                           CRegion lscrg, CRegion sscrg, double[,] adblTD, string strAreaAggregation)
        {
            var aCph        = lscrg.GetCphCol().ToArray();
            int intCpgCount = lscrg.GetCphCount();
            //double dblILPSmallValue = 0.000000001;
            //double dblILPSmallValue = 0;

            var x = new IIntVar[intCpgCount][][];

            for (int i = 0; i < intCpgCount; i++)
            {
                x[i] = new IIntVar[intCpgCount][];
                for (int j = 0; j < intCpgCount; j++)
                {
                    x[i][j] = model.BoolVarArray(intCpgCount);
                }
            }

            //cost in terms of type change
            var y = Generate4DNumVar(model, intCpgCount - 1, intCpgCount, intCpgCount, intCpgCount);

            //cost in terms of compactness (length of interior boundaries)
            var z = Generate4DNumVar(model, intCpgCount - 2, intCpgCount, intCpgCount, intCpgCount);


            var c = Generate4DNumVar(model, intCpgCount - 2, intCpgCount, intCpgCount, intCpgCount);

            var3    = new IIntVar[1][][][];
            var4    = new IIntVar[3][][][][];
            var3[0] = x;
            var4[0] = y;
            var4[1] = z;
            var4[2] = c;


            //model.AddEq(x[2][0][3], 1.0, "X1");
            //model.AddEq(x[2][1][3], 1.0, "X2");
            //model.AddEq(x[2][2][2], 1.0, "X3");
            //model.AddEq(x[2][3][3], 1.0, "X4");

            //add minimizations
            ILinearNumExpr pTypeCostExpr = model.LinearNumExpr();

            //ILinearNumExpr pTypeCostAssitantExpr = model.LinearNumExpr();
            for (int i = 0; i < intCpgCount - 1; i++)   //i represents indices
            {
                for (int j = 0; j < intCpgCount; j++)
                {
                    for (int k = 0; k < intCpgCount; k++)
                    {
                        for (int l = 0; l < intCpgCount; l++)
                        {
                            double dblCoe = aCph[j].dblArea * adblTD[aCph[k].intTypeIndex, aCph[l].intTypeIndex];
                            pTypeCostExpr.AddTerm(y[i][j][k][l], dblCoe);
                            //pTypeCostAssitantExpr.AddTerm(y[i][j][k][l], dblILPSmallValueMinimization);
                        }
                    }
                }
            }


            //this is actually for t=1, whose compactness is known
            double         dblCompCostFirstPart    = 0;
            ILinearNumExpr pCompCostSecondPartExpr = model.LinearNumExpr();
            var            pAdjCorrCphsSD          = lscrg.AdjCorrCphsSD;
            double         dblConst = Convert.ToDouble(intCpgCount - 1) / Convert.ToDouble(intCpgCount - 2);

            for (int i = 0; i < intCpgCount - 2; i++)   //i represents indices
            {
                double dblNminusT = intCpgCount - i - 2;
                //double dblTemp = (intCpgCount - i) * dblConst;
                dblCompCostFirstPart += 1 / dblNminusT;
                double dblSecondPartDenominator = lscrg.dblInteriorSegLength * dblNminusT * 2;

                //we don't need to divide the value by 2 because every boundary is only counted once
                foreach (var pCorrCphs in pAdjCorrCphsSD.Keys)
                {
                    for (int l = 0; l < intCpgCount; l++)
                    {
                        pCompCostSecondPartExpr.AddTerm(pCorrCphs.dblSharedSegLength / dblSecondPartDenominator,
                                                        z[i][pCorrCphs.FrCph.ID][pCorrCphs.ToCph.ID][l]);
                        pCompCostSecondPartExpr.AddTerm(pCorrCphs.dblSharedSegLength / dblSecondPartDenominator,
                                                        z[i][pCorrCphs.ToCph.ID][pCorrCphs.FrCph.ID][l]);
                    }
                }
                //var pSecondPartExpr =  model.Prod(pCompCostSecondPartExpr, 1 / dblSecondPartDenominator);
            }

            if (intCpgCount == 1)
            {
                model.AddMinimize(pTypeCostExpr);  //we just use an empty expression
            }
            else
            {
                //Our Model***************************************
                var Ftp = model.Prod(pTypeCostExpr, 1 / lscrg.dblArea);
                var Fcp = model.Prod(dblConst, model.Sum(dblCompCostFirstPart, model.Negative(pCompCostSecondPartExpr)));
                //model.AddMinimize(model.Prod(model.Sum(Ftp, Fcp), 0.5));
                model.AddMinimize(model.Sum(
                                      model.Prod(1 - CAreaAgg_Base.dblLamda, Ftp), model.Prod(CAreaAgg_Base.dblLamda, Fcp)));
                //model.AddMinimize(Fcp);
                //model.AddMaximize(Fcp);
                //model.AddObjective()
            }

            //for showing slacks
            var IRangeLt = new List <IRange>();

            //a polygon $p$ is assigned to exactly one polygon at a step $t$
            for (int i = 0; i < intCpgCount; i++)   //i represents indices
            {
                for (int j = 0; j < intCpgCount; j++)
                {
                    ILinearNumExpr pOneCenterExpr = model.LinearNumExpr();
                    for (int l = 0; l < intCpgCount; l++)
                    {
                        pOneCenterExpr.AddTerm(x[i][j][l], 1.0);
                    }
                    model.AddEq(pOneCenterExpr, 1.0, "AssignToOnlyOneCenter");
                }
            }

            //polygon $r$, which is assigned by other polygons, must be a center
            for (int i = 0; i < intCpgCount; i++)   //i represents indices
            {
                for (int j = 0; j < intCpgCount; j++)
                {
                    for (int l = 0; l < intCpgCount; l++)
                    {
                        model.AddLe(x[i][j][l], x[i][l][l], "AssignedIsCenter__" + i + "__" + j + "__" + l);
                    }
                }
            }

            //only one patch is aggregated into another patch at each step
            for (int i = 0; i < intCpgCount; i++)   //i represents indices
            {
                ILinearNumExpr pOneAggregationExpr = model.LinearNumExpr();
                for (int j = 0; j < intCpgCount; j++)
                {
                    pOneAggregationExpr.AddTerm(x[i][j][j], 1.0);
                }
                model.AddEq(pOneAggregationExpr, intCpgCount - i, "CountCenters");
            }

            //a center can disappear, but will never reappear afterwards
            for (int i = 0; i < intCpgCount - 1; i++)   //i represents indices
            {
                for (int j = 0; j < intCpgCount; j++)
                {
                    model.AddGe(x[i][j][j], x[i + 1][j][j], "SteadyCenters");
                }
            }


            //to make sure that the final aggregated polygon has the same color as the target polygon
            ILinearNumExpr pFinalStateExpr  = model.LinearNumExpr();
            int            intTypeIndexGoal = sscrg.GetSoloCphTypeIndex();

            for (int i = 0; i < intCpgCount; i++)
            {
                if (aCph[i].intTypeIndex == intTypeIndexGoal)
                {
                    pFinalStateExpr.AddTerm(x[intCpgCount - 1][i][i], 1.0);
                }
            }
            model.AddEq(pFinalStateExpr, 1.0, "EnsureTarget");


            //to restrict *y*
            for (int i = 0; i < intCpgCount - 1; i++)   //i represents indices
            {
                for (int j = 0; j < intCpgCount; j++)
                {
                    for (int k = 0; k < intCpgCount; k++)
                    {
                        //IRangeLt.Add(model.AddLe(model.Sum(y[i][j][k][k], x[i][j][k], x[i + 1][j][k]), 2.0 , "RestrictY"));

                        for (int l = 0; l < intCpgCount; l++)
                        {
                            var LieYRight = model.LinearIntExpr(-1);
                            LieYRight.AddTerm(x[i][j][k], 1);
                            LieYRight.AddTerm(x[i + 1][j][l], 1);

                            model.AddGe(y[i][j][k][l], LieYRight, "RestrictY1");
                            model.AddLe(y[i][j][k][l], x[i][j][k], "RestrictY2");
                            model.AddLe(y[i][j][k][l], x[i + 1][j][l], "RestrictY3");
                        }
                    }
                }
            }

            //to restrict *z*
            for (int i = 0; i < intCpgCount - 2; i++)   //i represents indices
            {
                for (int j = 0; j < intCpgCount; j++)
                {
                    //for (int k = j; k < intCpgCount; k++)  // pay attention
                    for (int k = 0; k < intCpgCount; k++)
                    {
                        for (int l = 0; l < intCpgCount; l++)
                        {
                            var LieZRight = model.LinearIntExpr(-1);
                            LieZRight.AddTerm(x[i + 1][j][l], 1);
                            LieZRight.AddTerm(x[i + 1][k][l], 1);

                            model.AddGe(z[i][j][k][l], LieZRight, "RestrictZ1");
                            model.AddLe(z[i][j][k][l], x[i + 1][j][l], "RestrictZ2");
                            model.AddLe(z[i][j][k][l], x[i + 1][k][l], "RestrictZ3");
                        }
                    }
                }
            }

            //to restrict *c*
            double dblCpgCountReciprocal = 1 / Convert.ToDouble(intCpgCount);

            for (int i = 0; i < intCpgCount - 2; i++)   //i represents indices
            {
                for (int j = 0; j < intCpgCount; j++)
                {
                    //for (int k = j; k < intCpgCount; k++)  // pay attention
                    for (int k = 0; k < intCpgCount; k++)
                    {
                        for (int l = 0; l < intCpgCount; l++)
                        {
                            if (k == l)
                            {
                                continue;
                            }

                            model.AddLe(c[i][j][k][l], x[i][j][k], "RestrictC1");

                            var pLieContiguityExpr = model.LinearIntExpr();
                            //pContiguityExpr.AddTerm(x[i][j][k], 1.0);  //including polygon j itself
                            foreach (var pAdjacentCph in aCph[j].AdjacentCphSS)
                            {
                                pLieContiguityExpr.AddTerm(x[i][pAdjacentCph.ID][l], 1);
                            }
                            model.AddLe(c[i][j][k][l], pLieContiguityExpr, "Contiguity");


                            foreach (var pAdjacentCph in aCph[j].AdjacentCphSS)
                            {
                                var pContiguityExpr2 = model.LinearNumExpr(-1);
                                pContiguityExpr2.AddTerm(x[i][j][k], 1);
                                pContiguityExpr2.AddTerm(x[i][pAdjacentCph.ID][l], 1);

                                model.AddGe(c[i][j][k][l], pContiguityExpr2, "Contiguity2");
                            }

                            var pContiguityExprRight3 = model.LinearIntExpr();
                            for (int m = 0; m < intCpgCount; m++)
                            {
                                pContiguityExprRight3.AddTerm(c[i][m][k][l], 1);
                            }
                            model.AddLe(y[i][k][k][l], pContiguityExprRight3, "Contiguity3");
                        }
                    }
                }
            }


            //If two polygons have been aggregated into one polygon, then they will
            //be aggregated together in later steps. Our sixth constraint achieve this by requiring
            for (int i = 0; i < intCpgCount - 3; i++)   //i represents indices
            {
                for (int j = 0; j < intCpgCount; j++)
                {
                    for (int k = 0; k < intCpgCount; k++)
                    {
                        var pAssignTogetherExprPre   = model.LinearIntExpr();
                        var pAssignTogetherExprAfter = model.LinearIntExpr();
                        for (int l = 0; l < intCpgCount; l++)
                        {
                            pAssignTogetherExprPre.AddTerm(z[i][j][k][l], 1);
                            pAssignTogetherExprAfter.AddTerm(z[i + 1][j][k][l], 1);
                        }
                        model.AddLe(pAssignTogetherExprPre, pAssignTogetherExprAfter, "AssignTogether");
                    }
                }
            }

            var2 = new IIntVar[1][][];
            if (strAreaAggregation == _strSmallest)
            {
                IIntVar[][] w = new IIntVar[intCpgCount - 1][];
                for (int i = 0; i < intCpgCount - 1; i++)
                {
                    w[i] = model.BoolVarArray(intCpgCount);
                }
                var2[0] = w;

                //there is only one smallest patch will be involved in each aggregation step
                for (int i = 0; i < intCpgCount - 1; i++)   //i represents indices
                {
                    var pOneSmallestExpr = model.LinearIntExpr();
                    for (int j = 0; j < intCpgCount; j++)
                    {
                        pOneSmallestExpr.AddTerm(w[i][j], 1);
                    }

                    model.AddEq(pOneSmallestExpr, 1.0, "OneSmallest");
                }

                //forces that the aggregation must involve the smallest patch.
                for (int i = 0; i < intCpgCount - 1; i++)   //i represents indices
                {
                    for (int j = 0; j < intCpgCount; j++)
                    {
                        var pInvolveSmallestExpr = model.LinearIntExpr();
                        for (int k = 0; k < intCpgCount; k++)
                        {
                            if (j == k) //o != r
                            {
                                continue;
                            }
                            pInvolveSmallestExpr.AddTerm(y[i][j][j][k], 1);
                            pInvolveSmallestExpr.AddTerm(y[i][k][k][j], 1);
                        }
                        model.AddLe(w[i][j], pInvolveSmallestExpr, "InvolveSmallest");
                    }
                }

                //To guarantee that patch $o$ is involved in aggregation is indeed the smallest patch
                double dblM = 1.1 * lscrg.dblArea;        //a very large value
                for (int i = 0; i < intCpgCount - 1; i++) //i represents indices
                {
                    var aAreaExpr = ComputeAreaExpr(model, x[i], aCph);
                    for (int j = 0; j < intCpgCount; j++)
                    {
                        for (int k = 0; k < intCpgCount; k++)
                        {
                            if (j == k) //o != r
                            {
                                continue;
                            }

                            var pSumExpr  = model.Sum(2.0, model.Negative(model.Sum(w[i][j], x[i][k][k]))); //(2-w_{t,o}-x_{t,r,r})
                            var pProdExpr = model.Prod(pSumExpr, dblM);                                     //M(2-w_{t,o}-x_{t,r,r})

                            //A_{t,o}-A_{t,r}<= M(2-w_{t,o}-x_{t,r,r})
                            model.AddLe(model
                                        .Sum(aAreaExpr[j], model.Negative(aAreaExpr[k])), pProdExpr, "IndeedSmallest");
                        }
                    }
                }
            }


            //***************compare with number of constraints counted manually************
            rng    = new IRange[1][];
            rng[0] = new IRange[IRangeLt.Count];
            for (int i = 0; i < IRangeLt.Count; i++)
            {
                rng[0][i] = IRangeLt[i];
            }
        }
Exemple #24
0
    internal static void BuildModelByColumn(IMPModeler model,
                                           Data       data,
                                           INumVar[]  Buy,
                                           NumVarType type)
    {
        int nFoods = data.nFoods;
          int nNutrs = data.nNutrs;

          IObjective cost       = model.AddMinimize();
          IRange[]   constraint = new IRange[nNutrs];

          for (int i = 0; i < nNutrs; i++) {
         constraint[i] = model.AddRange(data.nutrMin[i], data.nutrMax[i]);
          }

          for (int j = 0; j < nFoods; j++) {
         Column col = model.Column(cost, data.foodCost[j]);
         for (int i = 0; i < nNutrs; i++) {
            col = col.And(model.Column(constraint[i], data.nutrPerFood[i][j]));
         }
         Buy[j] = model.NumVar(col, data.foodMin[j], data.foodMax[j], type);
          }
    }
Exemple #25
0
   internal static void PopulateByNonzero(IMPModeler model,
                                          INumVar[][] var,
                                          IRange[][] rng) {
      double[]  lb = {0.0, 0.0, 0.0};
      double[]  ub = {40.0, System.Double.MaxValue, System.Double.MaxValue};
      INumVar[] x  = model.NumVarArray(3, lb, ub);
      var[0] = x;

      double[] objvals = {1.0, 2.0, 3.0};
      model.Add(model.Maximize(model.ScalProd(x, objvals)));

      rng[0] = new IRange[2];
      rng[0][0] = model.AddRange(-System.Double.MaxValue, 20.0);
      rng[0][1] = model.AddRange(-System.Double.MaxValue, 30.0);

      rng[0][0].Expr = model.Sum(model.Prod(-1.0, x[0]),
                                 model.Prod( 1.0, x[1]),
                                 model.Prod( 1.0, x[2]));
      rng[0][1].Expr = model.Sum(model.Prod( 1.0, x[0]),
                                 model.Prod(-3.0, x[1]),
                                 model.Prod( 1.0, x[2]));
      x[0].Name = "x1";
      x[1].Name = "x2";
      x[2].Name = "x3";

      rng[0][0].Name = "c1";
      rng[0][0].Name = "c2";
   }
Exemple #26
0
   internal static void PopulateByColumn(IMPModeler model,
                                         INumVar[][] var,
                                         IRange[][] rng) {
      IObjective obj = model.AddMaximize();

      rng[0] = new IRange[2];
      rng[0][0] = model.AddRange(-System.Double.MaxValue, 20.0, "c1");
      rng[0][1] = model.AddRange(-System.Double.MaxValue, 30.0, "c2");

      IRange r0 = rng[0][0];
      IRange r1 = rng[0][1];

      var[0] = new INumVar[3];
      var[0][0] = model.NumVar(model.Column(obj,  1.0).And(
                               model.Column(r0,  -1.0).And(
                               model.Column(r1,   1.0))),
                               0.0, 40.0, "x1");
      var[0][1] = model.NumVar(model.Column(obj,  2.0).And(
                               model.Column(r0,   1.0).And(
                               model.Column(r1,  -3.0))),
                               0.0, System.Double.MaxValue, "x2");
      var[0][2] = model.NumVar(model.Column(obj,  3.0).And(
                               model.Column(r0,   1.0).And(
                               model.Column(r1,   1.0))),
                               0.0, System.Double.MaxValue, "x3");
   }
Exemple #27
0
   // The following methods all populate the problem with data for the following
   // linear program:
   //
   //    Maximize
   //     x1 + 2 x2 + 3 x3
   //    Subject To
   //     - x1 + x2 + x3 <= 20
   //     x1 - 3 x2 + x3 <= 30
   //    Bounds
   //     0 <= x1 <= 40
   //    End
   //
   // using the IMPModeler API

   internal static void PopulateByRow(IMPModeler model,
                                      INumVar[][] var,
                                      IRange[][] rng) {
      double[]  lb      = {0.0, 0.0, 0.0};
      double[]  ub      = {40.0, System.Double.MaxValue, System.Double.MaxValue};
      string[]  varname = {"x1", "x2", "x3"};
      INumVar[] x       = model.NumVarArray(3, lb, ub, varname);
      var[0] = x;

      double[] objvals = {1.0, 2.0, 3.0};
      model.AddMaximize(model.ScalProd(x, objvals));

      rng[0] = new IRange[2];
      rng[0][0] = model.AddLe(model.Sum(model.Prod(-1.0, x[0]),
                                        model.Prod( 1.0, x[1]),
                                        model.Prod( 1.0, x[2])), 20.0, "c1");
      rng[0][1] = model.AddLe(model.Sum(model.Prod( 1.0, x[0]),
                                        model.Prod(-3.0, x[1]),
                                        model.Prod( 1.0, x[2])), 30.0, "c2");
   }