Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 16405 was 16405, checked in by ddorfmei, 5 years ago

#2931:

  • moved views to separate plugin HeuristicLab.MathematicalOptimization.Views
  • added button in LinearProgrammingProblemView to select the problem definition type
  • added views for problem definitions
  • added ExportFile parameter to LinearProgrammingAlgorithm
  • extended FileValue and FileValueView by the option to save a file
  • code cleanup
File size: 6.1 KB
RevLine 
[11484]1#region License Information
2/* HeuristicLab
[15583]3 * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[11484]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 */
[16288]20#endregion
[11484]21
[16172]22using System;
23using System.Linq;
24using System.Reflection;
25using Google.OrTools.LinearSolver;
[11484]26using HeuristicLab.Common;
27using HeuristicLab.Core;
28using HeuristicLab.Optimization;
29using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
[16172]30using HeuristicLab.Problems.Programmable;
31using HeuristicLab.Scripting;
[11484]32
[16405]33namespace HeuristicLab.MathematicalOptimization.LinearProgramming {
[16233]34
[16405]35  [Item("Programmable Linear/Mixed Integer Programming Problem Definition",
36    "Script that defines the model and evaluates the solution for a linear/mixed integer programming problem.")]
[11484]37  [StorableClass]
[16405]38  public sealed class ProgrammableLinearProgrammingProblemDefinition : Script, ILinearProgrammingProblemDefinition,
39    IStorableContent {
40    private readonly object compileLock = new object();
[11484]41
[16405]42    [Storable] private readonly VariableStore variableStore;
[16233]43
[16405]44    [Storable] private bool codeChanged;
[11484]45
[16405]46    private volatile ILinearProgrammingProblemDefinition compiledProblemDefinition;
[16172]47
[16405]48    public ProgrammableLinearProgrammingProblemDefinition()
49      : base(ScriptTemplates.CompiledLinearProgrammingProblemDefinition) {
50      Name = "Programmable Linear/Mixed Integer Programming Problem Definition";
51      variableStore = new VariableStore();
52    }
53
[11484]54    [StorableConstructor]
[16405]55    private ProgrammableLinearProgrammingProblemDefinition(bool deserializing) : base(deserializing) {
56    }
[16233]57
[16405]58    private ProgrammableLinearProgrammingProblemDefinition(ProgrammableLinearProgrammingProblemDefinition original,
59      Cloner cloner) : base(original, cloner) {
[16172]60      variableStore = cloner.Clone(original.variableStore);
61      codeChanged = original.codeChanged;
62    }
[11484]63
[16405]64    public event EventHandler ProblemDefinitionChanged;
[11484]65
[16405]66    public string Filename { get; set; }
67    public dynamic Instance => compiledProblemDefinition;
68    public VariableStore VariableStore => variableStore;
[16233]69
[16288]70    private ILinearProgrammingProblemDefinition CompiledProblemDefinition {
[16172]71      get {
72        // double checked locking pattern
73        if (compiledProblemDefinition == null) {
74          lock (compileLock) {
75            if (compiledProblemDefinition == null) {
[16233]76              if (codeChanged)
77                throw new ProblemDefinitionScriptException("The code has been changed, but was not recompiled.");
[16172]78              Compile(false);
79            }
80          }
81        }
[16405]82
[16172]83        return compiledProblemDefinition;
84      }
[11484]85    }
[16233]86
[16405]87    private bool SuppressEvents { get; set; }
[11484]88
[16405]89    public void Analyze(Solver solver, ResultCollection results) => CompiledProblemDefinition.Analyze(solver, results);
90
91    public void BuildModel(Solver solver) => CompiledProblemDefinition.BuildModel(solver);
92
93    public override IDeepCloneable Clone(Cloner cloner) {
94      return new ProgrammableLinearProgrammingProblemDefinition(this, cloner);
95    }
96
[16233]97    public override Assembly Compile() => Compile(true);
[11484]98
[16405]99    protected override void OnCodeChanged() {
100      base.OnCodeChanged();
101      compiledProblemDefinition = null;
102      codeChanged = true;
103    }
104
[16172]105    private Assembly Compile(bool fireChanged) {
106      var assembly = base.Compile();
107      var types = assembly.GetTypes();
108      if (!types.Any(x => typeof(CompiledProblemDefinition).IsAssignableFrom(x)))
[16405]109        throw new ProblemDefinitionScriptException("The compiled code doesn't contain a problem definition." + Environment.NewLine +
[16233]110                                                   "The problem definition must be a subclass of CompiledProblemDefinition.");
[16172]111      if (types.Count(x => typeof(CompiledProblemDefinition).IsAssignableFrom(x)) > 1)
[16405]112        throw new ProblemDefinitionScriptException("The compiled code contains multiple problem definitions." + Environment.NewLine +
[16233]113                                                   "Only one subclass of CompiledProblemDefinition is allowed.");
[16172]114
115      CompiledProblemDefinition inst;
116      try {
[16233]117        inst = (CompiledProblemDefinition)Activator.CreateInstance(types.Single(x =>
118         typeof(CompiledProblemDefinition).IsAssignableFrom(x)));
[16172]119      } catch (Exception e) {
120        compiledProblemDefinition = null;
[16233]121        throw new ProblemDefinitionScriptException(
122          "Instantiating the problem definition failed." + Environment.NewLine + "Check your default constructor.", e);
[16172]123      }
124
125      try {
126        inst.vars = new Variables(VariableStore);
127        inst.Initialize();
128      } catch (Exception e) {
129        compiledProblemDefinition = null;
[16233]130        throw new ProblemDefinitionScriptException(
131          "Initializing the problem definition failed." + Environment.NewLine + "Check your Initialize() method.", e);
[16172]132      }
133
134      try {
135        compiledProblemDefinition = (ILinearProgrammingProblemDefinition)inst;
136        if (fireChanged) OnProblemDefinitionChanged();
137      } catch (Exception e) {
138        compiledProblemDefinition = null;
[16233]139        throw new ProblemDefinitionScriptException(
140          "Using the problem definition in the problem failed." + Environment.NewLine +
141          "Examine this error message carefully (often there is an issue with the defined encoding).", e);
[16172]142      }
143
144      codeChanged = false;
145      return assembly;
[11484]146    }
[16172]147
[16233]148    private void OnProblemDefinitionChanged() => ProblemDefinitionChanged?.Invoke(this, EventArgs.Empty);
[11484]149  }
[16405]150}
Note: See TracBrowser for help on using the repository browser.