您的位置:首页 > 大数据 > 人工智能

Pair project II 群控电梯调度

2010-12-12 20:33 260 查看
电梯调度要求/article/4807272.html

Part 1 framework

分析群控电梯调度,需要以下对象:

1. 电梯

职责:记录内面板状态,判断收到命令是否符合物理规律,执行命令

2. 电梯群

职责:记录外面板状态(由于是群控电梯,外面板只有一个,由电梯群对象控制)

管理电梯,对外交互

3. 乘客

职责:维护在各个楼层,各电梯内的乘客信息

当电梯停止时,完成乘客上下电梯的乘客信息改变

给出某段时间内乘客对电梯内外面板的操作信息

4. 时钟

职责:维护一个系统时间

5. 建筑或者说God

职责:控制以上对象,辅助完成各方交互

除了以上基本状态之外,我们需要确定一种程序的时间/逻辑控制方法,两种选择

1. 一个实时调度程序,对时钟每个Tick,完成相应调度

优点:逻辑相对简单

缺点:重复调用调度程序,较为耗时

2. 由建筑操纵时间,因为一般情况下电梯调度是一个只与电梯状态(包括历史状态,即可分析上班、下班等状态)有关的算法,没有随机性,所以电梯调度程序的结果只会在有新的外部请求来和电梯停下、乘客上下时才会发生改变。基于以上论断建筑只需在以上两种情况下调用电梯调度算法,其余没有事件发生的时间段皆可压缩。

优点:节省时间

缺点:对随机调度算法无效

最后需要给调度程序两个接口

1. interface IScheduler

功能:让调度程序决定电梯目的地,及电梯停下时外部指示灯状态

2. interface IElevators

功能:给调度程序电梯的状态

以下我们实现的采用第二种时间控制方法的框架
电梯调度框架

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Elevator_Scheduler_Design
{
public enum ELEVATOR_REAL_STATE { STOP, RUNNING };
public enum ELEVATOR_SHOW_STATE { UP, DOWN };                           // show elevator will go up or down on the outerpanel

public interface IScheduler
{
void GoToWhichFloor(out uint elevator, out uint destination, bool lastdecision_right);
ELEVATOR_SHOW_STATE UpOrDownOnthePanel(uint elevator);              // decide up or down to show on the outer panel
}                                                                       // if show up, passengers who want to go down will not get in

public interface IElevators
{
// functions
uint GetCurrentWeight(uint elevator);
uint GetMaxWeight(uint elevator);
float GetCurrentFloor(uint elevator);
void GetOuterPanelState(out bool[] uppanelstate, out bool[] downpanelstate);
void GetInnerPanelState(uint elevator, out bool[] panelstate);
uint GetDestination(uint elevator);
ELEVATOR_REAL_STATE GetElevatorState(uint elevator);                    // running or stop
}

public class cElevators : IElevators
{
cElevators()
{
for (int i = 0; i < E_NUMBER_OF_ELEVATORS; i++)
{
m_cElevators[i] = new cElevator();                           //need passenger_Limit, weight_Limit, number_of_Floor
}
}

public uint GetCurrentWeight(uint elevator)
{
return m_cElevators[elevator].GetCurrentWeight();
}
public uint GetMaxWeight(uint elevator)
{
return m_cElevators[elevator].GetMaxWeight();
}
public float GetCurrentFloor(uint elevator)
{
return m_cElevators[elevator].GetCurrentFloor();
}
public ELEVATOR_REAL_STATE GetElevatorState(uint elevator)
{
return m_cElevators[elevator].GetElevatorState();
}
public void GetOuterPanelState(out bool[] uppanelstate, out bool[] downpanelstate)
{

}
public void GetInnerPanelState(uint elevator, out bool[] panelstate)
{

}

public uint GetDestination(uint elevator)
{
return m_cElevators[elevator].GetDestination();
}

private bool CanGotoOrNot(uint elevator, uint floor)
{
return false; //temp
}

public bool GoTo(uint elevator, uint floor)
{
if (CanGotoOrNot(elevator, floor) == false)
return false;
m_cElevators[elevator].SetElevatorState(ELEVATOR_REAL_STATE.RUNNING);
m_cElevators[elevator].SetDestination(floor);
return true;
}

public void Arrive_At(uint elevator, uint floor)                       //tell the scheduler elevator has arrived at which floor
{
m_cElevators[elevator].SetElevatorState(ELEVATOR_REAL_STATE.STOP);
m_cElevators[elevator].SetCurrentFloor((float)floor);
}

public void UpdateOutPanelState(bool[] uppanels, bool[] downpanels) { }

public void UpdateInnerPanelState(uint elevator, bool[] innerpanels) { }

public void SetCurrentWeight(uint elevator, uint weight)
{
m_cElevators[elevator].SetCurrentWeight(weight);
}
public void SetCurrentFloor(uint elevator, float floor)
{
m_cElevators[elevator].SetCurrentFloor(floor);
}

private const int E_NUMBER_OF_ELEVATORS = 4;
private const int E_NUMBER_OF_FLOORS = 21;
private cElevator[] m_cElevators;

//flags of panels on each floor
private bool[] m_fGoUp = new bool[E_NUMBER_OF_FLOORS];                  //flags for up_panel on each floor, true as pressed
private bool[] m_fGoDown = new bool[E_NUMBER_OF_FLOORS];                //flags for down_panel on each floor, true as pressed

}

public struct Passenger_Information
{
public uint uFloorFrom;
public uint uFloorTo;
public double dWeight;
public TimeSpan tpArriveTime;                                           //  Passenger arrive time
};
public class cPassengers
{
cPassengers()
{
for (int i = 0; i < 4; i++)
{
m_liInnerPassengers[i] = new List<Passenger_Information>();     // list of passengers in the elevator
}

m_liOuterPassengers = new List<Passenger_Information>();            // list of passengers out of the elevators
}

public uint CurrentPassengersCount()                                    // passenger count include in elevator and out
{
return 0; //temp
}

public void NewPassenger(Passenger_Information newone)                  // add new passenger
{
m_liOuterPassengers.Add(newone);
}

public void GetPassengersWaitingState(out bool[] goup, out bool[] godown) { }       //get the outer panel state

public void GetPassengersTravelingState(uint elevator, out bool[] innerpanel) { }  //get the inner panel state

public void PassengersExchange(uint elevator, uint floor, uint remainweight, ELEVATOR_SHOW_STATE showstate, out uint remainweightafter){}

private List<Passenger_Information>[] m_liInnerPassengers;                      // list of passengers in the elevator
private List<Passenger_Information> m_liOuterPassengers;                        // list of passengers out of the elevators

}
public class cElevator
{
public cElevator(uint passenger_Limit, uint weight_Limit, uint number_of_Floor)
{
m_uPassenger_Limit = passenger_Limit;
m_uWeight_Limit = weight_Limit;
m_fInnerPanel = new bool[number_of_Floor];
m_state = ELEVATOR_REAL_STATE.STOP;
}
public uint GetCurrentWeight()
{
return m_uCurrentWeight;
}
public uint GetMaxWeight()
{
return m_uWeight_Limit;
}
public float GetCurrentFloor()
{
return m_uCurrentFloor;
}
public uint GetDestination()
{
return m_uDestination;
}
public ELEVATOR_REAL_STATE GetElevatorState()
{
return m_state;
}
public void SetElevatorState(ELEVATOR_REAL_STATE state)
{
m_state = state;
}
public void SetDestination(uint destination)
{
m_uDestination = destination;
}
public void SetCurrentWeight(uint weight)
{
m_uCurrentWeight = weight;
}
public void SetCurrentFloor(float floor)
{
m_uCurrentFloor = floor;
}

private uint m_uPassenger_Limit;
private uint m_uWeight_Limit;
private bool[] m_fService_Floor;

private bool[] m_fInnerPanel;                                           //flags for panels in each elevator, true as pressed
private float m_uCurrentFloor;                                           //floor the elevator on
private uint m_uCurrentWeight;
private ELEVATOR_REAL_STATE m_state;                                         //show the elevator is running or stop
private uint m_uDestination;
}

public class cClock
{
private TimeSpan m_Time;
public void Time_Cost(TimeSpan cost_time)
{
m_Time += cost_time;
}
public TimeSpan Get_Current_Time()
{
return m_Time;
}
}

public class Building
{
private cClock m_clock;
private cPassengers m_passengers;
private cElevators m_elevators;
private List<Passenger_Information> m_liAllPassengersInformation;
private const int E_NUMBER_OF_ELEVATORS = 4;
private const float E_MOVE_FLOORS_PER_MINUTE = 5;

private void Load_Test(ref List<Passenger_Information> allPassengers) { }

private Passenger_Information Earliest_Coming_Passenger() { }        // get the passenge who come earliest from the test passengers

private void New_Passengers_Coming()                                // set the earliest passengers to the out of elevator passengers
{
TimeSpan tpEarliestTime = Earliest_Coming_Passenger().tpArriveTime;
while (tpEarliestTime == ((Passenger_Information)Earliest_Coming_Passenger()).tpArriveTime)
{
m_passengers.NewPassenger(Earliest_Coming_Passenger());
m_liAllPassengersInformation.Remove(Earliest_Coming_Passenger());
}
m_clock.Time_Cost(tpEarliestTime - m_clock.Get_Current_Time());
}

private TimeSpan Time_Calc() { }                                      //calculate the time elevlater travel

private void UpdatePassengerRequest()
{
bool[] fUpRequest;
bool[] fDownRequest;
bool[] fInnerRequest;
m_passengers.GetPassengersWaitingState(out fUpRequest, out fDownRequest);      // update the out panel state
m_elevators.UpdateOutPanelState(fUpRequest, fDownRequest);
for (uint i = 0; i < E_NUMBER_OF_ELEVATORS; i++)
{
m_passengers.GetPassengersTravelingState(i, out fInnerRequest);
m_elevators.UpdateInnerPanelState(i, fInnerRequest);
}

}

private float CalculateMovedFloors(TimeSpan duringtime)
{
return 0; //temp
}

public void main_control()
{
Load_Test(ref m_liAllPassengersInformation);                    //load test file, save to m_liAllPassengersInformation
IScheduler scheduler = new cScheduler();

uint destination;
uint elevator;
while (m_liAllPassengersInformation.Count != 0 && m_passengers.CurrentPassengersCount() != 0)
{
if (m_passengers.CurrentPassengersCount() == 0)           // if no passengers waiting elevators
{
New_Passengers_Coming();                                // add earliest passengers and clocked the time to the passenger coming time
}

UpdatePassengerRequest();

scheduler.GoToWhichFloor(out elevator, out destination, true);                  // scheduler which floor to go
if (m_elevators.GoTo(elevator, destination) == false)                           // if scheduler is wrong, one time to correct
{
scheduler.GoToWhichFloor(out elevator, out destination, false);
m_elevators.GoTo(elevator, destination);
}

if (((Passenger_Information)Earliest_Coming_Passenger()).tpArriveTime           //if during the elevator travel there is
>= m_clock.Get_Current_Time() + Time_Calc())
{
m_clock.Time_Cost(Time_Calc());                                             // elevator travel time
uint remainweight = m_elevators.GetMaxWeight(elevator) - m_elevators.GetCurrentWeight(elevator);
uint remainweightafter;
m_elevators.Arrive_At(elevator, destination);
m_passengers.PassengersExchange(elevator, destination, remainweight, scheduler.UpOrDownOnthePanel(elevator), out remainweightafter);
m_elevators.SetCurrentWeight(elevator, m_elevators.GetMaxWeight(elevator) - remainweightafter);
m_clock.Time_Cost(Time_Calc());                                             // passengers exchange time
}
else                                                                            //else
{
TimeSpan movestarttime = m_clock.Get_Current_Time();
New_Passengers_Coming();                                                    //add new passengers and go while update state and schedule
TimeSpan traveledtime = m_clock.Get_Current_Time() - movestarttime;

float currentfloor = m_elevators.GetDestination(elevator) > m_elevators.GetCurrentFloor(elevator)?
m_elevators.GetCurrentFloor(elevator) + CalculateMovedFloors(traveledtime):
m_elevators.GetCurrentFloor(elevator) - CalculateMovedFloors(traveledtime);
m_elevators.SetCurrentFloor(elevator, currentfloor);
}
}
}
}
}


下面是第一种采用时间按控制方法的框架的详细UML类图(by Sen Xiang):





Part 2 Scheduler

I. 首先我们考虑每一部电梯的调度策略

对于向上的电梯,响应请求的优先级如下(从高到低):

1. 电梯所在楼层以上向上的请求

2. 电梯所在楼层以上向下的请求

3. 电梯所在楼层以下向下的请求

4. 电梯所在楼层以下向上的请求

对于向下的电梯,同理对称可得

由以上优先级可以找到一个优先级最高的调度目标,或者将电梯置为禁止

II. 然后我们从全局考虑对所有电梯的调度顺序

目的是如果某个电梯外部请求被响应,要将这个请求派给代价最小的电梯

由于只有外部请求被电梯公用,此部分只需考虑外部请求

1. 找出对所有未被调度电梯来说代价最小的一个未被响应外部请求,及相应电梯

2. 对该电梯调用(I) 中单部电梯调度算法,分配其目标,然后将该电梯置为已调度,如果目标是外部请求,将该请求置为已响应

3. 重复1过程,直至所有电梯调度完毕

III. 最后我们考虑对平时、上班、下班三种情况进行各自优化

这部分可以使用各种学习方法,鉴于时间原因,我们只实现了最简单的

首先我们统计请求的情况,当然没有利用framework的漏洞

具体来说统计是这样的,比如1楼有人要向上,OK,外部1楼向上这个请求加1,之后,重复的请求不计,然后电梯下到一楼接到人,将该1楼外部向上的请求指示灯熄灭,如果之后1楼又有人要向上,这个请求再加1

然后根据由0、1楼向上之类特殊请求与总请求的比例,我们可以估计是三种情况中的那一种,这里对于比例阈值我们采用了较保守的值,因为即使把上班判成平时也没有太大影响,而判成下班影响就会很大

对于上班时,我们修改了响应请求的优先级为:

对于向上的电梯,响应请求的优先级如下(从高到低):

1. 电梯所在楼层以上向上的请求

2. 电梯所在楼层以下向下的请求

3. 电梯所在楼层以下向上的请求

4. 电梯所在楼层以上向下的请求

5. 将电梯目标置为1楼

因为此时底楼来人较多,电梯的首要任务是到底楼接乘客,并把他们送到高层,至于高层向下的乘客会相对较少,方便的时候顺带接下即可

对于向下的电梯,我们没有进行相应优化,因为优化之后也没什么明显的效果

对于下班时,我们仿照上班进行了优化,结果没有上班时明显,应为下班时电梯目标较为分散,使得第5部置目标的效果不好

以上就是我们的具体设计

最后也是最重要的

非常非常感谢xuyong童鞋的耐心和细心,合作愉快








By Shaoqing
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: