package util.statemachine.implementation.propnet;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import util.gdl.grammar.Gdl;
import util.gdl.grammar.GdlConstant;
import util.gdl.grammar.GdlProposition;
import util.gdl.grammar.GdlRelation;
import util.gdl.grammar.GdlSentence;
import util.gdl.grammar.GdlTerm;
import util.propnet.architecture.Component;
import util.propnet.architecture.PropNet;
import util.propnet.architecture.components.Proposition;
import util.propnet.factory.CachedPropNetFactory;
import util.statemachine.MachineState;
import util.statemachine.Move;
import util.statemachine.Role;
import util.statemachine.StateMachine;
import util.statemachine.exceptions.GoalDefinitionException;
import util.statemachine.exceptions.MoveDefinitionException;
import util.statemachine.exceptions.TransitionDefinitionException;
import util.statemachine.implementation.prover.query.ProverQueryBuilder;
@SuppressWarnings("unused")
public class PropNetStateMachine extends StateMachine {
/** The underlying proposition shef.network */
private PropNet propNet;
/** The topological ordering of the propositions */
private List<Proposition> ordering;
/** The player roles */
private List<Role> roles;
/**
* Initializes the PropNetStateMachine. You should compute the topological
* ordering here. Additionally you may compute the initial state here, at
* your discretion.
*/
@Override
public void initialize(List<Gdl> description) {
propNet = CachedPropNetFactory.create(description);
roles = propNet.getRoles();
ordering = getOrdering();
}
/**
* Computes if the state is terminal. Should return the value
* of the terminal proposition for the state.
*/
@Override
public boolean isTerminal(MachineState state) {
// TODO: Compute whether the MachineState is terminal.
return false;
}
/**
* Computes the goal for a role in the current state.
* Should return the value of the goal proposition that
* is true for that role. If there is not exactly one goal
* proposition true for that role, then you should throw a
* GoalDefinitionException because the goal is ill-defined.
*/
@Override
public int getGoal(MachineState state, Role role)
throws GoalDefinitionException {
// TODO: Compute the goal for role in state.
return -1;
}
/**
* Returns the initial state. The initial state can be computed
* by only setting the truth value of the INIT proposition to true,
* and then computing the resulting state.
*/
@Override
public MachineState getInitialState() {
// TODO: Compute the initial state.
return null;
}
/**
* Computes the legal roles for role in state.
*/
@Override
public List<Move> getLegalMoves(MachineState state, Role role)
throws MoveDefinitionException {
// TODO: Compute legal roles.
return null;
}
/**
* Computes the next state given state and the list of roles.
*/
@Override
public MachineState getNextState(MachineState state, List<Move> moves)
throws TransitionDefinitionException {
// TODO: Compute the next state.
return null;
}
/**
* This should compute the topological ordering of propositions.
* Each component is either a proposition, logical gate, or transition.
* Logical gates and transitions only have propositions as inputs.
*
* The base propositions and input propositions should always be exempt
* from this ordering.
*
* The base propositions values are set from the MachineState that
* operations are performed on and the input propositions are set from
* the Moves that operations are performed on as well (if any).
*
* @return The order in which the truth values of propositions need to be set.
*/
public List<Proposition> getOrdering()
{
// List to contain the topological ordering.
List<Proposition> order = new LinkedList<Proposition>();
// All of the components in the PropNet
List<Component> components = new ArrayList<Component>(propNet.getComponents());
// All of the propositions in the PropNet.
List<Proposition> propositions = new ArrayList<Proposition>(propNet.getPropositions());
// TODO: Compute the topological ordering.
return order;
}
/* Already implemented for you */
@Override
public Move getMoveFromSentence(GdlSentence sentence) {
return new PropNetMove(sentence);
}
/* Already implemented for you */
@Override
public MachineState getMachineStateFromSentenceList(
Set<GdlSentence> sentenceList) {
return new PropNetMachineState(sentenceList);
}
/* Already implemented for you */
@Override
public Role getRoleFromProp(GdlProposition proposition) {
return new PropNetRole(proposition);
}
/* Already implemented for you */
@Override
public List<Role> getRoles() {
return roles;
}
/* Helper methods */
/**
* The Input propositions are indexed by (does ?player ?action).
*
* This translates a list of Moves (backed by a sentence that is simply ?action)
* into GdlTerms that can be used to get Propositions from inputPropositions.
* and accordingly set their values etc. This is a naive implementation when coupled with
* setting input values, feel free to change this for a more efficient implementation.
*
* @param roles
* @return
*/
private List<GdlTerm> toDoes(List<Move> moves)
{
List<GdlTerm> doeses = new ArrayList<GdlTerm>(moves.size());
Map<Role, Integer> roleIndices = getRoleIndices();
for (int i = 0; i < roles.size(); i++)
{
int index = roleIndices.get(roles.get(i));
doeses.add(ProverQueryBuilder.toDoes(roles.get(i), moves.get(index)).toTerm());
}
return doeses;
}
/**
* Takes in a Legal Proposition and returns the appropriate corresponding Move
* @param p
* @return a PropNetMove
*/
public static Move getMoveFromProposition(Proposition p)
{
return new PropNetMove(p.getName().toSentence().get(1).toSentence());
}
/**
* Helper method for parsing the value of a goal proposition
* @param goalProposition
* @return the integer value of the goal proposition
*/
private int getGoalValue(Proposition goalProposition)
{
GdlRelation relation = (GdlRelation) goalProposition.getName().toSentence();
GdlConstant constant = (GdlConstant) relation.get(1);
return Integer.parseInt(constant.toString());
}
/**
* A Naive implementation that computes a PropNetMachineState
* from the true BasePropositions. This is correct but slower than more advanced implementations
* You need not use this method!
* @return PropNetMachineState
*/
public PropNetMachineState getStateFromBase()
{
Set<GdlSentence> contents = new HashSet<GdlSentence>();
for (Proposition p : propNet.getBasePropositions().values())
{
p.setValue(p.getSingleInput().getValue());
if (p.getValue())
{
contents.add(p.getName().toSentence());
}
}
return new PropNetMachineState(contents);
}
}