/**
*
*/
package eu.quanticol.carma.examples.smarttaxis;
import java.util.Arrays;
import org.apache.commons.math3.random.RandomGenerator;
import org.cmg.ml.sam.sim.sampling.Measure;
import eu.quanticol.carma.simulator.CarmaComponent;
import eu.quanticol.carma.simulator.CarmaInput;
import eu.quanticol.carma.simulator.CarmaOutput;
import eu.quanticol.carma.simulator.CarmaPredicate;
import eu.quanticol.carma.simulator.CarmaProcess;
import eu.quanticol.carma.simulator.CarmaProcessAutomaton;
import eu.quanticol.carma.simulator.CarmaProcessPredicate;
import eu.quanticol.carma.simulator.CarmaSequentialProcess;
import eu.quanticol.carma.simulator.CarmaStore;
import eu.quanticol.carma.simulator.CarmaStoreUpdate;
import eu.quanticol.carma.simulator.CarmaSystem;
import eu.quanticol.carma.simulator.ComponentPredicate;
/**
* @author loreti
*
*/
public class SmartTaxisDefinitions {
/*
* 0 -> 1 , 3
* 1 -> 0 , 2 , 4
* 2 -> 1 , 5
* 3 -> 0 , 4 , 6
* 3 ->
*
*/
public static class InfoClass {
private boolean[] info;
private int elements;
public InfoClass( int size ) {
this.info = new boolean[size];
this.elements = 0;
}
public InfoClass(boolean[] info) {
this.info = info;
}
public boolean get( int i ) {
return this.info[i];
}
public InfoClass merge( InfoClass ic ) {
InfoClass newInfo = new InfoClass(info.length);
for( int i=0 ; i<info.length ; i++ ) {
if (this.info[i]||ic.info[i]) {
newInfo.set(i);
}
}
return newInfo;
}
public void age(int i) {
if (elements == 0 ) {
return ;
}
int count = i;
for( int j = 0 ; j<info.length ; j++ ) {
if (info[j]) {
if (count==0) {
info[j]=false;
} else {
count--;
}
}
}
this.elements--;
}
public void set(int i) {
if (!this.info[i]) {
this.info[i] = true;
this.elements++;
}
}
public double getMovingProbability(int loc) {
double stay = 0.0;
double move = 0.0;
if (info[loc]) {
stay = 0.9;
} else {
stay = 0.1;
}
double count = 0.0;
for( int i=0 ; i<info.length ; i++ ) {
if (info[i]&&(i!=loc)) {
count += 1.0;
}
}
if (count > 0) {
move = count/(info.length-1);
} else {
move = 0.01;
}
double toReturn = (move/(stay+move));
// System.out.println(toReturn);
return toReturn;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return Arrays.toString(info) ;
}
public int elements() {
return elements;
}
}
public static final int GRID_WIDTH = 3;
public static final int GRID_HEIGHT = 3;
public static final int NUMBER_OF_LOCATIONS = GRID_HEIGHT*GRID_WIDTH;
/* ACTIVITIES */
public static final int CALL = 0;
public static final int TAKE = 1;
public static final int CHANGE = 2;
public static final int MOVE = 3;
public static final int AGE = 5;
public static final int EXCH = 6;
public static final int ARRIVE = 7;
/* ATTRIBUTES */
public static final String LOC_ATTRIBUTE = "loc";
public static final Class<Integer> LOC_ATTRIBUTE_TYPE = Integer.class;
public static final String DEST_ATTRIBUTE = "dest";
public static final Class<Integer> DEST_ATTRIBUTE_TYPE = Integer.class;
public static final String OCCUPIED_ATTRIBUTE = "occupied";
public static final Class<Boolean> OCCUPIED_ATTRIBUTE_TYPE = Boolean.class;
public static final String INFO_ATTRIBUTE = "info";
public static final Class<InfoClass> INFO_ATTRIBUTE_TYPE = InfoClass.class;
public static final CarmaProcessAutomaton UserProcess = createUserProcess();
public static final CarmaProcessAutomaton TaxiProcess = createTaxiProcess();
public static final CarmaProcessAutomaton InfoProcess = createInfoProcess();
public static final CarmaProcessAutomaton ArrivalProcess = createArrivalProcess();
//Time units: 1 minute;
public static final double CALL_RATE = 0.25; //A user asks for a taxi every 10 t.u.
public static final double EXCH_RATE = 0.0;
public static final double TAKE_RATE = 1.0; //When available a taxi needs 1 t.u. to take a user.
public static final double P_LOST = 0.75; //A taxi ignores a call with probability 0.25
public static final double STEP_RATE = 2.0; //Average time needed to move from one zone to an adiacent one.
public static final double CHANGE_RATE = 5.0; //Each taxi waits in a zone 30 t.u. before changing the zone.
public static final double AGE_RATE = 0.5; //Info are updated
public static final double ARRIVAL_RATE = 10.0; //A users needs a taxi every 10 minutes.
public static final CarmaProcessPredicate WAITING_USER_PROCESS = new CarmaProcessPredicate() {
@Override
public boolean eval(CarmaProcess p) {
return (p instanceof CarmaSequentialProcess)&&
(((CarmaSequentialProcess) p).automaton() == UserProcess)&&
(((CarmaSequentialProcess) p).getState() != null);
}
};
public static final double LIMIT = 400;
public static final int TAXIS = 5;
public static ComponentPredicate getWaitingUserPredicate( final int loc ) {
return new ComponentPredicate() {
@Override
public boolean eval(double now,CarmaComponent c) {
return (c.get(LOC_ATTRIBUTE, LOC_ATTRIBUTE_TYPE).equals( loc ))&&(c.isRunning(WAITING_USER_PROCESS));
}
};
}
public static ComponentPredicate getAvailableTaxiPredicate( final int loc ) {
return new ComponentPredicate() {
@Override
public boolean eval(double now,CarmaComponent c) {
return (c.get(LOC_ATTRIBUTE, LOC_ATTRIBUTE_TYPE).equals( loc ))&&
(c.get(OCCUPIED_ATTRIBUTE, OCCUPIED_ATTRIBUTE_TYPE) != null)&&
(c.get(OCCUPIED_ATTRIBUTE, OCCUPIED_ATTRIBUTE_TYPE).equals(false))&&
(c.get(DEST_ATTRIBUTE, DEST_ATTRIBUTE_TYPE).equals(-1));
}
};
}
public static ComponentPredicate getAvailableTaxiPredicate( ) {
return new ComponentPredicate() {
@Override
public boolean eval(double now,CarmaComponent c) {
return (c.get(OCCUPIED_ATTRIBUTE, OCCUPIED_ATTRIBUTE_TYPE) != null)&&
(c.get(OCCUPIED_ATTRIBUTE, OCCUPIED_ATTRIBUTE_TYPE).equals(false))&&
(c.get(DEST_ATTRIBUTE, DEST_ATTRIBUTE_TYPE).equals(-1));
}
};
}
public static ComponentPredicate getMovingTaxiPredicate( final int loc ) {
return new ComponentPredicate() {
@Override
public boolean eval(double now,CarmaComponent c) {
return (c.get(LOC_ATTRIBUTE, LOC_ATTRIBUTE_TYPE).equals( loc ))&&
(c.get(OCCUPIED_ATTRIBUTE, OCCUPIED_ATTRIBUTE_TYPE) != null)&&
(c.get(OCCUPIED_ATTRIBUTE, OCCUPIED_ATTRIBUTE_TYPE).equals(false))&&
(!c.get(DEST_ATTRIBUTE, DEST_ATTRIBUTE_TYPE).equals(-1));
}
};
}
public static ComponentPredicate getMovingTaxiPredicate( ) {
return new ComponentPredicate() {
@Override
public boolean eval(double now,CarmaComponent c) {
return (c.get(OCCUPIED_ATTRIBUTE, OCCUPIED_ATTRIBUTE_TYPE) != null)&&
(c.get(OCCUPIED_ATTRIBUTE, OCCUPIED_ATTRIBUTE_TYPE).equals(false))&&
(!c.get(DEST_ATTRIBUTE, DEST_ATTRIBUTE_TYPE).equals(-1));
}
};
}
private static CarmaProcessAutomaton createUserProcess() {
CarmaProcessAutomaton toReturn = new CarmaProcessAutomaton("User");
CarmaProcessAutomaton.State stateW = toReturn.newState("W");
// CaspaOutput callAction = new CaspaOutput( CALL , true ) {
CarmaOutput callAction = new CarmaOutput( CALL , false ) {
@Override
protected Object getValue(CarmaSystem sys, CarmaStore store, double now) {
return store.get(LOC_ATTRIBUTE, LOC_ATTRIBUTE_TYPE);
}
@Override
protected CarmaStoreUpdate getUpdate(CarmaSystem sys, double now) {
return new CarmaStoreUpdate() {
@Override
public void update(RandomGenerator r, CarmaStore store) {
}
};
}
@Override
protected CarmaPredicate getPredicate(CarmaSystem sys, final CarmaStore userStore) {
return CarmaPredicate.TRUE;
// return new CaspaPredicate() {
//
// @Override
// public boolean satisfy(CaspaStore store) {
// return userStore.get(LOC_ATTRIBUTE, LOC_ATTRIBUTE_TYPE).equals(
// store.get(LOC_ATTRIBUTE, LOC_ATTRIBUTE_TYPE)
// );
// }
//
// };
}
};
CarmaOutput takeAction = new CarmaOutput( TAKE , false ) {
@Override
protected Object getValue(CarmaSystem sys, CarmaStore store, double now) {
return store.get(DEST_ATTRIBUTE, DEST_ATTRIBUTE_TYPE);
}
@Override
protected CarmaStoreUpdate getUpdate(CarmaSystem sys, double now) {
return new CarmaStoreUpdate() {
@Override
public void update(RandomGenerator r, CarmaStore store) {
}
};
}
@Override
protected CarmaPredicate getPredicate(CarmaSystem sys, final CarmaStore userStore) {
return new CarmaPredicate() {
@Override
public boolean satisfy(double now,CarmaStore store) {
return userStore.get(LOC_ATTRIBUTE, LOC_ATTRIBUTE_TYPE).equals(
store.get(LOC_ATTRIBUTE, LOC_ATTRIBUTE_TYPE)
);
}
};
}
};
toReturn.addTransition(stateW, callAction, stateW);
toReturn.addTransition(stateW, takeAction, null);
return toReturn;
}
private static CarmaProcessAutomaton createArrivalProcess() {
CarmaProcessAutomaton toReturn = new CarmaProcessAutomaton("Arrival");
CarmaProcessAutomaton.State stateA = toReturn.newState("A");
CarmaOutput arrive = new CarmaOutput(ARRIVE , true) {
@Override
protected Object getValue(CarmaSystem sys, CarmaStore store, double now) {
return new Object();
}
@Override
protected CarmaStoreUpdate getUpdate(CarmaSystem sys, double now) {
return new CarmaStoreUpdate() {
@Override
public void update(RandomGenerator r, CarmaStore store) {
}
};
}
@Override
protected CarmaPredicate getPredicate(CarmaSystem sys, CarmaStore store) {
return CarmaPredicate.FALSE;
}
};
toReturn.addTransition(stateA, arrive, stateA);
return toReturn;
}
public static CarmaProcessAutomaton createInfoProcess() {
CarmaProcessAutomaton toReturn = new CarmaProcessAutomaton("Info");
CarmaProcessAutomaton.State stateI = toReturn.newState("I");
CarmaInput callAction = new CarmaInput(CALL,true) {
@Override
protected CarmaStoreUpdate getUpdate(CarmaSystem sys, final Object value, double now) {
if (value instanceof Integer) {
return new CarmaStoreUpdate() {
@Override
public void update(RandomGenerator r, CarmaStore store) {
InfoClass ic = store.get(INFO_ATTRIBUTE, INFO_ATTRIBUTE_TYPE);
// ic.set( store.get(LOC_ATTRIBUTE, LOC_ATTRIBUTE_TYPE));
ic.set( (Integer) value );
}
};
}
return null;
}
@Override
protected CarmaPredicate getPredicate(CarmaSystem sys, CarmaStore store, Object value) {
return CarmaPredicate.TRUE;
}
};
CarmaOutput ageAction = new CarmaOutput( AGE , true ) {
@Override
protected Object getValue(CarmaSystem sys, CarmaStore store, double now) {
return new Object();
}
@Override
protected CarmaStoreUpdate getUpdate(CarmaSystem sys, double now) {
return new CarmaStoreUpdate() {
@Override
public void update(RandomGenerator r, CarmaStore store) {
InfoClass ic = store.get(INFO_ATTRIBUTE, INFO_ATTRIBUTE_TYPE);
ic.age( r.nextInt( NUMBER_OF_LOCATIONS ) );
}
};
}
@Override
protected CarmaPredicate getPredicate(CarmaSystem sys, CarmaStore store) {
return CarmaPredicate.FALSE;
}
};
CarmaOutput exchOutAction = new CarmaOutput( EXCH , true ) {
@Override
protected Object getValue(CarmaSystem sys, CarmaStore store, double now) {
return store.get(INFO_ATTRIBUTE, INFO_ATTRIBUTE_TYPE);
}
@Override
protected CarmaStoreUpdate getUpdate(CarmaSystem sys, double now) {
return new CarmaStoreUpdate() {
@Override
public void update(RandomGenerator r, CarmaStore store) {
}
};
}
@Override
protected CarmaPredicate getPredicate(CarmaSystem sys, final CarmaStore taxiStore) {
return new CarmaPredicate() {
@Override
public boolean satisfy(double now,CarmaStore store) {
return taxiStore.get(LOC_ATTRIBUTE, LOC_ATTRIBUTE_TYPE).equals(
store.get(LOC_ATTRIBUTE, LOC_ATTRIBUTE_TYPE)
);
}
};
}
};
CarmaInput exchInAction = new CarmaInput( EXCH , true ) {
@Override
protected CarmaStoreUpdate getUpdate(CarmaSystem sys, final Object value, double now) {
if (value instanceof InfoClass) {
return new CarmaStoreUpdate() {
@Override
public void update(RandomGenerator r, CarmaStore store) {
store.set(INFO_ATTRIBUTE, store.get(INFO_ATTRIBUTE, INFO_ATTRIBUTE_TYPE).merge((InfoClass) value));
}
};
}
return new CarmaStoreUpdate() {
@Override
public void update(RandomGenerator r, CarmaStore store) {
}
};
}
@Override
protected CarmaPredicate getPredicate(CarmaSystem sys, CarmaStore store, Object value) {
return CarmaPredicate.TRUE;
}
};
toReturn.addTransition(stateI, callAction, stateI);
toReturn.addTransition(stateI, ageAction, stateI);
// toReturn.addTransition(stateI, exchOutAction, stateI);
// toReturn.addTransition(stateI, exchInAction, stateI);
return toReturn;
}
private static CarmaProcessAutomaton createTaxiProcess() {
CarmaProcessAutomaton toReturn = new CarmaProcessAutomaton("Taxi");
CarmaProcessAutomaton.State stateF = toReturn.newState("F");
CarmaProcessAutomaton.State stateG = toReturn.newState("G");
CarmaInput takeAction = new CarmaInput( TAKE , false ) {
@Override
protected CarmaPredicate getPredicate(CarmaSystem sys, final CarmaStore taxiStore, Object value) {
return CarmaPredicate.TRUE;
}
@Override
protected CarmaStoreUpdate getUpdate(CarmaSystem sys, final Object value, double now) {
return new CarmaStoreUpdate() {
@Override
public void update(RandomGenerator r, CarmaStore store) {
store.set(DEST_ATTRIBUTE, value);
store.set(OCCUPIED_ATTRIBUTE, true);
}
};
}
};
// CaspaInput callAction = new CaspaInput(CALL,true) {
CarmaInput callAction = new CarmaInput(CALL,false) {
@Override
protected CarmaStoreUpdate getUpdate(CarmaSystem sys, final Object value, double now) {
if (value instanceof Integer) {
return new CarmaStoreUpdate() {
@Override
public void update(RandomGenerator r, CarmaStore store) {
store.set(DEST_ATTRIBUTE, value);
}
};
}
return null;
}
@Override
protected CarmaPredicate getPredicate(CarmaSystem sys, final CarmaStore taxiStore, Object value) {
return new CarmaPredicate() {
@Override
public boolean satisfy(double now,CarmaStore store) {
return !taxiStore.get(LOC_ATTRIBUTE, LOC_ATTRIBUTE_TYPE).equals(
store.get(LOC_ATTRIBUTE, LOC_ATTRIBUTE_TYPE)
);
}
};
}
};
// CaspaOutput changeAction = new CaspaOutput( CHANGE , true ) {
//
// @Override
// protected Object getValue(CaspaStore store) {
// return new Object();
// }
//
// @Override
// protected CaspaStoreUpdate getUpdate() {
// return new CaspaStoreUpdate() {
//
// @Override
// public void update(RandomGenerator r, CaspaStore store) {
// int[] nearLoc = SmartTaxisDefinitions.near( store.get(LOC_ATTRIBUTE, LOC_ATTRIBUTE_TYPE));
// int newLoc = nearLoc[r.nextInt(nearLoc.length)];
// store.set(DEST_ATTRIBUTE, newLoc);
// }
//
// };
// }
//
// @Override
// protected CaspaPredicate getPredicate(CaspaStore store) {
// return CaspaPredicate.FALSE;
// }
// };
CarmaOutput moveAction = new CarmaOutput( MOVE , true ) {
@Override
protected Object getValue(CarmaSystem sys, CarmaStore store, double now) {
return new Object();
}
@Override
protected CarmaStoreUpdate getUpdate(CarmaSystem sys, double now) {
return new CarmaStoreUpdate() {
@Override
public void update(RandomGenerator r, CarmaStore store) {
store.set(LOC_ATTRIBUTE, store.get(DEST_ATTRIBUTE, DEST_ATTRIBUTE_TYPE));
store.set(DEST_ATTRIBUTE, -1);
store.set(INFO_ATTRIBUTE, new InfoClass(NUMBER_OF_LOCATIONS));
store.set(OCCUPIED_ATTRIBUTE, false);
}
};
}
@Override
protected CarmaPredicate getPredicate(CarmaSystem sys, CarmaStore store) {
return CarmaPredicate.FALSE;
}
};
toReturn.addTransition(stateF, takeAction, stateG);
toReturn.addTransition(stateF, callAction, stateG);
// toReturn.addTransition(stateF, changeAction, stateG);
toReturn.addTransition(stateG, moveAction, stateF);
return toReturn;
}
public static int[] near(int loc) {
int y = loc/3;
int x = loc%3;
if ((x == 0)&&(y==0)) {
return new int[] { getLocId(x,y+1) , getLocId(x+1,y) };
}
if ((x == 0)&&(y==(GRID_HEIGHT-1))) {
return new int[] { getLocId(x,y-1) , getLocId(x+1,y) };
}
if ((x == (GRID_WIDTH-1))&&(y==0)) {
return new int[] { getLocId(x,y+1) , getLocId(x-1,y) };
}
if ((x == (GRID_WIDTH-1))&&(y==(GRID_HEIGHT-1))) {
return new int[] { getLocId(x,y-1) , getLocId(x-1,y) };
}
if ((x == 0)&&(y>0)&&(y<GRID_HEIGHT-1)) {
return new int[] {
getLocId(x, y-1) ,
getLocId(x+1,y),
getLocId(x,y+1)
};
}
if ((x == (GRID_WIDTH-1))&&(y>0)&&(y<GRID_HEIGHT-1)) {
return new int[] {
getLocId(x, y-1) ,
getLocId(x-1,y),
getLocId(x,y+1)
};
}
if ((x>0)&&(x < (GRID_WIDTH-1))&&(y==0)) {
return new int[] {
getLocId(x+1, y) ,
getLocId(x,y+1),
getLocId(x-1,y)
};
}
if ((x>0)&&(x < (GRID_WIDTH-1))&&(y==GRID_HEIGHT-1)) {
return new int[] {
getLocId(x+1, y) ,
getLocId(x,y-1),
getLocId(x-1,y)
};
}
return new int[] {
getLocId(x+1, y) ,
getLocId(x-1, y) ,
getLocId(x, y-1) ,
getLocId(x, y+1)
};
}
public static int getLocId(int x, int y) {
return x*GRID_WIDTH+y;
}
public static Measure<CarmaSystem> getMeasureOfWaitingUsers( final int loc ) {
return new Measure<CarmaSystem>() {
ComponentPredicate predicate = SmartTaxisDefinitions.getWaitingUserPredicate(loc);
@Override
public double measure(CarmaSystem t) {
return t.measure(predicate);
}
@Override
public String getName() {
return "WAITING_AT_"+loc;
}
};
}
public static Measure<CarmaSystem> getMeasureOfAvailabelTaxis( final int loc ) {
return new Measure<CarmaSystem>() {
ComponentPredicate predicate = SmartTaxisDefinitions.getAvailableTaxiPredicate(loc);
@Override
public double measure(CarmaSystem t) {
double mes = t.measure(predicate);
// System.out.println(mes+" "+(TAXIS*NUMBER_OF_LOCATIONS)+" "+(mes/(TAXIS*NUMBER_OF_LOCATIONS)));
return mes/(TAXIS*NUMBER_OF_LOCATIONS);
}
@Override
public String getName() {
return "FREE_AT_"+loc;
}
};
}
public static Measure<CarmaSystem> getMeasureOfAvailabelTaxis( ) {
return new Measure<CarmaSystem>() {
ComponentPredicate predicate = SmartTaxisDefinitions.getAvailableTaxiPredicate();
@Override
public double measure(CarmaSystem t) {
return t.measure(predicate)/(TAXIS*NUMBER_OF_LOCATIONS);
}
@Override
public String getName() {
return "TOTAL_FREE";
}
};
}
public static Measure<CarmaSystem> getMeasureOfMovingTaxis( final int loc ) {
return new Measure<CarmaSystem>() {
ComponentPredicate predicate = SmartTaxisDefinitions.getMovingTaxiPredicate(loc);
@Override
public double measure(CarmaSystem t) {
return t.measure(predicate);
}
@Override
public String getName() {
return "MOVING_AT_"+loc;
}
};
}
public static Measure<CarmaSystem> getMeasureOfMovingTaxis( ) {
return new Measure<CarmaSystem>() {
ComponentPredicate predicate = SmartTaxisDefinitions.getMovingTaxiPredicate();
@Override
public double measure(CarmaSystem t) {
double mes = t.measure(predicate);
// System.out.println(mes+" "+(TAXIS*NUMBER_OF_LOCATIONS)+" "+(mes/(TAXIS*NUMBER_OF_LOCATIONS)));
return mes/(TAXIS*NUMBER_OF_LOCATIONS);
}
@Override
public String getName() {
return "TOTAL_MOVING";
}
};
}
public static double steps(Integer from, Integer to) {
int y1 = from/3;
int x1 = from%3;
int y2 = to/3;
int x2 = to%3;
int steps = Math.abs(x1-x2)+Math.abs(y1-y2);
if (steps == 0) {
return 1.0;
}
return steps;
}
public static double arrivalRate(double d, int loc) {
// if (d<=LIMIT/2) {
// if (loc==getLocId(1, 1)) {
// return 0.25*ARRIVAL_RATE/NUMBER_OF_LOCATIONS;
// } else {
// return 0.75*ARRIVAL_RATE/NUMBER_OF_LOCATIONS;
// }
// } else {
// if (loc==getLocId(1, 1)) {
// return 0.75*ARRIVAL_RATE/NUMBER_OF_LOCATIONS;
// } else {
// return 0.25*ARRIVAL_RATE/NUMBER_OF_LOCATIONS;
// }
// }
return ARRIVAL_RATE/((double) NUMBER_OF_LOCATIONS);
}
public static int getDestination(double now, int loc, RandomGenerator r) {
if (loc == getLocId(1, 1)) {
return r.nextInt(NUMBER_OF_LOCATIONS);
} else {
return getLocId(1, 1);
}
// return r.nextInt(NUMBER_OF_LOCATIONS);
}
}