| |||||||||||||
Contract - Semi-continuous variables Description A small MIP-problem example demonstrating how to define semi-continuous variables.
Source Files By clicking on a file name, a preview is opened at the bottom of this page.
ContractAllocation.cs // (c) 2023-2024 Fair Isaac Corporation using System; using Optimizer; using Optimizer.Objects; using static Optimizer.Objects.Utils; namespace XpressExamples { /// <summary>Contract allocation example.</summary> class ContractAllocation { static readonly int NDISTRICT = 6; /* Number of districts */ static readonly int NCONTRACT = 10; /* Number of contracts */ private static readonly double[] output = new double[]{ /* Max. output per district */ 50, 40, 10, 20, 70, 50 }; private static readonly double[] cost = new double[]{ /* Cost per district */ 50, 20, 25, 30, 45, 40 }; private static readonly double[] volume = new double[]{ /* Volume of contracts */ 20, 10, 30, 15, 20, 30, 10, 50, 10, 20 }; public static void Main(string[] args) { using (XpressProblem prob = new XpressProblem()) { // Output all messages. prob.callbacks.AddMessageCallback(DefaultMessageListener.Console); /**** VARIABLES ****/ /* Variables indicating whether a project is chosen */ Variable[,] x = prob.AddVariables(NDISTRICT, NCONTRACT) .WithType(ColumnType.Binary) .WithName((d, c) => $"x_d{d + 1}_c{c + 1}") .ToArray(); /* Quantities allocated to contractors */ Variable[,] y = prob.AddVariables(NDISTRICT, NCONTRACT) .WithType(ColumnType.SemiContinuous) .WithUB((d, c) => output[d]) .WithName((d, c) => $"q_d{d + 1}_c{c + 1}") .WithLimit(5) // Set limit for the semi-continous variable .ToArray(); /**** CONSTRAINTS ****/ // Cover the required volume // for all c in [0,NCONTRACT[ // sum(d in [0,NDISTRICT[) y[d][c] >= volume[c] prob.AddConstraints(NCONTRACT, c => Sum(NDISTRICT, d => y[d, c]).Geq(volume[c]).SetName($"Size_{c}") ); // "Min": at least 2 districts / contract // for all c in [0,NCONTRACT[ // sum(d in [0,NDISTRICT[) x[d][c] >= 2 prob.AddConstraints(NCONTRACT, c => Sum(NDISTRICT, d => x[d, c]).Geq(2.0).SetName($"Min_{c}") ); // Do not exceed max. output // for all d in [0,NDISTRICT[ // sum(c in [0,NCONTRACT[) y[d][c] <= output[d] prob.AddConstraints(NDISTRICT, d => Sum(NCONTRACT, c => y[d, c]).Leq(output[d]).SetName($"Output_{d}") ); // If a contract is allocated to a district, then at least 1 unit is allocated to it // for all d in [0,NDISTRICT[ // for all c in [0,NCONTRACT[ // x[d][c] <= y[d][c] prob.AddConstraints(NDISTRICT, NCONTRACT, (d, c) => x[d, c].Leq(y[d, c]).SetName($"XY_{d}{c}") ); /****OBJECTIVE****/ prob.SetObjective( Sum( NCONTRACT, c => Sum(NDISTRICT, d => y[d, c] * cost[d])), Optimizer.ObjSense.Minimize ); // Output the matrix in LP format prob.WriteProb("Contract.lp", "l"); // Solve prob.MipOptimize(); if (prob.SolStatus != Optimizer.SolStatus.Optimal && prob.SolStatus != Optimizer.SolStatus.Feasible) throw new Exception("optimization failed with status " + prob.SolStatus); // Print out the solution double[] sol = prob.GetSolution(); Console.WriteLine("Objective: {0}", prob.MIPObjVal); foreach (Variable v in y) { if (v.GetValue(sol) > 0.5) Console.WriteLine($"{v.GetName()}:{v.GetValue(sol)} "); } } } } } | |||||||||||||
© Copyright 2024 Fair Isaac Corporation. |