如何在 Anylogic 的一个流程图中处理不同的材料?
Posted
技术标签:
【中文标题】如何在 Anylogic 的一个流程图中处理不同的材料?【英文标题】:How can I handle different materials in one flowchart in Anylogic? 【发布时间】:2019-11-08 07:03:55 【问题描述】:对于我的流程图,我通过不同的来源生成了三个不同的代理。现在我想在流程图的不同块中以不同的方式处理它们。例如,我想为代理设置不同的延迟时间。由于我是 AnyLogic 新手,并且对 Java 不太熟悉,因此我很难理解如何处理模型中的代理。
我为代理提供了一个带有名称的字符串参数,并尝试使用带有 if-else 语句的函数来区分延迟中的代理。下图总结了我的方法(我希望我做得对):
函数中的代码是:
if (agent.TypeComponent == "blade" || agent.TypeComponent == "narcelle")
return uniform(3.5, 6);
else return uniform(1, 3);
我收到错误报告(从德语翻译):
代理无法解析为变量。
Main 类型的 delayPrepFeeder() 方法不适用于参数(Agent)
谢谢你和亲切的问候。
【问题讨论】:
【参考方案1】:简短的回答:您只能有 一个 代理类型在您的流程图中流动并正确使用它。因此,要么只使用一个源,要么确保所有源都创建相同的代理类型,例如。 组件。有关以下不同方面的更多详细信息。
流程图代理类型定义
每个流程图块都定义了一个代理类型,这是该块所期望的:
您仍然可以通过流程图发送与此定义的代理类型不匹配的代理,但您将无法访问其任何变量、参数和函数!如果您仍然尝试访问类型不是已定义类型的字段,您将收到此错误:MyField cannot be resolved or is not a field
。为什么?因为当您通过 agent.
访问流动代理时,您正在使用的 Java 类型将是定义的代理类型,或者换句话说,您的代理已强制转换为定义的类型,无论他的真正的类型是以前。
源代理类型
确保在您的 Sources 中将 New Agent 和 Agent Type 设置为您的特定代理类型:
New Agent 设置定义了创建的流动对象的实际类型。 代理类型 在所有流程图块中都可用,它定义了您可以处理流动对象的类型(或在 Java speek 中:当您访问 agent
时将其转换为哪种类型)。
函数的输入参数
在您的delayPrepFeeder()
函数中检查您是否定义了一个输入参数并且您将其定义为正确的类型。这样做(当然使用您自己的自定义类型名称):
代码必须使用您刚刚为输入参数定义的名称(此处为:myAgent)。在此函数中,您无法使用agent
直接访问代理,这仅在流程图块中直接有效。因此我们定义了输入参数myAgent
,并引用agent
调用函数。同样,流程模块将向您调用agent
,这是此流程图块中定义的类型的对象引用,它必须与源中定义的类型和您在输入参数中使用的类型相匹配,并且函数。
if (myAgent.TypeComponent.equalsIgnoreCase("blade") || myAgent.TypeComponent.equalsIgnoreCase("narcelle"))
return uniform(3.5, 6);
else
return uniform(1, 3);
我真的需要在一个流程图中使用几种不同的代理类型吗?
你可能不知道。
如果您的类型仅在属性上有所不同,请使用字段(变量和参数)来区分它们。例如,始终使用代理类型Component
,然后使用名为type
的参数进行区分。这个type
参数可以是一个字符串(例如:“Rotorblade”),或者更好的是来自AnyLogic Option List 的条目,您预先定义了所有可能的类型。
您真正需要不同类型的唯一情况是您的代理类型中有完全不同(复杂)的状态图、动作图、可视化或其他自定义 AnyLogic 元素。
如果我真的需要在一个流程图中使用多个代理类型怎么办?
您可以使用继承来做到这一点。创建一个“基础”代理(到目前为止只是一个普通代理),例如 Component。此基础代理将是您在所有流程图块中设置为流经类型的代理。在此基础代理中,您可以添加所有类型共有的所有变量、参数、函数等以及您希望在流程图中访问的。
接下来,您将创建继承的代理。同样,将它们创建为普通代理类型。您可以通过以下简单设置让它们从基础代理继承:
现在您将看到,在您的基础代理中定义的内容也将在您继承的代理中显示(灰色):
还有一件事:您实际上可以访问继承代理的字段和函数,方法是将其从基本类型转换为正确的类型:(MyInheritedAgent)agent
。但是你必须事先确定这个对象确实属于这种类型,否则你会得到一个转换错误。
结论
您可以(不使用继承的代理)每个 AnyLogic 流程图仅使用 一个 单一代理类型。 因此,请确保在以下位置始终将代理类型设置为相同的一个代理类型:
来源:新特工 来源:代理类型 流程图块:代理类型 使用流动agent
的函数:输入参数
如果一个还不够,使用代理继承。
作为旁注,请使用equals()
或equalsIgnoreCase()
代替==
进行字符串比较,原因正在解释here。
【讨论】:
非常感谢您的帮助,弗洛里安。当延迟块尝试执行该函数时,仍然会出现第一个错误。我尝试了 delayPrepFeeder(myAgent),就像你的例子一样。可能由于更根本的错误而发生错误,我必须回到书本上。 您是否也将代码更改为“if (myAgent.TypeComponent......”?您给输入参数的名称(这里:myAgent)必须与中相同代码。在函数内部引用“代理”不起作用,您只能直接在流程图块本身中访问“代理”。在您的函数中,它只能通过您在输入参数定义中给出的名称访问。 我确实相应地修改了函数。我认为我的问题是设置代理(材料)的正确方法。反正。再次感谢。 好吧,忘记上面写的一切。您在这里遇到的问题是您将不同的代理类型发送到一个流程流中。这里的问题是您必须在每个流程块中指定流过的类型。您必须选择一个,例如 Towersegment 或 Rotorblades。然后您将只能访问该 EXACT 类型的字段(TypeComponents)。即使您的所有类型都具有相同的变量(TypeComponents),您也无法访问它们。建议:与其创建3种不同的Agent类型,不如只创建一种,用String隔开! 您可以通过创建一个包含 TypeComponent 字段的基本代理类型来做您想做的事情,然后只需从该类型创建继承的代理类型。然后在源和进程块中定义基本类型并可以访问参数,即使流经的实际类型是继承的类型之一。请参阅this,了解如何创建继承的代理类型。以上是关于如何在 Anylogic 的一个流程图中处理不同的材料?的主要内容,如果未能解决你的问题,请参考以下文章
Anylogic:如何让代理在队列中等待直到它改变状态? (离散事件流程图)