如何为基于代理的模型实施基于规则的决策者?

How to implement a rule-based decision maker for an agent-based model?

我很难理解如何将基于规则的决策制定方法结合到我尝试开发的基于代理的模型中。

代理的界面非常简单。

public interface IAgent
{
   public string ID { get; }

   public Action Percept(IPercept percept);
}

为了示例,我们假设代理代表车辆,这些车辆在大型仓库内穿过道路,以便装卸货物。他们的路线(道路顺序,从起点到代理人的目的地)由另一个代理人 Supervisor 分配。车辆代理的目标是遍历其分配的路线,卸载货物,装载新货物,接收主管分配的另一条路线并重复该过程。

车辆还必须意识到潜在的碰撞,例如在交叉点,并根据一些规则给予优先权(例如,运载最重货物的优先)。

据我了解,这是我要构建的代理的内部结构:

所以车辆代理可以是这样的:

public class Vehicle : IAgent
{
  public VehicleStateUpdater { get; set; }

  public RuleSet RuleSet { get; set; }

  public VehicleState State { get; set; }

  public Action Percept(IPercept percept)
  {
    VehicleStateUpdater.UpdateState(VehicleState, percept);
    Rule validRule = RuleSet.Match(VehicleState);
    VehicleStateUpdater.UpdateState(VehicleState, validRule);
    Action nextAction = validRule.GetAction();
    return nextAction;
  }
}

对于 Vehicle 代理的内部状态,我正在考虑如下内容:

public class VehicleState
{
  public Route Route { get; set; }

  public Cargo Cargo { get; set; }

  public Location CurrentLocation { get; set; }
}

对于此示例,必须为车辆代理实施 3 条规则。

  1. 如果代理附近有其他车辆(例如小于 50 米),则货物最重的车辆优先,其他代理必须保持原位。
  2. 当代理人到达目的地时,他们卸下货物,装载新货物并等待主管分配新路线。
  3. 在任何给定时刻,无论出于何种原因,监管者都可能会发送命令,接收车辆必须遵守该命令(保持位置或继续)。

VehicleStateUpdater 必须考虑代理的当前状态、接收到的感知类型并相应地更改状态。因此,为了让国家反映这一点,例如Supervisor 收到一条命令,可以修改如下:

public class VehicleState
{
  public Route Route { get; set; }

  public Cargo Cargo { get; set; }

  public Location CurrentLocation { get; set; }

  // Additional Property
  public RadioCommand ActiveCommand { get; set; }
}

其中 RadioCommand 可以是具有值 None、Hold、Continue 的枚举。

但现在如果有另一辆车靠近,我也必须在代理状态下注册。所以我必须向 VehicleState 添加另一个 属性。

public class VehicleState
{
  public Route Route { get; set; }

  public Cargo Cargo { get; set; }

  public Location CurrentLocation { get; set; }

  public RadioCommand ActiveCommand { get; set; }

  // Additional properties
  public bool IsAnotherVehicleApproaching { get; set; }

  public Location ApproachingVehicleLocation { get; set; }
}

这是我在理解如何进行时遇到很大困难的地方,我觉得我没有真正遵循正确的方法。首先,我不确定如何使 VehicleState class 更加模块化和可扩展。其次,我不确定如何实施定义决策过程的基于规则的部分。我是否应该创建相互排斥的规则(这意味着每种可能的状态只能对应一个规则)?有没有一种设计方法可以让我添加额外的规则,而不必来回切换 VehicleState class 和 add/modify 属性,以确保可以处理每种可能的 Percept 类型通过代理的内部状态?

我看过《人工智能:现代方法》课程手册和其他资源中演示的示例,但可用的示例太简单了,我无法在必须设计更复杂的模型时“掌握”相关概念。

如果有人能指出有关基于规则部分的实施的正确方向,我将不胜感激。

我正在用 C# 编写,但据我所知,它与我试图解决的更广泛的问题并不真正相关。

更新:

我尝试合并的规则示例:

public class HoldPositionCommandRule : IAgentRule<VehicleState>
{
    public int Priority { get; } = 0;

    public bool ConcludesTurn { get; } = false;


    public void Fire(IAgent agent, VehicleState state, IActionScheduler actionScheduler)
    {
        state.Navigator.IsMoving = false;
        //Use action scheduler to schedule subsequent actions...
    }

    public bool IsValid(VehicleState state)
    {
        bool isValid = state.RadioCommandHandler.HasBeenOrderedToHoldPosition;
        return isValid;
    }
}

我也尝试实现的代理决策者示例。

public void Execute(IAgentMessage message,
                    IActionScheduler actionScheduler)
{
    _agentStateUpdater.Update(_state, message);
    Option<IAgentRule<TState>> validRule = _ruleMatcher.Match(_state);
    validRule.MatchSome(rule => rule.Fire(this, _state, actionScheduler));
}

我认为您的问题包含两个主要的子问题:

  • 建模灵活性,特别是关于如何更轻松地向系统添加属性和规则。
  • 如何提出正确的规则集以及如何组织它们以使代理正常工作。

所以让我们逐一分析。

建模灵活性

我觉得你现在的情况其实还不错。让我解释一下原因。

您表达了对存在“一种允许我添加额外规则而无需来回 VehicleState class 和 add/modify 属性的设计方法”的担忧。

我认为答案是否定的,除非您遵循完全不同的路径让代理自主学习规则和属性(如 Deep Reinforcement Learning),这会带来一系列困难。

如果您要按照问题中的描述手动编码代理知识,那么您将如何避免在添加新规则时引入新属性的需要?您当然可以尝试预测您将需要的所有属性,并且不允许自己编写需要新属性的规则,但新规则的本质是带来问题的新方面,这通常需要新属性。这与需要多次迭代和更改的软件工程没有什么不同。

基于规则的建模

规则的写法有两种:命令式和声明式。

  • 在命令式风格中,您编写执行操作所需的条件。当两者都适用时,您还必须注意选择一个动作而不是另一个动作(可能有优先系统)。因此,您可以制定一条沿路线行驶的规则,以及在优先级更高的车辆接近时停止的另一条规则。这似乎是您目前正在追求的方法。

  • 在声明式中,您声明环境规则是什么、操作如何影响环境以及您关心什么(将 实用程序 分配给特定状态或子状态),然后让系统处理所有这些来为您计算最佳动作。因此,在这里您声明做出移动决定如何影响您的位置,您声明碰撞如何发生,并且您声明到达路线的尽头是好的,碰撞是坏的。请注意,在这里您没有做出决定的规则;系统使用规则来确定给定特定情况下具有最大值的操作。

理解命令式和声明式风格之间区别的一种直观方法是考虑编写一个下棋的代理。程序员以命令式的方式编码下棋的规则,还有如何下棋,如何开局,如何选择最佳走法等等。也就是说,系统会体现程序员的棋艺。在声明式风格中,程序员只需对国际象棋规则以及系统如何自动探索这些规则并确定最佳着法进行编码。在这种情况下,程序员不需要知道如何下象棋,程序也能真正下出一盘像样的棋。

命令式风格更易于实现,但灵活性较低,并且随着系统复杂性的增加会变得非常混乱。你必须开始考虑各种场景,例如,当三辆车相遇时该怎么做。在国际象棋的例子中,想象一下如果我们稍微改变国际象棋的规则;需要审查整个系统!在某种程度上,命令式系统中几乎没有“人工智能”和“推理”,因为是程序员在提前进行所有推理,提出所有解决方案并对其进行编码。它只是一个常规程序,而不是人工智能程序。这似乎是你所说的那种困难。

声明式风格更加优雅和可扩展。你不需要弄清楚如何确定最佳行动;系统会为你做。在国际象棋示例中,您可以轻松地在代码中更改一条国际象棋规则,系统将使用新规则在更改后的游戏中找到最佳着法。然而,它需要一个推理引擎,这个软件知道如何接受大量规则和实用程序并决定哪个是最好的行动。这样的推理机就是系统中的“人工智能”。它会自动考虑所有可能的场景(不一定一一考虑,因为它通常会采用更智能的技术来考虑 classes 场景)并确定每个场景中的最佳操作.然而,推理引擎实施起来很复杂,或者,如果您使用现有的推理引擎,它可能非常有限,因为它们通常是研究包。我相信,当谈到使用声明式方法的实际应用程序时,人们几乎会为他们的特定需求编写定制系统。

我找到了几个类似的研究开源项目(见下文);这将使您了解可用的内容。如您所见,这些都是研究项目,范围相对有限。

毕竟,如何进行?我不知道你的具体目标是什么。如果你正在开发一个玩具问题来练习,你当前的命令式风格系统可能就足够了。如果你想了解声明式风格,深入阅读 AIMA 教材会很好。作者也维护 open source repository with implementations for some of the algorithms in the book

https://www.jmlr.org/papers/v18/17-156.html

https://github.com/douthwja01/OpenMAS

https://smartgrid.ieee.org/newsletters/may-2021/multi-agent-opendss-an-open-source-and-scalable-distribution-grid-platform