Docplex:以前没有的Keyerror

问题描述

我正在尝试进行复制研究,并且多次运行有问题的代码而没有出现错误。我花了一点时间来处理其他一些项目,但它突然不起作用,每次我尝试运行代码时都会遇到以下错误(具有不同的键号)。

回溯(最近一次调用最后一次): 文件“main.py”,第 145 行,在 total_requests_served = run_epoch(envt,oracle,central_agent,value_function,day,is_training=True) 文件“main.py”,第 58 行,在 run_epoch score_final_actions = central_agent.choose_actions(scored_actions_all_agents,is_training=is_training,epoch_num=envt.num_days_trained) 文件“C:\Users\src\CentralAgent.py”,第 33 行,在选择操作中 返回 self._choose(agent_action_choices,is_training,epoch_num) 文件“C:\Users\src\CentralAgent.py”,第 53 行,_additive_noise final_actions = self._choose_actions_ILP(agent_action_choices,get_noise=get_noise) 文件“C:\Users\src\CentralAgent.py”,第 132 行,在 _choose_actions_ILP assigned_action_id =assigned_actions[agent_idx] 密钥错误:579

我尝试过从 docplex 导入不同的内容,如果为 False,我尝试使用带有 pass 语句的 dict.get,如果为 False,我尝试使用带有 break 语句的 dict.get。所有要么使代码崩溃,要么在 break 语句的情况下使结果输出无用。我也试过卸载和重新安装python包,卸载和重新安装anaconda。

这里是似乎导致错误代码,这是从论文的github中提取的。

def _choose_actions_ILP(self,agent_action_choices: List[List[Tuple[Action,float]]],get_noise: Callable[[Var],float]=lambda x: 0) -> List[Tuple[Action,float]]:
    # Model as ILP
    model = Model()

    # For converting Action -> action_id and back
    action_to_id: Dict[Action,int] = {}
    id_to_action: Dict[int,Action] = {}
    current_action_id = 0

    # For constraint 2
    requests: Set[Request] = set()

    # Create decision variables and their coefficients in the objective
    # There is a decision variable for each (Action,Agent).
    # The coefficient is the value associated with the decision variable
    decision_variables: Dict[int,Dict[int,Tuple[Any,float]]] = {}
    for agent_idx,scored_actions in enumerate(agent_action_choices):
        for action,value in scored_actions:
            # Convert action -> id if it hasn't already been done
            if action not in action_to_id:
                action_to_id[action] = current_action_id
                id_to_action[current_action_id] = action
                current_action_id += 1

                action_id = current_action_id - 1
                decision_variables[action_id] = {}
            else:
                action_id = action_to_id[action]

            # Update set of requests in actions
            for request in action.requests:
                if request not in requests:
                    requests.add(request)

            # Create variable for (action_id,agent_id)
            variable = model.binary_var(name='x{},{}'.format(action_id,agent_idx))

            # Save to decision_variable data structure
            decision_variables[action_id][agent_idx] = (variable,value)

    # Create Constraint 1: Only one action per Agent
    for agent_idx in range(len(agent_action_choices)):
        agent_specific_variables: List[Any] = []
        for action_dict in decision_variables.values():
            if agent_idx in action_dict:
                agent_specific_variables.append(action_dict[agent_idx])
        model.add_constraint(model.sum(variable for variable,_ in agent_specific_variables) == 1)

    # Create Constraint 2: Only one action per Request
    for request in requests:
        relevent_action_dicts: List[Dict[int,float]]] = []
        for action_id in decision_variables:
            if (request in id_to_action[action_id].requests):
                relevent_action_dicts.append(decision_variables[action_id])
        model.add_constraint(model.sum(variable for action_dict in relevent_action_dicts for variable,_ in action_dict.values()) <= 1)

    # Create Objective
    score = model.sum((value + get_noise(variable)) * variable for action_dict in decision_variables.values() for (variable,value) in action_dict.values())
    model.maximize(score)

    # Solve ILP
    solution = model.solve()
    assert solution  # making sure that the model doesn't fail

    # Get vehicle specific actions from ILP solution
    assigned_actions: Dict[int,int] = {}
    for action_id,action_dict in decision_variables.items():
        for agent_idx,(variable,_) in action_dict.items():
            if (solution.get_value(variable) == 1):
                assigned_actions[agent_idx] = action_id


    final_actions: List[Tuple[Action,float]] = []
    for agent_idx in range(len(agent_action_choices)):

        assigned_action_id = assigned_actions[agent_idx]
        assigned_action = id_to_action[assigned_action_id]

        scored_final_action = None
        for action,score in agent_action_choices[agent_idx]:
            if (action == assigned_action):
                scored_final_action = (action,score)
                break

        assert scored_final_action is not None
        final_actions.append(scored_final_action)

    return final_actions

这是我第一次使用 docplex,所以我什至不确定这是否是问题所在。任何建议都会非常有帮助,谢谢。

解决方法

在不运行代码的情况下猜测问题并不简单。不过,有一行对我来说似乎很可疑,这个测试:

        if (solution.get_value(variable) == 1):

不稳健:CPLEX 处理浮点数,并且整数/二进制变量产生在(小)容差范围内的整数值。偏差可能会随版本和平台而变化。换句话说,一个二元变量最终可能以 0.9999991 作为解决方案中的值,这与容差一致,但不会通过“==1”测试。 此测试的可靠版本是:

        if ( abs(solution[variable] -1 ) <= 1e-6): 

1e-6 是 CPLEX 中的默认完整性容差。