- Timestamp:
- 04/14/10 03:52:07 (15 years ago)
- Location:
- trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt
- Files:
-
- 1 deleted
- 4 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/ExhaustiveInversionMoveGenerator.cs
r3233 r3340 31 31 public static InversionMove[] Apply(Permutation permutation) { 32 32 int length = permutation.Length; 33 int totalMoves = (length) * (length - 1) / 2; // - 3;34 InversionMove[] moves = n ew InversionMove[totalMoves];33 int totalMoves = (length) * (length - 1) / 2; 34 InversionMove[] moves = null; 35 35 int count = 0; 36 36 37 37 if (permutation.PermutationType == PermutationTypes.RelativeUndirected) { 38 moves = new InversionMove[totalMoves - 3]; 38 39 for (int i = 0; i < length - 1; i++) { 39 40 for (int j = i + 1; j < length; j++) { … … 44 45 } 45 46 } else { 46 for (int i = 0; i < length - 1; i++) 47 for (int j = i + 1; j < length; j++) { 48 moves[count++] = new InversionMove(i, j); 49 } 47 moves = new InversionMove[totalMoves]; 48 for (int i = 0; i < length - 1; i++) 49 for (int j = i + 1; j < length; j++) { 50 moves[count++] = new InversionMove(i, j); 51 } 50 52 } 51 53 return moves; -
trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/InversionMoveAbsoluteAttribute.cs
r3233 r3340 26 26 [Item("InversionMoveAbsoluteAttribute", "Specifies the tabu attributes for an inversion move (2-opt) on an absolute position permutation.")] 27 27 [StorableClass] 28 public class InversionMoveAbsoluteAttribute : Item{28 public class InversionMoveAbsoluteAttribute : PermutationMoveAttribute { 29 29 [Storable] 30 30 public int Index1 { get; private set; } … … 42 42 43 43 public InversionMoveAbsoluteAttribute() 44 : this(-1, -1, -1, -1 ) { }44 : this(-1, -1, -1, -1, -1) { } 45 45 46 public InversionMoveAbsoluteAttribute(int index1, int number1, int index2, int number2 )47 : base( ) {46 public InversionMoveAbsoluteAttribute(int index1, int number1, int index2, int number2, double moveQuality) 47 : base(moveQuality) { 48 48 Index1 = index1; 49 49 Number1 = number1; -
trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/InversionMoveHardTabuCriterion.cs
r3307 r3340 29 29 30 30 namespace HeuristicLab.Encodings.PermutationEncoding { 31 [Item("PreventRemovalInversionMoveTabuChecker", "Prevents deleting of previously added edges.")] 31 [Item("InversionMoveHardTabuCriterion", @"For relative postion encoded permutations it prevents readding of previously deleted edges as well as deleting previously added edges. 32 For absolute position encoded permutations it prevents moving a number if it was previously moved. 33 34 If the aspiration condition is activated, a move will not be considered tabu against a move in the tabu list if it leads to a better solution than the quality recorded with the move in the tabu list.")] 32 35 [StorableClass] 33 public class PreventRemovalInversionMoveTabuChecker: SingleSuccessorOperator, IPermutationInversionMoveOperator, ITabuChecker {36 public class InversionMoveHardTabuCriterion : SingleSuccessorOperator, IPermutationInversionMoveOperator, ITabuChecker { 34 37 public override bool CanChangeName { 35 38 get { return false; } … … 47 50 get { return (ILookupParameter<BoolValue>)Parameters["MoveTabu"]; } 48 51 } 49 private ScopeParameter CurrentScopeParameter { 50 get { return (ScopeParameter)Parameters["CurrentScope"]; } 52 public IValueLookupParameter<BoolValue> MaximizationParameter { 53 get { return (IValueLookupParameter<BoolValue>)Parameters["Maximization"]; } 54 } 55 public ILookupParameter<DoubleValue> MoveQualityParameter { 56 get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; } 57 } 58 public ValueParameter<BoolValue> UseAspirationCriterionParameter { 59 get { return (ValueParameter<BoolValue>)Parameters["UseAspirationCriterion"]; } 51 60 } 52 61 53 public PreventRemovalInversionMoveTabuChecker() 62 public BoolValue UseAspirationCriterion { 63 get { return UseAspirationCriterionParameter.Value; } 64 set { UseAspirationCriterionParameter.Value = value; } 65 } 66 67 public InversionMoveHardTabuCriterion() 54 68 : base() { 55 69 Parameters.Add(new LookupParameter<InversionMove>("InversionMove", "The move to evaluate.")); … … 57 71 Parameters.Add(new LookupParameter<Permutation>("Permutation", "The solution as permutation.")); 58 72 Parameters.Add(new LookupParameter<ItemList<IItem>>("TabuList", "The tabu list.")); 59 Parameters.Add(new ScopeParameter("CurrentScope", "The current scope.")); 73 Parameters.Add(new ValueParameter<BoolValue>("UseAspirationCriterion", "Whether to use the aspiration criterion or not.", new BoolValue(true))); 74 Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem, else if it is a minimization problem.")); 75 Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The quality of the current move.")); 60 76 } 61 77 … … 65 81 Permutation permutation = PermutationParameter.ActualValue; 66 82 int length = permutation.Length; 83 double moveQuality = MoveQualityParameter.ActualValue.Value; 84 bool maximization = MaximizationParameter.ActualValue.Value; 85 bool useAspiration = UseAspirationCriterion.Value; 67 86 bool isTabu = false; 87 68 88 foreach (IItem tabuMove in tabuList) { 69 switch (permutation.PermutationType) { 70 case PermutationTypes.RelativeUndirected: { 71 int E1S = permutation.GetCircular(move.Index1 - 1); 72 int E1T = permutation[move.Index1]; 73 int E2S = permutation[move.Index2]; 74 int E2T = permutation.GetCircular(move.Index2 + 1); 75 InversionMoveRelativeAttribute relAttrib = (tabuMove as InversionMoveRelativeAttribute); 76 if (relAttrib != null) { 77 if (relAttrib.Edge1Source == E1S && relAttrib.Edge2Source == E1T || relAttrib.Edge1Source == E1T && relAttrib.Edge2Source == E1S 78 || relAttrib.Edge1Source == E2S && relAttrib.Edge2Source == E2T || relAttrib.Edge1Source == E2T && relAttrib.Edge2Source == E2S 79 // if previously added Edge1Target-Edge2Target is deleted 80 || relAttrib.Edge1Target == E2S && relAttrib.Edge2Target == E2T || relAttrib.Edge1Target == E2T && relAttrib.Edge2Target == E2S 81 || relAttrib.Edge1Target == E1S && relAttrib.Edge2Target == E1T || relAttrib.Edge1Target == E1T && relAttrib.Edge2Target == E1S) { 82 isTabu = true; 89 PermutationMoveAttribute attrib = (tabuMove as PermutationMoveAttribute); 90 if (!useAspiration 91 || maximization && moveQuality <= attrib.MoveQuality 92 || !maximization && moveQuality >= attrib.MoveQuality) { 93 switch (permutation.PermutationType) { 94 case PermutationTypes.RelativeUndirected: { 95 int E1S = permutation.GetCircular(move.Index1 - 1); 96 int E1T = permutation[move.Index1]; 97 int E2S = permutation[move.Index2]; 98 int E2T = permutation.GetCircular(move.Index2 + 1); 99 InversionMoveRelativeAttribute relAttrib = (attrib as InversionMoveRelativeAttribute); 100 if (relAttrib != null) { 101 if (relAttrib.Edge1Source == E1S && relAttrib.Edge2Source == E1T || relAttrib.Edge1Source == E1T && relAttrib.Edge2Source == E1S 102 || relAttrib.Edge1Source == E2S && relAttrib.Edge2Source == E2T || relAttrib.Edge1Source == E2T && relAttrib.Edge2Source == E2S 103 // if previously added Edge1Target-Edge2Target is deleted 104 || relAttrib.Edge1Target == E2S && relAttrib.Edge2Target == E2T || relAttrib.Edge1Target == E2T && relAttrib.Edge2Target == E2S 105 || relAttrib.Edge1Target == E1S && relAttrib.Edge2Target == E1T || relAttrib.Edge1Target == E1T && relAttrib.Edge2Target == E1S) { 106 isTabu = true; 107 } 83 108 } 84 109 } 85 }86 break;87 case PermutationTypes.RelativeDirected: {88 int E1S = permutation.GetCircular(move.Index1 - 1);89 int E1T = permutation[move.Index1];90 int E2S = permutation[move.Index2];91 int E2T = permutation.GetCircular(move.Index2 + 1);92 InversionMoveRelativeAttribute relAttrib = (tabuMove as InversionMoveRelativeAttribute);93 if (relAttrib != null) {94 if (relAttrib.Edge1Source == E1S && relAttrib.Edge2Source == E1T95 || relAttrib.Edge1Source == E2S && relAttrib.Edge2Source == E2T96 // if previously added Edge1Target-Edge2Target is deleted97 || relAttrib.Edge1Target == E2S && relAttrib.Edge2Target == E2T98 || relAttrib.Edge1Target == E1S && relAttrib.Edge2Target == E1T) {99 isTabu = true;110 break; 111 case PermutationTypes.RelativeDirected: { 112 int E1S = permutation.GetCircular(move.Index1 - 1); 113 int E1T = permutation[move.Index1]; 114 int E2S = permutation[move.Index2]; 115 int E2T = permutation.GetCircular(move.Index2 + 1); 116 InversionMoveRelativeAttribute relAttrib = (attrib as InversionMoveRelativeAttribute); 117 if (relAttrib != null) { 118 if (relAttrib.Edge1Source == E1S && relAttrib.Edge2Source == E1T 119 || relAttrib.Edge1Source == E2S && relAttrib.Edge2Source == E2T 120 // if previously added Edge1Target-Edge2Target is deleted 121 || relAttrib.Edge1Target == E2S && relAttrib.Edge2Target == E2T 122 || relAttrib.Edge1Target == E1S && relAttrib.Edge2Target == E1T) { 123 isTabu = true; 124 } 100 125 } 101 126 } 102 } 103 break; 104 case PermutationTypes.Absolute: { 105 int i1 = move.Index1; 106 int n1 = permutation[move.Index1]; 107 int i2 = move.Index2; 108 int n2 = permutation[move.Index2]; 109 InversionMoveAbsoluteAttribute absAttrib = (tabuMove as InversionMoveAbsoluteAttribute); 110 if (absAttrib != null) { 111 if (absAttrib.Number1 == n1 || absAttrib.Number1 == n2 112 || absAttrib.Number2 == n2 || absAttrib.Number2 == n1) 113 isTabu = true; 127 break; 128 case PermutationTypes.Absolute: { 129 int i1 = move.Index1; 130 int n1 = permutation[move.Index1]; 131 int i2 = move.Index2; 132 int n2 = permutation[move.Index2]; 133 InversionMoveAbsoluteAttribute absAttrib = (attrib as InversionMoveAbsoluteAttribute); 134 if (absAttrib != null) { 135 if (absAttrib.Number1 == n1 || absAttrib.Number1 == n2 136 || absAttrib.Number2 == n2 || absAttrib.Number2 == n1) 137 isTabu = true; 114 138 139 } 115 140 } 116 }117 break;118 default: {119 throw new InvalidOperationException(Name + ": Unknown permutation type.");120 141 break; 142 default: { 143 throw new InvalidOperationException(Name + ": Unknown permutation type."); 144 } 145 } 121 146 } 122 147 if (isTabu) break; -
trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/InversionMoveRelativeAttribute.cs
r3233 r3340 26 26 [Item("InversionMoveRelativeAttribute", "Specifies the tabu attributes for an inversion move (2-opt) on a relative position permutation.")] 27 27 [StorableClass] 28 public class InversionMoveRelativeAttribute : Item{28 public class InversionMoveRelativeAttribute : PermutationMoveAttribute { 29 29 [Storable] 30 30 public int Edge1Source { get; private set; } … … 42 42 43 43 public InversionMoveRelativeAttribute() 44 : this(-1, -1, -1, -1 ) { }44 : this(-1, -1, -1, -1, -1) { } 45 45 46 public InversionMoveRelativeAttribute(int edge1Source, int edge1Target, int edge2Source, int edge2Target )47 : base( ) {46 public InversionMoveRelativeAttribute(int edge1Source, int edge1Target, int edge2Source, int edge2Target, double moveQuality) 47 : base(moveQuality) { 48 48 Edge1Source = edge1Source; 49 49 Edge1Target = edge1Target; -
trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/InversionMoveSoftTabuCriterion.cs
r3307 r3340 29 29 30 30 namespace HeuristicLab.Encodings.PermutationEncoding { 31 [Item("PreventReaddInversionMoveTabuChecker", "Prevents readding of previously deleted edges, but allows deleting previously added edges.")] 31 [Item("InversionMoveSoftTabuCriterion", @"For relative postion encoded permutations it just prevents readding of previously deleted edges, but allows deleting previously added edges. 32 For absolute position encoded permutations it prevents moving a number to a position it has previously occupied. 33 34 If the aspiration condition is activated, a move will not be considered tabu against a move in the tabu list if it leads to a better solution than the quality recorded with the move in the tabu list.")] 32 35 [StorableClass] 33 public class PreventReaddInversionMoveTabuChecker: SingleSuccessorOperator, IPermutationInversionMoveOperator, ITabuChecker {36 public class InversionMoveSoftTabuCriterion : SingleSuccessorOperator, IPermutationInversionMoveOperator, ITabuChecker { 34 37 public override bool CanChangeName { 35 38 get { return false; } … … 47 50 get { return (ILookupParameter<BoolValue>)Parameters["MoveTabu"]; } 48 51 } 49 private ScopeParameter CurrentScopeParameter { 50 get { return (ScopeParameter)Parameters["CurrentScope"]; } 52 public IValueLookupParameter<BoolValue> MaximizationParameter { 53 get { return (IValueLookupParameter<BoolValue>)Parameters["Maximization"]; } 54 } 55 public ILookupParameter<DoubleValue> MoveQualityParameter { 56 get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; } 57 } 58 public ValueParameter<BoolValue> UseAspirationCriterionParameter { 59 get { return (ValueParameter<BoolValue>)Parameters["UseAspirationCriterion"]; } 51 60 } 52 61 53 public PreventReaddInversionMoveTabuChecker() 62 public BoolValue UseAspirationCriterion { 63 get { return UseAspirationCriterionParameter.Value; } 64 set { UseAspirationCriterionParameter.Value = value; } 65 } 66 67 public InversionMoveSoftTabuCriterion() 54 68 : base() { 55 69 Parameters.Add(new LookupParameter<InversionMove>("InversionMove", "The move to evaluate.")); … … 57 71 Parameters.Add(new LookupParameter<Permutation>("Permutation", "The solution as permutation.")); 58 72 Parameters.Add(new LookupParameter<ItemList<IItem>>("TabuList", "The tabu list.")); 59 Parameters.Add(new ScopeParameter("CurrentScope", "The current scope.")); 73 Parameters.Add(new ValueParameter<BoolValue>("UseAspirationCriterion", "Whether to use the aspiration criterion or not.", new BoolValue(true))); 74 Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem, else if it is a minimization problem.")); 75 Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The quality of the current move.")); 60 76 } 61 77 … … 65 81 Permutation permutation = PermutationParameter.ActualValue; 66 82 int length = permutation.Length; 83 double moveQuality = MoveQualityParameter.ActualValue.Value; 84 bool maximization = MaximizationParameter.ActualValue.Value; 85 bool useAspiration = UseAspirationCriterion.Value; 67 86 bool isTabu = false; 87 68 88 foreach (IItem tabuMove in tabuList) { 69 switch (permutation.PermutationType) { 70 case PermutationTypes.RelativeUndirected: { 71 int E1S = permutation.GetCircular(move.Index1 - 1); 72 int E1T = permutation[move.Index1]; 73 int E2S = permutation[move.Index2]; 74 int E2T = permutation.GetCircular(move.Index2 + 1); 75 InversionMoveRelativeAttribute relAttrib = (tabuMove as InversionMoveRelativeAttribute); 76 if (relAttrib != null) { 77 // if previously deleted Edge1Source-Target is readded 78 if (relAttrib.Edge1Source == E1S && relAttrib.Edge1Target == E2S || relAttrib.Edge1Source == E2S && relAttrib.Edge1Target == E1S 79 || relAttrib.Edge1Source == E1T && relAttrib.Edge1Target == E2T || relAttrib.Edge1Source == E2T && relAttrib.Edge1Target == E1T 80 // if previously deleted Edge2Source-Target is readded 81 || relAttrib.Edge2Source == E1T && relAttrib.Edge2Target == E2T || relAttrib.Edge2Source == E2T && relAttrib.Edge2Target == E1T 82 || relAttrib.Edge2Source == E1S && relAttrib.Edge2Target == E2S || relAttrib.Edge2Source == E2S && relAttrib.Edge2Target == E1S) { 83 isTabu = true; 89 PermutationMoveAttribute attrib = (tabuMove as PermutationMoveAttribute); 90 if (!useAspiration 91 || maximization && moveQuality <= attrib.MoveQuality 92 || !maximization && moveQuality >= attrib.MoveQuality) { 93 switch (permutation.PermutationType) { 94 case PermutationTypes.RelativeUndirected: { 95 int E1S = permutation.GetCircular(move.Index1 - 1); 96 int E1T = permutation[move.Index1]; 97 int E2S = permutation[move.Index2]; 98 int E2T = permutation.GetCircular(move.Index2 + 1); 99 InversionMoveRelativeAttribute relAttrib = (attrib as InversionMoveRelativeAttribute); 100 if (relAttrib != null) { 101 // if previously deleted Edge1Source-Target is readded 102 if (relAttrib.Edge1Source == E1S && relAttrib.Edge1Target == E2S || relAttrib.Edge1Source == E2S && relAttrib.Edge1Target == E1S 103 || relAttrib.Edge1Source == E1T && relAttrib.Edge1Target == E2T || relAttrib.Edge1Source == E2T && relAttrib.Edge1Target == E1T 104 // if previously deleted Edge2Source-Target is readded 105 || relAttrib.Edge2Source == E1T && relAttrib.Edge2Target == E2T || relAttrib.Edge2Source == E2T && relAttrib.Edge2Target == E1T 106 || relAttrib.Edge2Source == E1S && relAttrib.Edge2Target == E2S || relAttrib.Edge2Source == E2S && relAttrib.Edge2Target == E1S) { 107 isTabu = true; 108 } 84 109 } 85 110 } 86 }87 break;88 case PermutationTypes.RelativeDirected: {89 int E1S = permutation.GetCircular(move.Index1 - 1);90 int E1T = permutation[move.Index1];91 int E2S = permutation[move.Index2];92 int E2T = permutation.GetCircular(move.Index2 + 1);93 InversionMoveRelativeAttribute relAttrib = (tabuMove as InversionMoveRelativeAttribute);94 if (relAttrib != null) {95 if (relAttrib.Edge1Source == E1S && relAttrib.Edge1Target == E2S96 || relAttrib.Edge1Source == E1T && relAttrib.Edge1Target == E2T97 // if previously deleted Edge2Source-Target is readded98 || relAttrib.Edge2Source == E1T && relAttrib.Edge2Target == E2T99 || relAttrib.Edge2Source == E1S && relAttrib.Edge2Target == E2S) {100 isTabu = true;111 break; 112 case PermutationTypes.RelativeDirected: { 113 int E1S = permutation.GetCircular(move.Index1 - 1); 114 int E1T = permutation[move.Index1]; 115 int E2S = permutation[move.Index2]; 116 int E2T = permutation.GetCircular(move.Index2 + 1); 117 InversionMoveRelativeAttribute relAttrib = (attrib as InversionMoveRelativeAttribute); 118 if (relAttrib != null) { 119 if (relAttrib.Edge1Source == E1S && relAttrib.Edge1Target == E2S 120 || relAttrib.Edge1Source == E1T && relAttrib.Edge1Target == E2T 121 // if previously deleted Edge2Source-Target is readded 122 || relAttrib.Edge2Source == E1T && relAttrib.Edge2Target == E2T 123 || relAttrib.Edge2Source == E1S && relAttrib.Edge2Target == E2S) { 124 isTabu = true; 125 } 101 126 } 102 127 } 103 } 104 break; 105 case PermutationTypes.Absolute: { 106 int i1 = move.Index1; 107 int n1 = permutation[move.Index1]; 108 int i2 = move.Index2; 109 int n2 = permutation[move.Index2]; 110 InversionMoveAbsoluteAttribute absAttrib = (tabuMove as InversionMoveAbsoluteAttribute); 111 if (absAttrib != null) { 112 if ((absAttrib.Index1 == i1 || absAttrib.Index1 == i2) && (absAttrib.Number1 == n1 || absAttrib.Number1 == n2) 113 || (absAttrib.Index2 == i2 || absAttrib.Index2 == i1) && (absAttrib.Number2 == n2 || absAttrib.Number2 == n1)) 114 isTabu = true; 128 break; 129 case PermutationTypes.Absolute: { 130 int i1 = move.Index1; 131 int n1 = permutation[move.Index1]; 132 int i2 = move.Index2; 133 int n2 = permutation[move.Index2]; 134 InversionMoveAbsoluteAttribute absAttrib = (attrib as InversionMoveAbsoluteAttribute); 135 if (absAttrib != null) { 136 if ((absAttrib.Index1 == i1 || absAttrib.Index1 == i2) && (absAttrib.Number1 == n1 || absAttrib.Number1 == n2) 137 || (absAttrib.Index2 == i2 || absAttrib.Index2 == i1) && (absAttrib.Number2 == n2 || absAttrib.Number2 == n1)) 138 isTabu = true; 115 139 140 } 116 141 } 117 }118 break;119 default: {120 throw new InvalidOperationException(Name + ": Unknown permutation type.");121 142 break; 143 default: { 144 throw new InvalidOperationException(Name + ": Unknown permutation type."); 145 } 146 } 122 147 } 123 148 if (isTabu) break; -
trunk/sources/HeuristicLab.Encodings.PermutationEncoding/3.3/Moves/TwoOpt/InversionMoveTabuMaker.cs
r3233 r3340 29 29 30 30 namespace HeuristicLab.Encodings.PermutationEncoding { 31 [Item("InversionMoveTabuMaker", "Declares a given inversion move (2-opt) as tabu, by adding its attributes to the tabu list .")]31 [Item("InversionMoveTabuMaker", "Declares a given inversion move (2-opt) as tabu, by adding its attributes to the tabu list and also store the solution quality or the move quality (whichever is better).")] 32 32 [StorableClass] 33 33 public class InversionMoveTabuMaker : TabuMaker, IPermutationInversionMoveOperator { … … 48 48 } 49 49 50 protected override IItem GetTabuAttribute( ) {50 protected override IItem GetTabuAttribute(bool maximization, double quality, double moveQuality) { 51 51 InversionMove move = InversionMoveParameter.ActualValue; 52 52 Permutation permutation = PermutationParameter.ActualValue; 53 double baseQuality = moveQuality; 54 if (maximization && quality > moveQuality || !maximization && quality < moveQuality) baseQuality = quality; // we make an uphill move, the lower bound is the solution quality 53 55 if (permutation.PermutationType == PermutationTypes.Absolute) 54 return new InversionMoveAbsoluteAttribute(move.Index1, permutation[move.Index1], move.Index2, permutation[move.Index2] );56 return new InversionMoveAbsoluteAttribute(move.Index1, permutation[move.Index1], move.Index2, permutation[move.Index2], baseQuality); 55 57 else 56 58 return new InversionMoveRelativeAttribute(permutation.GetCircular(move.Index1 - 1), 57 59 permutation[move.Index1], 58 60 permutation[move.Index2], 59 permutation.GetCircular(move.Index2 + 1)); 61 permutation.GetCircular(move.Index2 + 1), 62 baseQuality); 60 63 } 61 64 }
Note: See TracChangeset
for help on using the changeset viewer.