/*
* Kodkod -- Copyright (c) 2005-present, Emina Torlak
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package kodkod.instance;
/**
* Represents a sequence of atoms drawn from a given {@link kodkod.instance.Universe universe}.
* Note that a Tuple of arity n whose atoms belong to a Universe u encodes an n-digit number in
* base u.size. The decimal representation of this number is taken to be the index of the tuple
* in an n-dimensional space over the Universe u.
*
* @specfield arity: int
* @specfield universe: Universe
* @specfield atoms: [0..arity)->one Object
* @invariant atoms[int] in universe.atoms[int]
*
* @author Emina Torlak
*/
public abstract class Tuple {
/**
* Returns the universe from which the atoms in this
* tuple are drawn.
* @return this.universe
*/
public abstract Universe universe();
/**
* Returns the arity of this tuple.
* @return this.arity
*/
public abstract int arity();
/**
* A Tuple encodes a number with this.arity digits in radix this.universe.size;
* a Tuple's index is the decimal representation of this number.
*
* @return sum({i: [0..arity) | universe.index(atoms[i]) * universe.size^(arity - 1 - i)})
*/
public abstract int index();
/**
* Returns the atom at the specified index
*
* @return this.atoms[i]
* @throws IndexOutOfBoundsException i < 0 || i >= this.arity
*/
public abstract Object atom(int i);
/**
* Returns the index of the ith atom as given by this.universe.
* The effect of this method is the same as calling this.universe.index(this.atom(i)).
*
* @return this.universe.index(this.atoms[i])
* @throws IndexOutOfBoundsException i < 0 || i >= this.arity
*/
public abstract int atomIndex(int i);
/**
* Returns true if atom is in this tuple, otherwise returns false.
*
* @return atom in this.atoms[int]
* @throws IllegalArgumentException atom !in this.universe.atoms[int]
*/
public abstract boolean contains(Object atom);
/**
* Returns the cross product of this and the specified tuple.
*
* @return {t : Tuple | t.atoms = this.atoms->tuple.atoms}
* @throws NullPointerException tuple = null
* @throws IllegalArgumentException tuple.universe != this.universe
*/
public abstract Tuple product(Tuple tuple);
/**
* Returns true if o is a tuple with the same sequence of atoms as this,
* drawn from the same universe as this. Otherwise returns false.
*
* @return o in Tuple && o.universe = this.universe && o.atoms = this.atoms
*/
public boolean equals(Object o) {
if (this==o) return true;
else if (o instanceof Tuple) {
final Tuple t = (Tuple) o;
return universe().equals(t.universe()) && arity()==t.arity() && index()==t.index();
}
else return false;
}
/**
* Returns a hash code based on the tuple's arity, index, and the hash code
* of its universe, so that the general contract of Object.hashCode is obeyed.
* @return the hashcode for this tuple
*/
public int hashCode() {
return (arity() * 19 + index())^universe().hashCode();
}
/**
* @see java.lang.Object#toString()
*/
public String toString() {
final StringBuilder ret = new StringBuilder("[");
ret.append(atom(0));
for (int i = 1; i < arity(); i++) {
ret.append(", ");
ret.append(atom(i));
}
ret.append("]");
return ret.toString();
}
}