=Paper=
{{Paper
|id=Vol-2543/rpaper01
|storemode=property
|title=On Deterministic Parallel Implementation of
the Branch-and-Bound Method with Monotonic Objects
|pdfUrl=https://ceur-ws.org/Vol-2543/rpaper01.pdf
|volume=Vol-2543
|authors=Alexei Adamovich,Andrei Klimov
|dblpUrl=https://dblp.org/rec/conf/ssi/AdamovichK19
}}
==On Deterministic Parallel Implementation of
the Branch-and-Bound Method with Monotonic Objects==
On Deterministic Parallel Implementation of the Branch-and-Bound Method with Monotonic Objects Alexei Adamovich1[0000-0003-1392-8871] and Andrei Klimov2[0000-0003-0418-7311] 1 Ailamazyan Program Systems Institute of RAS, Peter I str., 4a, selo Veskovo, Pereslavl-Zalessky, Yaroslavl region, 152021, Russia 2 Keldysh Institute of Applied Mathematics of RAS, Miusskaya sq., 4, Moscow, 125047, Russia klimov@keldysh.ru Abstract. This paper continues the authors’ research into the development of a system of deterministic parallel programming and the creation of libraries of so- called monotonic classes. The system is two-level and uses two input lan- guages: a universal object-oriented language like Java for the implementation of monotonic classes, which makes up the lower-level subsystem, and a higher- level functional language with the ability to create and use immutable and mon- otonic objects. The libraries of monotonic classes ensure that all programs in the higher-level language that use only monotonic classes are deterministic and idempotent when they are parallelized by asynchronous calls of all functions. An important part of the development of such a system is the creation of mono- tonic class libraries for various fields of application and the demonstration of solutions to several applied problems using them. This paper is devoted specifi- cally to implementing the search for the minimum weight of paths in a graph by the branch-and-bound method. We provide a solution referred to as conditional- ly monotonic, where the monotonicity holds only for nonnegative edge weights. The problem of the exact implementation of the branch-and-bound method with monotonic objects is stated. Keywords: Models of Parallel Computation, Deterministic Programs, Mono- tonic Objects, Branch-and-Bound Method. 1 Introduction 1.1 The General Problem The problem discussed in this article belongs to the following general direction: building a system and class library for deterministic parallel and concurrent pro- gramming based on object-oriented languages. The system developed by the authors is intended for programming only those tasks that give a deterministic result, and for that part of them that allow parallel and con- current implementation in the form of a deterministic program by means of this sys- tem. We explore object-oriented programming in languages such as Java using threads, including light-weight threads, fibers, and coroutines. Currently, the princi- Copyright © 2020 for this paper by its authors. Use permitted under Creative Commons License Attribution 4.0 International (CC BY 4.0). 2 ples of constructing a system are inapplicable to numerical problems with specific programming tools based on MPI, OpenMP, etc., and do not overlap with the domain and methods of, e.g., the Norma language [7] for declarative and deterministic pro- gramming of such problems. The goal is to provide the application programmer with object-oriented language tools and libraries, so that, when programming with their use, any program is guaran- teed to be deterministic and well scalable on parallel hardware. However, there is no finite and complete set of tools that can be fixed once and for all and provided in the top-level language so that all programs in it are deterministic and use all the variety of parallel programming tools. Therefore, the system should be open for the convenience of creating new domain-specific libraries. The literature on the development of various deterministic parallel programming tools demonstrates (see our review [5]) that they are generally implemented in low- level languages (such as C or VHDL), providing high-level tools for the application programmer1. It turns out that in order to implement new means, it is necessary to use the lower level with high labor costs. The task is to raise the system library development tools to a fairly high level of an object-oriented language such as Java, providing the application developer with a subset of tools, which guarantee the determinacy of her programs. To advance in this direction, a project of a two-level programming system was proposed in articles [5, 6] and explained in Section 2. This paper continues the series of works of the authors [2-6,11] on deterministic parallel programming and is based on our earlier work on the T-system [1] and mono- tonic objects [8,12]. The notion of monotonic classes and objects implies two proper- ties: determinacy and idempotency of user programs. The idempotency is of great practical importance for ensuring fault tolerance of parallel and distributed systems. We share the goals of the authors of the article with the self-explanatory title “Par- allel Programming Must Be Deterministic by Default” [14], but we offer other means for solving it. Our approach resembles the work [17, 18] on the determinacy of paral- lel computing with shared data belonging to some semilattices2 but we generalize it in the framework of object-oriented languages. Our work contributes to solving one more fundamental problem: building a model of computation between functional and object-oriented languages. It allows for ex- plicit references to objects which can mutate (albeit in a disciplined way). At the same time the basic properties of functional languages are preserved: determinacy, idempo- tency, the existence of a kind of denotational semantics, and some adequate replace- ment of referential transparency, which is broken by side effects and the operators of object creation, which generate new references. 1 A case in point: The libraries of parallel and concurrent programming of the purely functional language Haskell [19] are implemented using low-level means that are inexpressible in Haskell itself. 2 https://en.wikipedia.org/wiki/Semilattice 3 1.2 The Specific Problem A significant part of the system we are developing is libraries of monotonic classes for various problem domains, the use of which guarantees determinacy and idempo- tency. This library is accumulated in the process of solving samples of applied prob- lems. The first set of notions required in many tasks is a way to efficiently represent graphs. This is natural in usual object-oriented programming but is nontrivial when implemented with monotonic objects. In [11], the problem of constructing cyclic data structures with monotonic objects is explained by examples, and the solutions are demonstrated. Here explicit references are used to represent the relationships between vertices and edges of graphs, as in object-oriented programming. Notice that this is not available in purely functional languages (where the main data structure is trees 3). These constructs are needed for many programs. In this paper, we consider a specific task — to find the minimum weight of simple4 paths in a graph from a given vertex. The edges of the graph are labeled with non- negative weights, and the weight of a path is defined as the sum of the weights of its constituent edges. This problem has many variations. A wide-spread version: the paths that end in the second given vertex are examined. In our experimental study, for the convenience of measuring the scalability of the program executed on a multicore system, we took another version, in which all simple paths of a fixed length from a given vertex, without fixing their end, are explored. This kind of algorithms is well parallelized and is deterministic by nature. The pro- cesses that enumerate various paths communicate via a shared variable that stores the minimum weight found to date. A process that has found a shorter path assigns a new weight to the variable. As the minimum on a finite set of numbers is unequivocal, in order to prove the correctness and determinacy of the algorithm implementation, one only has to ensure that all paths (or enough of them) are visited. The classic way to solve this problem is the branch-and-bound method5. Its core idea is the pruning operation, which cancels the current partial path when its weight exceeds or equates to the minimum reached so far. Here, the main subtlety is that the comparison operation with the current minimum is nonmonotonic, and hence cannot be directly used in the higher-level language. Therefore, it must be “hidden” inside a monotonic object. 3 The work [13] proposes an “efficient” graph representation in the functional language Haskell, but we consider it a “non-solution”. A representation of graphs in the form of lists of vertices and edges (that is, in the form of trees) is given, and then it is suggested that an efficient representation with the same operations is implemented by low-level means. 4 In graph theory, a path without self-intersection is called simple. 5 https://en.wikipedia.org/wiki/Branch_and_bound 4 1.3 Contribution We describe an implementation of the branch-and-bound method satisfying the fol- lowing requirements: the top-level part of the algorithm is written in a functional language and is paral- lelized by asynchronous calls of all (or part of) the functions; monotonic objects are used for the communication between processes; the determinacy of a user program in the higher-level language is guaranteed by the implementation of monotonic classes; the difference between the versions of the program, first, with the complete enu- meration of paths and, second, with pruning by the branch-and-bound method, is implemented in one place inside a monotonic object. This simplifies proving the equivalence of the versions and the correctness of the program with pruning. The presented solution demonstrates the use of a higher-order monotonic object, that is, with an operation that takes a lambda expression as an argument. We assume that without a higher-order operation, it is impossible to implement the branch-and- bound method with monotonic objects. 1.4 Outline In Section 2 we explain the goals and principles of constructing a two-level system of deterministic parallel programming. Section 3 gives the definition of monotonic ob- jects and classes. Section 4 is the main one: it presents a program for finding the min- imum weight of paths from a given vertex of a graph, implemented according to our approach. In Section 5, we find out that this solution does not exactly meet the mono- tonicity conditions and is just conditionally monotonic, depending on the non- negativity of the edge weights, and we explain why an exact solution should be sought. Related work is discussed in Section 6. In Section 7 we conclude. 2 A Two-Level System of Deterministic Parallel Programming The principles of constructing the system for deterministic parallel programming are applicable for any mature object-oriented language that satisfies the following re- quirements: The object-oriented language must have a functional subset. The presence of suita- ble syntactic sugar (e.g., lambda expressions) is desirable, but not necessary. It should be possible to implement the verifier that checks that a program belongs to the functional subset (without this, guarantees of determinacy would be lost), or to implement a domain-specific language translated to the functional subset. Automatic memory management and garbage collection should be present in the implementation of the object-oriented language. Without these, it is impossible to 5 program in the functional style. For example, languages on the JVM and MS.NET platforms are suitable. Parallel and concurrent programming tools should be present, that allow the im- plementation of asynchronous function calls and their synchronization on access to shared data. We are prototyping the system using the JVM platform, the Java and Kotlin6 lan- guages, the Ajl language developed by ourselves [3], the Quasar7 library that imple- ments light-weight threads, fibers, on the JVM. We also follow the development of the Loom project8, which will be more tightly integrated with Java than Quasar and will eventually be included in the standard JVM. We develop our language tools in the Eclipse9 IDE. Since the goal of the project is twofold — to provide both guaranteed deterministic programming to the application developer, and the open lower level to parallel pro- gramming experts who can use all the means of the object-oriented language, — the input language must be distinctly subdivided into two parts, guaranteed deterministic and indeterministic: The upper level is the deterministic part, where application programmers write program code in a functional subset. Here, the determinacy of any program that us- es the libraries specially prepared at the lower level, is guaranteed. The lower level is the potentially indeterministic part, where qualified program- mers create class libraries for specific application domains in a universal object- oriented language using all indeterministic parallel programming tools. The library authors are responsible to the users of the higher level for the determinacy of paral- lel programs. 3 The Notion of a Monotonic Class and Object We refer to objects and classes defined in the lower-level language and used in the upper-level functional language as monotonic, since their state changes monotonically in some semilattice, which, as a rule, can be constructed using the class code. Howev- er, the formal definition, which is convenient to use in reasoning about programs and proving their properties, is given operationally below [6,8,12]. Monotonic objects and classes are such that, when they are created and used in any program in a functional language, all expressions satisfy the following two properties: Determinacy: the results obtained by parallel computation (in any possible order) of an expression several times from the same initial state, are equivalent, and their side effects are indistinguishable programmatically in the functional language. 6 http://kotlin.jetbrains.org/ 7 https://github.com/puniverse/quasar 8 https://wiki.openjdk.java.net/display/loom/Main 9 https://www.eclipse.org/ 6 Idempotency: simultaneous parallel computation of two copies of an expression instead of one, produces the equivalent results and the side effect is indistinguisha- ble programmatically in the functional language from the side effect of one compu- tation. These properties must be satisfied simultaneously for all monotonic classes when they are used together in any functional program. At present, we are constructing monotonic classes, using these properties informal- ly and naively. In the future, we expect that computer-assisted verification tools for proving monotonicity will be developed. Although fully automatic tools for all cases cannot be built, as in the general case of program verification, we hope that this is achievable for most practical definitions of monotonic classes. 4 Deterministic Parallel Implementation of the Branch-and- Bound Method with a Monotonic Object In this section, a deterministic parallel implementation of the algorithm that finds the minimum weight of a path in a graph from a given vertex, is presented. The pseudo- code in Fig. 1 is written in a Java/Kotlin-like syntax10. The code in Fig. 1 uses the following classes (only those operations11 are listed that are used in the code): Immutable class Graph represents a graph. The single Graph instance is stored in a global variable graph. The objects of classes Vertex and Edge access it to perform their operations. Immutable class Vertex represents vertices with the following operation: ─ function vertex.outgoingEdges returns an Iterator over the list of edges outgoing from the vertex. Immutable class Edge represents edges with the following operation: ─ function edge.endVertex returns the end vertex of the edge (that is, the vertex, for which this edge is incoming). Immutable class Path represents paths in the graph with the following operations: ─ predicate path.isComplete checks whether the path is completed, e.g., has a giv- en length or has reached a given vertex, depending on the problem statement; ─ predicate path.contains(vertex) checks whether the path contains the vertex; ─ function path.weight returns the path weight, that is, the sum of the weights of its edges; 10 As compared to Java, we omit empty parameters at the end of invocation as in Kotlin, braces and semicolons. 11 We avoid using the object-oriented term “method” for operations of classes and call them functions (with a value), procedures (without a value) and operations in classes and objects, in order not to be confused with the general meaning of the term “method”, as in: “the branches-and-bound method.” For the invocations of functions and procedures, we use the object-oriented syntax: x.f instead of f (x) and x.f (y) instead of f (x, y). 7 Input and initial state Graph graph — the global variable that references to the graph representation, used in the classes Vertex and Edge Vertex root — an initial vertex from which the examined paths start Minimizer minimizer — a global variable with the monotonic object that computes the minimum of a finite set of numbers, in the initial state “negative infinity” Initial invocation of the recursive procedure findMinimumPathWeight findMinimumPathWeight(root) Recursive procedure findMinimumPathWeight findMinimumPathWeight(Path path) if (path.isComplete) minimizer.addValue(path.weight) else minimizer.branch(path.weight, () -> for (Edge edge : path.lastVertex.outgoingEdges) if (!path.contains(edge.endVertex)) findMinimumPathWeight(path.extendedWith(edge)) ) Returning result after the completion of the findMinimumPathWeight procedure minimizer.minimum returns the minimum weight Fig. 1. The program to find the minimum weight of paths from the initial edge root, with the monotonic object minimizer ─ function path.lastVertex returns the last vertex visited in the path; ─ function path.extendedWith(edge) returns a path object obtained by adding the edge to the end of the path. Monotonic class Minimizer has the single instance stored in the global variable minimizer, with the following operations: ─ function minimizer.minimum returns the minimum among the numbers sent to the minimizer, after the findMinimumPathWeight procedure completes (see dis- cussion below); ─ procedure minimizer.addValue(value) adds the number value to the set from which the minimum is taken; ─ procedure minimizer.branch(pathWeight, step) executes the continuation step, which is a lambda expression without arguments and value. In the version with pruning (corresponding to the branch-and-bound method proper), step is not computed of pathWeight is greater than the current minimum. 8 In Fig. 1, the findMinimumPathWeight procedure recursively searches for the min- imum path weight among the completed paths from a given vertex root. The proce- dure findMinimumPathWeight has no result and accumulates the result by side effects — by writing path.weight to the monotonic object minimizer by calling minimizer .addValue(path.weight). This algorithm may be executed sequentially, but it can be easily parallelized by running all calls to the findMinimumPathWeight procedure asynchronously and waiting for all findMinimumPathWeight processes to complete before the minimizer.minimum function returns the result. For experts on the branch and bound method, the algorithm in Fig. 1 looks natural and does not seem to contain anything tricky. Indeed, it is close to the Wikipedia article12 except for the order of some code pieces. A notable difference is the higher order minimizer.branch procedure with the lambda expression in the second argument step. It has no explicit arguments, taking the path and minimizer values from the sur- rounding context. Note the syntax “() ->” in bold. The code of the findMinimumPathWeight procedure is suitable for exhaustive search of all paths, as well as for pruning by the branch-and-bound method. The vari- ants are selected by varying the code of minimizer.branch operation inside the mono- tonic class Minimizer: in the former case, step is always executed; in the latter case with pruning, step is not executed when the current path.weight is greater than or equal to the current minimum weight of the paths passed. The code in Fig. 1 is imperfect in some respects. First, it does not yet satisfy all the requirements of monotonicity. This is discussed in Section 5. Second, the minimizer object has the following semantic subtlety: the result of min- imizer.minimum must be returned only after all findMinimumPathWeight processes have completed. In the real-world implementations of the branch-and-bound method, a synchronization barrier is puts here that fits poorly into the theory of monotonic objects (although local deviations from the “high theory” are natural in practice). Each of the following two solutions is better suited to the world of monotonic objects. A pragmatic solution. An asynchronous procedure invocation returns a handler ob- ject, the waitAll operation on which ensures that all processes created by this invoca- tion have completed. After the operation returns, the minimizer.minimum function can be invoked. This solution is not consistent with the principles stated in Section 2, because re- quires certain programming style. A theoretically consistent solution. Two kinds of references to monotonic objects are to be distinguished: 1. A reference of the general “write” kind allows the operations to mutate (monoton- ically) the state of the referenced object and that of the objects recursively accessi- ble through it. 12 https://en.wikipedia.org/wiki/Branch_and_bound 9 2. A reference of the “read-only” kind allows only retrieving information from the objects without programmatically visible mutations. With this solution, the findMinimumPathWeight procedure would use a “write” reference in the minimizer object, and the minimizer.minimum function would use a “read-only” reference. An operation on a “read-only” reference completes only when all the “write” references to this object disappear (or for some semantic reasons it becomes clear that the result of this operation can no longer be changed). This can be implemented either by reference counters, or by means of “weak references” and garbage collection. The first alternative with reference counters is only suitable under the assumption that cyclic structures are not formed. The second alternative with gar- bage collection is generally correct by less efficient. Both alternatives do not violate monotonicity. 5 Non-monotonicity of This Version of the Algorithm Now we have to make the main statement that the Minimizer class with the given semantics is monotonic, that is, any functional program that uses it is deterministic and idempotent. However, we can state this only for the first variant of the minimizer .branch operation considered above, where step is always executed and hence the exhaustive search is performed. But this is not the branch-and-bound method, which we are interested in. In the version with pruning by to the branch-and-bound method, it must be ensured that the recursive calls to findMinimumPathWeight in the lambda expression for step wittingly increase the weight of the current path. Now this can be ensured either by the precondition that the weights of all edges are non-negative, or by the path.extendedWith(edge) function, which would check that the weight of the edge is non-negative and hence the weight of the path does not decrease. In both cases, the guarantees are given outside of the Minimizer class, while our definition of mono- tonicity implies the determinacy and idempotency of any higher-level program. Therefore, this solution is just conditionally monotonic, that is, monotonic with the requirement that an external condition is satisfied. In this paper, we leave open the question of constructing a truly monotonous im- plementation of the branch-and-bound method. This is our future work. 6 Related Works A survey of the works on deterministic parallel programming that we are aware of, is given in [5]. Here we review only two of the most closely related approaches. The goal of the first approach is like ours: deterministic parallel programming in an object-oriented language. But it fundamentally differs in the methods for achieving it. In a series of works, of which we single out one with the self-explanatory title [14], their authors develop a static analysis of programs in Java with certain extensions, called Deterministic Parallel Java, DPJ. The analysis determines the cases where side 10 effects do not lead to indeterminacy. The language extensions enable the programmer to provide additional information to the analysis. These methods are further develop- ment of the typing systems that take side effects into account (effect systems13). We do not explore this further here, since in our approach no static analysis is used. The second approach is close to ours in both goals and methods. It is based on monotonic changes of shared variables. This idea is quite old and has been already implemented in various specific cases. Their common idea is that, to communicate parallel processes, special data structures are used such that determinacy is not violat- ed. Below are the most well-known of them: I-structures [10]; Kahn networks [15]; TStreams, Concurrent Collections [16]; lattice-based data structures [17,18]. These (and our) approaches have a common feature: variables via which parallel processes communicate, change their state monotonically, only upwards on some semilattice from the undefined state (⊥) to more and more defined ones. The upper element of the lattice (⊤) means “over-defined” value; this corresponds to an error, an exception in program code. For example, the set of values of an I-structure with inte- ger values is described by the lattice that consists of the lower element “undefined” (⊥), incomparable integers and the upper element “over-defined” (⊤). When the value y is assigned to a variable with a value x, the smallest upper bound of the values x and y is stored in it. If the result is the upper element ⊤, an exception is thrown. This idea was elaborated in the PhD thesis by Lindsey Kuper [17] and in publica- tions together with her colleagues [18]. They proved the determinacy of parallel exe- cution of processes communicating via variables that take values from an arbitrary semilattice. In our work, we use these ideas and generalize them to objects with mon- otonically changing states, having given them the operational definition rather then through lattices. In our future work, we should compare the verification technique of the implemen- tation of the branch-and-bound method according to our approach and the existing proofs of its correctness, e.g., described in [9]. 7 Conclusion The task of developing libraries of so-called monotonic classes within a two-level object-oriented deterministic parallel programming system was discussed. In this system, the higher-level language is close to a functional language that allows for parallelization of all functions by asynchronous calls. Processes communicate via monotonic objects, whose classes are defined in the lower-level language, which is a mature object-oriented language with parallel and concurrent programming means. 13 https://en.wikipedia.org/wiki/Effect_system 11 The implementation of monotonic classes guarantees the determinacy and idempoten- cy of all programs in the higher-level language. In the framework of such a general approach, this article is devoted to solving a particular problem — the implementation of the search for the minimum path weight in a graph among the paths from a given vertex, using the monotonic object that com- putes the minimum of the numbers sent to it. The presented solution is just condition- ally monotonic, as it requires that the input graph is checked preliminarily, to ensure that the weights of the edges are non-negative. The open problem of completely im- plementing the branch-and-bound method using monotonic objects has been posed. The solution should guarantee the determinacy of any higher-level program, in such way that all necessary checks are done in the code of monotonic classes. Acknowledgements. We express our gratitude to our English teacher, Philippa Jeph- son, who helped us edit this paper, fix a lot of errors and turn it into a much more readable form. The remaining glitches are ours. This work was carried out with the financial support of the Ministry of Education and Science of Russia (grant No. RFMEFI61319X0092). References 1. Abramov, S.M., Adamovich, A.I., Kovalenko, M.R.: T-System — An Environment Sup- porting Automatic Dynamic Parallelization of Programs: An Example of the Implementa- tion of an Image Rendering Algorithm Based on the Ray Tracing Method. Programmiro- vanie 25(2), 100–107 (1999). (In Russian). 2. Adamovich, A.I.: Fibers as the Basis for the Implementation of the Notion of the T- Process for the JVM Platform. Program Systems: Theory and Applications 6(4), 177–195 (2015). doi:10.25209/2079-3316-2017-8-4-221-244. (In Russian). 3. Adamovich, A.I.: The Ajl Programming Language: The Automatic Dynamic Paralleliza- tion for the JVM Platform // Program Systems: Theory and Applications 7(4), 83–117 (2016). doi:10.25209/2079-3316-2016-7-4-83-117. (In Russian). 4. Adamovich, A.I., Klimov, And.V.: On Experience of Using the Metaprogramming Devel- opment Environment Eclipse/TMF for Construction of Domain-Specific Languages. In: Nauchny`j servis v seti Internet : Trudy` XVIII Vserossijskoj nauchnoj konferencii, pp. 3– 8. Keldysh Institute of Appl. Math. of RAS, Moscow, Russia (2016). doi:10.20948/abrau- 2016-45. (In Russian). 5. Adamovich, A.I., Klimov, And.V.: How to Create Deterministic by Construction Parallel Programs? Problem Statement and Survey of Related Works. Program Systems: Theory and Applications 8(4), 221–244 (2017). doi:10.25209/2079-3316-2017-8-4-221-244. (In Russian). 6. Adamovich, A.I., Klimov, And.V.: An Approach to Deterministic Parallel Programming System Construction Based on Monotonic Objects. Vestnik SibGUTI 2019(3), 14–26 (2019). URL: http://vestnik.sibsutis.ru/showpapper.php?act=showpapper&id=870. (In Russian). 7. Andrianov, A.N., Baranova, T.P., Bugerya, A.B., Yefimkin, K.N.: Nonprocedural NORMA language translation for GPUs. Keldysh Institute Preprints 2016(73), 1–24 (2016) doi:10.20948/prepr-2016-73. 12 8. Klimov, And.V.: Deterministic Parallel Computation with Monotonic Objects. In: Nauch- ny`j servis v seti Internet: mnogoyaderny`j komp`yuterny`j mir : Trudy` Vserossijskoj nauchnoj konferencii, pp. 212–217. Izd-vo Moskovskogo universiteta, Moscow, Russia (2007). 9. Shilov N.V.: Verification of Backtracking and Branch and Bound Design Templates. Modeling and Analysis of Information Systems 18(4), 168–180 (2011). URL: https://www.mais-journal.ru/jour/article/view/1107/820. 10. Arvind, Nikhil, R.S., Pingali, K.K.: I-structures: Data Structures for Parallel Computing. ACM Trans. Program. Lang. Syst. 11(4), 598–632 (1989). doi:10.1145/69558.69562. 11. Adamovich, A.I., Klimov, And.V.: Building Cyclic Data in a Functional-Like Language Extended with Monotonic Objects. In: X Workshop PSSV: Program Semantics, Specifica- tion and Verification: Theory and Applications (Novosibirsk, Akademgorodok, Russia, Ju- ly 1–2, 2019) : Abstracts, pp. 11-19. A.P. Ershov Institute of Informatics Systems, Novo- sibirsk, Russia (2019). ISBN 978-5-4437-0918-5. 12. Klimov, And.V.: Dynamic Specialization in Extended Functional Language with Mono- tone Objects. SIGPLAN Not. 26(9), 199–210 (1991). doi:10.1145/115865.376287. 13. Erwig, M.: Inductive graphs and functional graph algorithms. J. Funct. Program. 11 (5), 467–492 (2001). doi:10.1017/S0956796801004075. 14. Bocchino, R.L. (Jr.), Adve, V.S., Adve, S.V., Snir, M.: Parallel Programming Must Be De- terministic by Default. In: Fifth USENIX Conference on Hot Topics in Parallelism, Hot- Par’09, pp. 4–4 (6 pages). USENIX Association (2009). 15. Kahn, G.: The Semantics of Simple Language for Parallel Programming. In: IFIP Con- gress, pp. 471–475 (1974). 16. Burke, M.G., Knobe, K., Newton, R., Sarkar, V.: Concurrent Collections Programming Model. In: Encyclopedia of Parallel Computing, pp. 364–371. Springer US (2011). doi:10.1007/978-0-387-09766-4_238. 17. Kuper, L.: Lattice-based Data Structures for Deterministic Parallel and Distributed Pro- gramming. Ph.D. Thesis. 253 pages. Indiana University, IN, USA (2015). 18. Kuper, L., Todd, A., Tobin-Hochstadt, S., Newton, R.R.: Taming the Parallel Effect Zoo: Extensible Deterministic Parallelism with LVish. ACM SIGPLAN Not. 49(6), 2–14 (2014). doi:10.1145/2666356.2594312. 19. Marlow, S.: Parallel and Concurrent Programming in Haskell. 322 pages. O'Reilly Media, CA, USA (2013).