=Paper= {{Paper |id=Vol-2026/paper13 |storemode=property |title=Solving the TTC Families to Persons Case with FunnyQT |pdfUrl=https://ceur-ws.org/Vol-2026/paper13.pdf |volume=Vol-2026 |authors=Tassilo Horn |dblpUrl=https://dblp.org/rec/conf/staf/Horn17 }} ==Solving the TTC Families to Persons Case with FunnyQT== https://ceur-ws.org/Vol-2026/paper13.pdf
        Solving the TTC Families to Persons Case with FunnyQT

                                                           Tassilo Horn
                                                          tsdh@gnu.org
                                                         The GNU Project




                                                             Abstract
                           This paper describes the FunnyQT solution to the bidirectional Fami-
                           lies to Persons transformation case of TTC 2017. The solution is simple
                           and concise and passes all batch transformations and some incremental
                           tests.

    1     Introduction
    This paper describes the FunnyQT1 [Hor16, Hor15] solution of the Families to Persons case [ABW17] of TTC
    2017. With only 52 lines of declarative code, the solution is able to pass all batch transformation tests and
    some incremental tests. The solution project is available on Github2 and it is integrated into the benchmarx 3
    framework.
       FunnyQT is a model querying and transformation library for the functional Lisp dialect Clojure4 . Queries
    and transformations are Clojure functions using the features provided by the FunnyQT API.
       Clojure provides strong metaprogramming capabilities that are used by FunnyQT in order to define several
    embedded domain-specific languages (embedded DSL [Fow10]) for different querying and transformation tasks.
       FunnyQT is designed to be extensible. By default, it supports EMF [SBPM08] and JGraLab5 TGraph models.
    Support for other modeling frameworks can be added without having to touch FunnyQT’s internals.
       The FunnyQT API is structured into several namespaces, each namespace providing constructs supporting
    concrete querying and transformation use-cases, e.g., model management, functional querying, polymorphic func-
    tions, relational querying, pattern matching, in-place transformations, out-place transformations, bidirectional
    transformations, and some more. For solving the Families to Persons case, its bidirectional transformation and
    relational model querying DSLs have been used.

    2     Solution Description
    This section explains the FunnyQT solution. First, Section 2.1 explains the actual transformation solving the
    case. Then, Section 2.2 explains how the solution is integrated into the benchmarx framework.

    2.1    The Families to Persons Transformation
    As a first step, relational querying APIs for the two metamodels are generated.
1   (rel/generate-metamodel-relations "metamodels/Families.ecore" f)
2   (rel/generate-metamodel-relations "metamodels/Persons.ecore" p)

      This makes the relations for the families metamodel available with the namespace alias f and those of the
    persons metamodel with alias p. Relations are generated for every metamodel element. For example, there is a

    Copyright c by the paper’s authors. Copying permitted for private and academic purposes.
    In: A. Garcia-Dominguez, G. Hinkel and F. Krikava (eds.): Proceedings of the 10th Transformation Tool Contest, Marburg, Germany,
    21-07-2017, published at http://ceur-ws.org
        1 http://funnyqt.org   2 https://github.com/tsdh/ttc17-families2persons-bx      3 https://github.com/eMoflon/benchmarx/
        4 http://clojure.org   5 https://github.com/jgralab/jgralab
     relation (f/Family f family) which succeeds for every family in the given family model f. There is a relation
     (f/name f el n) which succeeds if el is a member or family of the family model f whose name is n. And there
     are reference relations like (f/->sons f parent child) which succeed if child is a son of parent.
        Before the transformation itself, we define a helper relation which defines the possible kinds of relationships
     between a family and a family member depending on if we prefer to create parents over creating children (parameter
     pref-parent). This is a higher-order relation in that the two remaining parameters are a parent relation prel
     (either f/->father or f/->mother) and a child relation (either f/->daughters or f/->sons).
3  (defn relationshipo [pref-parent f family member prel crel]
4    (ccl/conda
 5    [(bx/target-directiono :right)     ;; (1)
 6     (ccl/conde
 7      [(prel f family member)]
 8      [(crel f family member)])]
 9    [(bx/existing-elemento? member)]   ;; (2)
10    [(ccl/== pref-parent false)        ;; (3)
11     (crel f family member)]
12    [(bx/unseto? f family prel member) ;; (4)
13     (prel f family member)]
14    [(crel f family member)]))         ;; (5)

        ccl/conda is like a short-cutting logical disjunction. The n-th clause is only tried if all preceeding clauses fail.
     The first clause succeeds when we are transforming into the direction of the right model, i.e., the person register.
     In this case, member may be in a parental role of family (prel), or it might be in a child role (crel). We don’t
     really care but want to ensure that all members of the given family are reachable, thus we use a non-short-cutting
     ccl/conde which gives both clauses a chance to succeed.
        All other clauses deal with transforming a person model to a family model, i.e., the backward transformation.
     The second clause deals with the case where member is an already existing element, i.e., not created by the current
     execution of the transformation. Here, we assume that this member is already properly assigned to a family, so
     we simply succeed without doing anything.
        In the third clause, if we do not prefer assigning to parental roles, then the child relation crel must succeed
     between the family and the member. The child relations can always succeed because a family can have an arbitrary
     number of daughters and sons. Thus, in the remaining clauses we have to deal only with the case where assigning
     to parental roles is preferred.
        In the fourth clause, if the family’s parental role is still unset or already assigned to member, then the parental
     relation must succeed between the family and the member.
        Lastly, if no clause has succeeded until now, then the child relation has to succeed. As said, this goal6 can
     always succeed.

       In the following, the actual transformation definition is explained. It is defined using the deftransformation
     macro provided by FunnyQT.
15 (bx/deftransformation families2persons [f p prefer-parent prefer-ex-family]
16   :delete-unmatched-target-elements true
17   :id-init-fn bx/number-all-source-model-elements

         The name of the transformation is families2persons and it declares four parameters. The parameter f is
     the family model (the left model), p is the persons model (the right model), prefer-parent is a Boolean flag
     determining if we prefer creating parents to creating children, and prefer-ex-family is a Boolean flag, too,
     determining if we prefer re-using existing families over creating new families for new family members.
         By default, bidirectional FunnyQT transformations will never delete elements from the current target model,
     i.e., the model being created or modified by the synchronization. The reason for that behavior is that it allows to
     run the transformation in one direction first and then in the other direction in order to perform a full synchroniza-
     tion where missing elements are created in each of the two models. Thus, after running a transformation, e.g., in
     the direction of the right model, it is only ensured that for each element (considered by the transformation’s rules)
     in the left model, there is a corresponding counterpart in the right model. However, the right model might still
     contain elements which have no counterpart in the left model. With option :delete-unmatched-target-elements
     set to true, this behavior is changed. Elements in the current target model which are not required by the current
     source model and the transformation relations are deleted.
       6 The application of a relation is called a goal.
        The next option, :id-init-fn, has the following purpose. In this transformation case, family members and
     persons do not have some kind of unique identity. For example, it is allowed to have two members named Jim with
     the same name in the very same family Smith. However, FunnyQT BX transformations have forall-there-exists
     semantics where it would suffice to create just one person in the right model with the name set to “Smith, Jim”.
     But the case description mandates that we create one person for every member and vice versa, no matter if they
     can be distinguished based on their attribute values. For such scenarios, FunnyQT’s bidirectional transformation
     DSL provides a concept of synthetic ID attributes. The value of :id-init-fn has to be a function which returns
     a map from elements to their synthetic IDs. The built-in function bx/number-all-source-model-elements returns
     a map where every element in the source model gets assigned a unique integer number. These synthetic IDs are
     then used in a transformation relation which is discussed further below.
        The first transformation relation, family-register2person-register, transforms between family and person
     registers.
18     (^:top family-register2person-register
19      :left [(f/FamilyRegister f ?family-register)]
20      :right [(p/PersonRegister p ?person-register)]
21      :where [(member2female :?family-register ?family-register :?person-register ?person-register)
22              (member2male :?family-register ?family-register :?person-register ?person-register)])

        It is defined as a top-level rule meaning that it will be executed as the entry point of the transformation. Its
     :left and :right clauses describe that for every ?family-register there has to be a ?person-register and vice
     versa. We assume that there is always just one register in each model.
        The :where clause defines that after this relation has been enforced (or checked in checkonly mode), then the
     two transformation relations member2female and member2male have to be enforced (or tested) between the current
     ?family-register and ?person-register7 .
        The next transformation relation, member2person, describes how family members of a family contained in a
     family register in the left model correspond to persons contained in a person register in the right model. As it can
     be seen, there is no goal describing how the ?family and the ?member are connected in the :left clause and in the
     :right clause we are dealing with just a ?person of type Person which is an abstract class. As such, this relation
     is not sufficient for the complete synchronization between members in the different roles of a family to females
     and males. Instead, it only captures the aspects that are common in the cases where mothers and daughters are
     synchronized with females and fathers and sons are synchronized with males. Therefore, this relation is declared
     abstract.
23     (^:abstract member2person
24      :left [(f/->families f ?family-register ?family)
25              (f/Family f ?family)
26              (f/name f ?family ?last-name)
27              (f/FamilyMember f ?member)
28              (f/name f ?member ?first-name)
29              (id ?member ?id)
30              (ccl/conda
31               [(ccl/== prefer-ex-family true)]
32               [(bx/existing-elemento? ?member)
33                (id ?family ?last-name)]
34               [(id ?family ?id)])]
35      :right [(p/->persons p ?person-register ?person)
36              (p/Person p ?person)
37              (p/name p ?person ?full-name)
38              (id ?person ?id)]
39      :when [(rel/stro ?last-name ", " ?first-name ?full-name)])

        So what are these common aspects? Well, a ?member of a ?family (where we have not determined the role, yet)
     contained in the ?family-register passed in as parameter from family-register2person-register corresponds
     to a ?person (where we have not determined the gender, yet) contained in the ?person-register passed in as the
     other parameter from family-register2person-register. The :when clause defines that the concatenation of the
     ?family’s ?last-name, the string ", " and the ?member’s ?first-name gives the ?full-name of the ?person.
        What has not been described so far are the id goals in lines 29, and 34 and the ccl/conda goal starting in
     line 30. The first two define that the ?member and the corresponding ?person must have the same synthetic ID.
     Remember the :id-init-fn in line 17 which assigned a unique number to every element in the respective source
        7 Transformation relations are called with keyword parameters. The two calls in the :where clause state that the current

     ?family-register will be bound to the logic variable with the same name in the called relation and the same is true for the
     ?person-register.
     model of the transformation. With these synthetic IDs, the transformation is able to create one person for every
     member and vice versa even in the case where two elements are equal based on their attribute values.
         Lastly, the ccl/conda goal starting in line 30 of the :left clause handles the preference of re-using existing
     families, i.e., assigning new members to existing families, over creating new families for new members. By default,
     FunnyQT would always try to re-use an existing family. Thus, if the prefer-ex-family parameter is true, nothing
     needs to be done. Likewise, if ?member is an existing element for which we assume she is already assigned to some
     family, we can also just stick to the default behavior but define the ID of the ?family to be its name (although
     it is probably not unique). If the first two ccl/conda clauses fail, i.e., prefer-ex-family is false and ?member is
     a new member which is just going to be created by the enforcement of this relation, then we define that the ID
     of the ?family must equal to the IDs of the ?member and ?person. Thus, in this case and only in this case, new
     members force the creation of a new family even when there is already a family with the right name.
         The last two transformation relations extend the member2person relation for synchronizing between members
     in the role of a family mother or daughter and female persons and between family fathers or sons and male
     persons.
40     (member2female
41      :extends [(member2person)]
42      :left [(relationshipo prefer-parent f ?family ?member f/->mother f/->daughters)]
43      :right [(p/Female p ?person)])
44     (member2male
45      :extends [(member2person)]
46      :left [(relationshipo prefer-parent f ?family ?member f/->father f/->sons)]
47      :right [(p/Male p ?person)]))

        In the :left clauses we use the relationshipo helper relation described in the beginning of this section which
     chooses the right female or male role based on the preference parameter prefer-parent and the current state of
     the family, i.e., by checking if the respective parental role is still unset. In the two :right clauses, we only need
     to specify that the Person ?person is actually a Female or Male.
        These 33 lines of transformation specification plus the 12 lines for the relationshipo helper, and two lines
     for the generation of the metamodel-specific relational querying APIs form the complete functional parts of the
     solution. The only thing omitted from the paper are the namespace declarations8 consisting of 5 lines of code.

     2.2     Gluing the Solution with the Framework
     Typically, open-source Clojure libraries and programs are distributed as JAR files that contain the source files
     rather than byte-compiled class files. This solution does almost the same except that the JAR contains the
     solution source code, FunnyQT itself (also as sources) and every dependency of FunnyQT (like Clojure) except
     for EMF which the benchmarx project already provides.
        Calling Clojure functions from Java is really easy and FunnyQT transformations are no exception because they
     are plain Clojure functions, too. The BXTool implementation FunnyQTFamiliesToPerson extends the BXToolForEMF
     class. Essentially, it has just a static member T which is set to the transformation.
     public class FunnyQTFamiliesToPerson extends BXToolForEMF {
         private final static Keyword LEFT = (Keyword) Clojure.read(":left");
         private final static Keyword RIGHT = (Keyword) Clojure.read(":right");
         private final static IFn T; // <-- The FunnyQT Transformation
           static {
               final String transformationNamespace = "ttc17-families2persons-bx.core";
               // Clojure’s require is similar to Java’s import. However, it also loads the required
               // namespace from a source code file and immediately compiles it.
               final IFn require = Clojure.var("clojure.core", "require");
               require.invoke(Clojure.read(transformationNamespace));
               T = Clojure.var(transformationNamespace, "families2persons");
           }

        All Clojure functions implement the IFn interface and can be called using invoke(). And exactly this is done
     to call the transformation.
           private void transform(Keyword direction) {
               T.invoke(srcModel, trgModel, direction,
                        configurator.decide(Decisions.PREFER_CREATING_PARENT_TO_CHILD),
                        configurator.decide(Decisions.PREFER_EXISTING_FAMILY_TO_NEW));
           }

       This corresponds to a direct Clojure call (families2persons src trg dir prefer-parent prefer-ex-family).
       8 The Clojure equivalent of Java’s package statement and imports.
3     Evaluation and Conclusion
In this section, the test results of the FunnyQT solution are presented and classified as requested by the case
description [ABW17]. Since the bidirectional transformation DSL of FunnyQT is state-based and not incremental
at all (and by design), many of the incremental tests are mostly out of scope. However, in its core use case,
non-incremental bidirectional transformations, the solution passes all tests.
BatchForward.* All tests result in an expected pass.
BatchBwdEandP.* All tests result in an expected pass.
BatchBwdEnotP.* All tests result in an expected pass.
BatchBwdNotEandP.* All tests result in an expected pass.
BatchBwdNotEnotP.* All tests result in an expected pass.
IncrementalForward.* The solution expectedly passes the tests testStability, testHippocraticness, and
     testIncrementalInserts. All remaining tests fail expectedly because those tests require incremental abil-
     ities. For example, in some tests the birthdates are set manually in the persons model. The re-execution of
     the transformation causes deletion and re-creation of those persons, however then they get assigned default
     birthdates and not the manually edited ones as the transformation does not consider this attribute at all.
IncrementalBackward.* The               solution      expectedly      passes      the     tests      testStability,
     testIncrementalInsertsFixedConfig, testIncrementalOperational, and testHippocraticness.              The test
     testIncrementalInsertsDynamicConfig fails unexpectedly. When we neither prefer existing families nor
     assigning to parental roles, the transformation still adds the new Seymore to an existing family in a parental
     role. All other tests are expected fails due to the fact that they require incremental capabilities.
   In summary, the correctness is satisfying. There is only one test which fails unexpectedly. All other fails are
expected and can hardly be solved by a non-incremental approach.
   A very weak point of the solution is its performance. It is at least an order of magnitude slower than the
other solutions already integrated in the benchmarx project (BiGUL, eMoflon, BXtend, MediniQVT). Where
their runtimes are in the tenth of seconds or below, the FunnyQT solution takes seconds. With models in the
size of thousands of elements, you might have to wait a bit for the transformation to finish. One reason is that
the FunnyQT BX implementation is state-based and thus needs to recompute the correspondences between all
elements in the source and target models on every invocation instead of just propagating small deltas like incre-
mental approaches do. Furthermore, FunnyQT’s bidirectional transformation DSL is built upon the relational
programming library core.logic 9 which is not tuned for performance but for simplicity and extensibility of its
implementation and FunnyQT probably does not use it in the best possible way.
   Other good points of the solution are its conciseness and simplicity. With only 52 lines of code, it is by far
the most concise solution currently integrated in the benchmarx project. And it is quite simple to understand.
The only complexities it has arose from the different alternatives depending on external parameters.

References
[ABW17] Anthony Anjorin, Thomas Buchmann, and Bernhard Westfechtel. The Families to Persons Case.
        In Antonio Garcia-Dominguez, Georg Hinkel, and Filip Krikava, editors, Proceedings of the 10th
        Transformation Tool Contest, a part of the Software Technologies: Applications and Foundations
        (STAF 2017) federation of conferences, CEUR Workshop Proceedings. CEUR-WS.org, July 2017.
[Fow10]      Martin Fowler. Domain-Specific Languages. Addison-Wesley Professional, 2010.

[Hor15]      Tassilo Horn. Graph Pattern Matching as an Embedded Clojure DSL. In International Conference
             on Graph Transformation - 8th International Conference, ICGT 2015, L’Aquila, Italy, July 2015,
             2015.
[Hor16]      Tassilo Horn. A Functional, Comprehensive and Extensible Multi-Platform Querying and Transfor-
             mation Approach. PhD thesis, University Koblenz-Landau, Germany, 2016.

[SBPM08] Dave Steinberg, Frank Budinsky, Marcelo Paternostro, and Ed Merks. EMF: Eclipse Modeling Frame-
         work. Addison-Wesley Professional, 2 edition, 2008.


    9 https://github.com/clojure/core.logic