目标
目前已经完成了可以运行的代码。下一步要把代码重构,以使其支持如下功能:
- 可以在任何时候修改reward函数。支持稀疏的以及连续的reward。
- 可以选择decentralized或centralized的P网络,也就是所有agent(同个net内)共用一个或者各有一个。
- 其他修改(比如action)
关于Action的讨论
现在的action是上下左右停,有没有别的方式去进行routing的操作?比如Undo,比如“指出路径上的一点,并给出从此点出发走到的下一个点”,但是这样的话动作空间会大大加大。
另一个方式就是,增设一个动作,叫Undo,这就赋予了agent返回刚才一步的权利。
也许有另一种实现方式,就是如果agent选择的步骤回到了刚才走过的路,则等于Undo,但是这样的话就不能实现这个操作:“agent甲先碰到了agent乙,然后原路返回至一个中间地点,然后再奔赴agent丙”。
所以综上所述应该是用Undo操作。Undo之后,agent回退一步,刚刚走过的位置被归零(恢复原状,注意不是一刀切的写成0,而仅仅是把这个agent产生的影响消去)。如果回到了初始位置,Undo后不会有任何变化。
如何才能实现Undo呢?我们要先知道agent的动作到底是在哪个时候哪个函数才Embed到
observation的设计(Env的输出,P、Q的输入)
无论是否是中心化的P网络,env返回的obs都应该一致(即使agent的输入obs是partially observed的,那也是在外面其他地方产生individual obs,而不是env返回的。)
对于obs的设计应该满足以下几个规范:
- 包含了所有agent的信息
- 能够满足可变N的需求(关于N的不变性)
- 直接不管三七二十一,全部内容写在一个矩阵里,类似于我们之前的做法。把obs拆分的工作留在外面。
- 包含了所有层级的信息(先放一放)
- 能够适用于2D和3D(先放一放)
对于P
无论考不考虑中心化的P,传入P的ob一定要具有以下属性:
- 有本agent的信息
- 有其他agent的信息
所以其实考虑原来的方法:传入一个图像,用1表示已有的轨道,用2表示目前的位置,已经基本满足。但是考虑到加入了Undo操作,要加入上一步信息才行。
对于Q
P网络的中心化与非中心化
这个章节我们要讨论P网络的设计以及对应Env的代码写法。
在我们的问题中,Q网络毫无疑问应该是中心化的。最需要讨论的是P网络中心化与否。鉴于中心化的P是最容易实现的,先讨论这种情况,并引申出代码的实现细节。
中心化的P网络
action(Env的输入,P网络的输出)
输入的action是一个N长list:action_n
,每个元素是一个数字(或者one-hot),数字是[0, 5]之间的(考虑Undo操作)整数。
*如何在可变agents数目的情况下应对P网络的输出呢?直接输出6个值就好了
非中心化的P网络
先不予讨论。
—-
以下内容为工程解决方案,不具有任何指导意义
代码结构
- maddpg
- experiments
- train.py
- learning_curves
- models
- gym-routing
* setup.py
- gym_routing
- __init__.py
- envs
- __init__.py
- core.py
- environment.py(TODO:恢复原来的N list输出!)
- routing2D.py
- scenario.py
- gym_routing
- maddpg
- __init__.py # 别动
- common
- distributions.py # 别动(完毕)
- tf_util.py # 别动(完毕)
- trainer
- maddpg.py # 尽量别动(TODO:恢复一个同时支持decen和cen的状态,接口不要变动)
- replay_buffer.py # 别动(完毕)
- experiments
reward函数
reward来自Env,Env来自MultiAgentEnv中的reward_callback函数,在每个step中,MultiAgentEnv会这样调用这个函数:reward_callback(agent)
,这个callback函数要在创建MultiAgentEnv的时候传入,它的输入的是一个agent对象。这显然是不合理的,agent对象中保存了自己的位置,但是没有保存ind和观察到的东西或者是其他跟环境有关的东西。
为了顾及中心化和非中心化P网络,以及随时修改reward函数的功能,我们建议把reward_callback在创建Env的时候传入,这个函数应该在train.py完成。这样的话,可以在实验过程中传入不同的reward函数。而且,此函数的输入不应该只有一个agent,应该包含:包含了所有信息的Map,最好的办法是与Env的返回Obs完全一致。也就是说,此函数的输入应该包含了全局信息和agent自己的信息(比如Ind或Loc)。
- TODO:重新设计Reward函数
Observation
- TODO:修改了OB之后,外围程序都要相应修改。从第一个得到OB的地方开始!
obs来自于Env,Env来自于scenario创建的MultiAgentEnv,MAE来自于obs_callback
,obs_callback
来自于scenario创建的World,World内部含有一个self.map
,而这个map来自于创建world的时候,scenario通过gen_data
函数创建一堆pin,然后构造一个矩阵,然后再传入World。
所以目前的做法是Env直接返回这个矩阵,他的最原始产出地是在routing2D.py
,它的形式是这样的:
- shape: [N+1, X, Y]
- Map的每一层(除了最后一层)只包含了此层的index对应的agent的走过的路径,全部用1表示。
- Map的最后一层为所有agent走过的路径。用1表示。
可以看出这个矩阵的设计,只针对于2D问题。
新增:agent增加属性self.index
agent的构造位置为routing2D.py
中,这个scenario的`reset_world。
TODO:修改所有的enumerate