/* Copyright 2009-2016 David Hadka * * This file is part of the MOEA Framework. * * The MOEA Framework is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * The MOEA Framework 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the MOEA Framework. If not, see <http://www.gnu.org/licenses/>. */ package org.moeaframework.core.variable; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.moeaframework.core.PRNG; import org.moeaframework.core.Variable; /** * Decision variable for permutations. */ public class Permutation implements Variable { private static final long serialVersionUID = 5690584295426235286L; /** * The permutation array. */ private int[] permutation; /** * Constructs a permutation variable with the specified number of * elements. * * @param size the number of elements in the permutation */ public Permutation(int size) { super(); permutation = new int[size]; for (int i = 0; i < size; i++) { permutation[i] = i; } } /** * Constructs a permutation variable using the specified permutation * array. * * @param permutation the permutation array * @throws IllegalArgumentException if the permutation array is not a valid * permutation */ public Permutation(int[] permutation) { super(); this.permutation = permutation; //this call is necessary to ensure the invariants hold fromArray(permutation); } @Override public Permutation copy() { return new Permutation(permutation); } /** * Returns the number of elements in this permutation. * * @return the number of elements in this permutation */ public int size() { return permutation.length; } /** * Returns the value of the permutation at the specified index. * * @param index the index of the permutation value to be returned * @return the permutation element at the specified index * @throws ArrayOutOfBoundsException if the index is out of range {@code [0, * size()-1]} */ public int get(int index) { return permutation[index]; } /** * Swaps the {@code i}th and {@code j}th elements in this permutation. * * @param i the first index * @param j the second index * @throws ArrayIndexOutOfBoundsException if {@code i} or {@code j} is out * or range @{code [0, size()-1]} */ public void swap(int i, int j) { int temp = permutation[i]; permutation[i] = permutation[j]; permutation[j] = temp; } /** * Removes the {@code i}th element and inserts it at the {@code j}th * position. * * @param i the first index * @param j the second index * @throws ArrayIndexOutOfBoundsException if {@code i} or {@code j} is out * or range @{code [0, size()-1]} */ public void insert(int i, int j) { int temp = permutation[i]; // shifts entries in the permutation if (i < j) { for (int k = i + 1; k <= j; k++) { permutation[k - 1] = permutation[k]; } } else if (i > j) { for (int k = i - 1; k >= j; k--) { permutation[k + 1] = permutation[k]; } } permutation[j] = temp; } /** * Returns a copy of the permutation array. * * @return a copy of the permutation array */ public int[] toArray() { return permutation.clone(); } /** * Sets the permutation array. * * @param permutation the permutation array * @throws IllegalArgumentException if the permutation array is not a valid * permutation */ public void fromArray(int[] permutation) { if (!isPermutation(permutation)) { throw new IllegalArgumentException("invalid permutation"); } if (this.permutation.length != permutation.length) { throw new IllegalArgumentException("invalid permutation length"); } this.permutation = permutation.clone(); } /** * Returns {@code true} if the specified permutation is valid; {@code false} * otherwise. * * @param permutation the permutation array * @return {@code true} if the specified permutation is valid; {@code false} * otherwise */ public static boolean isPermutation(int[] permutation) { for (int i = 0; i < permutation.length; i++) { boolean contains = false; for (int j = 0; j < permutation.length; j++) { if (permutation[j] == i) { contains = true; break; } } if (!contains) { return false; } } return true; } @Override public int hashCode() { return new HashCodeBuilder().append(permutation).toHashCode(); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } else if ((obj == null) || (obj.getClass() != getClass())) { return false; } else { Permutation rhs = (Permutation)obj; return new EqualsBuilder().append(permutation, rhs.permutation) .isEquals(); } } @Override public void randomize() { PRNG.shuffle(permutation); } }