#region License Information /* HeuristicLab * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Linq; using System.Text; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.ConditionActionEncoding; using HeuristicLab.Encodings.IntegerVectorEncoding; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Encodings.CombinedIntegerVectorEncoding { [StorableClass] [Item("CombinedIntegerVector", "Represents a combined vector of integer values.")] public class CombinedIntegerVector : IntegerVector, IClassifier { [Storable] protected int actionLength; public int ActionLength { get { return actionLength; } } /// /// The bounds must contain at least one row with two columns. The first two columns specify min and max values. /// The max value -1 in a row is the don't care symbol for LCS. /// Each row represents the bounds for a certain dimension. If fewer rows are given, the rows are cycled /// [Storable] protected IntMatrix bounds; public IntMatrix Bounds { get { return (IntMatrix)bounds.Clone(); } } [StorableConstructor] protected CombinedIntegerVector(bool deserializing) : base(deserializing) { } public CombinedIntegerVector() : base() { } public CombinedIntegerVector(int[] elements, int actionPart, IntMatrix bounds) : base(elements) { this.actionLength = actionPart; //check if combinedVector satisfies bounds and if bounds is set correctly (at leats one row with 2 columns) is missing! this.bounds = bounds; } public CombinedIntegerVector(IntegerVector combinedVector, int actionPart, IntMatrix bounds) : this(combinedVector.ToArray(), actionPart, bounds) { } public CombinedIntegerVector(IntegerVector condition, IntegerVector action, IntMatrix bounds) : base(condition.Concat(action).ToArray()) { actionLength = action.Length; //check if combinedVector satisfies bounds and if bounds is set correctly (at leats one row with 2 columns) is missing! this.bounds = bounds; } public CombinedIntegerVector(IntegerVector condition, IntMatrix conditionBounds, IntegerVector action, IntMatrix actionBounds) : this(condition, action, CombineBounds(conditionBounds, actionBounds)) { } private static IntMatrix CombineBounds(IntMatrix conditionBounds, IntMatrix actionBounds) { int columns = conditionBounds.Columns < actionBounds.Columns ? conditionBounds.Columns : actionBounds.Columns; IntMatrix bounds = new IntMatrix(conditionBounds.Rows + actionBounds.Rows, columns); for (int i = 0; i < conditionBounds.Rows; i++) { for (int j = 0; j < columns; j++) { bounds[i, j] = conditionBounds[i % conditionBounds.Rows, j]; } } for (int i = conditionBounds.Rows; i < actionBounds.Rows + conditionBounds.Rows; i++) { for (int j = 0; j < columns; j++) { bounds[i, j] = actionBounds[i % actionBounds.Rows, j]; } } return bounds; } public CombinedIntegerVector(IRandom random, int length, int min, int max, int actionLenght, int actionMin, int actionMax) : this(new IntegerVector(length, random, min, max), new IntegerVector(actionLenght, random, actionMin, actionMax), null) { bounds = new IntMatrix(length + actionLenght, 2); for (int i = 0; i < length; i++) { bounds[i, 0] = min; bounds[i, 1] = max; } for (int i = length; i < length + actionLenght; i++) { bounds[i, 0] = actionMin; bounds[i, 1] = actionMax; } } public CombinedIntegerVector(int length, int actionPart, IntMatrix bounds) : base(length) { this.actionLength = actionPart; this.bounds = bounds; } protected CombinedIntegerVector(CombinedIntegerVector original, Cloner cloner) : base(original, cloner) { actionLength = original.actionLength; bounds = (IntMatrix)original.bounds.Clone(); } public override IDeepCloneable Clone(Cloner cloner) { return new CombinedIntegerVector(this, cloner); } public IClassifier Condition { get { int[] condition = new int[Length - actionLength]; Array.Copy(this.array, condition, Length - actionLength); return new CombinedIntegerVector(condition, 0, bounds); } } public IClassifier Action { get { int[] action = new int[actionLength]; Array.Copy(this.array, Length - actionLength, action, 0, actionLength); IntMatrix actionBounds = GetElementsOfBoundsForAction(bounds, Length, actionLength); return new CombinedIntegerVector(action, actionLength, actionBounds); } } private IntMatrix GetElementsOfBoundsForAction(IntMatrix bounds, int length, int actionPartLength) { IntMatrix actionBounds = new IntMatrix(actionPartLength, bounds.Columns); int start = length - actionPartLength; for (int i = start; i < length; i++) { int pos = i % bounds.Rows; for (int j = 0; j < bounds.Columns; j++) { actionBounds[i - start, j] = bounds[pos, j]; } } return actionBounds; } public bool MatchCondition(IClassifier target) { var targetVector = target as CombinedIntegerVector; if (targetVector == null) return false; if (targetVector.Length != this.Length) return false; int curbounds; for (int i = 0; i < this.Length - this.actionLength; i++) { curbounds = i % bounds.Rows; //if don't care symbol is matched, next indices can be checked if (this[i].Equals(bounds[curbounds, 1] - 1)) { continue; } if (!this[i].Equals(targetVector[i])) { return false; } } return true; } // no "don't care" symbols have to be considered public bool MatchAction(IClassifier target) { var targetVector = target as CombinedIntegerVector; if (targetVector == null) return false; if (targetVector.actionLength != this.actionLength) return false; int curPos = this.Length - this.actionLength; int curTargetPos = targetVector.Length - targetVector.actionLength; for (int i = 0; i < this.actionLength; i++) { if (!this[curPos + i].Equals(targetVector[curTargetPos + i])) { return false; } } return true; } public override string ToString() { StringBuilder strBuilder = new StringBuilder(this.Length); strBuilder.Append('['); int curbounds; for (int i = 0; i < this.Length; i++) { curbounds = i % bounds.Rows; if (i >= this.Length - this.actionLength || this[i] < bounds[curbounds, 1] - 1) { strBuilder.Append(this[i]); } else { strBuilder.Append('#'); } if (i < this.Length - 1) { strBuilder.Append(';'); } } strBuilder.Append(']'); return strBuilder.ToString(); } public override bool Equals(object obj) { var cast = obj as CombinedIntegerVector; if (cast != null) { return this.Equals(cast); } return false; } public bool Equals(IClassifier other) { return this.MatchAction(other) && this.MatchCondition(other); } public override int GetHashCode() { int result = actionLength; for (int i = 0; i < array.Length; i++) { result ^= array[i]; } return result.GetHashCode(); } } }