/*******************************************************************************
* Copyright 2014 Felipe Takiyama
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package br.usp.poli.takiyama.common;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* A random variable is a function that, given an element from its domain,
* returns a real number.
* @author ftakiyama
*
*/
public final class RandomVariable {
private final String name;
private final ArrayList<String> domain;
private final ArrayList<BigDecimal> values;
/**
* A static factory of random variables.
* Creates a random variable given its name and the mapping from the
* elements of the domain to real numbers.
* @param name The name of this variable
* @param domain The domain of this random variable
* @param values A mapping from the elements of the domain to the real
* numbers.
* @return A random variable.
*/
public static RandomVariable createRandomVariable(String name, ArrayList<String> domain, ArrayList<BigDecimal> values) {
return new RandomVariable(name, domain, values);
}
/**
* A static factory of random variables.
* Creates a random variable given its name and the mapping from the
* elements of the domain to real numbers.
* @param name The name of this variable
* @param domain The domain of this random variable
* @return A random variable.
*/
public static RandomVariable createRandomVariable(String name, List<String> domain) {
return new RandomVariable(name, domain);
}
/**
* Returns a copy of the specified random variable.
* @param rv The random variable to be copied
* @return A copy of the specified random variable.
*/
public static RandomVariable copyOf(RandomVariable rv) {
return new RandomVariable(rv.name, rv.domain, rv.values);
}
/**
* Private constructor.
* Creates a random variable given its name and the mapping from the
* elements of the domain to real numbers.
* @param name The name of this variable
* @param domain The domain of this random variable
* @param values A mapping from the elements of the domain to the real
* numbers.
* @throws IllegalArgumentException if the number of values is not equal
* to the size of the domain
*/
private RandomVariable(String name, ArrayList<String> domain, ArrayList<BigDecimal> values)
throws IllegalArgumentException {
this.name = name;
this.domain = new ArrayList<String>(domain);
this.values = new ArrayList<BigDecimal>(values);
if (domain.size() != values.size()) {
throw new IllegalArgumentException("The domain should have the" +
" same number of elements as values. Domain size: " +
domain.size() + ", Values size: " + values.size());
}
}
/**
* Private constructor.
* Creates a random variable given its name and the mapping from the
* elements of the domain to real numbers.
* @param name The name of this variable
* @param domain The domain of this random variable
*/
private RandomVariable(String name, List<String> domain) {
this.name = name;
this.domain = new ArrayList<String>(domain);
this.values = null;
}
/**
* Returns an iterator over the domain.
* @return An iterator over the domain of this random variable.
*/
public Iterator<String> getDomainIterator() {
return new ArrayList<String>(this.domain).iterator();
}
/**
* Returns the size of the domain.
* @return The size of the domain.
*/
public int getDomainSize() {
return this.domain.size();
}
/**
* Returns an element from the domain.
* @param index The index of the element from the domain.
* @return The element from the domain with the index specified.
*/
public String getElementFromDomain(int index) {
return this.domain.get(index);
}
/**
* Returns the real number corresponding to an element from the domain.
* @param elementFromDomain An element from the domain
* @return The real number corresponding to an element from the domain.<br>
* If the parameter given does not exist in the domain, then returns <b>null</b>.
*/
// private BigDecimal getValue(String elementFromDomain) {
// if (this.domain.contains(elementFromDomain)) {
// return this.values.get(this.domain.indexOf(elementFromDomain));
// } else {
// return null;
// }
// }
/**
* Returns the name of this random variable.
* @return The name of this random variable.
*/
public String getName() {
return this.name;
}
@Override
public String toString() {
// String result = "";
//
// // Create the rule - aesthetical
// int maxLength = 0;
// for (String elementFromDomain : this.domain) {
// if (elementFromDomain.length() > maxLength) {
// maxLength = elementFromDomain.length();
// }
// }
// String valueCellFormat = "%-10s\n";
// String cellFormat = "%-"+ Integer.toString(maxLength + 4) + "s";
// String midRule = String.format(cellFormat, "").replace(" ", "-")
// + String.format(valueCellFormat, "").replace(" ", "-");
// String thickRule = midRule.replace("-", "=");
//
// // Prints the top rule
// result += thickRule;
//
// // Prints the name of the variable
// result += this.name + "\n";
//
// // Prints the mid rule
// result += midRule;
//
// // Print the elements from the domain and their values
// for (String elementFromDomain : this.domain) {
// result += String.format(cellFormat, elementFromDomain);
// result += String.format(valueCellFormat, getValue(elementFromDomain).doubleValue());
// }
//
// // Prints the bottom rule
// result += thickRule + "\n";
return name;
}
@Override
public boolean equals(Object other) {
// Tests if both refer to the same object
if (this == other)
return true;
// Tests if the Object is an instance of this class
if (!(other instanceof RandomVariable))
return false;
// Tests if both have the same attributes
RandomVariable targetObject = (RandomVariable) other;
return (this.name.equals(targetObject.name)
&& ((this.domain == null) ? targetObject.domain == null : this.domain.equals(targetObject.domain))
&& ((this.values == null) ? targetObject.values == null : this.values.equals(targetObject.values)));
}
@Override
public int hashCode() {
return name.hashCode() + domain.hashCode();
}
}