/******************************************************************************* * * This file is part of iBioSim. Please visit <http://www.async.ece.utah.edu/ibiosim> * for the latest version of iBioSim. * * Copyright (C) 2017 University of Utah * * This library is free software; you can redistribute it and/or modify it * under the terms of the Apache License. A copy of the license agreement is provided * in the file named "LICENSE.txt" included with this software distribution * and also available online at <http://www.async.ece.utah.edu/ibiosim/License>. * *******************************************************************************/ package edu.utah.ece.async.lema.verification.platu.stategraph; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Set; import edu.utah.ece.async.lema.verification.lpn.LPN; import edu.utah.ece.async.lema.verification.lpn.Transition; import edu.utah.ece.async.lema.verification.platu.common.PlatuObj; import edu.utah.ece.async.lema.verification.platu.platuLpn.DualHashMap; import edu.utah.ece.async.lema.verification.platu.platuLpn.LpnTranList; import edu.utah.ece.async.lema.verification.platu.platuLpn.VarSet; import edu.utah.ece.async.lema.verification.timed_state_exploration.zone.TimedState; /** * State * @author Administrator * @author Chris Myers * @author <a href="http://www.async.ece.utah.edu/ibiosim#Credits"> iBioSim Contributors </a> * @version %I% */ public class State extends PlatuObj { public static int[] counts = new int[15]; protected int[] marking; protected int[] vector; protected boolean[] tranVector; // an indicator vector showing whether each transition is enabled or not private int hashVal = 0; protected LPN lpn; private int index; private boolean localEnabledOnly; protected boolean failure = false; // The TimingState that extends this state with a zone. Null if untimed. //protected TimedState timeExtension; // A list of all the TimedStates that are time extensions of this state. private ArrayList<TimedState> timeExtensions; @Override public String toString() { // String ret=Arrays.toString(marking)+""+ // Arrays.toString(vector); // return "["+ret.replace("[", "{").replace("]", "}")+"]"; return this.print(); } public State(final LPN lpn, int[] new_marking, int[] new_vector, boolean[] new_isTranEnabled) { this.lpn = lpn; this.marking = new_marking; this.vector = new_vector; if(new_isTranEnabled != null) this.tranVector = new_isTranEnabled; if (marking == null || vector == null || tranVector == null) { new NullPointerException().printStackTrace(); } //Arrays.sort(this.marking); //this.index = 0; localEnabledOnly = false; counts[0]++; } public State(State other) { if (other == null) { new NullPointerException().printStackTrace(); return; } this.lpn = other.lpn; this.marking = new int[other.marking.length]; System.arraycopy(other.marking, 0, this.marking, 0, other.marking.length); this.vector = new int[other.vector.length]; System.arraycopy(other.vector, 0, this.vector, 0, other.vector.length); this.tranVector = new boolean[other.tranVector.length]; System.arraycopy(other.tranVector, 0, this.tranVector, 0, other.tranVector.length); // this.hashVal = other.hashVal; this.hashVal = 0; this.index = other.index; this.localEnabledOnly = other.localEnabledOnly; counts[0]++; } // Temporarily commented out the two unused constructors, State() and State(Object otherState) // public State() { // this.marking = new int[0]; // this.vector = new int[0];//EMPTY_VECTOR.clone(); // this.hashVal = 0; // this.index = 0; // localEnabledOnly = false; // counts[0]++; // } //static PrintStream out = System.out; // public State(Object otherState) { // State other = (State) otherState; // if (other == null) { // new NullPointerException().printStackTrace(); // } // // this.lpnModel = other.lpnModel; // this.marking = new int[other.marking.length]; // System.arraycopy(other.marking, 0, this.marking, 0, other.marking.length); // // // this.vector = other.getVector().clone(); // this.vector = new int[other.vector.length]; // System.arraycopy(other.vector, 0, this.vector, 0, other.vector.length); // // this.hashVal = other.hashVal; // this.index = other.index; // this.localEnabledOnly = other.localEnabledOnly; // counts[0]++; // } public void setLpn(final LPN thisLpn) { this.lpn = thisLpn; } public LPN getLpn() { return this.lpn; } @Override public void setLabel(String lbl) { } @Override public String getLabel() { return "S" + getIndex(); } /** * This method returns the boolean array representing the status (enabled/disabled) of each transition in an LPN. * @return */ public boolean[] getTranVector() { return tranVector; } @Override public void setIndex(int newIndex) { this.index = newIndex; } @Override public int getIndex() { return this.index; } public boolean hasNonLocalEnabled() { return this.localEnabledOnly; } public void hasNonLocalEnabled(boolean nonLocalEnabled) { this.localEnabledOnly = nonLocalEnabled; } @SuppressWarnings("static-method") public boolean isFailure() { return false;// getType() != getType().NORMAL || getType() != // getType().TERMINAL; } public static long tSum = 0; @Override public State clone() { counts[6]++; State s = new State(this); return s; } public String print() { DualHashMap<String, Integer> VarIndexMap = this.lpn.getVarIndexMap(); String newLine = System.getProperty("line.separator");//This will retrieve line separator dependent on OS. String message = "State ID: " + index + newLine; message += "LPN: " + lpn.getLabel() + newLine; message += "Marking: ["; for (int i : marking) { message += i + ","; } message += "]" + newLine + "Vector: ["; for (int i = 0; i < vector.length; i++) { message += VarIndexMap.getKey(i) + "=>" + vector[i]+", "; } message += "]" + newLine + "Transition Vector: ["; for (int i = 0; i < tranVector.length; i++) { message += tranVector[i] + ","; } message += "]" + newLine + "Enabled Transition: ["; for (int i = 0; i < tranVector.length; i++) { if (tranVector[i]) { message += lpn.getTransition(i).getLabel(); } } message += "]" + newLine; return message; } @Override public int hashCode() { if(hashVal == 0){ final int prime = 31; int result = 1; result = prime * result + ((lpn == null) ? 0 : lpn.getLabel().hashCode()); result = prime * result + Arrays.hashCode(marking); result = prime * result + Arrays.hashCode(vector); result = prime * result + Arrays.hashCode(tranVector); hashVal = result; } return hashVal; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; State other = (State) obj; if (lpn == null) { if (other.lpn != null) return false; } else if (!lpn.equals(other.lpn)) return false; if (!Arrays.equals(marking, other.marking)) return false; if (!Arrays.equals(vector, other.vector)) return false; if (!Arrays.equals(tranVector, other.tranVector)) return false; return true; } public void print(DualHashMap<String, Integer> VarIndexMap) { System.out.print("Marking: ["); for (int i : marking) { System.out.print(i + ","); } System.out.println("]"); System.out.print("Vector: ["); for (int i = 0; i < vector.length; i++) { System.out.print(VarIndexMap.getKey(i) + "=>" + vector[i]+", "); } System.out.println("]"); System.out.print("Transition vector: ["); for (boolean bool : tranVector) { System.out.print(bool + ","); } System.out.println("]"); } /** * @return the marking */ public int[] getMarking() { return marking; } public void setMarking(int[] newMarking) { marking = newMarking; } /** * @return the vector */ public int[] getVariableVector() { // new Exception("StateVector getVector(): "+s).printStackTrace(); return vector; } public HashMap<String, Integer> getOutVector(VarSet outputs, DualHashMap<String, Integer> VarIndexMap) { HashMap<String, Integer> outVec = new HashMap<String, Integer>(); for(int i = 0; i < vector.length; i++) { String var = VarIndexMap.getKey(i); if(outputs.contains(var) == true) outVec.put(var, vector[i]); } return outVec; } public State getLocalState() { //VarSet lpnOutputs = this.lpnModel.getOutputs(); //VarSet lpnInternals = this.lpnModel.getInternals(); Set<String> lpnOutputs = this.lpn.getAllOutputs().keySet(); Set<String> lpnInternals = this.lpn.getAllInternals().keySet(); DualHashMap<String,Integer> varIndexMap = this.lpn.getVarIndexMap(); int[] outVec = new int[this.vector.length]; /* * Create a copy of the vector of mState such that the values of inputs are set to 0 * and the values for outputs/internal variables remain the same. */ for(int i = 0; i < this.vector.length; i++) { String curVar = varIndexMap.getKey(i); if(lpnOutputs.contains(curVar) ==true || lpnInternals.contains(curVar)==true) outVec[i] = this.vector[i]; else outVec[i] = 0; } return new State(this.lpn, this.marking, outVec, this.tranVector); } /** * @return the enabledSet */ public static int[] getEnabledSet() { return null;// enabledSet; } public LpnTranList getEnabledTransitions() { LpnTranList enabledTrans = new LpnTranList(); for (int i=0; i<tranVector.length; i++) { if (tranVector[i]) { Transition tran = this.lpn.getTransition(i); if(tran.isLocal()) enabledTrans.addLast(tran); else enabledTrans.addFirst(tran); } } return enabledTrans; } @SuppressWarnings("static-method") public String getEnabledSetString() { String ret = ""; // for (int i : enabledSet) { // ret += i + ", "; // } return ret; } /** * Return a new state if the newVector leads to a new state from this state; otherwise return null. * @param newVector * @param VarIndexMap * @return */ public State update(StateGraph SG, HashMap<String, Integer> newVector, DualHashMap<String, Integer> VarIndexMap) { int[] newVariableVector = new int[this.vector.length]; boolean newState = false; for(int index = 0; index < vector.length; index++) { String var = VarIndexMap.getKey(index); int this_val = this.vector[index]; Integer newVal = newVector.get(var); if(newVal != null) { if(this_val != newVal) { newState = true; newVariableVector[index] = newVal; } else newVariableVector[index] = this.vector[index]; } else newVariableVector[index] = this.vector[index]; } if(newState == true) { boolean[] newTranVector = SG.updateTranVector(this, this.marking, newVariableVector, null); return new State(this.lpn, this.marking, newVariableVector, newTranVector); } return null; } /** * Return a new state if the newVector leads to a new state from this state; otherwise return null. * States considered here include a vector indicating enabled/disabled state of each transition. * @param newVector * @param VarIndexMap * @return */ public State update(HashMap<String, Integer> newVector, DualHashMap<String, Integer> VarIndexMap, boolean[] newTranVector) { int[] newStateVector = new int[this.vector.length]; boolean newState = false; for(int index = 0; index < vector.length; index++) { String var = VarIndexMap.getKey(index); int this_val = this.vector[index]; Integer newVal = newVector.get(var); if(newVal != null) { if(this_val != newVal) { newState = true; newStateVector[index] = newVal; } else newStateVector[index] = this.vector[index]; } else newStateVector[index] = this.vector[index]; } if (!this.tranVector.equals(newTranVector)) newState = true; if(newState == true) return new State(this.lpn, this.marking, newStateVector, newTranVector); return null; } static public void printUsageStats() { System.out.printf("%-20s %11s\n", "State", counts[0]); System.out.printf("\t%-20s %11s\n", "State", counts[10]); // System.out.printf("\t%-20s %11s\n", "State", counts[11]); // System.out.printf("\t%-20s %11s\n", "merge", counts[1]); System.out.printf("\t%-20s %11s\n", "update", counts[2]); // System.out.printf("\t%-20s %11s\n", "compose", counts[3]); System.out.printf("\t%-20s %11s\n", "equals", counts[4]); // System.out.printf("\t%-20s %11s\n", "conjunction", counts[5]); System.out.printf("\t%-20s %11s\n", "clone", counts[6]); System.out.printf("\t%-20s %11s\n", "hashCode", counts[7]); // System.out.printf("\t%-20s %11s\n", "resembles", counts[8]); // System.out.printf("\t%-20s %11s\n", "digest", counts[9]); } //TODO: (original) try database serialization public File serialize(String filename) throws FileNotFoundException, IOException { File f = new File(filename); ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(f)); os.writeObject(this); os.close(); return f; } public static State deserialize(String filename) throws FileNotFoundException, IOException, ClassNotFoundException { File f = new File(filename); ObjectInputStream os = new ObjectInputStream(new FileInputStream(f)); State zone = (State) os.readObject(); os.close(); return zone; } public static State deserialize(File f) throws FileNotFoundException, IOException, ClassNotFoundException { ObjectInputStream os = new ObjectInputStream(new FileInputStream(f)); State zone = (State) os.readObject(); os.close(); return zone; } public boolean failure(){ return this.failure; } public void setFailure(){ this.failure = true; } public void printStateInfo() { System.out.print("Marking: ["); for (int i=0; i < marking.length; i++) { System.out.print(lpn.getPlaceList()[i] + "=" + marking[i] + ", "); } System.out.println("]"); System.out.print("Vector: ["); for (int i = 0; i < vector.length; i++) { System.out.print(lpn.getVarIndexMap().getKey(i) + "=" + vector[i]+", "); } System.out.println("]"); System.out.print("Transition vector: ["); for (boolean bool : tranVector) { System.out.print(bool + ","); } System.out.println("]"); String arrayStr = ""; for (int i=0; i< tranVector.length; i++) { if (tranVector[i]) { arrayStr = arrayStr + lpn.getAllTransitions()[i].getFullLabel() + ", "; } } System.out.println("enabled transitions: " + arrayStr); } /** * Getter for the TimingState that extends this state. * @return * The TimingState that extends this state if it has been set. Null, otherwise. */ public ArrayList<TimedState> getTimeExtension(){ return timeExtensions; } /** * Setter for the TimingState that extends this state. * @param s * The TimingState that extends this state. */ public void setTimeExtension(ArrayList<TimedState> s){ timeExtensions = s; } public void addTimeExtension(TimedState s){ if(timeExtensions == null){ timeExtensions = new ArrayList<TimedState>(); } timeExtensions.add(s); } /** * Get the current value of the variable according to the state. * @param variable * The variable of interest. * @return * The value of the variable as stored in the state. */ public int getCurrentValue(String variable){ // Get the index of the variable according to the LPN. int index = lpn.getVarIndexMap().getValue(variable); return getCurrentValue(index); } /** * Get the current value of the variable according to the state. * @param variableIndex * The index of the variable of interest. * @return * The value of the variable as stored in the state. */ public int getCurrentValue(int variableIndex){ return vector[variableIndex]; } public String getFullLabel() { String fullLabel = "S" + getIndex() + "(" + getLpn().getLabel() +")"; return fullLabel; } /** * Returns the corresponding state graph that this state lives in. * @return */ public StateGraph getStateGraph() { return this.getLpn().getStateGraph(); } public Set<Transition> getOutgoingTranSet() { return this.getStateGraph().getNextStateMap().get(this).keySet(); } public State getNextLocalState(Transition outTran) { return this.getStateGraph().getNextState(this, outTran); } }