添加新算法
基本结构
- 任何与VNREAL一起使用的算法必须是从MuLaViTo的MuLaViTo派生出来的。IAlgorithm接口,
- 定义了访问运行算法状态信息的常用方式
- 允许显示一个GUI进度条
- 包装vnreal。算法包含了几个基类(实现了mulavito.IAlgorithm)来派生自己的算法
![[Pasted image 20220329153431.png]] - 算法仅仅提供了在运行算法之前和之后做事情的抽象方法
- ![[Pasted image 20220329153628.png]]•abstractsequentialalgorithm执行顺序处理,提供抽象方法hasNext和getNext
•abstractrevokablesequentialalgorithm额外提供了一个抽象的撤销方法
•基本算法原理
- 该算法得到一个vnreal.network.NetworkStack,它由
•具有资源的基板网络,
•有需求的虚拟网络列表 - 该算法通过搜索能够满足给定需求的资源来执行VNM和VLM
例子
samples包包含实验算法,比如SimpleDijkstraAlgorithm。这个示例算法执行如下操作
•任意虚拟节点映射(以任意方式在完成虚拟节点需求的基板节点之间选择节点映射),
•虚拟链接映射是通过使用Dijkstra算法计算出的基板网络中的最短路径来连接每一对映射的虚拟节点来实现的。
类SimpleDijkstraAlgorithm实现的第一部分是这样的
public final class SimpleDijkstraAlgorithm extends AbstractSequentialAlgorithm<VirtualLink> {
private final NetworkStack stack;
private Iterator<? extends Network<?, ?, ?>>
private Iterator<VirtualLink> curIt;
}
这是该算法的hasNext函数,它只是在虚拟网络请求集合上更新迭代器。如果一个虚拟网络请求已经被服务,它将把curNetIt移动到下一个虚拟网络请求,并更新curNetIt迭代器。如果没有更多的虚拟网络请求,则返回false。
@Override
protected boolean hasNext() {
if (curIt == null || !curIt.hasNext()) {
if (curNetIt.hasNext()) {
Network<?, ?, ?> tmp = curNetIt.next();
if (tmp instanceof SubstrateNetwork) tmp = curNetIt.next();
curIt = ((VirtualNetwork) tmp).getEdges().iterator();
return hasNext();
}
else
return false ;
}
else
return true ;
}
getNext方法返回将在流程方法中映射的以下虚拟链接。要查看示例代码的详细信息,请访问vnreal.algorithms.samples包。
@Override
protected VirtualLink getNext() {
if (!hasNext()) return null ;
else
return curIt.next();
}`
轻松重用现有的节点/链路映射算法
SimpleDijkstraAlgorithm是当虚拟链路和节点映射作为单个阶段执行时,如何实现算法来解决虚拟网络映射的一个例子。然而,大多数求解VNE的算法都分为两个阶段:
- 虚拟节点映射(首先执行)和
- 虚拟链接映射(排在第二位)。
为了便于实现VNE算法,应该使用抽象的GenericMappingAlgorithm类。
GenericMappingAlgorithm类接受两个参数:NodeMapping和LinkMapping。它们需要分别从两个类AbstractNodeMapping和AbstractLinkMapping派生出来。通过这种方式,节点映射和链接映射阶段可以相互独立地实现。这有一个重要的优点:不同算法的节点和链接映射阶段可以组合,可能得到不同的结果。
GenericMappingAlgorithm, AbstractNodeMapping和AbstractLinkMapping是vnreal的一部分。算法方案。
GenericMappingAlgorithm通过处理每次不同的虚拟网络请求来工作,因此getNext()方法返回一个虚拟网络请求。进程(VirtualNetwork p)方法,接收这个虚拟网络请求并执行节点映射和链路映射阶段。如果其中至少有一个不成功,那么该虚拟网络上的所有映射都会被撤消,该方法也会结束(没有实现该网络的映射);如果他们都成功了,这个方法就结束了。接下来是算法的流程图(图后详细介绍了AbstractNodeMapping和AbstractLinkMapping的不同方法。
![[Pasted image 20220329160234.png]]要实现一个同时具有:节点映射和链接映射阶段的新算法,需要实现两个类。从AbstractNodeMapping扩展的节点映射类和从AbstractLinkMapping扩展的链接映射类
AbstractNodeMapping
现在让我们检查AbstractNodeMapping的方法和变量:
`
public abstract class AbstractNodeMapping {
protected Map<VirtualNode, SubstrateNode> nodeMapping;
private List<VirtualNode> unmappedvNodes;
private List<SubstrateNode> unmappedsNodes;
protected List<SubstrateNode> mappedsNodes;
}
前面的全局变量的含义如下:
•nodemapping:这是一个Map类型的列表,在节点映射实现后,包含了每个虚拟节点到其对应的SubstrateNode的映射。在执行映射时,应该更新这个变量。
•unmappedvnodes:对于当前虚拟网络请求,在执行了预定义的节点映射之后,它是一个带有未映射的虚拟节点的列表。ALEVIN支持将一组虚拟节点(可能是全部)映射到相应的基板节点的可能性。
unmappedsnodes:在执行预定义的节点映射之后,对于当前的虚拟网络请求,它是一个包含未被映射的基板节点的列表。
•mappedsnodes:它是一个包含已映射的基板节点的列表,用于当前虚拟网络请求,执行预定义的节点映射。
`
public boolean isPreNodeMappingFeasible(VirtualNetwork vNet)小鲑鱼支持资源/需求称为节点id:用这种方法可以实现一个预定义的节点映射在算法运行之前,它是足够的分配的虚拟节点IdResource IdDemand衬底节点选择实现映射。isPreNodeMappingFeasible方法负责实现这种预定义的映射,并确保映射的基板节点的资源足以满足虚拟节点的需求。如果映射不能执行,该方法将返回一个假值。这个方法已经在AbstractNodeMapping中实现,并在GenericMappingAlgorithm中使用。在执行该方法之后;更新nodeMapping、unmappedvNodes、unmappedsNodes和mappedsNodes。
public boolean isPreNodeMappingComplete() {
return unmappedvNodes.isEmpty();
}
方法isPreNodeMappingComplete()检查在预定义的节点映射阶段,虚拟节点映射是否已经完全执行。如果所有虚拟节点都已映射,则完成映射,在这种情况下不应该执行任何虚拟节点映射。这个方法已经在AbstractNodeMapping中实现,并在GenericMappingAlgorithm中使用。
`
protected abstract boolean nodeMapping(VirtualNetwork vNet);`
nodeMapping方法是类中最重要的方法。这个方法必须在一个新类(扩展AbstractNodeMapping)中实现。很重要的一点是,在实现这个方法时,可能已经执行了一个预定义的映射,并且已经映射了虚拟网络请求的一些虚拟节点(请考虑nodeMapping、unmappedvNodes、unmappedsNodes和mappedsNodes变量)。在执行了nodeMapping之后,nodeMapping变量应该被更新,并且该方法应该返回一个布尔值(如果节点映射成功则为true,否则为false)
AbstractLinkMapping
现在让我们检查AbstractLinkMapping的方法和变量:
`
public abstract class AbstractLinkMapping {
protected int processedLinks, mappedLinks;`
}
AbstractLinkMapping变量procesedlinks和mappedLinks用于更新算法的进度条。当一个虚链接被映射时,processsedlinks应该加1,当它已经被映射时,mappedLinks也应该加1。
`
protected abstract boolean linkMapping(VirtualNetwork vNet,Map<VirtualNode, SubstrateNode> nodeMapping);`
AbstractLinkMapping类的主要方法是抽象linkMapping方法。这个方法必须在一个新类(扩展AbstractLinkMapping)中实现。输入是虚拟网络请求和已经执行的节点映射。如果节点映射成功,该方法的输出应为布尔值true,否则为false)。
需要GUI收养
如果你希望你的新算法出现在GUI中,只需扩展类vnreal. GUI .menu. algorithmmenu。
增加新的资源/需求类型对
概述
•所有资源类型都是从AbstractResource派生出来的
•资源只能添加到substratnetwork的实体中
•substratenwork由SubstrateLinks和SubstrateNodes组成
•所有的需求类型都是从AbstractDemand派生出来的
•需求只能添加到虚拟网络的实体中
•VirtualNetwork由virtuallink和VirtualNodes组成
我们使用访问者模式和适配器模式来避免
•强制转换为具体的需求/资源类,
•尽量使用Java的instanceof。
注意:我们以一种纠缠的方式使用这些设计模式。
•一个资源是一个访问者的需求提供占领和免费的访问者
•需求是访问者对资源的需求,该资源提供了接受和满足访问者的需求
•不要对此感到困惑。
•每个资源和需求都有一个名称。当您创建一个克隆时(使用getCopy),您必须将名称复制到克隆中。这样equals()方法就可以对克隆进行匹配。
•如果你不提供一个名称的名称是sat为“名称的所有者”_“this.hashCode()”
关于访问者模式
通常,访问者模式用于向现有对象结构添加新操作,而不需要修改每个对象。这些操作被封装在访问者中,然后访问者访问这些对象并与之交互。该对象只需提供一个简单的接口来接受访问者。
在这里,我们已经知道我们需要的所有操作(免费、占用、接受、完成),但希望能够添加新的资源/需求对到我们的网络,例如,新的对象,然后可以处理所有即将到来的资源/需求请求。
约束
对于ALEVIN的XML交换格式文档,资源类和需求类需要满足以下约束
•约束类必须实现一个或两个inodeconconstraint, ILinkConstraint接口。这显示了Constraint是否适用于节点、链接或两者。
•对于每个应该包含在交换格式中的参数,getter和setter方法必须用@ExchangeParameter声明和注释
•导出需要getter
•导入时需要设置
•这些方法的参数不能是简单类型(int, double),而是可以通过Java反射使用的类
•注意:目前,交换格式支持以下类型:Integer、Double、String和Boolean
•资源
•getter方法必须按照以下模式命名:get + <参数名>
•setter方法必须按照以下模式命名:get + <参数名>
•要求
•getter方法必须按照以下模式命名:getdemand++ <参数名>
•setter方法必须按照以下模式命名:setrequested + <参数名>
过程
要添加新的需求类型MyNewDemand和相应的资源类型MyNewResource,请执行以下步骤:
- 添加虚拟方法
•vnreal.demands.[[DemandVisitorAdapter.java]]
public boolean visit(MyNewDemand req) {
return false ;
}
• vnreal.resources.ResourceVisitorAdapter
public boolean visit(MyNewResource req) {
return false ;
}`
1.在vnreal包中创建一个新类MyNewResource。资源扩展AbstractResource
2.在vnreal.demand包中创建一个新的类MyNewDemand,
3.扩展AbstractDemand实现所有抽象方法(模仿现有代码,如IdDemand和IdResource)
需求如何映射到资源,反之亦然
需求和资源之间的映射是通过映射算法建立的。对于每个需求,算法决定满足它的资源。
要在需求和资源之间创建映射,需要以下步骤:
- 资源必须接受需求。在此步骤中,确定资源和需求是否兼容。
- 资源必须满足需求。这保证了资源足够满足需求的需求。
- 最后,需求占用了资源。在此步骤中,减少资源的空闲容量,并创建两个约束之间的映射。
要删除一个现有的映射,需求必须释放被占用的资源。
如何处理需求-资源映射
•访问
•从需求中获取被占用的资源:
AbstractDemand d;
for (vnreal.mapping.Mapping m : d.getMappings()) {
AbstractResource r = m.getResource();
}
•获取资源占用需求:
AbstractResource r;
for (vnreal.mapping.Mapping m : r.getMappings()) {
AbstractDemand d = m.getDemand();
}
•清除
AbstractDemand d;
AbstractResource r; d.getMapping(r).unregister();
占用和释放资源的示例
为了占用虚拟网络的资源,将调用对应的Demand的occupy()方法。occupy()方法从Resource中检索被占用的访问器,然后访问Resource。
首先,它检查资源是否能够通过调用资源的fulfills()方法来满足需求。fulfills()方法从Demand中获取已完成的访问者,然后该访问者访问Resource,如果它能够满足需求,就返回。这个结果被转发给被占用的访问者,然后被占用的访问者创建一个新的Mapping来占用所需的资源。映射在需求和资源处注册自己。
最后,如果资源占用成功,则占用访问器返回。这个结果被转发给occupy()方法的调用者。
<占领svg >
为了释放不再需要的资源,将调用相应Demand的free()方法。free()方法从Resource中检索自由访问器,然后资源访问该资源。
自由访问者采取相应的映射,并建议它从需求和资源注销自己。如果这是成功的,资源将被释放,结果将被转发到Demand,并从那里转发给free()方法的调用者。
<自由svg >
#添加新的指标
##概述
•metrics在vnreal.evaluations.metrics包中
•所有指标都来自EvaluationMetric界面
度量应该使用setStack(NetworkStack
>堆栈)方法
•metrics扩展了getValue()方法,以便计算特定NetworkStack上的值
•getstat()可以用来返回度量的状态的文本表示
•也有可能从AbstractEvaluation派生(反过来,从EvaluationMetric派生)
•在这种情况下,应该重写calculate()方法来获得单次运行的度量
•getvalue()可以用来获取聚合值(例如通过引入私有成员)
•tostring()将返回度量的简短文本描述