/** * This program (working title: MAS Prover) is an automated tableaux prover * for epistemic logic (S5n). * Copyright (C) 2007 Elske van der Vaart and Gert van Valkenhoef * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * 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 General Public License for more details. * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package nl.rug.ai.mas.oops.model; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; import java.util.Set; import nl.rug.ai.mas.oops.formula.AgentId; public class ConfigurableModel extends KripkeModel { Set<Relation> d_relationsModel; public enum Relation { TRANSITIVE, REFLEXIVE, SYMMETRIC, SERIAL; } public ConfigurableModel(Set<AgentId> agents, Collection<Relation> relationsModel) { super(agents); d_relationsModel = Collections.unmodifiableSet(new HashSet<Relation>(relationsModel)); } @Override public ConfigurableModel newModel() { return new ConfigurableModel(d_agents, d_relationsModel); } /** * Add a world to the model. This may include closure under reflexivity. */ public boolean addWorld(World w) { if (!super.addWorld(w)) { // the world already existed return false; } if (isReflexive()) { closeReflexivity(w); } return true; } /** * Add an arrow to the model. This may include closure under symmetry and transitivity. */ public boolean addArrow(Arrow r1) { if (!super.addArrow(r1)) { // the arrow already existed return false; } if (isSymmetric() && isTransitive()) { closeSymmetryAndTransitivity(r1); } else if (isSymmetric()) { closeSymmetry(r1); } else if (isTransitive()) { closeTransitivity(r1); } return true; } public boolean addArrow(AgentId agent, World source, World target) { return addArrow(new Arrow(agent, source, target)); } @Override public void closeModel() { if (isSerial()) { closeSeriality(); } } private boolean isReflexive() { return d_relationsModel.contains(Relation.REFLEXIVE); } private boolean isSymmetric() { return d_relationsModel.contains(Relation.SYMMETRIC); } private boolean isTransitive() { return d_relationsModel.contains(Relation.TRANSITIVE); } private boolean isSerial() { return d_relationsModel.contains(Relation.SERIAL); } private void closeReflexivity(World w) { for (AgentId agent : d_agents) { super.addArrow(agent, w, w); } } private void closeSymmetryAndTransitivity(Arrow r1) { Arrow r2 = new Arrow(r1.getAgent(), r1.getTarget(), r1.getSource()); super.addArrow(r2); LinkedList<Arrow> fringe = new LinkedList<Arrow>(); fringe.add(r1); fringe.add(r2); closeTransitivity(fringe); } private void closeSymmetry(Arrow r1) { Arrow r2 = new Arrow(r1.getAgent(), r1.getTarget(), r1.getSource()); super.addArrow(r2); } /** * Incrementally close relations under transitivity, given a newly added * arrow to an otherwise transitively closed set. */ private void closeTransitivity(Arrow r1) { LinkedList<Arrow> fringe = new LinkedList<Arrow>(); fringe.add(r1); closeTransitivity(fringe); } private void closeTransitivity(LinkedList<Arrow> fringe) { Arrow r = null; while ((r = fringe.poll()) != null) { // get all outgoing arrows from the target Set<Arrow> arrows = getArrowsFrom(r.getAgent(), r.getTarget()); // and add the merge of r and each arrow for (Arrow s : arrows) { Arrow t1 = new Arrow(r.getAgent(), r.getSource(), s.getTarget()); if (super.addArrow(t1)) { // t1 is a new arrow fringe.offer(t1); } } // get all in going arrows to the source arrows = getArrowsTo(r.getAgent(), r.getSource()); for (Arrow s : arrows) { Arrow t1 = new Arrow(r.getAgent(), s.getSource(), r.getTarget()); if (super.addArrow(t1)) { // t1 is a new arrow fringe.offer(t1); } } } } private void closeSeriality() { for(World world: getWorlds()) { for(AgentId agent: d_agents) { Set<Arrow> arrows = getArrowsFrom(agent, world); if(arrows.isEmpty()) { super.addArrow(agent, world, world); } } } } }