You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在OptaPy中使用constraint_factory定义列表元素约束

OptaPy 子对象未分配工具约束实现方案

现有类定义

class ToolFact:
    id : str
    type : str
    
@planning_entity
class SubObjectFact:
    id : str
    tool : ToolFact

@planning_entity
class ObjectFact:
    id : str
    sub_objects : list[SubObjectFact]

目标约束规则

遍历所有ObjectFact下挂载的SubObjectFact实例,当SubObjectFact的tool属性为None时施加惩罚,对应伪代码:

for each ObjectFact -> object
   for each SubOjectFact in object.sub_object -> sub_object 
       penalize if sub_object.tool is None 

可行实现

方案1:直接以SubObjectFact为入口(性能最优)

你要校验的核心主体是SubObjectFact的tool规划变量,不需要从ObjectFact层做嵌套遍历,直接匹配所有SubObjectFact事实即可,这是约束流的标准写法:

from optapy.score import HardSoftScore

def define_constraints(constraint_factory):
    return [
        # 未分配工具的子对象惩罚
        constraint_factory.for_each(SubObjectFact)
            .filter(lambda sub_object: sub_object.tool is None)
            .penalize("SubObject missing assigned tool", HardSoftScore.ONE_HARD)
    ]

该实现会自动利用OptaPlanner的增量分数计算能力,仅当SubObjectFact的tool属性变化时触发重算,性能最高。

方案2:从ObjectFact出发遍历(适合需关联父对象属性的场景)

如果后续规则需要同时用到ObjectFact的属性(比如根据父对象等级调整惩罚权重),可以用flatten_last方法将sub_objects列表展开为单个SubObjectFact实例,完全匹配你伪代码里的两层遍历逻辑:

from optapy.score import HardSoftScore

def define_constraints(constraint_factory):
    return [
        constraint_factory.for_each(ObjectFact)
            # 展开sub_objects列表,流中元素从ObjectFact变为 (ObjectFact, SubObjectFact) 元组
            .flatten_last(lambda parent_obj: parent_obj.sub_objects)
            .filter(lambda parent_obj, sub_object: sub_object.tool is None)
            .penalize("SubObject missing assigned tool", HardSoftScore.ONE_HARD)
    ]

注意事项

  • 不要在filter方法内手写嵌套循环遍历sub_objects,这类命令式写法会破坏OptaPlanner的增量计算逻辑,求解时性能会出现严重下降
  • 若没有必须读取ObjectFact属性的需求,优先选择方案1,求解速度更快

内容的提问来源于stack exchange,提问作者Adrien DAVID

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 13:48:13