Jelajahi Sumber

doc: graph.md

Michele Caini 3 tahun lalu
induk
melakukan
31dc732a74
1 mengubah file dengan 50 tambahan dan 50 penghapusan
  1. 50 50
      docs/md/graph.md

+ 50 - 50
docs/md/graph.md

@@ -23,15 +23,15 @@
 
 `EnTT` doesn't aim to offer everything one needs to work with graphs. Therefore,
 anyone looking for this in the _graph_ submodule will be disappointed.<br/>
-Quite the opposite is true. This submodule is minimal and contains only the data
-structures and algorithms strictly necessary for the development of some tools
-such as the _flow builder_.
+Quite the opposite is true though. This submodule is minimal and contains only
+the data structures and algorithms strictly necessary for the development of
+some tools such as the _flow builder_.
 
 # Data structures
 
 As anticipated in the introduction, the aim isn't to offer all possible data
 structures suitable for representing and working with graphs. Many will likely
-be added or refined over time, however I want to discourage anyone expecting
+be added or refined over time. However I want to discourage anyone expecting
 tight scheduling on the subject.<br/>
 The data structures presented in this section are mainly useful for the
 development and support of some tools which are also part of the same submodule.
@@ -49,7 +49,7 @@ The `directed_tag` type _creates_ the graph as directed. There is also an
 `undirected_tag` counterpart which creates it as undirected.<br/>
 The interface deviates slightly from the typical double indexing of C and offers
 an API that is perhaps more familiar to a C++ programmer. Therefore, the access
-and modification of an element will take place via the `contains`, `insert` and
+and modification of an element takes place via the `contains`, `insert` and
 `erase` functions rather than a double call to an `operator[]`:
 
 ```cpp
@@ -60,14 +60,14 @@ if(adjacency_matrix.contains(0u, 1u)) {
 }
 ```
 
-Both `insert` and` erase` are idempotent functions which have no effect if the
+Both `insert` and` erase` are _idempotent_ functions which have no effect if the
 element already exists or has already been deleted.<br/>
 The first one returns an `std::pair` containing the iterator to the element and
-a boolean value indicating whether the element has been inserted or was already
-present. The second one instead returns the number of deleted elements (0 or 1).
+a boolean value indicating whether the element was newly inserted or not. The
+second one returns the number of deleted elements (0 or 1).
 
-An adjacency matrix must be initialized with the number of elements (vertices)
-when constructing it but can also be resized later using the `resize` function:
+An adjacency matrix is initialized with the number of elements (vertices) when
+constructing it but can also be resized later using the `resize` function:
 
 ```cpp
 entt::adjacency_matrix<entt::directed_tag> adjacency_matrix{3u};
@@ -82,8 +82,8 @@ for(auto &&vertex: adjacency_matrix.vertices()) {
 }
 ```
 
-Note that the same result can be obtained with the following snippet, since the
-vertices are unsigned integral values:
+The same result is obtained with the following snippet, since the vertices are
+plain unsigned integral values:
 
 ```cpp
 for(auto last = adjacency_matrix.size(), pos = {}; pos < last; ++pos) {
@@ -93,8 +93,8 @@ for(auto last = adjacency_matrix.size(), pos = {}; pos < last; ++pos) {
 
 As for visiting the edges, a few functions are available.<br/>
 When the purpose is to visit all the edges of a given adjacency matrix, the
-`edges` function returns an iterable object that can be used to get them as
-pairs of vertices:
+`edges` function returns an iterable object that is used to get them as pairs of
+vertices:
 
 ```cpp
 for(auto [lhs, rhs]: adjacency_matrix.edges()) {
@@ -102,8 +102,8 @@ for(auto [lhs, rhs]: adjacency_matrix.edges()) {
 }
 ```
 
-On the other hand, if the goal is to visit all the in- or out-edges of a given
-vertex, the `in_edges` and `out_edges` functions are meant for that:
+If the goal is to visit all the in- or out-edges of a given vertex instead, the
+`in_edges` and `out_edges` functions are meant for that:
 
 ```cpp
 for(auto [lhs, rhs]: adjacency_matrix.out_edges(3u)) {
@@ -111,11 +111,11 @@ for(auto [lhs, rhs]: adjacency_matrix.out_edges(3u)) {
 }
 ```
 
-As might be expected, these functions expect the vertex to visit (that is, to
-return the in- or out-edges for) as an argument.<br/>
+Both the functions expect the vertex to visit (that is, to return the in- or
+out-edges for) as an argument.<br/>
 Finally, the adjacency matrix is an allocator-aware container and offers most of
-the functionality one would expect from this type of containers, such as `clear`
-or 'get_allocator` and so on.
+the functionalities one would expect from this type of containers, such as
+`clear` or 'get_allocator` and so on.
 
 ## Graphviz dot language
 
@@ -129,19 +129,19 @@ std::ostringstream output{};
 entt::dot(output, adjacency_matrix);
 ```
 
-However, there is also the option of providing a callback to which the vertices
-are passed and which can be used to add (`dot`) properties to the output from
-time to time:
+It's also possible to provide a callback to which the vertices are passed and
+which can be used to add (`dot`) properties to the output as needed:
 
 ```cpp
 std::ostringstream output{};
+
 entt::dot(output, adjacency_matrix, [](auto &output, auto vertex) {
     out << "label=\"v\"" << vertex << ",shape=\"box\"";
 });
 ```
 
 This second mode is particularly convenient when the user wants to associate
-data managed externally to the graph being converted.
+externally managed data to the graph being converted.
 
 # Flow builder
 
@@ -155,42 +155,42 @@ specified.<br/>
 Most of the functions in the API also return the flow builder itself, according
 to what is the common sense API when it comes to builder classes.
 
-Once all tasks have been registered and resources assigned to them, an execution
-graph in the form of an adjacency matrix is returned to the user.<br/>
+Once all tasks are registered and resources assigned to them, an execution graph
+in the form of an adjacency matrix is returned to the user.<br/>
 This graph contains all the tasks assigned to the flow builder in the form of
-_vertices_. The _vertex_ itself can be used as an index to get the identifier
-passed during registration.
+_vertices_. The _vertex_ itself is used as an index to get the identifier passed
+during registration.
 
 ## Tasks and resources
 
 Although these terms are used extensively in the documentation, the flow builder
 has no real concept of tasks and resources.<br/>
 This class works mainly with _identifiers_, that is, values of type `id_type`.
-That is, both tasks and resources are identified by integral values.<br/>
+In other terms, both tasks and resources are identified by integral values.<br/>
 This allows not to couple the class itself to the rest of the library or to any
 particular data structure. On the other hand, it requires the user to keep track
 of the association between identifiers and operations or actual data.
 
-Once a flow builder has been created (which requires no constructor arguments),
-the first thing to do is to bind a task. This will indicate to the builder who
-intends to consume the resources that will be specified immediately after:
+Once a flow builder is created (which requires no constructor arguments), the
+first thing to do is to bind a task. This tells to the builder _who_ intends to
+consume the resources that are specified immediately after:
 
 ```cpp
 entt::flow builder{};
 builder.bind("task_1"_hs);
 ```
 
-Note that the example uses the `EnTT` hashed string to generate an identifier
-for the task.<br/>
-Indeed, the use of `id_type` as an identifier type is not by accident. In fact,
+The example uses the `EnTT` hashed string to generate an identifier for the
+task.<br/>
+Indeed, the use of `id_type` as an identifier type isn't by accident. In fact,
 it matches well with the internal hashed string class. Moreover, it's also the
 same type returned by the hash function of the internal RTTI system, in case the
 user wants to rely on that.<br/>
 However, being an integral value, it leaves the user full freedom to rely on his
-own tools if he deems it necessary.
+own tools if necessary.
 
-Once a task has been associated with the flow builder, it can be assigned
-read-only or read-write resources, as appropriate:
+Once a task is associated with the flow builder, it's also assigned read-only or
+read-write resources as appropriate:
 
 ```cpp
 builder
@@ -203,7 +203,7 @@ builder
 
 As mentioned, many functions return the builder itself and it's therefore easy
 to concatenate the different calls.<br/>
-Also in the case of resources, these are identified by numeric values of type
+Also in the case of resources, they are identified by numeric values of type
 `id_type`. As above, the choice is not entirely random. This goes well with the
 tools offered by the library while leaving room for maximum flexibility.
 
@@ -217,10 +217,10 @@ before or after another task.<br/>
 In fact, the order of _registration_ on the resources also determines the order
 in which the tasks are processed during the generation of the execution graph.
 
-However, there is a way to force the execution order of two processes.<br/>
+However, there is a way to _force_ the execution order of two processes.<br/>
 Briefly, since accessing a resource in opposite modes requires sequential rather
-than parallel scheduling, it's possible to make use of fake resources to force
-the order execution:
+than parallel scheduling, it's possible to make use of fake resources to rule on
+the execution order:
 
 ```cpp
 builder
@@ -235,10 +235,10 @@ builder
         .ro("fake"_hs)
 ```
 
-This snippet forces the execution of `task_2` and `task_3` **after** `task_1`.
-This is due to the fact that the latter sets a read-write requirement on a fake
+This snippet forces the execution of `task_1` **before** `task_2` and `task_3`.
+This is due to the fact that the former sets a read-write requirement on a fake
 resource that the other tasks also want to access in read-only mode.<br/>
-Similarly, it's possible to force a task to run after a certain group:
+Similarly, it's possible to force a task to run **after** a certain group:
 
 ```cpp
 builder
@@ -261,7 +261,7 @@ others tasks.
 
 Sometimes it's useful to assign the role of _sync point_ to a node.<br/>
 Whether it accesses new resources or is simply a watershed, the procedure for
-assigning this role to a vertex is always the same: first it's tied to the flow
+assigning this role to a vertex is always the same. First it's tied to the flow
 builder, then the `sync` function is invoked:
 
 ```cpp
@@ -283,7 +283,7 @@ all specified constraints to return the best scheduling for the vertices:
 entt::adjacency_matrix<entt::directed_tag> graph = builder.graph();
 ```
 
-The search for the main vertices, that is those without in-edges, is usually the
+Searching for the main vertices (that is, those without in-edges) is usually the
 first thing required:
 
 ```cpp
@@ -294,6 +294,6 @@ for(auto &&vertex: graph) {
 }
 ```
 
-Starting from them, using the other functions appropriately (such as `out_edges`
-to retrieve the children of a given task or `edges` to access their identifiers)
-it will be possible to instantiate an execution graph.
+Then it's possible to instantiate an execution graph by means of other functions
+such as `out_edges` to retrieve the children of a given task or `edges` to get
+the identifiers.