source: branches/2931_OR-Tools_LP_MIP/HeuristicLab.MathematicalOptimization/3.3/LinearProgramming/Problems/LinearProblem.cs @ 16736

Last change on this file since 16736 was 16736, checked in by ddorfmei, 5 months ago

#2931: Upgraded persistence to HEAL.Attic

File size: 5.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.IO;
25using System.Linq;
26using System.Reflection;
27using Google.OrTools.LinearSolver;
28using HeuristicLab.Common;
29using HeuristicLab.Core;
30using HeuristicLab.Data;
31using HeuristicLab.Optimization;
32using HeuristicLab.Parameters;
33using HEAL.Attic;
34
35namespace HeuristicLab.ExactOptimization.LinearProgramming {
36
37  [Item("Mixed-Integer Linear Programming Problem (LP, MIP)", "Represents a linear/mixed integer problem.")]
38  [StorableType("0F6BD4A4-8C70-4922-9BA1-1F372820DD76")]
39  public sealed class LinearProblem : Problem, IStorableContent {
40
41    [Storable]
42    private readonly IValueParameter<ILinearProblemDefinition> problemDefinitionParam;
43
44    public LinearProblem() {
45      Parameters.Remove(Parameters["Operators"]);
46      Parameters.Add(problemDefinitionParam = new ValueParameter<ILinearProblemDefinition>("Model",
47        new ProgrammableLinearProblemDefinition(), false));
48    }
49
50    private LinearProblem(LinearProblem original, Cloner cloner)
51      : base(original, cloner) {
52      problemDefinitionParam = cloner.Clone(original.problemDefinitionParam);
53    }
54
55    [StorableConstructor]
56    private LinearProblem(StorableConstructorFlag _) : base(_) { }
57
58    public event EventHandler ProblemDefinitionChanged;
59
60    public string Filename { get; set; }
61
62    public ILinearProblemDefinition ProblemDefinition {
63      get => problemDefinitionParam.Value;
64      set {
65        if (problemDefinitionParam.Value == value)
66          return;
67        problemDefinitionParam.Value = value;
68        ProblemDefinitionChanged?.Invoke(this, EventArgs.Empty);
69      }
70    }
71
72    public IValueParameter<ILinearProblemDefinition> ProblemDefinitionParameter => problemDefinitionParam;
73
74    public override IDeepCloneable Clone(Cloner cloner) => new LinearProblem(this, cloner);
75
76    public override void CollectParameterValues(IDictionary<string, IItem> values) {
77      base.CollectParameterValues(values);
78
79      if (ProblemDefinition == null) return;
80
81      values.Add("Model Type", new StringValue(
82        (ProblemDefinition.GetType().GetCustomAttributes().Single(a => a is ItemAttribute) as ItemAttribute).Name));
83
84      if (ProblemDefinition is ProgrammableLinearProblemDefinition model) {
85        values.Add("Model Name", new StringValue(model.Name));
86      }
87    }
88
89    public void ExportModel(string fileName) {
90      if (string.IsNullOrWhiteSpace(fileName))
91        throw new ArgumentNullException(nameof(fileName));
92      if (ProblemDefinition == null)
93        throw new ArgumentNullException(nameof(ProblemDefinition));
94
95      var fileInfo = new FileInfo(fileName);
96
97      if (!fileInfo.Directory?.Exists ?? false) {
98        Directory.CreateDirectory(fileInfo.Directory.FullName);
99      }
100
101      var solver = new Solver(ProblemDefinition.ItemName, Solver.OptimizationProblemType.CbcMixedIntegerProgramming);
102
103      ProblemDefinition.BuildModel(solver);
104
105      var exportSuccessful = false;
106      switch (fileInfo.Extension) {
107        case ".lp":
108          var lpFormat = solver.ExportModelAsLpFormat(false);
109          if (!string.IsNullOrEmpty(lpFormat)) {
110            File.WriteAllText(fileName, lpFormat);
111            exportSuccessful = true;
112          }
113          break;
114
115        case ".mps":
116          var mpsFormat = solver.ExportModelAsMpsFormat(false, false);
117          if (!string.IsNullOrEmpty(mpsFormat)) {
118            File.WriteAllText(fileName, mpsFormat);
119            exportSuccessful = true;
120          }
121          break;
122
123        case ".prototxt":
124          exportSuccessful = solver.ExportModelAsProtoFormat(fileName,
125            (Google.OrTools.LinearSolver.ProtoWriteFormat)ProtoWriteFormat.ProtoText);
126          break;
127
128        case ".bin": // remove file extension as it is added by OR-Tools
129          fileName = Path.ChangeExtension(fileName, null);
130          exportSuccessful = solver.ExportModelAsProtoFormat(fileName,
131            (Google.OrTools.LinearSolver.ProtoWriteFormat)ProtoWriteFormat.ProtoBinary);
132          break;
133
134        default:
135          throw new NotSupportedException($"File format {fileInfo.Extension} to export model is not supported.");
136      }
137
138      if (!exportSuccessful)
139        throw new InvalidDataException("Model could not be exported.");
140    }
141
142    [StorableHook(HookType.AfterDeserialization)]
143    private void AfterDeserialization() {
144    }
145  }
146}
Note: See TracBrowser for help on using the repository browser.