/* * 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; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import kodkod.ast.Relation; import kodkod.util.ints.IntSet; import kodkod.util.ints.Ints; import kodkod.util.ints.SparseSequence; import kodkod.util.ints.TreeSequence; /** * Represents a model (an instance) of a relational formula, which is a mapping * from {@link kodkod.ast.Relation relations} and integers to {@link kodkod.instance.TupleSet sets of tuples} * drawn from a given {@link kodkod.instance.Universe universe}. * * @specfield universe: Universe * @specfield relations: set Relation * @specfield tuples: (relations -> one TupleSet) + (int -> lone TupleSet) * @invariant all r: tuples.TupleSet & Relation | r.arity = tuples[r].arity && tuples[r].universe = universe * @invariant all i: tuples.TupleSet & int | ints[i].arity = 1 && ints[i].size() = 1 * * @author Emina Torlak */ public final class Instance implements Cloneable { private final Map<Relation, TupleSet> tuples; private final SparseSequence<TupleSet> ints; private final Universe universe; private Instance(Universe u, Map<Relation, TupleSet> tuples, SparseSequence<TupleSet> ints) { this.universe = u; this.tuples = tuples; this.ints = ints; } /** * Constructs an empty instance over the given universe * * @ensures this.universe' = universe && no this.tuples' * @throws NullPointerException universe = null */ public Instance(final Universe universe) { if (universe==null) throw new NullPointerException("universe=null"); this.universe = universe; this.tuples = new LinkedHashMap<Relation, TupleSet>(); this.ints = new TreeSequence<TupleSet>(); } /** * Returns the universe from which the tuples in this instance * are drawn. * @return this.universe */ public Universe universe() { return universe; } /** * Returns true if this instance maps the given relation to a set * of tuples; otherwise returns false. * @return r in this.relations */ public boolean contains(Relation relation) { return tuples.containsKey(relation); } /** * Returns true if this instance maps the given integer to a singleton * tupleset; otherwise returns false. * @return some this.tuples[i] */ public boolean contains(int i) { return ints.containsIndex(i); } /** * Returns the relations mapped by this instance. The returned set * does not support addition. It supports remval if this is not an * unmodifiable instance. * @return this.relations */ public Set<Relation> relations() { return tuples.keySet(); } /** * Returns the integers mapped by this instance. The returned set * does not support addition. It supports remval if this is not an * unmodifiable instance. * @return this.ints.TupleSet */ public IntSet ints() { return ints.indices(); } /** * Maps the given relation to the given tuple set. * @ensures this.tuples' = this.tuples ++ relation->s * @throws NullPointerException relation = null || s = null * @throws IllegalArgumentException relation.arity != s.arity * @throws IllegalArgumentException s.universe != this.universe * @throws UnsupportedOperationException this is an unmodifiable instance */ public void add(final Relation relation, TupleSet s) { if (!s.universe().equals(universe)) throw new IllegalArgumentException("s.universe!=this.universe"); if (relation.arity()!=s.arity()) throw new IllegalArgumentException("relation.arity!=s.arity"); tuples.put(relation, s.clone().unmodifiableView()); } /** * Maps the given integer to the given tuple set. * @ensures this.tuples' = this.tuples ++ i->s * @throws NullPointerException s = null * @throws IllegalArgumentException s.arity != 1 || s.size() != 1 * @throws IllegalArgumentException s.universe != this.universe * @throws UnsupportedOperationException this is an unmodifiable instance */ public void add(int i, TupleSet s) { if (!s.universe().equals(universe)) throw new IllegalArgumentException("s.universe!=this.universe"); if (s.arity()!=1) throw new IllegalArgumentException("s.arity!=1: " + s); if (s.size()!=1) throw new IllegalArgumentException("s.size()!=1: " + s); ints.put(i, s.clone().unmodifiableView()); } /** * Returns the set of tuples assigned to the given relation by this Instance. * If the relation is not mapped by the model, null is returned. * * @return this.tuples[relation] */ public TupleSet tuples(Relation relation) { return tuples.get(relation); } /** * Returns a map view of Relation<:this.tuples. The returned map is unmodifiable. * @return a map view of Relation<:this.tuples. */ public Map<Relation, TupleSet> relationTuples() { return Collections.unmodifiableMap(tuples); } /** * Returns the set of tuples assigned to the given integer by this Instance. * If the integer is not mapped by the model, null is returned. * * @return this.tuples[i] */ public TupleSet tuples(int i) { return ints.get(i); } /** * Returns a sparse sequence view of int<:this.tuples. The returned sequence is unmodifiable. * @return a sparse sequence view of int<:this.tuples. */ public SparseSequence<TupleSet> intTuples() { return Ints.unmodifiableSequence(ints); } /** * Returns an unmodifiable view of this instance. * @return an unmodifiable view of this instance. */ public Instance unmodifiableView() { return new Instance(universe, Collections.unmodifiableMap(tuples), Ints.unmodifiableSequence(ints)); } /** * Returns a deep copy of this Instance object. * @return a deep copy of this Instance object. */ public Instance clone() { try { return new Instance(universe, new LinkedHashMap<Relation, TupleSet>(tuples), ints.clone()); } catch (CloneNotSupportedException cnse) { throw new InternalError(); // should not be reached } } /** * {@inheritDoc} * @see java.lang.Object#toString() */ public String toString() { return "relations: "+tuples.toString() + "\nints: " + ints; } }