/// <summary> /// Creates a new model from the given file. /// Supported file extensions: .mps only. /// </summary> /// <param name="fileName">The mps file to be imported.</param> /// <param name="variables">The full array of variables created for this new model.</param> /// <returns>The new model, or null if an error occurred.</returns> public static Model New(string fileName, out Variable[] variables) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName); string extension = Path.GetExtension(fileName).ToLower(); Model model = null; if (extension.Equals(".mps")) { #region New Model from .mps file string directoryName = Path.GetDirectoryName(fileName); if (directoryName.Length == 0) { directoryName = "."; } string fullPathWithoutExtension = Path.Combine(directoryName, fileNameWithoutExtension); CoinMpsIO m = new CoinMpsIO(); log.PassToCoinMpsIO(m); m.setInfinity(MathUtils.Infinity); int numberErrors = m.readMps(fullPathWithoutExtension); if (numberErrors != 0) { string message = string.Format("Errors occurred when reading the mps file '{0}'.", fileName); SonnetLog.Default.Error(message); throw new SonnetException(message); } // set objective function offest // setDblParam(OsiObjOffset,m.objectiveOffset()); // WHAT IS THIS?? model = NewHelper(out variables, m.isInteger, m.columnName, m.rowName, m.getColLower(), m.getColUpper(), m.getObjectiveName(), m.getObjCoefficients(), m.getNumCols(), m.getNumRows(), m.getRowSense(), m.getMatrixByRow(), m.getRowLower(), m.getRowUpper()); model.Name = fileNameWithoutExtension; #endregion } else if (extension.Equals(".lp")) { #region New Model from .lp file CoinLpIO m = new CoinLpIO(); log.PassToCoinLpIO(m); m.setInfinity(MathUtils.Infinity); // If the original problem is // a maximization problem, the objective function is immediadtly // flipped to get a minimization problem. m.readLp(fileName); model = NewHelper(out variables, m.isInteger, m.columnName, m.rowName, m.getColLower(), m.getColUpper(), m.getObjName(), m.getObjCoefficients(), m.getNumCols(), m.getNumRows(), m.getRowSense(), m.getMatrixByRow(), m.getRowLower(), m.getRowUpper()); model.Name = fileNameWithoutExtension; #endregion } else { string message = string.Format("Cannot import file {0} : unknown extension '{1}'.", fileName, extension); SonnetLog.Default.Error(message); throw new SonnetException(message); } return(model); }
/// <summary> /// Creates a new model from the given file. The name of the model will be the filename. /// </summary> /// <param name="fileName">The mps or lp file to be imported.</param> /// <param name="variables">The full array of variables created for this new model.</param> /// <returns>The new model, or an exception if an error occurred.</returns> public static Model New(string fileName, out Variable[] variables) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName); string extension = Path.GetExtension(fileName).ToLower(); Model model = null; if (extension.Equals(".mps")) { #region New Model from .mps file string directoryName = Path.GetDirectoryName(fileName); if (directoryName.Length == 0) { directoryName = "."; } string fullPathWithoutExtension = Path.Combine(directoryName, fileNameWithoutExtension); // Previously, CoinMpsIO was used but that doesnt read quad info. // To read MPS with QUAD info use ClpModel or CoinModel readMps. // CoinModel we havent Wrapped yet at all, so more work. // ClpModel (ClpSimplex) doesnt do row Sense needed for here, only lb / ub. // ClpModel also doesnt save the Objective name. // OsiClp can create row sense from lb / ub, but OsiClp uses CoinMpsIO, so cannot read Quad from OsiClp // So we use ClpSimplex to read the file, but use an OsiClp of it for rowsense ClpSimplex m = new ClpSimplex(); OsiClpSolverInterface osiClp = new OsiClpSolverInterface(m); log.PassToClpModel(m); int numberErrors = m.readMps(fileName, true, false); if (numberErrors != 0) { string message = string.Format("Errors occurred when reading the mps file '{0}'.", fileName); SonnetLog.Default.Error(message); throw new SonnetException(message); } // set objective function offest // Skip this: setDblParam(OsiObjOffset,m.objectiveOffset()) //ClpModel has ClpObjective which may be an implementatin of ClpQuadObjective. // This can be found by obj->type() == 2 (QuadCoef) bool fullQuadraticMatrix = false; CoinPackedMatrix quadraticObjective = null; ClpObjective clpObjective = m.objectiveAsObject(); if (clpObjective is ClpQuadraticObjective clpQuadraticObjective) { Ensure.IsTrue(clpObjective.type() == 2, $"Quadratic Objective must be type 2 but is {clpObjective.type()}."); fullQuadraticMatrix = clpQuadraticObjective.fullMatrix(); quadraticObjective = clpQuadraticObjective.quadraticObjective(); } model = NewHelper(out variables, m.isInteger, m.columnName, m.rowName, m.getColLower(), m.getColUpper(), "OBJROW", m.getObjCoefficients(), m.getNumCols(), m.getNumRows(), osiClp.getRowSense(), osiClp.getMatrixByRow(), m.getRowLower(), m.getRowUpper(), fullQuadraticMatrix, quadraticObjective); model.Name = fileNameWithoutExtension; #endregion } else if (extension.Equals(".lp")) { #region New Model from .lp file CoinLpIO m = new CoinLpIO(); log.PassToCoinLpIO(m); m.setInfinity(MathUtils.Infinity); // If the original problem is // a maximization problem, the objective function is immediadtly // flipped to get a minimization problem. m.readLp(fileName); model = NewHelper(out variables, m.isInteger, m.columnName, m.rowName, m.getColLower(), m.getColUpper(), m.getObjName(), m.getObjCoefficients(), m.getNumCols(), m.getNumRows(), m.getRowSense(), m.getMatrixByRow(), m.getRowLower(), m.getRowUpper(), false, null); model.Name = fileNameWithoutExtension; #endregion } else { string message = string.Format("Cannot import file {0} : unknown extension '{1}'.", fileName, extension); SonnetLog.Default.Error(message); throw new SonnetException(message); } if (model == null) { string message = $"An error occured while importing {fileName}. No model created."; SonnetLog.Default.Error(message); throw new SonnetException(message); } return(model); }