// SolutionSet.Java
//
// Author:
// Antonio J. Nebro <antonio@lcc.uma.es>
// Juan J. Durillo <durillo@lcc.uma.es>
//
// Copyright (c) 2011 Antonio J. Nebro, Juan J. Durillo
//
// This program 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.
//
// This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
package jmetal.core;
import jmetal.util.Configuration;
import java.io.*;
import java.util.*;
/**
* Class representing a SolutionSet (a set of solutions)
*/
public class SolutionSet implements Serializable {
/**
* Stores a list of <code>solution</code> objects.
*/
protected final List<Solution> solutionsList_;
/**
* Maximum size of the solution set
*/
private int capacity_ = 0;
/**
* Constructor.
* Creates an unbounded solution set.
*/
public SolutionSet() {
solutionsList_ = new ArrayList<Solution>();
} // SolutionSet
/**
* Creates a empty solutionSet with a maximum capacity.
* @param maximumSize Maximum size.
*/
public SolutionSet(int maximumSize){
solutionsList_ = new ArrayList<Solution>();
capacity_ = maximumSize;
} // SolutionSet
/**
* Inserts a new solution into the SolutionSet.
* @param solution The <code>Solution</code> to store
* @return True If the <code>Solution</code> has been inserted, false
* otherwise.
*/
public boolean add(Solution solution) {
if (solutionsList_.size() == capacity_) {
Configuration.logger_.severe("The population is full");
Configuration.logger_.severe("Capacity is : "+capacity_);
Configuration.logger_.severe("\t Size is: "+ this.size());
return false;
} // if
solutionsList_.add(solution);
return true;
} // add
public boolean add(int index, Solution solution) {
solutionsList_.add(index, solution) ;
return true ;
}
/*
public void add(Solution solution) {
if (solutionsList_.size() == capacity_)
try {
throw new JMException("SolutionSet.Add(): the population is full") ;
} catch (JMException e) {
e.printStackTrace();
}
else
solutionsList_.add(solution);
}
*/
/**
* Returns the ith solution in the set.
* @param i Position of the solution to obtain.
* @return The <code>Solution</code> at the position i.
* @throws IndexOutOfBoundsException Exception
*/
public Solution get(int i) {
if (i >= solutionsList_.size()) {
throw new IndexOutOfBoundsException("Index out of Bound "+i);
}
return solutionsList_.get(i);
} // get
/**
* Returns the maximum capacity of the solution set
* @return The maximum capacity of the solution set
*/
public int getMaxSize(){
return capacity_ ;
} // getMaxSize
/**
* Sorts a SolutionSet using a <code>Comparator</code>.
* @param comparator <code>Comparator</code> used to sort.
*/
public void sort(Comparator comparator){
if (comparator == null) {
Configuration.logger_.severe("No criterium for comparing exist");
return ;
} // if
Collections.sort(solutionsList_,comparator);
} // sort
/**
* Returns the index of the best Solution using a <code>Comparator</code>.
* If there are more than one occurrences, only the index of the first one is returned
* @param comparator <code>Comparator</code> used to compare solutions.
* @return The index of the best Solution attending to the comparator or
* <code>-1<code> if the SolutionSet is empty
*/
int indexBest(Comparator comparator){
if ((solutionsList_ == null) || (this.solutionsList_.isEmpty())) {
return -1;
}
int index = 0;
Solution bestKnown = solutionsList_.get(0), candidateSolution;
int flag;
for (int i = 1; i < solutionsList_.size(); i++) {
candidateSolution = solutionsList_.get(i);
flag = comparator.compare(bestKnown, candidateSolution);
if (flag == +1) {
index = i;
bestKnown = candidateSolution;
}
}
return index;
} // indexBest
/**
* Returns the best Solution using a <code>Comparator</code>.
* If there are more than one occurrences, only the first one is returned
* @param comparator <code>Comparator</code> used to compare solutions.
* @return The best Solution attending to the comparator or <code>null<code>
* if the SolutionSet is empty
*/
public Solution best(Comparator comparator){
int indexBest = indexBest(comparator);
if (indexBest < 0) {
return null;
} else {
return solutionsList_.get(indexBest);
}
} // best
/**
* Returns the index of the worst Solution using a <code>Comparator</code>.
* If there are more than one occurrences, only the index of the first one is returned
* @param comparator <code>Comparator</code> used to compare solutions.
* @return The index of the worst Solution attending to the comparator or
* <code>-1<code> if the SolutionSet is empty
*/
public int indexWorst(Comparator comparator){
if ((solutionsList_ == null) || (this.solutionsList_.isEmpty())) {
return -1;
}
int index = 0;
Solution worstKnown = solutionsList_.get(0), candidateSolution;
int flag;
for (int i = 1; i < solutionsList_.size(); i++) {
candidateSolution = solutionsList_.get(i);
flag = comparator.compare(worstKnown, candidateSolution);
if (flag == -1) {
index = i;
worstKnown = candidateSolution;
}
}
return index;
} // indexWorst
/**
* Returns the worst Solution using a <code>Comparator</code>.
* If there are more than one occurrences, only the first one is returned
* @param comparator <code>Comparator</code> used to compare solutions.
* @return The worst Solution attending to the comparator or <code>null<code>
* if the SolutionSet is empty
*/
public Solution worst(Comparator comparator){
int index = indexWorst(comparator);
if (index < 0) {
return null;
} else {
return solutionsList_.get(index);
}
} // worst
/**
* Returns the number of solutions in the SolutionSet.
* @return The size of the SolutionSet.
*/
public int size(){
return solutionsList_.size();
} // size
/**
* Writes the objective function values of the <code>Solution</code>
* objects into the set in a file.
* @param path The output file name
*/
public void printObjectivesToFile(String path){
try {
/* Open the file */
FileOutputStream fos = new FileOutputStream(path) ;
OutputStreamWriter osw = new OutputStreamWriter(fos) ;
BufferedWriter bw = new BufferedWriter(osw) ;
for (Solution aSolutionsList_ : solutionsList_) {
//if (this.vector[i].getFitness()<1.0) {
bw.write(aSolutionsList_.toString());
bw.newLine();
//}
}
/* Close the file */
bw.close();
}catch (IOException e) {
Configuration.logger_.severe("Error acceding to the file");
e.printStackTrace();
}
} // printObjectivesToFile
/**
* Writes the decision encodings.variable values of the <code>Solution</code>
* solutions objects into the set in a file.
* @param path The output file name
*/
public void printVariablesToFile(String path){
try {
FileOutputStream fos = new FileOutputStream(path) ;
OutputStreamWriter osw = new OutputStreamWriter(fos) ;
BufferedWriter bw = new BufferedWriter(osw) ;
if (size()>0) {
int numberOfVariables = solutionsList_.get(0).getDecisionVariables().length ;
for (Solution aSolutionsList_ : solutionsList_) {
for (int j = 0; j < numberOfVariables; j++)
bw.write(aSolutionsList_.getDecisionVariables()[j].toString() + " ");
bw.newLine();
}
}
bw.close();
}catch (IOException e) {
Configuration.logger_.severe("Error acceding to the file");
e.printStackTrace();
}
} // printVariablesToFile
/**
* Write the function values of feasible solutions into a file
* @param path File name
*/
public void printFeasibleFUN(String path) {
try {
FileOutputStream fos = new FileOutputStream(path) ;
OutputStreamWriter osw = new OutputStreamWriter(fos) ;
BufferedWriter bw = new BufferedWriter(osw) ;
for (Solution aSolutionsList_ : solutionsList_) {
if (aSolutionsList_.getOverallConstraintViolation() == 0.0) {
bw.write(aSolutionsList_.toString());
bw.newLine();
}
}
bw.close();
}catch (IOException e) {
Configuration.logger_.severe("Error acceding to the file");
e.printStackTrace();
}
}
/**
* Write the encodings.variable values of feasible solutions into a file
* @param path File name
*/
public void printFeasibleVAR(String path) {
try {
FileOutputStream fos = new FileOutputStream(path) ;
OutputStreamWriter osw = new OutputStreamWriter(fos) ;
BufferedWriter bw = new BufferedWriter(osw) ;
if (size()>0) {
int numberOfVariables = solutionsList_.get(0).getDecisionVariables().length ;
for (Solution aSolutionsList_ : solutionsList_) {
if (aSolutionsList_.getOverallConstraintViolation() == 0.0) {
for (int j = 0; j < numberOfVariables; j++)
bw.write(aSolutionsList_.getDecisionVariables()[j].toString() + " ");
bw.newLine();
}
}
}
bw.close();
}catch (IOException e) {
Configuration.logger_.severe("Error acceding to the file");
e.printStackTrace();
}
}
/**
* Empties the SolutionSet
*/
public void clear(){
solutionsList_.clear();
} // clear
/**
* Deletes the <code>Solution</code> at position i in the set.
* @param i The position of the solution to remove.
*/
public void remove(int i){
if (i > solutionsList_.size()-1) {
Configuration.logger_.severe("Size is: "+this.size());
} // if
solutionsList_.remove(i);
} // remove
/**
* Returns an <code>Iterator</code> to access to the solution set list.
* @return the <code>Iterator</code>.
*/
public Iterator<Solution> iterator(){
return solutionsList_.iterator();
} // iterator
/**
* Returns a new <code>SolutionSet</code> which is the result of the union
* between the current solution set and the one passed as a parameter.
* @param solutionSet SolutionSet to join with the current solutionSet.
* @return The result of the union operation.
*/
public SolutionSet union(SolutionSet solutionSet) {
//Check the correct size. In development
int newSize = this.size() + solutionSet.size();
if (newSize < capacity_)
newSize = capacity_;
//Create a new population
SolutionSet union = new SolutionSet(newSize);
for (int i = 0; i < this.size(); i++) {
union.add(this.get(i));
} // for
for (int i = this.size(); i < (this.size() + solutionSet.size()); i++) {
union.add(solutionSet.get(i-this.size()));
} // for
return union;
} // union
/**
* Replaces a solution by a new one
* @param position The position of the solution to replace
* @param solution The new solution
*/
public void replace(int position, Solution solution) {
if (position > this.solutionsList_.size()) {
solutionsList_.add(solution);
} // if
solutionsList_.remove(position);
solutionsList_.add(position,solution);
} // replace
/**
* Copies the objectives of the solution set to a matrix
* @return A matrix containing the objectives
*/
public double [][] writeObjectivesToMatrix() {
if (this.size() == 0) {
return null;
}
double [][] objectives;
objectives = new double[size()][get(0).getNumberOfObjectives()];
for (int i = 0; i < size(); i++) {
for (int j = 0; j < get(0).getNumberOfObjectives(); j++) {
objectives[i][j] = get(i).getObjective(j);
}
}
return objectives;
} // writeObjectivesMatrix
public void printObjectives() {
for (int i = 0; i < solutionsList_.size(); i++)
System.out.println(""+ solutionsList_.get(i)) ;
}
public void setCapacity(int capacity) {
capacity_ = capacity ;
}
public int getCapacity() {
return capacity_ ;
}
} // SolutionSet