📄 circlesim.java
字号:
// incoming queue size System.out.print("Q_SIZE:\t\t"); for(int i = 0; i < myCircle.nJ; i++) { System.out.print(inStat.niq[i] + "\t\t" + inStat.nsq[i] + "\t\t"); } System.out.print("\n"); // sector speed System.out.print("Sector V:\t\t"); for(int i = 0; i < myCircle.nJ; i++) { System.out.print("\t\t" + (int) inStat.secV[i] + "\t\t"); } System.out.print("\n"); // CWT System.out.print("QUEUE CWT:\t\t"); for(int i = 0; i < myCircle.nJ; i++) { System.out.print((int) inStat.jCWT[i] + "\t\t" + (int) inStat.sCWT[i] + "\t\t"); } System.out.print("\n"); // CWT System.out.print("SIGNAL:\t\t"); for(int i = 0; i < myCircle.nJ; i++) { System.out.print(myCircle.jc[i].sgn + "\t\t\t\t"); } System.out.print("\n"); } void getStatistics() { // number of cars on each sector for(int i = 0; i < myCircle.nJ; i++) { inStat.niq[i] = myCircle.jc[i].iq.size(); inStat.nCar[i] = myCircle.sc[i].nCar; } // incoming queue size for(int i = 0; i < myCircle.nJ; i++) { inStat.niq[i] = myCircle.jc[i].iq.size(); inStat.nsq[i] = myCircle.sc[i].q.size(); } // sector speed for(int i = 0; i < myCircle.nJ; i++) { inStat.secV[i] = myCircle.sc[i].v; //inStat.secLen[i] = myCircle.sc[i].len; } // CWT for(int i = 0; i < myCircle.nJ; i++) { inStat.jCWT[i] = myCircle.jc[i].cu.getCWT(); inStat.sCWT[i] = myCircle.sc[i].cu.getCWT(); } }}class LongTermStatistics{ int carCount; double totalDelay; LongTermStatistics() { carCount = 0; totalDelay = 0; } void print() { System.out.println("=========================STAT========================\n"); System.out.println("CAR TRANSFERRED:\t" + carCount); System.out.println("TOTAL DELAY:\t" + totalDelay); System.out.println("AVERAGE DELAY:\t" + totalDelay / carCount); }}class InstantStatistics{ int n; // number of junctions on the circle int[] nArr; // number of car arrivals int[] niq; // size of the junctions' incoming queue// int[] noq; // size of the junctions' outgoing queue int[] nsq; // size of the sectors' waiting queue double[] secV; // sectors' speed int[] nCar; // number of cars on each sector; double[] jCWT; // junction incoming queue CWT; double [] sCWT; // sector queue CWT InstantStatistics(int nJunction) { n = nJunction; nArr = new int[n]; niq = new int[n];// noq = new int[n]; nsq = new int[n]; secV = new double[n]; nCar = new int[n]; jCWT = new double[n]; sCWT = new double [n]; }}class Circle{ double r; // Circle radius in meters int nL, // Number of Lanes in the circle nJ; // Number of Junctions of the circle Junction [] jc; Sector [] sc; Circle() { try { StreamTokenizer stok = new StreamTokenizer( new BufferedReader(new FileReader(Const.CIRCLE_SPEC_FILE))); stok.parseNumbers(); stok.nextToken(); r = stok.nval; //System.out.println("radius: " + r); stok.nextToken(); nL = (int) stok.nval; //System.out.println("nLane: " + nL); stok.nextToken(); nJ = (int) stok.nval; //System.out.println("nJunc: " + nJ); jc = new Junction[nJ]; sc = new Sector[nJ]; for(int i = 0; i < nJ; i++) { stok.nextToken(); double Jpos = Tools.deg2rad(stok.nval); stok.nextToken(); int JnLane = (int) stok.nval; stok.nextToken(); int Jsign = (int) stok.nval; jc[i] = new Junction(i, Jpos, JnLane, Jsign); if(i > 0) sc[i - 1] = new Sector(i - 1, r * (jc[i].pos - jc[i - 1].pos), nL); } sc[nJ - 1] = new Sector(nJ - 1, r * ((jc[0].pos < jc[nJ - 1].pos) ? jc[0].pos - jc[nJ - 1].pos + 2 * Math.PI : jc[0].pos - jc[nJ - 1].pos), nL); }catch(IOException e) { System.out.println("File not found.\n"); System.exit(-1); } } }class Junction{ double pos, // Junction position (in terms of polar angle in rad unit) outCap, // Outgoing capacity outInc, // Outgoing capacity increment in each TIME_INC outV; // Outgoing speed int id, // Junction number; nL, // Number of Lanes in the incoming road (the same in the outgoing road) sgn; // the sign is always for the circle. // 0: free; // 1: stop (giving priority to the incoming road); // 2: yield (giving priority to the circle); // 3: red; // 4: green; Vector iq; // incoming queue;// oq; // outgoing queue; CWTUnit cu; // Cumulative Waiting Time Unit Junction(int Jid, double position, int nLane, int sign) { id = Jid; pos = position; nL = nLane; sgn = sign; iq = new Vector(); outCap = 0; outV = Const.OUTGOING_SPEED; outInc = nL * outV * Const.TIME_INC / (Const.CAR_LENGTH + Tools.safeDis(outV));// oq = new Vector(); cu = new CWTUnit(); //System.out.println("Junction " + id + ":\t" + (int) Math.round(Tools.rad2deg(pos) )+ "\t" + nL + "\t" + sgn + "\n"); } void addIncomingCar(Car car) { car.pos = pos; car.state = 0; car.v = 0; car.cu.reset(); car.cu.modInc(Const.TIME_INC); cu.modInc(Const.TIME_INC); iq.add(car); } void update() { outInc = nL * outV * Const.TIME_INC / (Const.CAR_LENGTH + Tools.safeDis(outV)); outCap += outInc; // too much accumulated capacity means no car passing // for a long time, so, in this circumstance, the // capacity should return to such in the initial state if(outCap > nL * Const.CAP_INTERVAL * Const.OUTGOING_TOP_CAP) outCap = nL * Const.OUTGOING_TOP_CAP; cu.update(); }}class Sector{ int id; // the id of the head junction double len, // the length v, // current speed of Sector inCap, // incoming capacity capInc; // capacity increment in each TIME_INC int nCar, // current number of cars on the sector; Cap, // sector capacity; nL; // number of lane, same as circle's nL Vector q; // sector queue; CWTUnit cu; // Cumulative Waiting Time Unit Sector(int head, double length, int nLane) { id = head; len = length; nL = nLane; v = Const.SECTOR_TOP_SPEED; nCar = 0; Cap = (int) (length * nL / Const.CAR_LENGTH); capInc = nL * v * Const.TIME_INC / (Const.CAR_LENGTH + Tools.safeDis(v)); inCap = 0; q = new Vector(); cu = new CWTUnit(); //System.out.println("Sector " + head + ":\t" + len + "\t" + v + "\n"); } void enterQue(Car car) { car.state = 0; // waiting car.v = 0; car.cu.reset(); car.cu.modInc(Const.TIME_INC); cu.modInc(Const.TIME_INC); q.add(car); } void update() { v = nCar > 0 ? Tools.safeV(len * nL / nCar - Const.CAR_LENGTH) : Const.SECTOR_TOP_SPEED; capInc = nCar > 0 ? v * Const.TIME_INC * nCar / len : nL * Const.SECTOR_TOP_CAP; if(nCar >= Cap) inCap = 0; else { inCap += capInc; // too much accumulated capacity means no car passing // for a long time, so, in this circumstance, the // capacity should return to such in the initial state if(inCap > nL * Const.CAP_INTERVAL * Const.SECTOR_TOP_CAP) inCap = nL * Const.SECTOR_TOP_CAP; if(inCap > Cap - 1) inCap = Cap - 1; } cu.update(); }}class Car{ int state, // 0: waiting // 1: running // 2: destroyed sid; // the sector where it is Junction from, // the junction from which it will enter to; // the junction from which it will exit double tEnter, // the time when it enters tExit, // the time when it exits pos, // car position (in terms of polar angle in rad unit) v; // current speed CWTUnit cu; Car(Junction enterJunction, Junction goalJunction, double entranceTime) { state = 0; // new car was assumed waiting at first sid = enterJunction.id; from = enterJunction; to = goalJunction; tEnter = entranceTime; tExit = -1; // negative time means invalid time pos = from.pos; v = 0; cu = new CWTUnit(); } }class Const{ final public static double SECTOR_TOP_SPEED = Tools.kpm2mps(60); final public static double OUTGOING_SPEED = Tools.kpm2mps(60); final public static String CIRCLE_SPEC_FILE = new String("data/circleSpec.txt"); final public static String INCOME_SPEC_FILE = new String("data/incomeSpec.txt"); final public static String CAR_SPEC_FILE = new String("data/carSpec.txt"); final public static double TIME_INC = 1; // in second final public static double TIME_START = 0; // in second final public static double TIME_STOP = 1000; // in second final public static double EPS_LENGTH = 0.5; // in meter final public static double CAR_LENGTH = 4.87; // in meter, 16 feet approx. final public static double SECTOR_TOP_CAP = SECTOR_TOP_SPEED / (CAR_LENGTH + Tools.safeDis(SECTOR_TOP_SPEED)); final public static double OUTGOING_TOP_CAP = OUTGOING_SPEED / (CAR_LENGTH + Tools.safeDis(OUTGOING_SPEED)); final public static double CAP_INTERVAL = 5; Const() { }}class Tools { public static double kpm2mps (double kpm) {return kpm / 3.6;} public static double deg2rad (double deg) {return deg * Math.PI / 180;} public static double unifyRad(double rad) { if(rad >= 0) { while(rad > 2 * Math.PI) rad -= 2 * Math.PI; } else { while(rad < 0) rad += 2 * Math.PI; } return rad; } public static double rad2deg (double rad) {return rad * 180 / Math.PI;} public static double safeDis (double v) {/* final double sv[] = {0, 8.9408, 13.4112, 17.8816, 22.352, 26.8224, 31.2928}; final double sd[] = {0, 13.4112, 24.9936, 40.2336, 58.5216, 80.4672, 105.4608}; for(int i = 1; i <= 6; i++) { if(sv[i] >= v) return (sd[i - 1] * (sv[i] - v) + sd[i] * (v - sv[i - 1])) / (sv[i] - sv[i - 1]); } return (v - sv[5]) * (sd[6] - sd[5]) / (sv[6] - sv[5]) + sd[5];*/ return 0.75 * v; } public static double safeV (double d) {/* if(d <= 0) return 0;// // final double sv[] = {0, 8.9408, 13.4112, 17.8816, 22.352, 26.8224, 31.2928};// final double sd[] = {0, 13.4112, 24.9936, 40.2336, 58.5216, 80.4672, 105.4608};// // double temp;// for(int i = 1; i <= 6; i++)// {// if(sd[i] >= d)// {// temp = (sv[i - 1] * (sd[i] - d) + sv[i] * (d - sd[i - 1])) / (sd[i] - sd[i - 1]);// if(temp > Const.SECTOR_TOP_SPEED)// temp = Const.SECTOR_TOP_SPEED;// }// }// temp = (d - sv[5]) * (sd[6] - sd[5]) / (sv[6] - sv[5]) + sd[5];*/ if(d <= 0) return 0; double temp = 1.33333333333 * d; if(temp > Const.SECTOR_TOP_SPEED) temp = Const.SECTOR_TOP_SPEED; return temp; } public static double angleDis(double a, double b) { return b - a + ( a > b ? 2 * Math.PI : 0);} Tools() { }}class CWTUnit{ double cwt; // cumulative waiting time double cwt_inc; CWTUnit() { reset(); } void reset() { cwt = 0; cwt_inc = 0; } double getCWT() { return cwt; } void modInc(double inc) // here the inc (which might be negative or possible) // will be added to cwt_inc { cwt_inc += inc; } void mod(double inc) // here the inc (which might be negative or possible) // will be added to cwt { cwt += inc; } void update() { cwt += cwt_inc; }}class Strategy{ int n = 0; // number of junctions int [] td; // time of next action for each junction double lambda; Strategy(int nJunc) { n = nJunc; td = new int[n]; lambda = 0.5; } boolean fuzzyLogic(InstantStatistics is, int[] sign, double time) { // returning true means some actions are applied boolean flag = false; for(int i = 0; i < n; i++) if(time >= td[i]) { int j = (i - 1 + n) % n; flag = true; if(is.sCWT[j] >= is.jCWT[i]) { sign[i] = 4; // yield, or circle has priority td[i] += (lambda * is.nsq[j] > Const.TIME_INC ? lambda * is.nsq[j] : Const.TIME_INC); } else { sign[i] = 3; // stop, or incoming road has priority td[i] += (lambda * is.niq[i] > Const.TIME_INC ? lambda * is.niq[i] : Const.TIME_INC); } } return flag; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -