Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Interval/IntervalConstraintsParser.cs @ 17631

Last change on this file since 17631 was 17607, checked in by chaider, 5 years ago

#3073 Added classes/views to define constraints

File size: 7.9 KB
Line 
1#region License Information
2
3/* HeuristicLab
4 * Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
5 *
6 * This file is part of HeuristicLab.
7 *
8 * HeuristicLab is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * HeuristicLab is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#endregion
23
24using System;
25using System.Collections.Generic;
26using System.Globalization;
27using System.Linq;
28using System.Text.RegularExpressions;
29
30namespace HeuristicLab.Problems.DataAnalysis {
31  public static class IntervalConstraintsParser {
32    public static IEnumerable<IntervalConstraint> ParseInput(string              inputText, string target,
33                                                             IEnumerable<string> variables) {
34      if (string.IsNullOrEmpty(inputText)) throw new ArgumentNullException("No input text has been provided.");
35      if (string.IsNullOrEmpty(target)) throw new ArgumentNullException("No target variable has been provided.");
36      if (variables == null) throw new ArgumentNullException("No variables have been provided.");
37      if (!variables.Any()) throw new ArgumentException("Variables are empty.");
38
39      var lines = inputText.Split(new[] {"\r\n", "\r", "\n"}, StringSplitOptions.None);
40      foreach (var line in lines) {
41        var trimmedLine = line.TrimStart();
42        //Check for target-variable constraint
43        if (trimmedLine.StartsWith("Target:")) {
44          var start            = "Target:".Length;
45          var end              = trimmedLine.Length;
46          var targetConstraint = trimmedLine.Substring(start, end - start);
47          var match = Regex.Match(targetConstraint,
48                                  @"(['](.*)[']|(.*[^\s]))\s*(\bin\b)\s*([\[])\s*(\S*)\s*(\.{2})\s*(\S*)\s*([\]])");
49          if (match.Success) {
50            if (match.Groups.Count != 10) throw new ArgumentException("The target-constraint is not complete.", line);
51
52            var targetVariable = match.Groups[1].Value.Trim();
53            if (match.Groups[1].Value.Trim().StartsWith("'") && match.Groups[1].Value.Trim().EndsWith("'"))
54              targetVariable = targetVariable.Substring(1, targetVariable.Length - 2);
55
56            if (targetVariable != target)
57              throw new
58                ArgumentException($"The target variable {targetVariable}  does not match the provided target {target}.",
59                                  line);
60
61            var lowerBound         = ParseIntervalBounds(match.Groups[6].Value);
62            var upperBound         = ParseIntervalBounds(match.Groups[8].Value);
63            var expression         = "Target:" + match.Groups[0].Value;
64            var parsedTarget       = match.Groups[1].Value.Trim();
65            var variable           = targetVariable;
66            var isEnabled          = true;
67            var numberOfDerivation = 0;
68            var interval           = new Interval(lowerBound, upperBound);
69
70            var constraint =
71              new IntervalConstraint(expression, variable, parsedTarget, numberOfDerivation, interval, isEnabled);
72
73            yield return constraint;
74          }
75          else {
76            throw new ArgumentException("The inserted target constraint is not valid.", line);
77          }
78
79          //Check for derivation
80        }
81        else if (trimmedLine.StartsWith("d") || trimmedLine.StartsWith("\u2202")) {
82          var match = Regex.Match(trimmedLine,
83                                  @"([d∂])([²³]?)\s*(['](.*)[']|(.*[^\s]))\s*(\/)\s*([d∂])\s*(['](.*)[']|(.*[^\s²³]))\s*([²³]?)\s*\bin\b\s*([\[])\s*(\S*)\s*(\.{2})\s*(\S*)\s*([\]])");
84
85          if (match.Success) {
86            if (match.Groups.Count != 17)
87              throw new ArgumentException("The given derivation-constraint is not complete.", line);
88
89            var derivationTarget   = match.Groups[3].Value.Trim();
90            var derivationVariable = match.Groups[8].Value.Trim();
91
92            if (match.Groups[3].Value.Trim().StartsWith("'") && match.Groups[3].Value.Trim().EndsWith("'"))
93              derivationTarget = derivationTarget.Substring(1, derivationTarget.Length - 2);
94
95            if (match.Groups[8].Value.Trim().StartsWith("'") && match.Groups[8].Value.Trim().EndsWith("'"))
96              derivationVariable = derivationVariable.Substring(1, derivationVariable.Length - 2);
97
98            if (derivationTarget != target)
99              throw new
100                ArgumentException($"The target variable {derivationTarget}  does not match the provided target {target}.",
101                                  line);
102
103            if (variables.All(v => v != derivationVariable))
104              throw new ArgumentException($"The given variable {derivationVariable} does not exist in the dataset.",
105                                          line);
106
107            if (match.Groups[2].Value.Trim() != "" || match.Groups[11].Value.Trim() != "") {
108              if (match.Groups[2].Value.Trim() == "" || match.Groups[11].Value.Trim() == "")
109                throw new ArgumentException("Number of derivation has to be written on both sides.", line);
110              if (match.Groups[2].Value.Trim() != match.Groups[11].Value.Trim())
111                throw new ArgumentException("Derivation number is not equal on both sides.", line);
112            }
113
114            var lowerBound         = ParseIntervalBounds(match.Groups[13].Value);
115            var upperBound         = ParseIntervalBounds(match.Groups[15].Value);
116            var expression         = match.Groups[0].Value;
117            var parsedTarget       = derivationTarget;
118            var isEnabled          = true;
119            var variable           = derivationVariable;
120            var numberOfDerivation = ParseDerivationCount(match.Groups[2].Value.Trim());
121            var interval           = new Interval(lowerBound, upperBound);
122
123            var constraint =
124              new IntervalConstraint(expression, variable, parsedTarget, numberOfDerivation, interval, isEnabled);
125
126            yield return constraint;
127          }
128          else {
129            throw new ArgumentException("The inserted derivation constraint is not valid.", line);
130          }
131
132          //Check for comment
133        }
134        else if (trimmedLine.StartsWith("#") || trimmedLine == "") {
135          //If it is a comment just continue without saving anything
136        }
137        else {
138          throw new
139            ArgumentException("Error at your constraints definition constraints have to start with (Target: | d | \u2202 | #)",
140                              line);
141        }
142      }
143    }
144
145    private static double ParseIntervalBounds(string input) {
146      input = input.ToLower();
147      switch (input) {
148        case "+inf.":
149        case "inf.":
150          return double.PositiveInfinity;
151        case "-inf.":
152          return double.NegativeInfinity;
153        default: {
154          if (double.TryParse(input, NumberStyles.Any, CultureInfo.InvariantCulture, out var value))
155            return value;
156          throw new ArgumentException("The given boundary is not a double value!");
157        }
158      }
159    }
160
161    private static int ParseDerivationCount(string input) {
162      switch (input) {
163        case "":
164          return 1;
165        case "²":
166          return 2;
167        case "³":
168          return 3;
169        default:
170          int.TryParse(input, out var value);
171          return value;
172      }
173    }
174  }
175}
Note: See TracBrowser for help on using the repository browser.