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

如何通过EML结合复杂比较规则合并项目模型?

EML模型合并规则修改问题

问题描述

我正在使用EML和Epsilon Language Workbench,将两个基于元模型MM1和MM2的项目模型合并到第三个目标元模型中。目前可基于元素名称实现简单合并,但需要一套更复杂的规则:根据特定条件将第二个模型(M2)中的任务分配给第一个模型(M1)中的人员。

期望结果

对于M1中的每个Person实例p,仅当p在M1中已参与超过2个任务时,才将M2中的Task t分配给p。

当前尝试

已创建Epsilon程序(program.eml和program.ecl)执行合并,使用Epsilon playground测试,示例改编自游乐场标准示例。

元模型

  • MM1(left.emf)
  • MM2(right.emf)
  • 目标元模型(target.emf)

模型

- M1 (left.flexmi)
- M2 (right.flexmi)

Epsilon程序

- program.eml
- program.ecl

元模型1 - MM1(left.emf)

@namespace(uri="psl", prefix="")
package psl;

class Project {
    attr String title;
    attr String description;
    val Task[*] tasks;
    @diagram(direction="right")
    val Person[*] people;
}

class Task {
    attr String title;
    attr int start;
    attr int duration;
    @diagram(direction="right")
    val Effort[*] effort;
}

class Person {
    attr String name;
}

class Effort {
    @diagram(direction="up")
    ref Person person;
    attr int percentage = 100;
}

元模型2 - MM2(right.emf)

@namespace(uri="psl", prefix="")
package psl;

class Project {
    attr String title;
    attr String description;
    val Task[*] tasks;
    @diagram(direction="right")
    val Person[*] people;
}

class Task {
    attr String title;
    attr int start;
    attr int duration;
    @diagram(direction="right")
    val Effort[*] effort;
}

class Person {
    attr String name;
}

class Effort {
    @diagram(direction="up")
    ref Person person;
    attr int percentage = 100;
}

模型1 - M1(left.flexmi)

<?nsuri psl?>
<project title="ACME">
    <person name="Alice"/>
    <person name="Bob"/>
    <task title="Analysis" start="1" dur="3">
        <effort person="Alice"/>
    </task>
    <task title="Design" start="4" dur="6">
        <effort person="Bob"/>
    </task>
    <task title="Implementation" start="7" dur="3">
        <effort person="Bob" perc="50"/>
        <effort person="Alice" perc="50"/>
    </task>
</project>

模型2 - M2(right.flexmi)

<?nsuri psl?>
<project title="ACME">
    <person name="Alice"/>
    <person name="Bob"/>
    <task title="Testing" start="10" dur="3">
        <effort person="Alice" perc="50"/>
    </task>
</project>

目标元模型(target.emf)

package psl;

class Project {
    attr String title;
    attr String description;
    val Task[*] tasks;
    @diagram(direction="right")
    val Person[*] people;
}

class Task {
    attr String title;
    attr int start;
    attr int duration;
    @diagram(direction="right")
    val Effort[*] effort;
}

class Person {
    attr String name;
}

class Effort {
    @diagram(direction="up")
    ref Person person;
    attr int percentage = 100;
}

program.eml

// This EML program merges two 
// project plan models as follows:
// - Persons are merged based on name
// - Tasks are not merged

// Matched projects are merged
// into a single project
rule ProjectWithProject
    merge l : Left!Project
    with r : Right!Project
    into m : Merged!Project {

    m.title = l.title;
    m.people ::= l.people + r.people;
    m.tasks ::= l.tasks + r.tasks;
}

// Matched persons are merged
// into a single person
rule PersonWithPerson
    merge l : Left!Person
    with r : Right!Person
    into m : Merged!Person {

    m.name = l.name;
}

// Tasks are not merged
// They are copied from the left
// and the right model to the 
// merged model
rule TaskWithTask
    transform s : Source!Task
    to t : Target!Task {

    t.title = s.title;
    t.start = s.start;
    t.duration = s.duration;
    t.effort ::= s.effort;
}

//merge efforts in the task ONLY when the people in the right worked in at least one task (i.e. has effort) in the left
rule EffortWithEffort
    merge l : Left!Effort
    with r : Right!Effort
    into m : Merged!Effort {
    
    m.person ::= l.person;
    m.percentage = l.percentage;
}

// Persons and Efforts found in only one of the
// two models are copied across
// to the merged model
rule Person2Person 
    transform s : Source!Person
    to t : Target!Person {

    t.name = s.name;
}

rule Effort2Effort
    transform s : Source!Effort
    to t : Target!Effort {

    t.person ::= s.person;
    t.percentage = s.percentage;
}

program.ecl

// We match persons by name
rule PersonWithPerson
    match l : Left!Person
    with r : Right!Person {

    compare: l.name = r.name
}


rule EffortWithEffort
    match l : Left!Person
    with r : Right!Person {

    compare: l.tasks->collect(e | e.effort)
            ->flatten()
            ->excluding(l)
            ->collect(e | e.effort)
            ->flatten()
            ->count(r) >= 1
}

// We expect only one project 
// in each model and therefore
// we match them unconditionally
rule ProjectWithProject
    match l : Left!Project
    with r : Right!Project {
    
    compare: true
}

修改方案

1. 修正program.ecl中的Effort匹配规则

当前EffortWithEffort规则匹配逻辑错误,需改为匹配左右两边对应同一Person的Effort:

rule EffortWithEffort
    match l : Left!Effort
    with r : Right!Effort {
    compare: l.person.name = r.person.name
}

2. 修改program.eml中的M2任务Effort过滤逻辑

通过修改TaskWithTask规则,对M2的Task进行Effort过滤,仅保留符合条件的分配:

rule TaskWithTask
    transform s : Source!Task
    to t : Target!Task {

    t.title = s.title;
    t.start = s.start;
    t.duration = s.duration;
    
    // 区分处理M1和M2的Task
    if (s.isTypeOf(Right!Task)) {
        // 仅保留M1中参与任务数>2的Person对应的Effort
        t.effort ::= s.effort->select(e | 
            Left!Person.allInstances()->select(p | p.name = e.person.name)
            ->first().eContainer().tasks->select(task | task.effort.person.name = e.person.name)->size() > 2
        );
    } else {
        // M1的Task直接复制所有Effort
        t.effort ::= s.effort;
    }
}

3. 优化Effort合并规则(可选)

若需合并同一Person在同一任务中的Effort,调整EffortWithEffort规则:

rule EffortWithEffort
    merge l : Left!Effort
    with r : Right!Effort
    into m : Merged!Effort {
    
    m.person ::= l.person;
    // 合并百分比(按需调整逻辑)
    m.percentage = l.percentage + r.percentage;
}

说明

  • 核心逻辑:通过Left!Person.allInstances()定位M1中的对应Person,统计其参与的任务数量,只有当数量超过2时才保留M2中的Effort分配。
  • 若需求为“至少参与2个任务”,将规则中的>2改为>=2即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 04:17:33