Permalink
Browse files

Scan

  • Loading branch information...
0 parents commit e2e9c299cc5f6a833d51b561b4c0d36e9ca92c7e elvin committed Oct 19, 2012
@@ -0,0 +1,9 @@
+emu
+thor
+ascii
+*~
+
+*.app
+*.plist
+*.pro
+*.xcodproj/*
@@ -0,0 +1,103 @@
+经过不懈的努力,终于将框架和具体实现区分开来了。从此算法的设计者不需要再考虑底层模型的实现和整个机制的运行细节。为了更方便的设计算法,在此详细地介绍设计算法可能用到的 API,如果觉得 API 有任何不足和需要改进的地方,一定提出修改,提高整体的工作效率。
+
+###1. 嵌入算法
+
+在此,用我的写的 FCFS(First Come First Service)做例子,FCFS 算法是一种优先处理请求队列头的算法,也就是“先按电梯的楼层先服务”,为了嵌入这一种算法:
+
+1 在 **Headers/controller.h** 中声明新的算法函数 **static void Fcfs()**, 务必声明为静态函数
+
+```
+class Controller
+{
+public:
+ static void Fcfs();
+ /* 在这里补充更多算法 */
+};
+```
+
+2 在 **Sources** 目录下创建算法的实现 fcfs.cpp
+
+```
+#include "../Headers/models.h"
+
+/* 找到最为空闲的电梯 */
+Elevator* Idlest() {
+ /* SOME CODE */
+}
+
+/* 调度 */
+void Controller::Fcfs() {
+ while(Idlest() != NULL) {
+ if (Emulator::orders.empty()) return;
+ Elevator* idle = Idlest();
+ Order* order = Emulator::orders.front();
+ Emulator::orders.pop_front();
+ idle->PushInst(new Instruction(order->from, 1));
+ }
+}
+```
+
+在这个文件里,首先包含了 models.h 这个文件,这个文件包含了所有的基本的类,所谓基本类就是指除了特种电梯意外的所有类,如果算法对数据结构没有特殊的要求(比如要求改写 Elevator 类),那么这个头文件就足够了。
+
+接下来我写了一个叫 Idlest 的 helper 函数,在接下来就是刚才在 controller.h 里声明的调度函数。
+
+至此,嵌入算法的基本流程就结束了。
+
+###2. 算法设计的输入与输出
+
+
+仍然是一 Fcfs 为例子,在刚才的 fcfs.cpp 中,实现了这样一个函数
+
+```
+/* 调度 */
+void Controller::Fcfs() {
+ while(Idlest() != NULL) {
+ if (Emulator::orders.empty()) return;
+ Elevator* idle = Idlest();
+ Order* order = Emulator::orders.front();
+ Emulator::orders.pop_front();
+ idle->PushInst(new Instruction(order->from, 1));
+ }
+}
+```
+整个代码的大意是:有空闲的电梯时,并且有未处理的 order 时,把请求队列的 front 弹出,根据这个order 的信息向空闲的电梯发送一条指令,这条指令指定电梯去 order 发出的地方,行进的方向是上下两个方向皆可(行进方向待会讨论)。
+
+从这个算法的实现过程中,可以看出算法实现是基于 Emulator::orders 和 Emulator::elevators 的,并且在最后向某一台电梯推送了一条指令。简要的说:
+
+输入 = 当前情况,这些情况由 Emulator 中的静态成员(类似于全局变量)表现
+输出 = 向某台电梯推送一条或多条 Instruction
+
+附
+
+```
+/* instruction.h */
+class Instruction
+{
+public:
+ Instruction(int dest_, int dirCode_) : dest(dest_), dirCode(dirCode_){};
+ int dest; // 目的地
+ int dirCode; // 电梯行进过程中可接受请求的方向
+};
+```
+###3. 程序运行的流程
+
+* Born( ), 产生新的乘客和新的请求
+* Control( ), 执行 Controller 中不同的算法
+* Move( ), 每个电梯依据指令移动
+* Update( ), 更新统计数据,绘制图形界面等
+
+
+###3. 一些需要注意的细节说明
+
+* 电梯会优先依据给定的指令(Instruction, 下用 inst 代替一个实例)工作,朝着 inst.dest 前进。
+* 电梯运行途中如果开门的话,会把本层楼 inst.dirCode 对应的上、下请求接受,并且从全局请求序列中去除掉对应的请求。
+* inst.dirCode == 1, 电梯开门会接受本层上下两个方向的请求; inst.dirCode == 2,电梯开门会接受向上的请求; inst.dirCode == 3,电梯开门会本层接受向下的请求; inst.dirCode == 0, 电梯开门不会再接受请求,停在原地直到 controller 调度。
+* 如果电梯没有得到指令的话,会将楼层里的人按照从 0 层到顶层的顺序送达。
+* 假设乘客是知道电梯运行的方向的,比如当 dirCode == 2 时,只有向上走的乘客会进入电梯。
+* 当一台电梯要去的目的地中途被另一座电梯通过 dirCode 给取消的时候,这台电梯会 pop 掉现有的以该层楼为 dest,dirCode 比取消请求的 dirCode 小的指令。
+* Emulator 保证,只要楼层有人,那么这层楼一定会有请求,所以如果电梯来却没有装完所有人的时候,这层楼的人会重新请求电梯。
+
+###4. API 细节
+
+请大家在设计算法的时候参考 emulator.h 中的 static member,值得注意的几个是 elevators(所有电梯), floors(所有楼层), orders(所有请求,动态更新),一些对象的细节可以去对应的头文件中去看,更实用简明的文档会被不断的更新补充。
+
@@ -0,0 +1,44 @@
+为了方便大家编译和调试,推出了 ascii 版的模拟系统,该系统与 Qt 界面的系统类似,每 1 单位时间刷新一场景,
+现在的单位时间是 0.2 秒。由于调用的是 Linux/Gnu 系操作系统的 clear 和 sleep 函数,因此 windows 系统
+下无法正常的工作,见谅(或者谁有空写一下。。)。
+
+在此将关于 ascii 界面程序的编译和算法设计相关事项阐述一下:
+
+###编译和运行
+
+编译直接在根目录下 `$ make` 就行了,会生成一个叫做 `ascii` 的可执行文件。这个程序的主函数在 Sources/ascii.cpp 中,从主函数中可以见到,为了方便,楼层数固定为 10,电梯固定为 4 架,泊松参数为 0.02, 程序持续 100 个单位时间,在没有命令行参数的情况下,运行程序还要求输入算法的名字。如果需要指定参数可以用命令行参数指定 `./ascii 10 4 0.02 100 FCFS`。不过。。。这个功能还没做。。先忍一忍或者谁写一下。。
+
+###插入算法
+插入算法的顺序的基本方法还是和本目录下的《API-说明》中叙述的一样,只是为了配合 main 函数,需要在 Sources/ascii.cpp 中添加一个分支。
+
+具体的步骤是
+
+* 按照《API-说明》完成算法设计
+*`Sources/ascii.cpp` 中的 `Control()` 函数中增添分支,代码片段如下,相信看注释就懂了
+
+```
+void Control() {
+ if (Emulator::elevatorType == "PFCFS") {
+ Controller::Fcfs();
+ } /* else if (Emulator::elevatorType == "costflow") {
+ /* Controller::costflow();
+ /*
+ /* } */
+}
+```
+* 更新 Makefile
+
+打开根目录下的 Makefile
+
+```
+ascii: Sources/ascii.cpp Sources/elevator.cpp Sources/emulator.cpp Sources/fcfs.cpp Sources/passenger.cpp \
+ Sources/floor.cpp Sources/PoissRand.cpp Headers/controller.h Headers/elevator.h \
+ Headers/emulator.h Headers/fcfs.h Headers/floor.h Headers/instruction.h Headers/models.h Headers/internlib.h \
+ Headers/passenger.h Headers/PoissRand.h Sources/order.cpp Sources/Print.cpp /* 在这里添加新创建的文件, 如 xx_algorithm.cpp */
+
+ $(CC) $(CFLAGS) $(LIBS) -o ascii Sources/ascii.cpp Sources/elevator.cpp Sources/emulator.cpp Sources/fcfs.cpp Sources/passenger.cpp \
+ Sources/floor.cpp Sources/PoissRand.cpp Sources/order.cpp Sources/Print.cpp
+ /* 在这里添加新创建的需要编译和链接的文件, 如 xx_algorithm.cpp */
+```
+
+* `$ make`, 执行,就能够看见输出了~
@@ -0,0 +1,8 @@
+/*
+ * PARAMS:
+ * Emulator::lambda: the parameter Emulator::lambda in a Poiss Distribution(the average occurance of a event)
+ * RETURN:
+ * generates one ramdom number, and the sequence of these numbers is obay Poiss Distribution
+ */
+int PoissRand(double lambda);
+double Rand(double a, double b);
@@ -0,0 +1,17 @@
+#ifndef __EleEmu__controller__
+#define __EleEmu__controller__
+/* 电梯调度器,每一个静态函数是一个调度算法 */
+class Controller
+{
+public:
+ static void Fcfs(); /* FCFS 算法 */
+
+ static void Scan();
+
+ static void CostFLow();
+
+ static void PickUp();
+
+ /* 在这里补充更多算法 */
+};
+#endif /* defined(__EleEmu__controller__) */
@@ -0,0 +1,14 @@
+#ifndef EleEmu_costflow_h
+#define EleEmu_costflow_h
+
+/*
+ * 称某电梯对某order顺路,如果该电梯开往的方向刚好可以到达order,或者该电梯闲置
+ * 电梯到达order的经过的楼层数目是电梯i到达楼层j的代价
+ * 构图做最小费用最大流,以保证在当前情况下满足最多数量的order并且总代价最小
+ */
+
+int spfa();
+void addEdge(int, int, int, int);
+int BytheWay(Elevator *, Order *);
+
+#endif
@@ -0,0 +1,74 @@
+#ifndef ELEVATOR_H
+#define ELEVATOR_H
+#include <vector>
+#include <list>
+#include "passenger.h"
+#include "instruction.h"
+/* 电梯基类 */
+class Elevator
+{
+ friend class Controller;
+ friend class Emulator;
+protected:
+ int pos;
+ bool doorStatus; /* 0: close, 1: open, 2: in toggle door */
+
+ int toggleDoorCounter; /* 计算开/关门已花费时间,用以控制门的状态过渡 */
+
+ static int timeToggleDoor; /* 开/关门所需时间 */
+
+ static int timeMove; /* 电梯移动所需时间 */
+
+ static int capacity; /* 电梯最大容量 */
+
+ static int throughput; /* 所有电梯总吞吐量 */
+
+ char dir; /* 电梯运动方向 */
+
+ int defaultDir; /* 电梯默认接客方向 */
+
+ static double acceleration; /* 电梯加速度 */
+
+ std::list<Passenger*> passengers; /* 电梯内乘客 */
+
+ std::list<Instruction*> instructions; /* 电梯现有指令栈 */
+
+ int speed;
+
+ void Letout();
+
+ void Letin(int cancelCode);
+
+ void OpenDoor();
+
+ void CloseDoor();
+public:
+ void LetThemMove();
+
+ Elevator(); /* Constructor */
+
+ int Get_pos(); /* Get current position */
+
+ int Get_nPassenger(); /* Get current passenger number */
+
+ char Dir(); /* Get current direction. ^: upwards, v: downwards, -: stopping */
+
+ void ToggleDoor(); /* Toggle door's status, open if closed, close if opened */
+
+ virtual void Move(); /* 继承具有不同算法的电梯,添加所需的成员及方法,实现自己的 Move, Move 将在主函数中被调用 */
+
+ void PushInst(Instruction*); /* 添加指令 */
+
+ std::list<Instruction*> *Get_inst();/* 得到指令栈的指针 */
+
+ static int AverThrput(); /* Calculate and return AverThrput */
+
+ static int Get_capacity(); /* Get method for static member capacity */
+
+ void Set_defaultDir(int dir);
+
+ int Get_defaultDir();
+};
+
+typedef std::vector<Elevator*>::iterator EleIter;
+#endif
@@ -0,0 +1,35 @@
+/* Emulator is a class like a controller(engine) manage all the logic */
+#ifndef __AsciiEleEmu__emulator__
+#define __AsciiEleEmu__emulator__
+
+#include <vector>
+#include <string>
+#include "models.h"
+#include "internlib.h"
+
+class Emulator
+{
+
+public:
+ Emulator();
+
+ static int dual; /* dual: Time consumed with the whole duration */
+
+ static int nElevator; /* Total number of all elevators */
+
+ static int UNIT_TIME; /* Unit time is set to time consumed by moving elevator up or down a floor */
+
+ static vector<Elevator*> elevators; /* All the elevators functioning */
+
+ static double lambda; /* Poiss process parameter lambda */
+
+ static Floor floors[30]; /* Floors */
+
+ static int nFloor; /* Total number of all floors */
+
+ static string elevatorType;
+
+ static list<Order*> orders;
+};
+
+#endif
@@ -0,0 +1,43 @@
+#ifndef FLOOR_H
+#define FLOOR_H
+#include <list>
+using namespace std;
+
+class Passenger;
+class Order;
+class Floor
+{
+private:
+ list<Passenger*> passengers;
+ Order* upOrder;
+ Order* downOrder;
+public:
+ Floor(); /* Construct funtion */
+
+ void PushPassenger(Passenger *p); /* Let a new passenger p comes in */
+
+ int Get_nPassenger(); /* Get totalnum of passengers on a floor */
+
+ Passenger *PopPassenger(); /* Pop and return the frontest passenger from queue */
+
+ Passenger *FrontPassenger(); /* Get passenger at the front of the queue(list) */
+
+ void LetThemWait(); /* Let passengers wait for one unit time */
+
+ bool Ordered(); /* Return true if floor has order an elevator */
+
+ void Set_downOrder(Order* order);
+
+ void Set_upOrder(Order* order);
+
+ bool UpOrdered();
+
+ bool DownOrdered();
+
+ void CancelOrder(char dir);
+
+ friend class Passenger;
+
+ void CheckOrder();
+};
+#endif
@@ -0,0 +1,17 @@
+#ifndef EleEmu_instruction_h
+#define EleEmu_instruction_h
+
+/* 电梯指令,算法的输出 */
+class Instruction
+{
+public:
+ Instruction(int dest_, int dirCode_) : dest(dest_), dirCode(dirCode_){};
+ int dest; /* 指令目的地 */
+ int dirCode; /* 指令的载人方向
+ 1: 中途开门接受上、下两个方向乘客
+ 2: 中途开门只接受向上的乘客
+ 3: 中途开门只接受向下的乘客
+ */
+};
+
+#endif
@@ -0,0 +1,12 @@
+/* A lib file with lots of include */
+#include <iostream>
+#include <cstdlib>
+#include <ctime>
+#include <cmath>
+#include <queue>
+#include <cstdio>
+#include <vector>
+#include <climits>
+#include <list>
+#include <algorithm>
+#include <stack>
Oops, something went wrong.

0 comments on commit e2e9c29

Please sign in to comment.