diff --git a/.circleci/config.yml b/.circleci/config.yml index 341fa7df9..71e06c76c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -81,8 +81,9 @@ jobs: - run: name: Install Required Tools command: | - apk add --no-cache bash git g++ make cmake clang py-pip shellcheck shfmt grep + apk add --no-cache bash git g++ make cmake clang py-pip shellcheck shfmt grep npm pip install cpplint + npm install -g markdownlint-cli - run: name: Lint diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index d2e3a6eab..79cdc7b3c 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -2,47 +2,75 @@ First, thanks for contributing! :thumbsup: -These are the guidelines designed to make the development smooth, efficient, and fun for all of us. But remember, we are the ones who write them, and *anybody* is welcome to propose changes. Just open a pull request. +These are the guidelines designed to make the development smooth, efficient, and fun for all of us. But remember, we are +the ones who write them, and *anybody* is welcome to propose changes. Just open a pull request. -There are fundamentally three kinds of things you can contribute: [issues](#issues) ([reports](#weed-reports-something-is-not-working) and [ideas](#feature-suggestions)), [code](#code), and [research notes](#research). +There are fundamentally three kinds of things you can +contribute: [issues](#issues) ([reports](#weed-reports-something-is-not-working) and [ideas](#feature-suggestions)) +, [code](#code), and [research notes](#research). # Issues ## Weed reports (something is not working) -First off, while it's common to call problems with the code "bugs", we call them *weeds* here instead (kudos to [@aokellermann](https://github.com/aokellermann)). That's because using the word "bug" in a negative context implicitly sends a message that *bugs* (aka insects) are someone bad and should be squashed. We don't agree with that sentiment, as *bugs* :ant: :beetle: :spider: are living creatures who deserve moral consideration. Hence, let's leave "bugs" alone, and go *weed whacking*. +First off, while it's common to call problems with the code "bugs", we call them *weeds* here instead (kudos +to [@aokellermann](https://github.com/aokellermann)). That's because using the word "bug" in a negative context +implicitly sends a message that *bugs* (aka insects) are someone bad and should be squashed. We don't agree with that +sentiment, as *bugs* :ant: :beetle: :spider: are living creatures who deserve moral consideration. Hence, let's leave " +bugs" alone, and go *weed whacking*. -The issues in this repository are only related to *SetReplace*, not the entire Wolfram Physics Project. If you have found an issue with a Wolfram Physics [bulletin](https://www.wolframphysics.org/bulletins/), or with anything else on the Wolfram Physics [website](https://www.wolframphysics.org), please report it using the tools available there. The bulletins that also appear as [research notes](/Research) in this repository are the only exceptions. The issues with these should be reported here. +The issues in this repository are only related to *SetReplace*, not the entire Wolfram Physics Project. If you have +found an issue with a Wolfram Physics [bulletin](https://www.wolframphysics.org/bulletins/), or with anything else on +the Wolfram Physics [website](https://www.wolframphysics.org), please report it using the tools available there. The +bulletins that also appear as [research notes](/Research) in this repository are the only exceptions. The issues with +these should be reported here. -Similarly, the weeds in function repository functions should be reported on the function repository website rather than here. +Similarly, the weeds in function repository functions should be reported on the function repository website rather than +here. To report a weed, follow these steps: -1. Go to the [Issues page](https://github.com/maxitg/SetReplace/issues), and use the search to check if the weed you have encountered is in the list already. If it is, and it was not getting much attention lately, the best you can do is to comment that you care about it being fixed, and to leave the example you have encountered that's not working (if it's not similar to ones already there). + +1. Go to the [Issues page](https://github.com/maxitg/SetReplace/issues), and use the search to check if the weed you + have encountered is in the list already. If it is, and it was not getting much attention lately, the best you can do + is to comment that you care about it being fixed, and to leave the example you have encountered that's not working ( + if it's not similar to ones already there). 2. If the weed is not in the list, click "New issue", and then "Get started" next to the "Weed report". 3. Fill in all the fields including: - * Brief description in natural language. - * The line of Wolfram Language code that results in unexpected behavior (or a screenshot if the weed is in the UI). - * The actual output you are getting. - * The output you expect to see. - * The output of `SystemInformation["Small"]` and `$SetReplaceGitSHA`. - * If the weed appears randomly and is not easy to reproduce, add details about how often and in what circumstances you encounter it. -4. If you have a Mathematica notebook with more details, you can attach it to the issue, just compress it to a `ZIP` file first. + * Brief description in natural language. + * The line of Wolfram Language code that results in unexpected behavior (or a screenshot if the weed is in the UI). + * The actual output you are getting. + * The output you expect to see. + * The output of `SystemInformation["Small"]` and `$SetReplaceGitSHA`. + * If the weed appears randomly and is not easy to reproduce, add details about how often and in what circumstances + you encounter it. + +4. If you have a Mathematica notebook with more details, you can attach it to the issue, just compress it to a `ZIP` + file first. 5. Click "Submit new issue". -6. Your issue is now on the list, and a developer will look at it if/when they have a chance. But if it does not get any attention, the best you can do is to [fix it yourself](#code). +6. Your issue is now on the list, and a developer will look at it if/when they have a chance. But if it does not get any + attention, the best you can do is to [fix it yourself](#code). -Also, please understand that mistakes happen and are unavoidable. We never blame people for unintentional mistakes in this project. Instead, we improve our development process to minimize the probability of mistakes in the future. +Also, please understand that mistakes happen and are unavoidable. We never blame people for unintentional mistakes in +this project. Instead, we improve our development process to minimize the probability of mistakes in the future. ## Feature suggestions -If you have an idea to improve an existing function, add a property to `WolframModel`, or add a new function that does not currently exist, you can suggest it by creating a feature request. There are no guarantees, but someone might implement it if they like the idea. You are welcome to suggest research ideas as long as they are directly related to the models implemented in *SetReplace*. +If you have an idea to improve an existing function, add a property to `WolframModel`, or add a new function that does +not currently exist, you can suggest it by creating a feature request. There are no guarantees, but someone might +implement it if they like the idea. You are welcome to suggest research ideas as long as they are directly related to +the models implemented in *SetReplace*. -The process is similar to weed reports, just use the "Feature request" option instead. Don't include any version information in feature requests. +The process is similar to weed reports, just use the "Feature request" option instead. Don't include any version +information in feature requests. ## Labels -It is helpful to add [labels](https://github.com/maxitg/SetReplace/labels) to your issue. This makes it easier for developers to find something they are interested in and comfortable working with. We have several categories of labels corresponding to different colors. +It is helpful to add [labels](https://github.com/maxitg/SetReplace/labels) to your issue. This makes it easier for +developers to find something they are interested in and comfortable working with. We have several categories of labels +corresponding to different colors. First, assign one of the *type* labels to your pull request: + * `feature`: new functionality, or change in existing functionality. * `weed`: fixes something that was not working. * `test`: adds new tests for existing functionality. @@ -51,38 +79,56 @@ First, assign one of the *type* labels to your pull request: * `convenience`: makes the syntax more convenient without significantly changing functionality. * `design`: changes the visual design (styles, colors, icons, etc.) without affecting functionality. * `refactor`: does not change functionality, but makes the code better organized or more readable. -* `research`: introduces new ideas about the structure of the models themselves ([research notes](#research) will typically have this label). +* `research`: introduces new ideas about the structure of the models themselves ([research notes](#research) will + typically have this label). Then, assign one of the *component* labels: + * `evolution`: modifies code for running the evolution of the model. * `analysis`: adds or changes evolution analysis tools, e.g., `WolframModelEvolutionObject` properties. * `visualization`: has to do with visualization code, such as `HypergraphPlot`. * `physics`: explores a connection with known physics. Would typically only be used with some `research` notes. -* `utilities`: implements a tool that does not fit in the above categories (e.g., [`Subhypergraph`](https://github.com/maxitg/SetReplace/pull/431)). +* `utilities`: implements a tool that does not fit in the above categories ( + e.g., [`Subhypergraph`](https://github.com/maxitg/SetReplace/pull/431)). * `infrastructure`: implements changes to the development process, e.g., build scripts, CI, testing utilities, etc. -It is also helpful to specify the language one expects to use to solve the issue. This helps developers to find issues they are comfortable working with. The current choices are `c++`, `wolfram language`, and `english` (e.g., for research documents). +It is also helpful to specify the language one expects to use to solve the issue. This helps developers to find issues +they are comfortable working with. The current choices are `c++`, `wolfram language`, and `english` (e.g., for research +documents). Also, one of the following may be used: + * `critical`: fixes something that severely breaks the package (usually used for weeds). * `breaking`: introduces API changes that would break existing code, better to avoid if possible. -* `blocked`: another issue needs to be closed before this one can be started. If using this label, you need to mention the blocking issue in the description. +* `blocked`: another issue needs to be closed before this one can be started. If using this label, you need to mention + the blocking issue in the description. # Code If you would like to contribute code, thanks again! :tada: :balloon: :tada: -In the sections below, we describe our [development process](#development-process), [the code structure](#code-structure), and [our code style rules](#code-style). However, if you are unsure about something, don't let these rules deter you from opening pull requests! If something is missing, or if there are issues with the code style, someone will help you fix them during code review. +In the sections below, we describe our [development process](#development-process) +, [the code structure](#code-structure), and [our code style rules](#code-style). However, if you are unsure about +something, don't let these rules deter you from opening pull requests! If something is missing, or if there are issues +with the code style, someone will help you fix them during code review. ## Development process -Each change to the code must fundamentally pass through 5 steps, more or less in that order: [writing code](#writing-code), [opening a pull request](#opening-a-pull-request), passing [automated tests](#automated-tests), passing [code review](#code-review), and [merging the PR](#merging). +Each change to the code must fundamentally pass through 5 steps, more or less in that +order: [writing code](#writing-code), [opening a pull request](#opening-a-pull-request), +passing [automated tests](#automated-tests), passing [code review](#code-review), and [merging the PR](#merging). ### Building in-place -The main workflow we recommend is what we are calling an "in-place build". This largely happens automatically when you load the *SetReplace* package by calling `Get["~/git/SetReplace/Kernel/init.m"]` or equivalent. If the C++ library (*libSetReplace*) has not already been built, it will automatically be built for you, and the resulting libraries placed in the `LibraryResources` subdirectory of the repository root. +The main workflow we recommend is what we are calling an "in-place build". This largely happens automatically when you +load the *SetReplace* package by calling `Get["~/git/SetReplace/Kernel/init.m"]` or equivalent. If the C++ library (* +libSetReplace*) has not already been built, it will automatically be built for you, and the resulting libraries placed +in the `LibraryResources` subdirectory of the repository root. -If you later modify the C++ code and call `Get[...]` again, the library will be automatically rebuilt, and hot-loaded into your current Mathematica session (you do not need to run `Quit[]`). Moreover, builds of the library will be cached based on the hash of the C++ code, making it easy to switch quickly between several library versions (say, in different Git branches). +If you later modify the C++ code and call `Get[...]` again, the library will be automatically rebuilt, and hot-loaded +into your current Mathematica session (you do not need to run `Quit[]`). Moreover, builds of the library will be cached +based on the hash of the C++ code, making it easy to switch quickly between several library versions (say, in different +Git branches). If you wish to invoke the library build process *directly*, you run the following on the command line: @@ -102,7 +148,9 @@ Doing so will automatically rebuild the library, if necessary. ### Build Paclets -You may occasionally want to build and install a paclet from the current state of the repository. This will package together all the Wolfram Language source code, along with the library, and various metadata, into a single ".paclet" file, which has an automatically computed version number associated with it. +You may occasionally want to build and install a paclet from the current state of the repository. This will package +together all the Wolfram Language source code, along with the library, and various metadata, into a single ".paclet" +file, which has an automatically computed version number associated with it. To simply build the paclet, without installing it, just run: @@ -111,71 +159,126 @@ cd ~/git/SetReplace ./pack.wls ``` -This will automatically build the library if needed and produce a paclet file, placing it in the `BuiltPaclets` directory. +This will automatically build the library if needed and produce a paclet file, placing it in the `BuiltPaclets` +directory. -If you wish to also install the paclet you've built, you can run the following (instead of the step above, not in addition to it): +If you wish to also install the paclet you've built, you can run the following (instead of the step above, not in +addition to it): ```bash cd ~/git/SetReplace ./install.wls ``` -The paclet will be installed in your system, replacing any existing version of the paclet you may have. This will allow you to load the paclet in the future by running simply ``Get["SetReplace`"] ``. +The paclet will be installed in your system, replacing any existing version of the paclet you may have. This will allow +you to load the paclet in the future by running simply ``Get["SetReplace`"]``. ### Writing code In addition to the code itself, each pull request should include unit tests and documentation. -To help you get started, see how the code is [organized](#code-structure) and our notes on [code style](#code-style). Also, we are keeping dependencies to a minimum to make the paclet as easy to compile and run as possible. So, avoid adding dependencies if at all possible. That includes Wolfram Function Repository functions. Even though they don't require installation, most of them are not stable enough for use in *SetReplace*. Also, using them may result in unexpected behavior as they can be updated independently of *SetReplace*, and there is no way to enforce a specific version. They also require an Internet connection in a way that's hard to control. If you still think adding a dependency is worth it, please open a feature request first to discuss it. If you need functionality from a resource function, you are always welcome to add the function to *SetReplace*, but you will have to improve it to follow the same quality standards as the rest of the code. - -The unit tests are particularly important if you are implementing a weed fix, as it is crucial to make sure the weed you are fixing is not going to return in the future. And if you are implementing a new function, unit tests should cover not only the functionality but also the behavior in case the function is called with invalid arguments. Each function should have at least some unit tests; there is a test in [meta.wlt](/Tests/meta.wlt) to enforce that. - -If sharing variables among multiple tests, use [`With`](https://reference.wolfram.com/language/ref/With.html) instead of [`Module`](https://reference.wolfram.com/language/ref/Module.html) or global assignment, because otherwise, variables will not appear resolved in the command line error message if the test fails (which makes it harder to weed whack). Also, try to avoid large inputs and outputs for the tests, if at all possible (by, for example, replacing `VerificationTest[large1[], large2[]]` with `VerificationTest[large1[] === large2[]]`). - -You should also modify the [README](/README.md) or the corresponding files in the Documentation directory if you are implementing new functionality, or causing any outputs there to change. - -**Never put notebooks (.nb files) in the repository**, as they, even though text files, are not human readable, cannot be reviewed line-by-line, and are guaranteed to cause conflicts, which would be almost impossible to resolve. In fact, `.nb` files are listed in the `.gitignore` file precisely so that you cannot accidentally add them. +To help you get started, see how the code is [organized](#code-structure) and our notes on [code style](#code-style). +Also, we are keeping dependencies to a minimum to make the paclet as easy to compile and run as possible. So, avoid +adding dependencies if at all possible. That includes Wolfram Function Repository functions. Even though they don't +require installation, most of them are not stable enough for use in *SetReplace*. Also, using them may result in +unexpected behavior as they can be updated independently of *SetReplace*, and there is no way to enforce a specific +version. They also require an Internet connection in a way that's hard to control. If you still think adding a +dependency is worth it, please open a feature request first to discuss it. If you need functionality from a resource +function, you are always welcome to add the function to *SetReplace*, but you will have to improve it to follow the same +quality standards as the rest of the code. + +The unit tests are particularly important if you are implementing a weed fix, as it is crucial to make sure the weed you +are fixing is not going to return in the future. And if you are implementing a new function, unit tests should cover not +only the functionality but also the behavior in case the function is called with invalid arguments. Each function should +have at least some unit tests; there is a test in [meta.wlt](/Tests/meta.wlt) to enforce that. + +If sharing variables among multiple tests, use [`With`](https://reference.wolfram.com/language/ref/With.html) instead +of [`Module`](https://reference.wolfram.com/language/ref/Module.html) or global assignment, because otherwise, variables +will not appear resolved in the command line error message if the test fails (which makes it harder to weed whack). +Also, try to avoid large inputs and outputs for the tests, if at all possible (by, for example, +replacing `VerificationTest[large1[], large2[]]` with `VerificationTest[large1[] === large2[]]`). + +You should also modify the [README](/README.md) or the corresponding files in the Documentation directory if you are +implementing new functionality, or causing any outputs there to change. + +**Never put notebooks (.nb files) in the repository**, as they, even though text files, are not human readable, cannot +be reviewed line-by-line, and are guaranteed to cause conflicts, which would be almost impossible to resolve. In +fact, `.nb` files are listed in the `.gitignore` file precisely so that you cannot accidentally add them. ### Opening a pull request -Each pull request message should include detailed information on what was changed, optional comments for the reviewer, and **examples**, including screenshots if the output is a [`Graphics`](https://reference.wolfram.com/language/ref/Graphics.html) object. If your pull request closes an existing issue (as it generally should, as it's best to discuss your changes before implementing them), reference that issue in your pull request message. For an example of a good pull request message, see [#268](https://github.com/maxitg/SetReplace/pull/268). +Each pull request message should include detailed information on what was changed, optional comments for the reviewer, +and **examples**, including screenshots if the output is +a [`Graphics`](https://reference.wolfram.com/language/ref/Graphics.html) object. If your pull request closes an existing +issue (as it generally should, as it's best to discuss your changes before implementing them), reference that issue in +your pull request message. For an example of a good pull request message, +see [#268](https://github.com/maxitg/SetReplace/pull/268). -Next, assign the labels. The convention for labels is the same as for [issues](#labels), and usually, labels will be the same as in the issue the pull request is closing or working toward. +Next, assign the labels. The convention for labels is the same as for [issues](#labels), and usually, labels will be the +same as in the issue the pull request is closing or working toward. -Next, assign a reviewer to your pull request. Ideally, it should be someone who has recently edited the same files. If in doubt, assign to [@maxitg](https://github.com/maxitg). +Next, assign a reviewer to your pull request. Ideally, it should be someone who has recently edited the same files. If +in doubt, assign to [@maxitg](https://github.com/maxitg). -It is essential to keep your pull requests as small as possible (definitely under 1000 lines, preferably under 500 lines). Keeping them small streamlines the review process and makes it more likely your changes will find their way into master, as it's always possible you will get distracted and won't be able to finish one giant pull request. It also helps keep your pull requests up-to-date with master, which is useful because master's changes might introduce conflicts or break your code. +It is essential to keep your pull requests as small as possible (definitely under 1000 lines, preferably under 500 +lines). Keeping them small streamlines the review process and makes it more likely your changes will find their way into +master, as it's always possible you will get distracted and won't be able to finish one giant pull request. It also +helps keep your pull requests up-to-date with master, which is useful because master's changes might introduce conflicts +or break your code. ### Automated tests -To run the tests, `cd` to the repository root, and run `./test.wls` from the command line. Note that `./test.wls` will automatically rebuild *libSetReplace* for you before running the tests if your *libSetReplace* is out of date (for example, if you changed some C++ files but you did not either `Get` *SetReplace* or run `./build.wls`). If everything is ok, you will see `[ok]` next to each group of tests, and "Tests passed." message at the end. Otherwise, you will see error messages telling you which test inputs failed and for what reason. - -The `test.wls` script accepts various arguments. Running `./test.wls testfile`, where `testfile` is the name (without trailing `.wlt`) of a test file under the `Tests` directory, will limit the test run to only that file. With the `--load-installed-paclet` (or `-lip`) flag, the script will load the *installed paclet* instead of the local codebase. With the `--disable-parallelization` (or `-dp`) flag, you can disable the use of parallel sub-kernels to perform tests. Using parallel sub-kernels will accelerate running the entire test suite, so it is the default behavior, but if you are running only a single test file with a small number of tests, the startup time of the sub-kernels can outweigh any speedup they give, and so `--disable-parallelization` will improve performance. - -We have a CI that automatically runs tests for all commits on all branches (kudos to [Circle CI](https://circleci.com) for providing free resources for this project). You need collaborator access to run the CI. If you don't have such access yet, the reviewer will run it for you. - -We have a workflow ([example](https://app.circleci.com/pipelines/github/maxitg/SetReplace/1452/workflows/75b2a72b-c36e-43e2-bb51-2ff0e690e64c)) that builds a paclet (in wolfram-language-paclet-test) with libraries for Linux (also in wolfram-language-paclet-test), Mac (macos-build) and Windows (windows-build) and runs both C++ (cpp-test and cpp-32-test) and Wolfram Language (wolfram-language-paclet-test) tests. +To run the tests, `cd` to the repository root, and run `./test.wls` from the command line. Note that `./test.wls` will +automatically rebuild *libSetReplace* for you before running the tests if your *libSetReplace* is out of date (for +example, if you changed some C++ files but you did not either `Get` *SetReplace* or run `./build.wls`). If everything is +ok, you will see `[ok]` next to each group of tests, and "Tests passed." message at the end. Otherwise, you will see +error messages telling you which test inputs failed and for what reason. + +The `test.wls` script accepts various arguments. Running `./test.wls testfile`, where `testfile` is the name (without +trailing `.wlt`) of a test file under the `Tests` directory, will limit the test run to only that file. With +the `--load-installed-paclet` (or `-lip`) flag, the script will load the *installed paclet* instead of the local +codebase. With the `--disable-parallelization` (or `-dp`) flag, you can disable the use of parallel sub-kernels to +perform tests. Using parallel sub-kernels will accelerate running the entire test suite, so it is the default behavior, +but if you are running only a single test file with a small number of tests, the startup time of the sub-kernels can +outweigh any speedup they give, and so `--disable-parallelization` will improve performance. + +We have a CI that automatically runs tests for all commits on all branches (kudos to [Circle CI](https://circleci.com) +for providing free resources for this project). You need collaborator access to run the CI. If you don't have such +access yet, the reviewer will run it for you. + +We have a +workflow ([example](https://app.circleci.com/pipelines/github/maxitg/SetReplace/1452/workflows/75b2a72b-c36e-43e2-bb51-2ff0e690e64c)) +that builds a paclet (in wolfram-language-paclet-test) with libraries for Linux (also in wolfram-language-paclet-test), +Mac (macos-build) and Windows (windows-build) and runs both C++ (cpp-test and cpp-32-test) and Wolfram Language ( +wolfram-language-paclet-test) tests. Your code must successfully complete all builds and pass all tests to be mergeable to master. The paclets built by the wolfram-language-paclet-test job are the same as we use for releases. -In addition to correctness tests, we have a performance testing tool, which is currently in the early stage of development, and only allows testing of the performance of the evolution. To use it, run in the repository root: +In addition to correctness tests, we have a performance testing tool, which is currently in the early stage of +development, and only allows testing of the performance of the evolution. To use it, run in the repository root: ```bash ./performanceTest.wls oldCommit newCommit testCount ``` -Here `oldCommit` and `newCommit` are the git SHAs or branch names which should be compared, and `testCount` determines how many times to run each test for averaging (higher numbers decrease errors proportional to the square root, but take linearly longer to evaluate). +Here `oldCommit` and `newCommit` are the git SHAs or branch names which should be compared, and `testCount` determines +how many times to run each test for averaging (higher numbers decrease errors proportional to the square root, but take +linearly longer to evaluate). -A short-hand syntax is available as well, specifically, `./performanceTest.wls oldCommit newCommit` runs each test 5 times, `./performanceTest.wls oldCommit` compares the `HEAD` to the `oldCommit`, and `./performanceTest.wls` compares the `HEAD` to `master`. +A short-hand syntax is available as well, specifically, `./performanceTest.wls oldCommit newCommit` runs each test 5 +times, `./performanceTest.wls oldCommit` compares the `HEAD` to the `oldCommit`, and `./performanceTest.wls` compares +the `HEAD` to `master`. -The tool will checkout other branches while testing, so don't use git/modify any files while it's running. Results depend on the other activity happening on the machine, so do not perform any CPU-intensive tasks while running tests to avoid introducing bias to the results. +The tool will checkout other branches while testing, so don't use git/modify any files while it's running. Results +depend on the other activity happening on the machine, so do not perform any CPU-intensive tasks while running tests to +avoid introducing bias to the results. As an example, test an optimization done to *libSetReplace* by [@aokellermann](https://github.com/aokellermann): -``` -> ./performanceTest.wls db6f15c7b4ae1be98be5ced0c188859e2f9eef29 8910175fe9be3847f96a1cf3c877a3b54a64823d +```console +$ ./performanceTest.wls db6f15c7b4ae1be98be5ced0c188859e2f9eef29 8910175fe9be3847f96a1cf3c877a3b54a64823d Testing db6f15c7b4ae1be98be5ced0c188859e2f9eef29 Build done. @@ -193,22 +296,31 @@ Exponential-match-count rule 23.7 ± 0.8 % CA emulator 0.42 ± 0.21 % ``` -Note, percentages correspond to runtime difference compared to the `oldBranch`, so, e.g., a positive `67 %` means there is a 3x improvement, whereas `-100 %` implies a 2x regression. +Note, percentages correspond to runtime difference compared to the `oldBranch`, so, e.g., a positive `67 %` means there +is a 3x improvement, whereas `-100 %` implies a 2x regression. ### Code review -First, if someone has assigned a `critical` pull request to you, please stop reading and review it as soon as possible (understand what the issue is, and verify the fix works). Many people might be blocked by it right now. +First, if someone has assigned a `critical` pull request to you, please stop reading and review it as soon as possible ( +understand what the issue is, and verify the fix works). Many people might be blocked by it right now. Otherwise, please review within one or two days or give an ETA to the pull request author if that is not possible. The main objectives for the code review: + 1. Verify the code works (i.e., make sure you can reproduce examples in the pull request message). -2. Read the code, understand it, and see if you can spot any potential weeds/unnecessary slowdowns/issues with it (including issues with code style as we currently only have a linter for the C++ and Bash, but not for the Wolfram Language code). +2. Read the code, understand it, and see if you can spot any potential weeds/unnecessary slowdowns/issues with it ( + including issues with code style as we currently only have a linter for the C++ and Bash, but not for the Wolfram + Language code). 3. Check the pull request has unit tests and changes documentation if appropriate. -We use [Reviewable](https://reviewable.io) for code review, which greatly simplifies the tracking of comments (Reviewable button should automatically appear on the bottom of pull requests). Please comment directly on the lines of code. +We use [Reviewable](https://reviewable.io) for code review, which greatly simplifies the tracking of comments ( +Reviewable button should automatically appear on the bottom of pull requests). Please comment directly on the lines of +code. -If you are reviewing a pull request from a fork, CI will not run automatically. You can (and need to) still run it manually, however, by pushing the changes to a new branch on GitHub. To do that, run the following where `123` is the pull request number: +If you are reviewing a pull request from a fork, CI will not run automatically. You can (and need to) still run it +manually, however, by pushing the changes to a new branch on GitHub. To do that, run the following where `123` is the +pull request number: ```bash git fetch origin pull/123/head:pr/123 @@ -218,33 +330,52 @@ git push -u origin pr/123 The CI will automatically run and will be linked to the existing pull request. -After you receive a review and work on the changes, please reply to the reviewer on Reviewable so that they know when to look at your changes. +After you receive a review and work on the changes, please reply to the reviewer on Reviewable so that they know when to +look at your changes. -Last but not least, [be respectful](https://help.github.com/en/github/site-policy/github-community-guidelines), and give constructive criticism. Don't just say something is bad, say how to improve it. +Last but not least, [be respectful](https://help.github.com/en/github/site-policy/github-community-guidelines), and give +constructive criticism. Don't just say something is bad, say how to improve it. ### Merging -Generally speaking, the author of the pull request should be the one merging it. However, if you don't yet have collaborator access to the repository, you will have to ask someone else to do it. +Generally speaking, the author of the pull request should be the one merging it. However, if you don't yet have +collaborator access to the repository, you will have to ask someone else to do it. -Once you see the green "Squash and merge" button, all the necessary checks have passed, and you can merge your pull request! Congratulations! :tada: Push the green button, ***paste your pull request message to the commit message field***, and confirm. Your changes are now in and will be included in the next release. +Once you see the green "Squash and merge" button, all the necessary checks have passed, and you can merge your pull +request! Congratulations! :tada: Push the green button, ***paste your pull request message to the commit message +field***, and confirm. Your changes are now in and will be included in the next release. ## Code structure -The most important components of the package are the [Wolfram Language code](#wolfram-language-code), [C++ code](#libsetreplace), [tests](#tests), [documentation](#documentation), and [various scripts](#scripts). +The most important components of the package are the [Wolfram Language code](#wolfram-language-code) +, [C++ code](#libsetreplace), [tests](#tests), [documentation](#documentation), and [various scripts](#scripts). ### Wolfram Language code -The Wolfram Language code, which constitutes most of the package, lives in the [Kernel](/Kernel) directory. We use the [new-style package structure](https://mathematica.stackexchange.com/a/176489/46895). +The Wolfram Language code, which constitutes most of the package, lives in the [Kernel](/Kernel) directory. We use +the [new-style package structure](https://mathematica.stackexchange.com/a/176489/46895). -Specifically, [init.m](/Kernel/init.m) is loaded first, followed by the rest of the files which are picked up automatically. Generally, each public Wolfram Language symbol would go to a separate file except for tiny ones (like constants), or huge functions that rely on other internal symbols (like [`WolframModel`](/Kernel/WolframModel.m)). +Specifically, [init.m](/Kernel/init.m) is loaded first, followed by the rest of the files which are picked up +automatically. Generally, each public Wolfram Language symbol would go to a separate file except for tiny ones (like +constants), or huge functions that rely on other internal symbols (like [`WolframModel`](/Kernel/WolframModel.m)). -Each file should start with a ``Package["SetReplace`"]`` line, followed by lines of the form `PackageExport["PublicSymbolName"]` for publicly available symbols, and `PackageScope["PackageSymbolName"]` for private symbols that need to be used in other files. The symbols not included in either of these declarations are only available in that specific file. +Each file should start with a ``Package["SetReplace`"]`` line, followed by lines of the +form `PackageExport["PublicSymbolName"]` for publicly available symbols, and `PackageScope["PackageSymbolName"]` for +private symbols that need to be used in other files. The symbols not included in either of these declarations are only +available in that specific file. -Note these declarations are macros, not Wolfram Language code, so you have to put each one of them on a separate line, and you cannot use them with Wolfram Language code, like mapping them over a [`List`](https://reference.wolfram.com/language/ref/List.html). +Note these declarations are macros, not Wolfram Language code, so you have to put each one of them on a separate line, +and you cannot use them with Wolfram Language code, like mapping them over +a [`List`](https://reference.wolfram.com/language/ref/List.html). -Your public symbols should also include a `usage` message, which should be created with the [`SetUsage`](https://github.com/maxitg/SetReplace/blob/7f89c5103cae6a7c1d21b967973811fdeacfd63b/Kernel/GeneralizedGridGraph.m#L9) function. For more information, see ``?GeneralUtilities`SetUsage``. +Your public symbols should also include a `usage` message, which should be created with +the [`SetUsage`](https://github.com/maxitg/SetReplace/blob/7f89c5103cae6a7c1d21b967973811fdeacfd63b/Kernel/GeneralizedGridGraph.m#L9) +function. For more information, see ``?GeneralUtilities`SetUsage``. -Further, public symbols must include [`SyntaxInformation`](https://reference.wolfram.com/language/ref/SyntaxInformation.html), see [an example](https://github.com/maxitg/SetReplace/blob/6b9df76dc7fa3c08ac8803b90d625ce454f51f0c/Kernel/WolframModel.m#L23) for `WolframModel`. +Further, public symbols must +include [`SyntaxInformation`](https://reference.wolfram.com/language/ref/SyntaxInformation.html), +see [an example](https://github.com/maxitg/SetReplace/blob/6b9df76dc7fa3c08ac8803b90d625ce454f51f0c/Kernel/WolframModel.m#L23) +for `WolframModel`. Functions must handle invalid inputs correctly. For example, if you try to evaluate @@ -256,7 +387,10 @@ you would get a helpful error message. If we did not do any checks here, we woul and the function would not even terminate, which is confusing and hostile to the user. -One way to implement such argument checking is to make special `valid*Q` functions, which would check each argument before running the function. This approach could work well for small functions. Still, it's not an ideal way to do it because sometimes the validity of the arguments can only be detected deep in the evaluation logic, and the validation function would be too complicated and lead to code duplication. +One way to implement such argument checking is to make special `valid*Q` functions, which would check each argument +before running the function. This approach could work well for small functions. Still, it's not an ideal way to do it +because sometimes the validity of the arguments can only be detected deep in the evaluation logic, and the validation +function would be too complicated and lead to code duplication. A better approach is to setup the function to catch exceptions, i.e., @@ -276,32 +410,54 @@ failUniverse[badUniverse_] := ( ) ``` -This way, the error can occur arbitrarily deep in the function logic, and it would still be easy to immediately abort and return the function unevaluated. +This way, the error can occur arbitrarily deep in the function logic, and it would still be easy to immediately abort +and return the function unevaluated. --- -The main dispatch function of *SetReplace* is the package-scope [`setSubstitutionSystem`](/Kernel/setSubstitutionSystem.m). It is essentially the generic evolution function. It is used by [`WolframModel`](/Kernel/WolframModel.m), [`SetReplace`](/Kernel/SetReplace.m), [`SetReplaceAll`](/Kernel/SetReplaceAll.m), etc. +The main dispatch function of *SetReplace* is the +package-scope [`setSubstitutionSystem`](/Kernel/setSubstitutionSystem.m). It is essentially the generic evolution +function. It is used by [`WolframModel`](/Kernel/WolframModel.m), [`SetReplace`](/Kernel/SetReplace.m) +, [`SetReplaceAll`](/Kernel/SetReplaceAll.m), etc. -[`setSubstitutionSystem`](/Kernel/setSubstitutionSystem.m) parses the options (except for [`WolframModel`](/Kernel/WolframModel.m)-specific ones), and uses one of the method functions, [`setSubstitutionSystem$cpp`](/Kernel/setSubstitutionSystem$cpp.m) or [`setSubstitutionSystem$wl`](/Kernel/setSubstitutionSystem$wl.m) to run the evolution. +[`setSubstitutionSystem`](/Kernel/setSubstitutionSystem.m) parses the options (except +for [`WolframModel`](/Kernel/WolframModel.m)-specific ones), and uses one of the method +functions, [`setSubstitutionSystem$cpp`](/Kernel/setSubstitutionSystem$cpp.m) +or [`setSubstitutionSystem$wl`](/Kernel/setSubstitutionSystem$wl.m) to run the evolution. -[`setSubstitutionSystem$wl`](/Kernel/setSubstitutionSystem$wl.m) is the pure Wolfram Language implementation, which is more general (it supports arbitrary pattern rules and disconnected rules), but less efficient. +[`setSubstitutionSystem$wl`](/Kernel/setSubstitutionSystem$wl.m) is the pure Wolfram Language implementation, which is +more general (it supports arbitrary pattern rules and disconnected rules), but less efficient. -[`setSubstitutionSystem$cpp`](/Kernel/setSubstitutionSystem$cpp.m) on the other hand is the LibraryLink interface to [*libSetReplace*](#libsetreplace), which is the C++ implementation of Wolfram models. +[`setSubstitutionSystem$cpp`](/Kernel/setSubstitutionSystem$cpp.m) on the other hand is the LibraryLink interface to [* +libSetReplace*](#libsetreplace), which is the C++ implementation of Wolfram models. -If you'd like to implement a small utility useful throughout the package (but not accessible externally), put it in [utilities.m](/Kernel/utilities.m). +If you'd like to implement a small utility useful throughout the package (but not accessible externally), put it +in [utilities.m](/Kernel/utilities.m). ### libSetReplace -*libSetReplace* is the C++ library that implements the `"LowLevel"` method of [`WolframModel`](/Kernel/WolframModel.m). It lives in [`libSetReplace`](/libSetReplace) directory, and there is also the [Xcode project](/SetReplace.xcodeproj) for it. [`SetReplace.cpp`](/libSetReplace/SetReplace.cpp) and [`SetReplace.hpp`](/libSetReplace/SetReplace.hpp) implement the interface with Wolfram Language code. +*libSetReplace* is the C++ library that implements the `"LowLevel"` method of [`WolframModel`](/Kernel/WolframModel.m). +It lives in [`libSetReplace`](/libSetReplace) directory, and there is also the [Xcode project](/SetReplace.xcodeproj) +for it. [`SetReplace.cpp`](/libSetReplace/SetReplace.cpp) and [`SetReplace.hpp`](/libSetReplace/SetReplace.hpp) +implement the interface with Wolfram Language code. -The C++ implementation keeps an index of all possible rule matches and updates it after every replacement. The reindexing algorithm looks only at the local region of the graph close to the rewrite site. Thus time complexity is linear with the number of events and does not depend on the graph size as long as vertex degrees are small. The downside is that it has exponential complexity (both in time and memory) in the vertex degrees because an exponential number of matches might exist in that case. Currently, it also does not work for non-local rules (i.e., rule inputs that do not form a connected hypergraph) and rules that are not hypergraph rules (i.e., pattern rules that have non-trivial nesting or conditions). +The C++ implementation keeps an index of all possible rule matches and updates it after every replacement. The +reindexing algorithm looks only at the local region of the graph close to the rewrite site. Thus time complexity is +linear with the number of events and does not depend on the graph size as long as vertex degrees are small. The downside +is that it has exponential complexity (both in time and memory) in the vertex degrees because an exponential number of +matches might exist in that case. Currently, it also does not work for non-local rules (i.e., rule inputs that do not +form a connected hypergraph) and rules that are not hypergraph rules (i.e., pattern rules that have non-trivial nesting +or conditions). -Every time the `"LowLevel"` implementation of [`WolframModel`](/Kernel/WolframModel.m) is called, an instance of class [`Set`](/libSetReplace/Set.hpp) is created. [`Set`](/libSetReplace/Set.hpp) in turn uses the [`Matcher`](/libSetReplace/Match.hpp) class to perform the matching of set elements to rule inputs. [This class](/libSetReplace/Match.cpp) is the core of *SetReplace*. +Every time the `"LowLevel"` implementation of [`WolframModel`](/Kernel/WolframModel.m) is called, an instance of +class [`Set`](/libSetReplace/Set.hpp) is created. [`Set`](/libSetReplace/Set.hpp) in turn uses +the [`Matcher`](/libSetReplace/Match.hpp) class to perform the matching of set elements to rule +inputs. [This class](/libSetReplace/Match.cpp) is the core of *SetReplace*. #### Compile C++ library with CMake -The *libSetReplace* library can be used outside of Wolfram Language. It provides a CMake project for easy interaction with the C++ ecosystem. -To compile the core library using CMake: +The *libSetReplace* library can be used outside of Wolfram Language. It provides a CMake project for easy interaction +with the C++ ecosystem. To compile the core library using CMake: ```bash mkdir build && cd build @@ -311,7 +467,8 @@ cmake --build . By default, the build type is set to Release. To use Debug, set `-DCMAKE_BUILD_TYPE=Debug`. -If configuring for Visual Studio on Windows, the Visual Studio solution with both Debug and Release configs will be created. Then, to build Release, replace the third line in the above with: +If configuring for Visual Studio on Windows, the Visual Studio solution with both Debug and Release configs will be +created. Then, to build Release, replace the third line in the above with: ```bash cmake --build . --config Release @@ -319,17 +476,18 @@ cmake --build . --config Release Options available for CMake: -- `SET_REPLACE_BUILD_TESTING`: -Enable cpp testing using googletest, which is downloaded at build time. This is not supported on Windows at this time. +* `SET_REPLACE_BUILD_TESTING`: + Enable cpp testing using googletest, which is downloaded at build time. This is not supported on Windows at this time. -- `SET_REPLACE_ENABLE_ALLWARNINGS`: -For developers and contributors. Useful for continuous integration. Add compile options to the targets enabling extra warnings and treating warnings as errors. +* `SET_REPLACE_ENABLE_ALLWARNINGS`: + For developers and contributors. Useful for continuous integration. Add compile options to the targets enabling extra + warnings and treating warnings as errors. -- `SET_REPLACE_EXTRA_COMPILE_OPTIONS`: -Add extra compilation options in addition to ones added by using the options above. +* `SET_REPLACE_EXTRA_COMPILE_OPTIONS`: + Add extra compilation options in addition to ones added by using the options above. -- `SET_REPLACE_COMPILE_OPTIONS_OVERRIDE`: -Set all compilations options directly. +* `SET_REPLACE_COMPILE_OPTIONS_OVERRIDE`: + Set all compilations options directly. For example, to build *libSetReplace* with tests, replace the second line in the above with @@ -364,9 +522,20 @@ Each file consists of a single [`Association`](https://reference.wolfram.com/lan <|"FunctionName" -> <|"init" -> ..., "tests" -> {VerificationTest[...], ...}, "options" -> ...|>, ...|> ``` -`"FunctionName"` is the name of a test group. It's what appears in the command line output of the test script to the left from `[ok]`. `"init"` is the code that runs before the tests. It usually contains definitions of test functions or constants commonly used in the tests. `"tests"` is code, which if evaluated after `"init"` results in the arbitrarily-nested structure of lists of [`VerificationTest`](https://reference.wolfram.com/language/ref/VerificationTest.html)s. Finally, `"options"` is currently only used to disable parallelization, which can be done by setting it to `{"Parallel" -> False}`. - -Apart from [`VerificationTest`](https://reference.wolfram.com/language/ref/VerificationTest.html), there are other convenience testing functions defined in [testUtilities.m](/Kernel/testUtilities.m). For example, `testUnevaluated` can be used to test if the function returns unevaluated for given arguments. `testSymbolLeak` can check if internal symbols are not garbage-collected during the evaluation. `checkGraphics` and `graphicsQ` can check if the `Graphics` objects are valid (i.e., don't have pink background if shown in the Mathematica Front End). Since these are `PackageScope` functions, they need to be used as, e.g., ``SetReplace`PackageScope`testUnevaluated[VerificationTest, args]``. To avoid typing `PackageScope` every time, however, it is convenient to define them in `"init"` as, e.g., +`"FunctionName"` is the name of a test group. It's what appears in the command line output of the test script to the +left from `[ok]`. `"init"` is the code that runs before the tests. It usually contains definitions of test functions or +constants commonly used in the tests. `"tests"` is code, which if evaluated after `"init"` results in the +arbitrarily-nested structure of lists +of [`VerificationTest`](https://reference.wolfram.com/language/ref/VerificationTest.html)s. Finally, `"options"` is +currently only used to disable parallelization, which can be done by setting it to `{"Parallel" -> False}`. + +Apart from [`VerificationTest`](https://reference.wolfram.com/language/ref/VerificationTest.html), there are other +convenience testing functions defined in [testUtilities.m](/Kernel/testUtilities.m). For example, `testUnevaluated` can +be used to test if the function returns unevaluated for given arguments. `testSymbolLeak` can check if internal symbols +are not garbage-collected during the evaluation. `checkGraphics` and `graphicsQ` can check if the `Graphics` objects are +valid (i.e., don't have pink background if shown in the Mathematica Front End). Since these are `PackageScope` +functions, they need to be used as, e.g., ``SetReplace`PackageScope`testUnevaluated[VerificationTest, args]``. To avoid +typing `PackageScope` every time, however, it is convenient to define them in `"init"` as, e.g., ```wl Attributes[Global`testUnevaluated] = {HoldAll}; @@ -382,26 +551,36 @@ testUnevaluated[ ] ``` -Note that it's essential to test not only the functionality but also the behavior of the function in case it's called with invalid (or missing) arguments. +Note that it's essential to test not only the functionality but also the behavior of the function in case it's called +with invalid (or missing) arguments. -The tests should be deterministic so that they can be easily reproduced. If the test cases are randomly generated, this can be achieved by setting [`SeedRandom`](https://reference.wolfram.com/language/ref/SeedRandom.html). +The tests should be deterministic so that they can be easily reproduced. If the test cases are randomly generated, this +can be achieved by setting [`SeedRandom`](https://reference.wolfram.com/language/ref/SeedRandom.html). -If you want to implement performance tests, put them in the [`./performanceTest.wls` script](/performanceTest.wls) instead of the [Tests directory](/Tests). +If you want to implement performance tests, put them in the [`./performanceTest.wls` script](/performanceTest.wls) +instead of the [Tests directory](/Tests). ### Documentation -The *SetReplace* documentation is contained in three places: [README.md](/README.md), [CONTRIBUTING.md](CONTRIBUTING.md) (this file), and the code comments. +The *SetReplace* documentation is contained in three places: [README.md](/README.md) +, [CONTRIBUTING.md](CONTRIBUTING.md) (this file), and the code comments. Some things to note are: + * Large [README](/README.md) sections should include navigation bars in the beginning. -* All references to functions should be links, either to [the Wolfram Language documentation](https://reference.wolfram.com/language/) or to the corresponding section in [README](/README.md). -* The comments in the Wolfram Language code are encouraged, and the C++ code is documented using [Doxygen](http://www.doxygen.nl). +* All references to functions should be links, either + to [the Wolfram Language documentation](https://reference.wolfram.com/language/) or to the corresponding section + in [README](/README.md). +* The comments in the Wolfram Language code are encouraged, and the C++ code is documented + using [Doxygen](http://www.doxygen.nl). ### Scripts -If you are using the *in-place* workflow, you will typically only need to run the [test.wls](/test.wls) script, but this section will describe the other scripts too. +If you are using the *in-place* workflow, you will typically only need to run the [test.wls](/test.wls) script, but this +section will describe the other scripts too. The four main scripts of *SetReplace* are: + * [build.wls](/build.wls), which builds *libSetReplace* (if necessary) * [test.wls](/test.wls), which first calls `build.wls`, then runs the full test suite. * [pack.wls](/pack.wls), which first calls `build.wls`, then produces a `.paclet` file @@ -409,20 +588,27 @@ The four main scripts of *SetReplace* are: All four scripts use functionality defined in the [DevUtils](/DevUtils) package. -Note that the `pack.wls` script will auto-generate the paclet version number based on the number of commits to master from the checkpoint defined in [version.wl](/scripts/version.wl). +Note that the `pack.wls` script will auto-generate the paclet version number based on the number of commits to master +from the checkpoint defined in [version.wl](/scripts/version.wl). -## Code style +## Style -#### Wolfram Language +### Wolfram Language -Unfortunately, there are no established style guidelines for Wolfram Language code. Here, the best rule is to try to be consistent as much as possible with the existing *SetReplace* code. +Unfortunately, there are no established style guidelines for Wolfram Language code. Here, the best rule is to try to be +consistent as much as possible with the existing *SetReplace* code. In addition to that, here are some more-or-less established rules: + * Keep line widths within 120 characters. -* Use at most a single empty line to separate code paragraphs (note, the Front End uses two by default, which should be manually fixed if you use the Front End for editing). +* Use at most a single empty line to separate code paragraphs (note, the Front End uses two by default, which should be + manually fixed if you use the Front End for editing). * Don't use section and cell definitions for comments, such as `(* ::Text:: *)`. * Use spaces instead of tabs, and use 2 spaces for indentation. -* Close code block function brackets on the new line (for functions such as [`Module`](https://reference.wolfram.com/language/ref/Module.html), [`With`](https://reference.wolfram.com/language/ref/With.html) and [`If`](https://reference.wolfram.com/language/ref/If.html)): +* Close code block function brackets on the new line (for functions such + as [`Module`](https://reference.wolfram.com/language/ref/Module.html) + , [`With`](https://reference.wolfram.com/language/ref/With.html) + and [`If`](https://reference.wolfram.com/language/ref/If.html)): ```wl Module[{result = f[x]}, @@ -445,7 +631,8 @@ In addition to that, here are some more-or-less established rules: longArgument1, longArgument2, longArgument3] ``` -* The function arguments should either all go on the same line, or should each be put on a separate line (except for special cases where a large quantity of short arguments is used): +* The function arguments should either all go on the same line, or should each be put on a separate line (except for + special cases where a large quantity of short arguments is used): ```wl hypergraphPlot[ @@ -463,8 +650,17 @@ In addition to that, here are some more-or-less established rules: ...] ``` -* Avoid using [`Flatten`](https://reference.wolfram.com/language/ref/Flatten.html) and [`ReplaceAll`](https://reference.wolfram.com/language/ref/ReplaceAll.html) without explicit level arguments. That is because it is very easy to accidentally assume that the user's input is not a [`List`](https://reference.wolfram.com/language/ref/List.html) (e.g., a vertex name), even though it can be, in which case you would [`Flatten`](https://reference.wolfram.com/language/ref/Flatten.html) too much, and cause a weed. It is preferred to use [`Catenate`](https://reference.wolfram.com/language/ref/Catenate.html) and [`Replace`](https://reference.wolfram.com/language/ref/Replace.html) instead of these functions. -* Similar issue could happen with [`Thread`](https://reference.wolfram.com/language/ref/Thread.html), especially when used to thread a single element over multiple. For example, it is easy to assume naively that `Thread[x -> {1, 2, 3}]` would always yield `{x -> 1, x -> 2, x -> 3}`. Except, sometimes it might be called as `With[{x = {4, 5, 6}}, Thread[x -> {1, 2, 3}]]`. +* Avoid using [`Flatten`](https://reference.wolfram.com/language/ref/Flatten.html) + and [`ReplaceAll`](https://reference.wolfram.com/language/ref/ReplaceAll.html) without explicit level arguments. That + is because it is very easy to accidentally assume that the user's input is not + a [`List`](https://reference.wolfram.com/language/ref/List.html) (e.g., a vertex name), even though it can be, in + which case you would [`Flatten`](https://reference.wolfram.com/language/ref/Flatten.html) too much, and cause a weed. + It is preferred to use [`Catenate`](https://reference.wolfram.com/language/ref/Catenate.html) + and [`Replace`](https://reference.wolfram.com/language/ref/Replace.html) instead of these functions. +* Similar issue could happen with [`Thread`](https://reference.wolfram.com/language/ref/Thread.html), especially when + used to thread a single element over multiple. For example, it is easy to assume naively that `Thread[x -> {1, 2, 3}]` + would always yield `{x -> 1, x -> 2, x -> 3}`. Except, sometimes it might be called + as `With[{x = {4, 5, 6}}, Thread[x -> {1, 2, 3}]]`. * Use uppercase camel for public symbols, lowercase camel for internal (including PackageScope) symbols: ```wl @@ -473,8 +669,18 @@ In addition to that, here are some more-or-less established rules: PackageScope["propertyEvaluate"] ``` -* Start global constants with `$`, whether internal or public, and tags (such as used in [`Throw`](https://reference.wolfram.com/language/ref/Throw.html) or [`Sow`](https://reference.wolfram.com/language/ref/Sow.html), or as generic enum labels) with `$$`. Global pure functions (defined as [`OwnValues`](https://reference.wolfram.com/language/ref/OwnValues.html)) should still be treated as ordinary (e.g., [`DownValues`](https://reference.wolfram.com/language/ref/DownValues.html)) functions and not start with `$`, unless they are public, in which case they should start with `$` and end with the word `Function`. -* Use the macros `ModuleScope` and `Scope` (defined in ``"GeneralUtilities`"``) instead of `Module` and `Block` (respectively) when defining functions of the form `f[x__] := (Module|Block)[...]`. The main benefit of using them is that there is no need to specify a list of local variables (i.e. `{localVar1, localVar2, ...}`) at the beginning, as a list of local variables will be automatically generated by looking for expressions of the form `Set` (`=`) or `SetDelayed` (`:=`) anywhere in the body of the function (See `?Scope` and [#460](https://github.com/maxitg/SetReplace/pull/460) for more information). For example: +* Start global constants with `$`, whether internal or public, and tags (such as used + in [`Throw`](https://reference.wolfram.com/language/ref/Throw.html) + or [`Sow`](https://reference.wolfram.com/language/ref/Sow.html), or as generic enum labels) with `$$`. Global pure + functions (defined as [`OwnValues`](https://reference.wolfram.com/language/ref/OwnValues.html)) should still be + treated as ordinary (e.g., [`DownValues`](https://reference.wolfram.com/language/ref/DownValues.html)) functions and + not start with `$`, unless they are public, in which case they should start with `$` and end with the word `Function`. +* Use the macros `ModuleScope` and `Scope` (defined in ``"GeneralUtilities`"``) instead of `Module` and `Block` ( + respectively) when defining functions of the form `f[x__] := (Module|Block)[...]`. The main benefit of using them is + that there is no need to specify a list of local variables (i.e. `{localVar1, localVar2, ...}`) at the beginning, as a + list of local variables will be automatically generated by looking for expressions of the form `Set` (`=`) + or `SetDelayed` (`:=`) anywhere in the body of the function (See `?Scope` + and [#460](https://github.com/maxitg/SetReplace/pull/460) for more information). For example: ```wl example[hypergraph1_, hypergraph2_] := ModuleScope[ @@ -485,6 +691,7 @@ In addition to that, here are some more-or-less established rules: ]; ] ``` + is expanded to: ```wl @@ -497,16 +704,18 @@ In addition to that, here are some more-or-less established rules: ] ``` -#### C++ +### C++ + The code should follow [Google C++ Style](https://google.github.io/styleguide/cppguide.html) guidelines, save for the following exceptions: + * Maximum line length is 120 characters. * Function and variable names, including const and constexpr variables, use lower camel case. * Namespace and class names use upper camel case. * C++ exceptions may be thrown. * White space in pointer and reference declarations goes after the `*` or `&` character. For example: - * `int* foo;` - * `const std::string& string;` + * `int* foo;` + * `const std::string& string;` * If splitting function arguments into multiple lines, each argument should go on a separate line. * License, authors, and file descriptions should not be put at the top of files. * Doxygen format is used for documentation. @@ -518,15 +727,18 @@ We use [`clang-format`](https://clang.llvm.org/docs/ClangFormat.html) for format We use [`shfmt`](https://github.com/mvdan/sh) for formatting and [`shellcheck`](https://github.com/koalaman/shellcheck) for linting Bash code. -To run these automatically, call `./lint.sh`. This will print a formatting diff and error messages from `cpplint` and `shellcheck`. -If there are no errors found, it will exit with no output. -To edit the code in place with the fixed formatting use `./lint.sh -i`. +To run these automatically, call `./lint.sh`. This will print a formatting diff and error messages from `cpplint` +and `shellcheck`. If there are no errors found, it will exit with no output. To edit the code in place with the fixed +formatting use `./lint.sh -i`. We have two useful git hooks that you may install: + 1. `pre-commit` formats any staged files before committing. 2. `pre-push` checks for formatting and linting errors before pushing. -You may install these hooks by running `./scripts/install_git_hooks.sh`. By default, both hooks will be installed. If you only wish to install one, pass the name of the hook as an argument (e.g., `./scripts/install_git_hooks.sh pre-commit`). +You may install these hooks by running `./scripts/install_git_hooks.sh`. By default, both hooks will be installed. If +you only wish to install one, pass the name of the hook as an argument ( +e.g., `./scripts/install_git_hooks.sh pre-commit`). You may uninstall a hook by running `rm .git/hooks/hook-name` where `hook-name` is `pre-commit` or `pre-push`. @@ -539,18 +751,23 @@ comments section. If you want to disable formatting, use `// clang-format off` and `// clang-format on` around the manually formatted code. -#### Markdown +### Markdown + We are using GitHub-flavored Markdown for documentation and research notes. +We use [`markdownlint`](https://github.com/DavidAnson/markdownlint) for formatting and linting markdown text. + #### Manual image embedding -Images (e.g., of output cells) can be made by selecting the relevant cells in the Front End, copying them as bitmaps, and saving them as .png files to [Documentation/Images](/Documentation/Images) (in the documentation) or to the Images directory of the corresponding research note. They should then be inserted using the code similar to this: +Images (e.g., of output cells) can be made by selecting the relevant cells in the Front End, copying them as bitmaps, +and saving them as .png files to [Documentation/Images](/Documentation/Images) (in the documentation) or to the Images +directory of the corresponding research note. They should then be inserted using the code similar to this: ```html ``` - where the `width` should be computed as +where the `width` should be computed as ```wl Round[0.6 First @ Import["$RepoRoot/Documentation/Images/image.png", "ImageSize"]] @@ -558,38 +775,60 @@ Images (e.g., of output cells) can be made by selecting the relevant cells in th #### Markdown automation -The above process can be somewhat automated from within a notebook by using the `RasterizePreviousInputOutputAndExportToMarkdown` function in the ``DevUtils` `` support package. To use this workflow, first load DevUtils by running the following (where you should substitute the actual location of your *SetReplace* repository): +The above process can be somewhat automated from within a notebook by using +the `RasterizePreviousInputOutputAndExportToMarkdown` function in the ``DevUtils` `` support package. To use this +workflow, first load DevUtils by running the following (where you should substitute the actual location of your * +SetReplace* repository): ```wl Get["~/git/SetReplace/DevUtils/init.m"]; ``` -Next, find the input/output cell pair that you wish to include in your markdown. Then, create a new input cell *after* the pair, containing the following code, and run it: +Next, find the input/output cell pair that you wish to include in your markdown. Then, create a new input cell *after* +the pair, containing the following code, and run it: ```wl RasterizePreviousInputOutputAndExportToMarkdown["Documentation/Images/NameOfTargetFile.png"] ``` -This will rasterize the previous *output* cell, save the resulting image to the given location within the repository, and produce a snippet of markdown code that contains the right image tag. In addition, the markdown will contain a code block that contains the textual form of the preceding *input* cell. You can copy-paste this markdown code into the appropriate markdown file. +This will rasterize the previous *output* cell, save the resulting image to the given location within the repository, +and produce a snippet of markdown code that contains the right image tag. In addition, the markdown will contain a code +block that contains the textual form of the preceding *input* cell. You can copy-paste this markdown code into the +appropriate markdown file. -Note that for convenience, the relative directory "Documentation/Images/" will be automatically used if you do not specify a directory for the image file. +Note that for convenience, the relative directory "Documentation/Images/" will be automatically used if you do not +specify a directory for the image file. -If the image is too large, you can use the option "ColorMapLength" -> 10 (or below) to reduce the file size. You can experiment with the value 10 to balance file size with accuracy. +If the image is too large, you can use the option "ColorMapLength" -> 10 (or below) to reduce the file size. You can +experiment with the value 10 to balance file size with accuracy. -Run `?RasterizePreviousInputOutputAndExportToMarkdown` to see more information and options, as well as related rasterization functions. +Run `?RasterizePreviousInputOutputAndExportToMarkdown` to see more information and options, as well as related +rasterization functions. # Research -We have recently started publishing research notes directly in *SetReplace*. These research notes should go to the [Research](/Research) directory. - -The idea here is to have a mini-"journal", where the peer review is implemented in the same way as code review, the documents are organized as a wiki (by subject rather than by date), and can be updated any time. - -We expect the same high level of quality here as in the rest of *SetReplace*. In particular, we should be reasonably confident that everything written in the research notes is correct. This means: -* If you are discussing a hypothesis or speculation that is not necessarily correct, it should be explicitly mentioned in the text. -* If you rely on results of a computation, you can only use stable code to run that computation. This includes *SetReplace* and build-in Wolfram Language functions. However, it ***does not*** include Wolfram Function Repository functions. If you need to rely on such functions' output, you will need to add similar functionality to *SetReplace* first. -* However, you can use Wolfram Function Repository functions for demonstration purposes in cases where their output can be easily verified by a reviewer. -* You are equally welcome to modify existing research notes as well as create new ones. You don't have to be the original author of the note to modify it (although it is a good idea to request a review from the original author). - -Research notes should follow the same [development process](#development-process) as the rest of *SetReplace* except for tests. In particular, pull requests should still be kept under 500 lines and follow the [Markdown formatting rules](#markdown). +We have recently started publishing research notes directly in *SetReplace*. These research notes should go to +the [Research](/Research) directory. + +The idea here is to have a mini-"journal", where the peer review is implemented in the same way as code review, the +documents are organized as a wiki (by subject rather than by date), and can be updated any time. + +We expect the same high level of quality here as in the rest of *SetReplace*. In particular, we should be reasonably +confident that everything written in the research notes is correct. This means: + +* If you are discussing a hypothesis or speculation that is not necessarily correct, it should be explicitly mentioned + in the text. +* If you rely on results of a computation, you can only use stable code to run that computation. This includes * + SetReplace* and build-in Wolfram Language functions. However, it ***does not*** include Wolfram Function Repository + functions. If you need to rely on such functions' output, you will need to add similar functionality to *SetReplace* + first. +* However, you can use Wolfram Function Repository functions for demonstration purposes in cases where their output can + be easily verified by a reviewer. +* You are equally welcome to modify existing research notes as well as create new ones. You don't have to be the + original author of the note to modify it (although it is a good idea to request a review from the original author). + +Research notes should follow the same [development process](#development-process) as the rest of *SetReplace* except for +tests. In particular, pull requests should still be kept under 500 lines and follow +the [Markdown formatting rules](#markdown). That's all for our guidelines, now let's go figure out the fundamental theory of physics! :rocket: diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index ac8eaa95b..524709ed6 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -8,13 +8,17 @@ assignees: '' --- ### The problem + Is your feature request related to a problem? Please describe. Ex. I'm always frustrated when [...] ### Possible solution + A clear and concise description of what you want to happen. ### Alternative solutions + A clear and concise description of any alternative solutions or features you've considered. ### Additional context + Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/weed_report.md b/.github/ISSUE_TEMPLATE/weed_report.md index 1b467cef8..9068e830f 100644 --- a/.github/ISSUE_TEMPLATE/weed_report.md +++ b/.github/ISSUE_TEMPLATE/weed_report.md @@ -8,25 +8,33 @@ assignees: '' --- ### The problem + A clear and concise description of what is not working. + ```wl In[] := minimal input that is not working ``` + image of the actual output. ### Expected behavior + A clear and concise description of what you expected to happen. ### Version + ```wl In[] := SystemInformation["Small"] ``` + image of the output ```wl In[] := $SetReplaceGitSHA ``` + paste the output here without quotes. ### Additional context + Add any other context or screenshots about the weed report here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0c7cefacc..a0e3d5408 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,9 +1,12 @@ ## Changes + * Reference resolved issues. * Add a few comments about what this pull request changes. ## Comments + * Add comments for the reviewer. ## Examples + * Add explicit inputs and outputs (as screenshots in case of graphics) showcasing new functionality. diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 000000000..6383c1d12 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,10 @@ +{ + "line-length": { + "line_length": 120, + "headers": false + }, + "no-inline-html": false, + "first-line-h1": false, + "no-blanks-blockquote": false, + "no-duplicate-heading": false +} diff --git a/Documentation/SymbolsAndFunctions/HypergraphPlot.md b/Documentation/SymbolsAndFunctions/HypergraphPlot.md index 6b8a0199e..ad67e59c6 100644 --- a/Documentation/SymbolsAndFunctions/HypergraphPlot.md +++ b/Documentation/SymbolsAndFunctions/HypergraphPlot.md @@ -2,9 +2,15 @@ # HypergraphPlot -[Edge Type](#edge-type) | [GraphHighlight and GraphHighlightStyle](#graphhighlight-and-graphhighlightstyle) | ["HyperedgeRendering"](#hyperedgerendering) | [VertexCoordinateRules](#vertexcoordinaterules) | [VertexLabels](#vertexlabels) | [VertexSize and "ArrowheadLength"](#vertexsize-and-arrowheadlength) | ["MaxImageSize"](#maximagesize) | [Style Options](#style-options) | [Graphics Options](#graphics-options) +[Edge Type](#edge-type) | [GraphHighlight and GraphHighlightStyle](#graphhighlight-and-graphhighlightstyle) +| ["HyperedgeRendering"](#hyperedgerendering) | [VertexCoordinateRules](#vertexcoordinaterules) +| [VertexLabels](#vertexlabels) | [VertexSize and "ArrowheadLength"](#vertexsize-and-arrowheadlength) +| ["MaxImageSize"](#maximagesize) | [Style Options](#style-options) | [Graphics Options](#graphics-options) -**`HypergraphPlot`** (aka `WolframModelPlot`) is a function used to visualize [`WolframModel`](WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md) states. It treats lists of vertices as ordered hypergraphs, and displays each hyperedge as a polygon with arrows showing the ordering: +**`HypergraphPlot`** (aka `WolframModelPlot`) is a function used to +visualize [`WolframModel`](WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md) +states. It treats lists of vertices as ordered hypergraphs, and displays each hyperedge as a polygon with arrows showing +the ordering: ```wl In[] := HypergraphPlot[{{1, 2, 3}, {3, 4, 5}, {5, 6, 7, 1}}] @@ -12,7 +18,8 @@ In[] := HypergraphPlot[{{1, 2, 3}, {3, 4, 5}, {5, 6, 7, 1}}] -Edges of any arity can be mixed. The binary edges are displayed as non-filled arrows, and the unary edges are shown as circles around the vertices: +Edges of any arity can be mixed. The binary edges are displayed as non-filled arrows, and the unary edges are shown as +circles around the vertices: ```wl In[] := HypergraphPlot[{{1, 2, 3}, {3, 4}, {4, 3}, {4, 5, @@ -37,7 +44,8 @@ In[] := HypergraphPlot[{{1, 2, 1}, {2, 3}, {3, 2}}] -Multiedges are shown in a darker color (because of overlaid partially transparent polygons), or as separate polygons depending on the layout (and are admittedly sometimes hard to understand): +Multiedges are shown in a darker color (because of overlaid partially transparent polygons), or as separate polygons +depending on the layout (and are admittedly sometimes hard to understand): ```wl In[] := HypergraphPlot[{{1, 2, 3}, {3, 4, 5}, {3, 4, 5}, {1, 6, 6}, {1, 6, @@ -56,11 +64,17 @@ In[] := HypergraphPlot[{{{1, 2, 3}}, -Many [`WolframModel`](WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md) properties, such as [`"FinalStatePlot"`](WolframModelAndWolframModelEvolutionObject/Properties/PlotsOfStates.md) and [`"EventStatesPlotsList"`](WolframModelAndWolframModelEvolutionObject/Properties/PlotsOfEvents.md), use `HypergraphPlot` to produce output. They accept the same set of options, as enumerated below. +Many [`WolframModel`](WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md) +properties, such as [`"FinalStatePlot"`](WolframModelAndWolframModelEvolutionObject/Properties/PlotsOfStates.md) +and [`"EventStatesPlotsList"`](WolframModelAndWolframModelEvolutionObject/Properties/PlotsOfEvents.md), +use `HypergraphPlot` to produce output. They accept the same set of options, as enumerated below. ## Edge Type -By default, `HypergraphPlot` assumes the hypergraph edges are ordered. It is also possible to treat edges as cyclic instead (i.e., assume [`RotateLeft`](https://reference.wolfram.com/language/ref/RotateLeft.html) and [`RotateRight`](https://reference.wolfram.com/language/ref/RotateRight.html) don't change the edge), in which case `"Cyclic"` should be used as the second argument to `HypergraphPlot`: +By default, `HypergraphPlot` assumes the hypergraph edges are ordered. It is also possible to treat edges as cyclic +instead (i.e., assume [`RotateLeft`](https://reference.wolfram.com/language/ref/RotateLeft.html) +and [`RotateRight`](https://reference.wolfram.com/language/ref/RotateRight.html) don't change the edge), in which +case `"Cyclic"` should be used as the second argument to `HypergraphPlot`: ```wl In[] := HypergraphPlot[{{1, 2, 3}, {3, 4, 5}, {5, 6, 7, 1}}, "Cyclic"] @@ -100,7 +114,10 @@ In[] := HypergraphPlot[{{1, 2, 3}, {3, 4, 5}, {5, 6, 7, 1}, {7, 8, 2}, {4, ## "HyperedgeRendering" -By default, `HypergraphPlot` represents each hyperedge as a polygon. It is possible instead to drop the polygons (and the vertex layout adjustments that come with them), and simply split each hyperedge into a collection of binary edges by setting **`"HyperedgeRendering"`** to `"Subgraphs"`. This loses information (`{{1, 2}, {2, 3}}` and `{{1, 2, 3}}` would look the same), but might be useful if one does not care to see the separation between hyperedges: +By default, `HypergraphPlot` represents each hyperedge as a polygon. It is possible instead to drop the polygons (and +the vertex layout adjustments that come with them), and simply split each hyperedge into a collection of binary edges by +setting **`"HyperedgeRendering"`** to `"Subgraphs"`. This loses information (`{{1, 2}, {2, 3}}` and `{{1, 2, 3}}` would +look the same), but might be useful if one does not care to see the separation between hyperedges: ```wl In[] := HypergraphPlot[{{1, 2, 3}, {3, 4, 5}, {5, 6, 7, 1}, {7, 8, 2}, {4, @@ -122,7 +139,10 @@ In[] := HypergraphPlot[{{1, 2, 3}, {2, 4, 5}, {2, 6, 7, 8}, {8, 9, 1}}, -Unfortunately, due to limitations of [`GraphEmbedding`](https://reference.wolfram.com/language/ref/GraphEmbedding.html), specifying coordinates of two or more vertices breaks the scaling of distances. As a result, vertices and arrowheads might appear too small or too large and need to be manually adjusted. This might also affect [`RulePlot`](RulePlotOfWolframModel.md) in some cases. +Unfortunately, due to limitations of [`GraphEmbedding`](https://reference.wolfram.com/language/ref/GraphEmbedding.html), +specifying coordinates of two or more vertices breaks the scaling of distances. As a result, vertices and arrowheads +might appear too small or too large and need to be manually adjusted. This might also +affect [`RulePlot`](RulePlotOfWolframModel.md) in some cases. ```wl In[] := HypergraphPlot[{{1, 2, 3}, {2, 4, 5}, {2, 6, 7, 8}, {8, 9, 1}}, @@ -141,7 +161,8 @@ In[] := HypergraphPlot[{{1, 2, 3}, {2, 4, 5}, {2, 6, 7, 8}, {8, 9, 1}}, ## VertexLabels -`"VertexLabels" -> Automatic` displays labels for vertices, similar to [`GraphPlot`](https://reference.wolfram.com/language/ref/GraphPlot.html): +`"VertexLabels" -> Automatic` displays labels for vertices, similar +to [`GraphPlot`](https://reference.wolfram.com/language/ref/GraphPlot.html): ```wl In[] := HypergraphPlot[{{1, 2, 3}, {2, 4, 5}, {2, 6, 7, 8}, {8, 9, 1}}, @@ -152,7 +173,8 @@ In[] := HypergraphPlot[{{1, 2, 3}, {2, 4, 5}, {2, 6, 7, 8}, {8, 9, 1}}, ## VertexSize and "ArrowheadLength" -The size of vertices and the length of arrowheads (in the internal graphics units), can be adjusted with **`VertexSize`** and **`"ArrowheadLength"`** options respectively: +The size of vertices and the length of arrowheads (in the internal graphics units), can be adjusted +with **`VertexSize`** and **`"ArrowheadLength"`** options respectively: ```wl In[] := HypergraphPlot[{{1, 2, 3, 4}, {1, 5, 6}, {2, 7, 8}, {4, 6, 9}}, @@ -161,7 +183,10 @@ In[] := HypergraphPlot[{{1, 2, 3, 4}, {1, 5, 6}, {2, 7, 8}, {4, 6, 9}}, -Note that unlike [`GraphPlot`](https://reference.wolfram.com/language/ref/GraphPlot.html), both vertices and arrowheads have a fixed size relative to the layout (in fact, the arrowheads are drawn manually as polygons). This fixed size implies that they scale proportionally when the image is resized, and do not overlay/disappear for tiny/huge graphs or image sizes. +Note that unlike [`GraphPlot`](https://reference.wolfram.com/language/ref/GraphPlot.html), both vertices and arrowheads +have a fixed size relative to the layout (in fact, the arrowheads are drawn manually as polygons). This fixed size +implies that they scale proportionally when the image is resized, and do not overlay/disappear for tiny/huge graphs or +image sizes. These options can also be used to get rid of vertices and arrowheads altogether: @@ -187,7 +212,8 @@ In[] := HypergraphPlot[{{1, 2, 2}, {2, 3, 3}, {3, 1, 1}}, ## "MaxImageSize" -**`"MaxImageSize"`** allows one to specify the image size while allowing for automatic reduction for very small hypergraphs. To demonstrate that, consider the difference: +**`"MaxImageSize"`** allows one to specify the image size while allowing for automatic reduction for very small +hypergraphs. To demonstrate that, consider the difference: ```wl In[] := HypergraphPlot[{{{1}}, {{1, 1}}, {{1, 2, 3}}}, @@ -246,7 +272,8 @@ In[] := HypergraphPlot[{{1, 2, 3}, {3, 4, 5}, {5, 6, 7, 1}, {7, 8, 2}, {4, -It is possible to specify styles separately for each edge and vertex. Vertex styles are specified in the same order as `Union @* Catenate` evaluated on the list of edges: +It is possible to specify styles separately for each edge and vertex. Vertex styles are specified in the same order +as `Union @* Catenate` evaluated on the list of edges: ```wl In[] := HypergraphPlot[{{1, 2, 3}, {3, 4, 5}, {5, 6, 7, 1}, {7, 8, 2}, {4, @@ -256,7 +283,9 @@ In[] := HypergraphPlot[{{1, 2, 3}, {3, 4, 5}, {5, 6, 7, 1}, {7, 8, 2}, {4, -Alternatively, one can specify different styles for different patterns of elements. In this case, styles are specified as [`Association`](https://reference.wolfram.com/language/ref/Association.html)s with patterns for keys. This can be used to, for example, differently color edges of different arities: +Alternatively, one can specify different styles for different patterns of elements. In this case, styles are specified +as [`Association`](https://reference.wolfram.com/language/ref/Association.html)s with patterns for keys. This can be +used to, for example, differently color edges of different arities: ```wl In[] := HypergraphPlot[WolframModel[{{1, 2, 3}, {4, 5, 6}, {2, 5}, {5, 2}} -> @@ -271,7 +300,10 @@ In[] := HypergraphPlot[WolframModel[{{1, 2, 3}, {4, 5, 6}, {2, 5}, {5, 2}} -> ## Graphics Options -All [`Graphics`](https://reference.wolfram.com/language/ref/Graphics.html) options are supported as well, such as [`Background`](https://reference.wolfram.com/language/ref/Background.html), [`PlotRange`](https://reference.wolfram.com/language/ref/PlotRange.html), [`Axes`](https://reference.wolfram.com/language/ref/Axes.html), etc.: +All [`Graphics`](https://reference.wolfram.com/language/ref/Graphics.html) options are supported as well, such +as [`Background`](https://reference.wolfram.com/language/ref/Background.html) +, [`PlotRange`](https://reference.wolfram.com/language/ref/PlotRange.html) +, [`Axes`](https://reference.wolfram.com/language/ref/Axes.html), etc.: ```wl In[] := HypergraphPlot[WolframModel[{{1, 2}} -> {{1, 3}, {1, 3}, {3, 2}}, diff --git a/Documentation/SymbolsAndFunctions/RulePlotOfWolframModel.md b/Documentation/SymbolsAndFunctions/RulePlotOfWolframModel.md index a410d502a..6299c1b56 100644 --- a/Documentation/SymbolsAndFunctions/RulePlotOfWolframModel.md +++ b/Documentation/SymbolsAndFunctions/RulePlotOfWolframModel.md @@ -2,7 +2,8 @@ # RulePlot of WolframModel -[**`RulePlot`**](https://reference.wolfram.com/language/ref/RulePlot.html) can be used to get a [`HypergraphPlot`](HypergraphPlot.md)-based visual representation of hypergraph substitution rules: +[**`RulePlot`**](https://reference.wolfram.com/language/ref/RulePlot.html) can be used to get +a [`HypergraphPlot`](HypergraphPlot.md)-based visual representation of hypergraph substitution rules: ```wl In[] := RulePlot[WolframModel[{{1, 2}, {1, 2}} -> @@ -11,7 +12,8 @@ In[] := RulePlot[WolframModel[{{1, 2}, {1, 2}} -> -The shared elements between rule sides (vertices `1` and `2` in the example above) are put at the same positions in the `RulePlot` and highlighted in a darker shade of blue. Shared edges are highlighted as well: +The shared elements between rule sides (vertices `1` and `2` in the example above) are put at the same positions in +the `RulePlot` and highlighted in a darker shade of blue. Shared edges are highlighted as well: ```wl In[] := RulePlot[WolframModel[{{1, 2, 3}} -> {{1, 2, 3}, {3, 4, 5}}]] @@ -29,13 +31,17 @@ In[] := RulePlot[WolframModel[{{{1, 1, 2}} -> -Passing a [`WolframModelEvolutionObject`](/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md) plots its [`"Rules"`](/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/Rules.md) property: +Passing +a [`WolframModelEvolutionObject`](/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md) +plots its [`"Rules"`](/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/Rules.md) +property: -Sometimes an incorrectly scaled layout might be produced due to the issue discussed above in [`VertexCoordinateRules`](HypergraphPlot.md#vertexcoordinaterules): +Sometimes an incorrectly scaled layout might be produced due to the issue discussed above +in [`VertexCoordinateRules`](HypergraphPlot.md#vertexcoordinaterules): ```wl In[] := RulePlot[WolframModel[{{1, 2}, {1, 3}, {1, 4}} -> @@ -55,9 +61,16 @@ In[] := RulePlot[WolframModel[{{1, 2}, {1, 3}, {1, 4}} -> -Some of the [`HypergraphPlot`](HypergraphPlot.md) options are supported, specifically [`GraphHighlightStyle`](HypergraphPlot.md#graphhighlight-and-graphhighlightstyle), [`"HyperedgeRendering"`](HypergraphPlot.md#hyperedgerendering), [`VertexCoordinateRules`](HypergraphPlot.md#vertexcoordinaterules), [`VertexLabels`](HypergraphPlot.md#vertexlabels), [`VertexSize`, `"ArrowheadLength"`](HypergraphPlot.md#vertexsize-and-arrowheadlength), and [style options](HypergraphPlot.md#style-options). `"EdgeType"` is supported as an option instead of [the second argument](HypergraphPlot.md#edge-type) like in [`HypergraphPlot`](HypergraphPlot.md). +Some of the [`HypergraphPlot`](HypergraphPlot.md) options are supported, +specifically [`GraphHighlightStyle`](HypergraphPlot.md#graphhighlight-and-graphhighlightstyle) +, [`"HyperedgeRendering"`](HypergraphPlot.md#hyperedgerendering) +, [`VertexCoordinateRules`](HypergraphPlot.md#vertexcoordinaterules), [`VertexLabels`](HypergraphPlot.md#vertexlabels) +, [`VertexSize`, `"ArrowheadLength"`](HypergraphPlot.md#vertexsize-and-arrowheadlength), +and [style options](HypergraphPlot.md#style-options). `"EdgeType"` is supported as an option instead +of [the second argument](HypergraphPlot.md#edge-type) like in [`HypergraphPlot`](HypergraphPlot.md). -There are also two additional `RulePlot`-specific style options. **`Spacings`** controls the amount of empty space between the rule parts and the frame (or the space where the frame would be if it's not shown): +There are also two additional `RulePlot`-specific style options. **`Spacings`** controls the amount of empty space +between the rule parts and the frame (or the space where the frame would be if it's not shown): ```wl In[] := RulePlot[WolframModel[{{{1, 2}} -> {{1, 3}, {1, 3}, {3, 2}}, @@ -66,7 +79,8 @@ In[] := RulePlot[WolframModel[{{{1, 2}} -> {{1, 3}, {1, 3}, {3, 2}}, -**`"RulePartsAspectRatio"`** is used to control the aspect ratio of rule sides. As an example, it can be used to force rule parts to be square: +**`"RulePartsAspectRatio"`** is used to control the aspect ratio of rule sides. As an example, it can be used to force +rule parts to be square: ```wl In[] := RulePlot[WolframModel[{{1, 2}} -> {{1, 3}, {1, 3}, {3, 2}}], diff --git a/Documentation/SymbolsAndFunctions/SetReplace.md b/Documentation/SymbolsAndFunctions/SetReplace.md index a100dfd52..9c435075f 100644 --- a/Documentation/SymbolsAndFunctions/SetReplace.md +++ b/Documentation/SymbolsAndFunctions/SetReplace.md @@ -2,9 +2,16 @@ # SetReplace* -**`SetReplace`** (and related **`SetReplaceList`**, **`SetReplaceAll`**, **`SetReplaceFixedPoint`** and **`SetReplaceFixedPointList`**) are the functions the package is named after. They are quite simple, and perform replacement operations either one-at-a-time (as in the case of `SetReplace`), to all non-overlapping subsets (`SetReplaceAll`), or until no more matches can be made (`SetReplaceFixedPoint`). A suffix `*List` implies the function returns a list of sets after each step instead of just the final result. +**`SetReplace`** (and related **`SetReplaceList`**, **`SetReplaceAll`**, **`SetReplaceFixedPoint`** +and **`SetReplaceFixedPointList`**) are the functions the package is named after. They are quite simple, and perform +replacement operations either one-at-a-time (as in the case of `SetReplace`), to all non-overlapping +subsets (`SetReplaceAll`), or until no more matches can be made (`SetReplaceFixedPoint`). A suffix `*List` implies the +function returns a list of sets after each step instead of just the final result. -These functions are good for their simplicity and can be primarily used to obtain replacement results. [`WolframModel`](WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md) is an advanced version of these functions and incorporates all of their features plus more sophisticated analysis capabilities. +These functions are good for their simplicity and can be primarily used to obtain replacement +results. [`WolframModel`](WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md) is +an advanced version of these functions and incorporates all of their features plus more sophisticated analysis +capabilities. As was mentioned previously, `SetReplace` performs a single iteration if called with two arguments: @@ -19,14 +26,16 @@ In[] := SetReplace[{1, 2, 5, 3, 6}, {a_, b_} :> {a + b}] Out[] = {5, 3, 6, 3} ``` -It can be supplied a third argument specifying the number of replacements (the same can be achieved using [`Nest`](https://reference.wolfram.com/language/ref/Nest.html)): +It can be supplied a third argument specifying the number of replacements (the same can be achieved +using [`Nest`](https://reference.wolfram.com/language/ref/Nest.html)): ```wl In[] := SetReplace[{1, 2, 5, 3, 6}, {a_, b_} :> {a + b}, 2] Out[] = {6, 3, 8} ``` -If the number of replacements is set to [`Infinity`](https://reference.wolfram.com/language/ref/Infinity.html) calling `SetReplace` is equivalent to `SetReplaceFixedPoint`: +If the number of replacements is set to [`Infinity`](https://reference.wolfram.com/language/ref/Infinity.html) +calling `SetReplace` is equivalent to `SetReplaceFixedPoint`: ```wl In[] := SetReplace[{1, 2, 5, 3, 6}, {a_, b_} :> {a + b}, Infinity] @@ -41,7 +50,10 @@ In[] := SetReplace[{1, 2, 5, 3, 6}, Out[] = {3, 5, 8} ``` -`SetReplaceList` can be used to see the set after each replacement (here a list is omitted on the right-hand side of the rule, which can be done if the subset only contains a single element). Similar to `SetReplace`, if the number of steps is [`Infinity`](https://reference.wolfram.com/language/ref/Infinity.html), it's equivalent to `SetReplaceFixedPointList`: +`SetReplaceList` can be used to see the set after each replacement (here a list is omitted on the right-hand side of the +rule, which can be done if the subset only contains a single element). Similar to `SetReplace`, if the number of steps +is [`Infinity`](https://reference.wolfram.com/language/ref/Infinity.html), it's equivalent +to `SetReplaceFixedPointList`: ```wl In[] := SetReplaceList[{1, 2, 5, 3, 6}, {a_, b_} :> a + b, Infinity] @@ -55,7 +67,8 @@ In[] := SetReplaceAll[{1, 2, 5, 3, 6}, {a_, b_} :> a + b] Out[] = {6, 3, 8} ``` -`SetReplaceFixedPoint` and `SetReplaceFixedPointList` perform replacements for as long as possible as previously mentioned: +`SetReplaceFixedPoint` and `SetReplaceFixedPointList` perform replacements for as long as possible as previously +mentioned: ```wl In[] := SetReplaceFixedPoint[{1, 2, 5, 3, 6}, {a_, b_} :> a + b] @@ -67,4 +80,11 @@ In[] := SetReplaceFixedPointList[{1, 2, 5, 3, 6}, {a_, b_} :> a + b] Out[] = {{1, 2, 5, 3, 6}, {5, 3, 6, 3}, {6, 3, 8}, {8, 9}, {17}} ``` -All of these functions have [`Method`](WolframModelAndWolframModelEvolutionObject/Options/Method.md), [`TimeConstraint`](WolframModelAndWolframModelEvolutionObject/Options/TimeConstraint.md) and [`"EventOrderingFunction"`](WolframModelAndWolframModelEvolutionObject/Options/EventOrderingFunction.md) options. [`TimeConstraint`](WolframModelAndWolframModelEvolutionObject/Options/TimeConstraint.md) is self-explanatory. The other two work the same way as they do in [`WolframModel`](WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md), and we describe them further in the [`WolframModel`](WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md) section. +All of these functions have [`Method`](WolframModelAndWolframModelEvolutionObject/Options/Method.md) +, [`TimeConstraint`](WolframModelAndWolframModelEvolutionObject/Options/TimeConstraint.md) +and [`"EventOrderingFunction"`](WolframModelAndWolframModelEvolutionObject/Options/EventOrderingFunction.md) +options. [`TimeConstraint`](WolframModelAndWolframModelEvolutionObject/Options/TimeConstraint.md) is self-explanatory. +The other two work the same way as they do +in [`WolframModel`](WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md), and we +describe them further in +the [`WolframModel`](WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md) section. diff --git a/Documentation/SymbolsAndFunctions/ToPatternRules.md b/Documentation/SymbolsAndFunctions/ToPatternRules.md index d4c7cf564..717f5470c 100644 --- a/Documentation/SymbolsAndFunctions/ToPatternRules.md +++ b/Documentation/SymbolsAndFunctions/ToPatternRules.md @@ -13,10 +13,16 @@ This is the type of rule we study the most, and it satisfies the following set o * Both input and output subsets consist of ordered lists of atomic vertices. * The input (left-hand side) only contains patterns, it never refers to explicit vertex names. -* The name of the vertex is only used to identify it, it does not contain any additional information. In particular, there are no conditions on the left-hand side of the rule (neither on the entire subset nor on individual vertices or edges), except for the implicit condition of the same vertices appearing multiple times. -* The output may contain new vertices (the ones that don't appear on the left-hand side), in which case [`Module`](https://reference.wolfram.com/language/ref/Module.html) is used to create them. +* The name of the vertex is only used to identify it, it does not contain any additional information. In particular, + there are no conditions on the left-hand side of the rule (neither on the entire subset nor on individual vertices or + edges), except for the implicit condition of the same vertices appearing multiple times. +* The output may contain new vertices (the ones that don't appear on the left-hand side), in which + case [`Module`](https://reference.wolfram.com/language/ref/Module.html) is used to create them. -`ToPatternRules` provides a more straightforward way to specify such rules by automatically assuming that all level-2 expressions on the left-hand side are patterns, and vertices used on the right that don't appear on the left are new and should be created with a [`Module`](https://reference.wolfram.com/language/ref/Module.html). For example, the rule above can simply be written as +`ToPatternRules` provides a more straightforward way to specify such rules by automatically assuming that all level-2 +expressions on the left-hand side are patterns, and vertices used on the right that don't appear on the left are new and +should be created with a [`Module`](https://reference.wolfram.com/language/ref/Module.html). For example, the rule above +can simply be written as ```wl In[] := ToPatternRules[{{v1, v2, v3}, {v2, v4, v5}} -> @@ -34,7 +40,9 @@ Out[] = {{v1_, v2_, v3_}, {v2_, v4_, v5_}} :> Module[{v6}, {{v5, v6, v1}, {v6, v4, v2}, {v4, v5, v3}}] ``` -This last form of the rule is the one that we use most often and is also the one [`WolframModel`](WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md) accepts by default. +This last form of the rule is the one that we use most often and is also the +one [`WolframModel`](WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md) accepts +by default. `ToPatternRules` is listable in a trivial way: diff --git a/Documentation/SymbolsAndFunctions/UtilityFunctions/BuildData.md b/Documentation/SymbolsAndFunctions/UtilityFunctions/BuildData.md index 2a395d2d2..188383bdc 100644 --- a/Documentation/SymbolsAndFunctions/UtilityFunctions/BuildData.md +++ b/Documentation/SymbolsAndFunctions/UtilityFunctions/BuildData.md @@ -2,7 +2,8 @@ # Build Data -There are two constants containing information about the build. **`$SetReplaceGitSHA`** is a git SHA of the currently-used version of *SetReplace*: +There are two constants containing information about the build. **`$SetReplaceGitSHA`** is a git SHA of the +currently-used version of *SetReplace*: ```wl In[] := $SetReplaceGitSHA diff --git a/Documentation/SymbolsAndFunctions/UtilityFunctions/GeneralizedGridGraph.md b/Documentation/SymbolsAndFunctions/UtilityFunctions/GeneralizedGridGraph.md index 769d6000e..b6e65e005 100644 --- a/Documentation/SymbolsAndFunctions/UtilityFunctions/GeneralizedGridGraph.md +++ b/Documentation/SymbolsAndFunctions/UtilityFunctions/GeneralizedGridGraph.md @@ -2,7 +2,8 @@ # GeneralizedGridGraph -**`GeneralizedGridGraph`** is similar to [`GridGraph`](https://reference.wolfram.com/language/ref/GridGraph.html), but it allows for additional specifiers in each direction of the grid: +**`GeneralizedGridGraph`** is similar to [`GridGraph`](https://reference.wolfram.com/language/ref/GridGraph.html), but +it allows for additional specifiers in each direction of the grid: ```wl In[] := GeneralizedGridGraph[{5 -> "Directed", 5 -> "Circular"}] @@ -18,7 +19,8 @@ In[] := GeneralizedGridGraph[{3 -> {"Directed", "Circular"}, 6}] -The same options as [`GridGraph`](https://reference.wolfram.com/language/ref/GridGraph.html) are supported. In addition `"VertexNamingFunction" -> "Coordinates"` names vertices according to their position in a grid: +The same options as [`GridGraph`](https://reference.wolfram.com/language/ref/GridGraph.html) are supported. In +addition `"VertexNamingFunction" -> "Coordinates"` names vertices according to their position in a grid: ```wl In[] := GeneralizedGridGraph[{4, 5, 2}, diff --git a/Documentation/SymbolsAndFunctions/UtilityFunctions/HypergraphAutomorphismGroup.md b/Documentation/SymbolsAndFunctions/UtilityFunctions/HypergraphAutomorphismGroup.md index a828a2587..8225bc23a 100644 --- a/Documentation/SymbolsAndFunctions/UtilityFunctions/HypergraphAutomorphismGroup.md +++ b/Documentation/SymbolsAndFunctions/UtilityFunctions/HypergraphAutomorphismGroup.md @@ -2,7 +2,9 @@ # HypergraphAutomorphismGroup -**`HypergraphAutomorphismGroup`** does the same thing as [`GraphAutomorphismGroup`](https://reference.wolfram.com/language/ref/GraphAutomorphismGroup.html), but for ordered hypergraphs: +**`HypergraphAutomorphismGroup`** does the same thing +as [`GraphAutomorphismGroup`](https://reference.wolfram.com/language/ref/GraphAutomorphismGroup.html), but for ordered +hypergraphs: ```wl In[] := HypergraphAutomorphismGroup[{{1, 2, 3}, {1, 2, 4}}] diff --git a/Documentation/SymbolsAndFunctions/UtilityFunctions/HypergraphToGraph.md b/Documentation/SymbolsAndFunctions/UtilityFunctions/HypergraphToGraph.md index d7e6d8fa6..cc7695a55 100644 --- a/Documentation/SymbolsAndFunctions/UtilityFunctions/HypergraphToGraph.md +++ b/Documentation/SymbolsAndFunctions/UtilityFunctions/HypergraphToGraph.md @@ -2,11 +2,14 @@ # HypergraphToGraph -**`HypergraphToGraph`** converts a hypergraph to a [`Graph`](https://reference.wolfram.com/language/ref/Graph.html) object. There are (currently) 3 ways to perform this transformation: +**`HypergraphToGraph`** converts a hypergraph to a [`Graph`](https://reference.wolfram.com/language/ref/Graph.html) +object. There are (currently) 3 ways to perform this transformation: ## **"DirectedDistancePreserving"** -Converts a hypergraph to a directed graph with the same distance matrix, where distance between two vertices `v1` and `v2` in a hypergraph is defined as the minimum length of a path which connects `v1` and `v2` (i.e. 1 if both vertices belong to the same hyperedge): +Converts a hypergraph to a directed graph with the same distance matrix, where distance between two vertices `v1` +and `v2` in a hypergraph is defined as the minimum length of a path which connects `v1` and `v2` (i.e. 1 if both +vertices belong to the same hyperedge): ```wl In[]:= HypergraphToGraph[ @@ -20,7 +23,8 @@ In[]:= HypergraphToGraph[ ## **"UndirectedDistancePreserving"** -Converts a hypergraph to an undirected graph with the same distance matrix, that is, each hyperedge is mapped to a complete subgraph: +Converts a hypergraph to an undirected graph with the same distance matrix, that is, each hyperedge is mapped to a +complete subgraph: ```wl In[]:= HypergraphToGraph[ @@ -34,7 +38,9 @@ In[]:= HypergraphToGraph[ ## **"StructurePreserving"** -Converts a hypergraph to a graph by preserving its structure. This is achieved by a one-to-one correspondence between vertices and hyperedges in the hypergraph and 2 different kind of vertices - `{"Hyperedge", hyperedgeIndex_, vertexIndex_}` and `{"Vertex", vertexName_}` - in the graph: +Converts a hypergraph to a graph by preserving its structure. This is achieved by a one-to-one correspondence between + vertices and hyperedges in the hypergraph and 2 different kind of + vertices - `{"Hyperedge", hyperedgeIndex_, vertexIndex_}` and `{"Vertex", vertexName_}` - in the graph: ```wl In[]:= HypergraphToGraph[ @@ -45,7 +51,8 @@ In[]:= HypergraphToGraph[ -It is important to mention that this conversion does not lose any information, and it is possible to unambiguously retrieve the original hypergraph from the resulting [`Graph`](https://reference.wolfram.com/language/ref/Graph.html): +It is important to mention that this conversion does not lose any information, and it is possible to unambiguously +retrieve the original hypergraph from the resulting [`Graph`](https://reference.wolfram.com/language/ref/Graph.html): ```wl fromStructurePreserving[graph_Graph] := Values @ KeySort @ Join[ @@ -55,4 +62,4 @@ fromStructurePreserving[graph_Graph] := Values @ KeySort @ Join[ In[]:= {{x, x, y, z}, {}, {z, w}} === fromStructurePreserving @ HypergraphToGraph[ {{x, x, y, z}, {}, {z, w}}, "StructurePreserving"] Out[]= True -``` \ No newline at end of file +``` diff --git a/Documentation/SymbolsAndFunctions/UtilityFunctions/HypergraphUnifications.md b/Documentation/SymbolsAndFunctions/UtilityFunctions/HypergraphUnifications.md index 996757cd8..b6ac0f8ee 100644 --- a/Documentation/SymbolsAndFunctions/UtilityFunctions/HypergraphUnifications.md +++ b/Documentation/SymbolsAndFunctions/UtilityFunctions/HypergraphUnifications.md @@ -2,9 +2,15 @@ # HypergraphUnifications -When considering which matches could potentially exist to a given set of rule inputs, it is often useful to see all possible ways hypergraphs can overlap. **`HypergraphUnifications`** constructs all possible hypergraphs that contain subgraphs matching both of its arguments. The argument-hypergraphs must overlap by at least a single edge. `HypergraphUnifications` identifies vertices to the least extent possible, but it makes some identifications if necessary for matching. +When considering which matches could potentially exist to a given set of rule inputs, it is often useful to see all +possible ways hypergraphs can overlap. **`HypergraphUnifications`** constructs all possible hypergraphs that contain +subgraphs matching both of its arguments. The argument-hypergraphs must overlap by at least a single +edge. `HypergraphUnifications` identifies vertices to the least extent possible, but it makes some identifications if +necessary for matching. -The output format is a list of triples `{unified hypergraph, first argument edge matches, second argument edge matches}`, where the last two elements are associations mapping the edge indices in the input hypergraphs to the edge indices in the unified hypergraph. +The output format is a list of triples `{unified hypergraph, first argument edge matches, second argument edge matches}` +, where the last two elements are associations mapping the edge indices in the input hypergraphs to the edge indices in +the unified hypergraph. As an example, consider a simple case of two adjacent binary edges: @@ -18,7 +24,9 @@ Out[] = {{{{3, 1}, {3, 4}, {2, 3}}, <|1 -> 3, 2 -> 1|>, <|1 -> 3, 2 -> 2|>}, {{{1, 3}, {2, 3}, {3, 4}}, <|1 -> 1, 2 -> 3|>, <|1 -> 2, 2 -> 3|>}} ``` -In the first output here `{{{3, 1}, {3, 4}, {2, 3}}, <|1 -> 3, 2 -> 1|>, <|1 -> 3, 2 -> 2|>}`, the graphs are overlapping by a shared edge `{2, 3}`, and two inputs are matched respectively to `{{2, 3}, {3, 1}}` and `{{2, 3}, {3, 4}}`. +In the first output here `{{{3, 1}, {3, 4}, {2, 3}}, <|1 -> 3, 2 -> 1|>, <|1 -> 3, 2 -> 2|>}`, the graphs are +overlapping by a shared edge `{2, 3}`, and two inputs are matched respectively to `{{2, 3}, {3, 1}}` +and `{{2, 3}, {3, 4}}`. All unifications can be visualized with **`HypergraphUnificationsPlot`**: diff --git a/Documentation/SymbolsAndFunctions/UtilityFunctions/IsomorphicHypergraphQ.md b/Documentation/SymbolsAndFunctions/UtilityFunctions/IsomorphicHypergraphQ.md index 8bad57b75..359596e86 100644 --- a/Documentation/SymbolsAndFunctions/UtilityFunctions/IsomorphicHypergraphQ.md +++ b/Documentation/SymbolsAndFunctions/UtilityFunctions/IsomorphicHypergraphQ.md @@ -2,7 +2,11 @@ # IsomorphicHypergraphQ -**`IsomorphicHypergraphQ`** is the natural extension of [`IsomorphicGraphQ`](https://reference.wolfram.com/language/ref/IsomorphicGraphQ.html) for hypergraphs. It yields [`True`](https://reference.wolfram.com/language/ref/True.html) for [isomorphic](https://en.wikipedia.org/wiki/Hypergraph#Isomorphism_and_equality) (ordered) hypergraphs, and [`False`](https://reference.wolfram.com/language/ref/False.html) otherwise: +**`IsomorphicHypergraphQ`** is the natural extension +of [`IsomorphicGraphQ`](https://reference.wolfram.com/language/ref/IsomorphicGraphQ.html) for hypergraphs. It +yields [`True`](https://reference.wolfram.com/language/ref/True.html) +for [isomorphic](https://en.wikipedia.org/wiki/Hypergraph#Isomorphism_and_equality) (ordered) hypergraphs, +and [`False`](https://reference.wolfram.com/language/ref/False.html) otherwise: ```wl In[]:= IsomorphicHypergraphQ[ diff --git a/Documentation/SymbolsAndFunctions/UtilityFunctions/RandomHypergraph.md b/Documentation/SymbolsAndFunctions/UtilityFunctions/RandomHypergraph.md index 003920f8f..7f840fba2 100644 --- a/Documentation/SymbolsAndFunctions/UtilityFunctions/RandomHypergraph.md +++ b/Documentation/SymbolsAndFunctions/UtilityFunctions/RandomHypergraph.md @@ -2,7 +2,8 @@ # RandomHypergraph -**`RandomHypergraph`** generates a random hypergraph. The first argument specifies either the hypergraph "complexity" or its signature. The second (optional) argument is the maximum possible number of distinct vertices of said hypergraph. +**`RandomHypergraph`** generates a random hypergraph. The first argument specifies either the hypergraph "complexity" or +its signature. The second (optional) argument is the maximum possible number of distinct vertices of said hypergraph. Pass a positive integer `n` to generate a hypergraph where the total of all hyperedge arities is `n`: @@ -17,24 +18,28 @@ Out[] = 15 ``` Generate a random hypergraph with the same complexity but with at most 20 distinct vertices: + ```wl In[] := RandomHypergraph[15, 20] Out[] = {{14, 17, 11, 10}, {6}, {13, 12, 17}, {1}, {1, 12}, {3, 20, 12, 17}} ``` Pass `sig` to generate a hypergraph with `sig` as its signature: + ```wl In[] := RandomHypergraph[{5, 2}] Out[] = {{4, 3}, {2, 8}, {5, 7}, {9, 5}, {4, 7}} ``` A signature with multiple arities also works: + ```wl In[] := RandomHypergraph[{{5, 2}, {4, 3}}] Out[] = {{10, 22}, {18, 6}, {3, 19}, {1, 14}, {21, 2}, {11, 19, 20}, {11, 8, 3}, {18, 20, 3}, {3, 17, 17}} ``` Restrict this hypergraph to have `{1, 2}` as its vertex list: + ```wl In[] := RandomHypergraph[{{5, 2}, {4, 3}}, 2] Out[] = {{1, 1}, {1, 2}, {1, 2}, {2, 1}, {2, 1}, {2, 2, 2}, {1, 1, 2}, {1, 1, 2}, {1, 1, 1}} diff --git a/Documentation/SymbolsAndFunctions/UtilityFunctions/Subhypergraph.md b/Documentation/SymbolsAndFunctions/UtilityFunctions/Subhypergraph.md index 3654848a8..c8a0d726f 100644 --- a/Documentation/SymbolsAndFunctions/UtilityFunctions/Subhypergraph.md +++ b/Documentation/SymbolsAndFunctions/UtilityFunctions/Subhypergraph.md @@ -2,13 +2,16 @@ # Subhypergraph -**`Subhypergraph`** is a small utility function that selects hyperedges that only contain vertices from the requested list: +**`Subhypergraph`** is a small utility function that selects hyperedges that only contain vertices from the requested +list: ```wl In[]:= Subhypergraph[{{1, 1, 1}, {1, 2}, {2, 3, 3}, {2, 3, 4}}, {2, 3, 4}] Out[]= {{2, 3, 3}, {2, 3, 4}} ``` -**`WeakSubhypergraph`** is the weak version of the previous function, where hyperedges are selected if they contain any vertex from the requested list: + +**`WeakSubhypergraph`** is the weak version of the previous function, where hyperedges are selected if they contain any +vertex from the requested list: ```wl In[]:= WeakSubhypergraph[{{1, 1}, {2, 3}, {3, 4, 4}}, {1, 3}] diff --git a/Documentation/SymbolsAndFunctions/UtilityFunctions/WolframModelRuleValue.md b/Documentation/SymbolsAndFunctions/UtilityFunctions/WolframModelRuleValue.md index 49891cfa9..4942a77e4 100644 --- a/Documentation/SymbolsAndFunctions/UtilityFunctions/WolframModelRuleValue.md +++ b/Documentation/SymbolsAndFunctions/UtilityFunctions/WolframModelRuleValue.md @@ -2,9 +2,12 @@ # WolframModelRuleValue -[Transformation Count](#transformation-count) | [Arity](#arity) | [Node Counts](#node-counts) | [Connectedness](#connectedness) +[Transformation Count](#transformation-count) | [Arity](#arity) | [Node Counts](#node-counts) +| [Connectedness](#connectedness) -**`WolframModelRuleValue`** computes simple properties of rules, which can be determined without running the evolution. Only anonymous (not pattern) rules are supported at the moment. The full list of supported properties can be obtained with **`$WolframModelRuleProperties`**: +**`WolframModelRuleValue`** computes simple properties of rules, which can be determined without running the evolution. +Only anonymous (not pattern) rules are supported at the moment. The full list of supported properties can be obtained +with **`$WolframModelRuleProperties`**: ```wl In[] := $WolframModelRuleProperties @@ -47,7 +50,8 @@ In[] := WolframModelRuleValue[{{1, 2, 3}, {4, 5, 6}, {2, 5}, {5, 2}} -> -In this example, there are 2 binary and 2 ternary edges in the input, and 8 binary and 4 ternary edges in the output. The more machine-readable form of this can be obtained with **`Signature`** property: +In this example, there are 2 binary and 2 ternary edges in the input, and 8 binary and 4 ternary edges in the output. +The more machine-readable form of this can be obtained with **`Signature`** property: ```wl In[] := WolframModelRuleValue[{{1, 2, 3}, {4, 5, 6}, {2, 5}, {5, 2}} -> @@ -59,7 +63,8 @@ Out[] = {{2, 2}, {2, 3}} -> {{8, 2}, {4, 3}} ## Node Counts -One can count the vertices involved in the left- and right-hand sides of the rule with **`"NodeCounts"`**. For example, this rule has 5 vertices in the input, and 6 in the output: +One can count the vertices involved in the left- and right-hand sides of the rule with **`"NodeCounts"`**. For example, +this rule has 5 vertices in the input, and 6 in the output: ```wl In[] := WolframModelRuleValue[{{1, 2, 3}, {2, 4, 5}} -> {{5, 6, 1}, {6, 4, @@ -67,7 +72,8 @@ In[] := WolframModelRuleValue[{{1, 2, 3}, {2, 4, 5}} -> {{5, 6, 1}, {6, 4, Out[] = 5 -> 6 ``` -**`NodesDroppedAdded`** gives the counts of vertices that appear only on the left- and right-hand sides of the rule. Here for example, the first rule creates a vertex, and the second rule drops a vertex: +**`NodesDroppedAdded`** gives the counts of vertices that appear only on the left- and right-hand sides of the rule. +Here for example, the first rule creates a vertex, and the second rule drops a vertex: ```wl In[] := WolframModelRuleValue[{{{1, 1, 2}} -> {{2, 2, 1}, {2, 3, 2}, {1, 2, @@ -76,13 +82,16 @@ In[] := WolframModelRuleValue[{{{1, 1, 2}} -> {{2, 2, 1}, {2, 3, 2}, {1, 2, Out[] = {{0, 1}, {1, 0}} ``` -Keep in mind that rule dropping a vertex does not imply this vertex would be deleted from the state, as there may be other edges containing this vertex. +Keep in mind that rule dropping a vertex does not imply this vertex would be deleted from the state, as there may be +other edges containing this vertex. ## Connectedness There are three types of rule connectedness. -**`ConnectedInput`** checks if the left-hand side of the rule is a connected hypergraph. If it's [`True`](https://reference.wolfram.com/language/ref/True.html), the rule is local, and [`"LowLevel"` implementation](../WolframModelAndWolframModelEvolutionObject/Options/Method.md) can be used for it: +**`ConnectedInput`** checks if the left-hand side of the rule is a connected hypergraph. If +it's [`True`](https://reference.wolfram.com/language/ref/True.html), the rule is local, +and [`"LowLevel"` implementation](../WolframModelAndWolframModelEvolutionObject/Options/Method.md) can be used for it: ```wl In[] := WolframModelRuleValue[{{1, 2, 3}, {3, 4, 5}} -> {{2, 3, 1}, {4, 3, @@ -98,7 +107,9 @@ In[] := WolframModelRuleValue[{{1, 2, 3}, {3, 4, 5}} -> {{2, 3, 1}, {4, 3, Out[] = False ``` -**`ConnectedInputOutputUnion`** yields [`True`](https://reference.wolfram.com/language/ref/True.html) if the input is connected to the output. Note that it does not require either the input or the output to be connected within themselves, but neither of them can have pieces disconnected from the rest of the rule: +**`ConnectedInputOutputUnion`** yields [`True`](https://reference.wolfram.com/language/ref/True.html) if the input is +connected to the output. Note that it does not require either the input or the output to be connected within themselves, +but neither of them can have pieces disconnected from the rest of the rule: ```wl In[] := WolframModelRuleValue[{{1, 2, 3}, {3, 4, 5}} -> {{2, 3, 1}, {4, 3, @@ -106,7 +117,8 @@ In[] := WolframModelRuleValue[{{1, 2, 3}, {3, 4, 5}} -> {{2, 3, 1}, {4, 3, Out[] = True ``` -For multiple-rule systems, each rule needs to be connected for these properties to yield [`True`](https://reference.wolfram.com/language/ref/True.html): +For multiple-rule systems, each rule needs to be connected for these properties to +yield [`True`](https://reference.wolfram.com/language/ref/True.html): ```wl In[] := WolframModelRuleValue[{{{1, 2}} -> {{1, 3}, {3, 2}}, diff --git a/Documentation/SymbolsAndFunctions/UtilityFunctions/WolframPhysicsProjectStyleData.md b/Documentation/SymbolsAndFunctions/UtilityFunctions/WolframPhysicsProjectStyleData.md index edd3afbfa..8ba714879 100644 --- a/Documentation/SymbolsAndFunctions/UtilityFunctions/WolframPhysicsProjectStyleData.md +++ b/Documentation/SymbolsAndFunctions/UtilityFunctions/WolframPhysicsProjectStyleData.md @@ -2,7 +2,9 @@ # WolframPhysicsProjectStyleData -**`WolframPhysicsProjectStyleData`** allows one to lookup styles used in various *SetReplace* functions and properties such as [`HypergraphPlot`](../HypergraphPlot.md) and [`"CausalGraph"`](../WolframModelAndWolframModelEvolutionObject/Properties/CausalGraphs.md). +**`WolframPhysicsProjectStyleData`** allows one to lookup styles used in various *SetReplace* functions and properties +such as [`HypergraphPlot`](../HypergraphPlot.md) +and [`"CausalGraph"`](../WolframModelAndWolframModelEvolutionObject/Properties/CausalGraphs.md). For example, here is the default style used to draw polygons in [`HypergraphPlot`](../HypergraphPlot.md): @@ -12,7 +14,11 @@ In[] := WolframPhysicsProjectStyleData["SpatialGraph", "EdgePolygonStyle"] -The full specification is `WolframPhysicsProjectStyleData[theme, plot type, style element]`, however either the last or the last two elements can be omitted to obtain a full [`Association`](https://reference.wolfram.com/language/ref/Association.html) of styles. The `theme` argument can be omitted to get the result for the default plot theme (only `"Light"` theme is supported at the moment). Here are all styles used in [`"CausalGraph"`](../WolframModelAndWolframModelEvolutionObject/Properties/CausalGraphs.md) for example: +The full specification is `WolframPhysicsProjectStyleData[theme, plot type, style element]`, however either the last or +the last two elements can be omitted to obtain a +full [`Association`](https://reference.wolfram.com/language/ref/Association.html) of styles. The `theme` argument can be +omitted to get the result for the default plot theme (only `"Light"` theme is supported at the moment). Here are all +styles used in [`"CausalGraph"`](../WolframModelAndWolframModelEvolutionObject/Properties/CausalGraphs.md) for example: ```wl In[] := WolframPhysicsProjectStyleData["CausalGraph"] @@ -20,10 +26,11 @@ In[] := WolframPhysicsProjectStyleData["CausalGraph"] -This function is useful if one needs to produce "fake" example plots using styles consistent with the Wolfram Physics Project. +This function is useful if one needs to produce "fake" example plots using styles consistent with the Wolfram Physics +Project. -For graphs composed of only a single type of vertices and edges, there is a short-hand syntax. -One can get the list of all options that needs to be passed using an `"Options"` property: +For graphs composed of only a single type of vertices and edges, there is a short-hand syntax. One can get the list of +all options that needs to be passed using an `"Options"` property: ```wl In[] := WolframPhysicsProjectStyleData["SpatialGraph3D", "Options"] diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/EventDeduplication.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/EventDeduplication.md index fc76cbab4..f6179d1a7 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/EventDeduplication.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/EventDeduplication.md @@ -1,12 +1,11 @@ ###### [Symbols and Functions](/README.md#symbols-and-functions) > [WolframModel and WolframModelEvolutionObject](../WolframModelAndWolframModelEvolutionObject.md) > [Options](../WolframModelAndWolframModelEvolutionObject.md#options) > - # "EventDeduplication" -Some rules can match the same set of inputs in different ways. -For example, consider the rule `{{a, b}, {a, c}} -> {{b, c}}` starting with an initial condition `{{1, 2}, {1, 3}}`. -There are two possible ways to match it: `<|a -> 1, b -> 2, c -> 3|>` and `<|a -> 1, b -> 3, c -> 2|>`. -In this case, these matches yield different results, `{2, 3}` and `{3, 2}` respectively: +Some rules can match the same set of inputs in different ways. For example, consider the +rule `{{a, b}, {a, c}} -> {{b, c}}` starting with an initial condition `{{1, 2}, {1, 3}}`. There are two possible ways +to match it: `<|a -> 1, b -> 2, c -> 3|>` and `<|a -> 1, b -> 3, c -> 2|>`. In this case, these matches yield different +results, `{2, 3}` and `{3, 2}` respectively: ```wl In[] := WolframModel[{{a, b}, {a, c}} -> {{b, c}}, {{1, 2}, {1, 3}}, diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/EventOrderingFunction.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/EventOrderingFunction.md index 1766507e8..13a8cbb5d 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/EventOrderingFunction.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/EventOrderingFunction.md @@ -2,7 +2,8 @@ # "EventOrderingFunction" -In many `WolframModel` systems multiple matches are possible at any given step. As an example, two possible replacements are possible in the system below from the initial condition: +In many `WolframModel` systems multiple matches are possible at any given step. As an example, two possible replacements +are possible in the system below from the initial condition: ```wl In[] := WolframModel[{{1, 2}} -> {{1, 3}, {3, 2}}, @@ -19,7 +20,9 @@ In[] := WolframModel[{{1, 2}} -> {{1, 3}, {3, 2}}, -In this particular so-called non-overlapping system, the order of replacements does not matter. Regardless of order, the same final state (up to renaming of vertices) is produced for the same fixed number of generations. This will always be the case if there is only a single edge on the left-hand side of the rule: +In this particular so-called non-overlapping system, the order of replacements does not matter. Regardless of order, the +same final state (up to renaming of vertices) is produced for the same fixed number of generations. This will always be +the case if there is only a single edge on the left-hand side of the rule: ```wl In[] := WolframModel[{{1, 2}} -> {{1, 3}, {1, 3}, {3, 2}}, @@ -29,7 +32,8 @@ In[] := WolframModel[{{1, 2}} -> {{1, 3}, {1, 3}, {3, 2}}, -For some systems, however, the order of replacements does matter, and non-equivalent final states would be produced for different orders even if a fixed number of generations is requested: +For some systems, however, the order of replacements does matter, and non-equivalent final states would be produced for +different orders even if a fixed number of generations is requested: ```wl In[] := WolframModel[{{1, 2}, {2, 3}} -> {{4, 2}, {4, 1}, {2, 1}, {3, 4}}, @@ -46,15 +50,24 @@ In[] := WolframModel[{{1, 2}, {2, 3}} -> {{4, 2}, {4, 1}, {2, 1}, {3, 4}}, -In a case like that, it is important to be able to specify the desired evolution order, which is the purpose of the **`"EventOrderingFunction"`** option. `"EventOrderingFunction"` is specified as a list of sorting criteria such as the default `{"LeastRecentEdge", "RuleOrdering", "RuleIndex"}`. Note that most individual sorting criteria are insufficient to distinguish between all available matches. If multiple matches remain after exhausting all sorting criteria, one is chosen uniformly at random (which is why `{}` works as a shorthand for `"Random"`). +In a case like that, it is important to be able to specify the desired evolution order, which is the purpose of +the **`"EventOrderingFunction"`** option. `"EventOrderingFunction"` is specified as a list of sorting criteria such as +the default `{"LeastRecentEdge", "RuleOrdering", "RuleIndex"}`. Note that most individual sorting criteria are +insufficient to distinguish between all available matches. If multiple matches remain after exhausting all sorting +criteria, one is chosen uniformly at random (which is why `{}` works as a shorthand for `"Random"`). Possible sorting criteria are: -* `"OldestEdge"`: greedily select the edge closest to the beginning of the list (which would typically correspond to the oldest edge). Note, the edges within a single-event output are assumed oldest-to-newest left-to-right as written on the right-hand side of the rule. After this criterion, a fixed ***subset*** of edges is guaranteed to be chosen, but different orderings of that subset might be possible (which could allow for multiple non-equivalent matches). +* `"OldestEdge"`: greedily select the edge closest to the beginning of the list (which would typically correspond to the + oldest edge). Note, the edges within a single-event output are assumed oldest-to-newest left-to-right as written on + the right-hand side of the rule. After this criterion, a fixed ***subset*** of edges is guaranteed to be chosen, but + different orderings of that subset might be possible (which could allow for multiple non-equivalent matches). -* `"NewestEdge"`: similar to `"OldestEdge"` except edges are chosen from the end of the list rather than from the beginning. +* `"NewestEdge"`: similar to `"OldestEdge"` except edges are chosen from the end of the list rather than from the + beginning. -* `"LeastRecentEdge"`: this is similar to `"OldestEdge"`, but instead of greedily choosing the oldest edges, it instead avoids choosing newest ones. The difference is best demonstrated in an example: +* `"LeastRecentEdge"`: this is similar to `"OldestEdge"`, but instead of greedily choosing the oldest edges, it instead + avoids choosing newest ones. The difference is best demonstrated in an example: ```wl In[] := WolframModel[{{x, y}, {y, z}} -> {}, @@ -65,13 +78,18 @@ Possible sorting criteria are: Out[] = {{{1, {1, 4} -> {}}}, {{1, {2, 3} -> {}}}} ``` - Note that in this example `"OldestEdge"` has selected the first and the last edge, whereas `"LeastRecentEdge"`, in an attempt to avoid the most "recent" last edge, has selected the second and the third ones. In this case, similarly to `"OldestEdge"`, a fixed set of edges is guaranteed to be chosen, but potentially in multiple orders. + Note that in this example `"OldestEdge"` has selected the first and the last edge, whereas `"LeastRecentEdge"`, in an + attempt to avoid the most "recent" last edge, has selected the second and the third ones. In this case, similarly + to `"OldestEdge"`, a fixed set of edges is guaranteed to be chosen, but potentially in multiple orders. * `"LeastOldEdge"`: similar to `"LeastRecentEdge"`, but avoids old edges instead of new ones. - Note that counterintuitively `"OldestEdge"` sorting is not equivalent to the reverse of `"NewestEdge"` sorting, it is equivalent to the reverse of `"LeastOldEdge"`. Similarly, `"NewestEdge"` is the reverse of `"LeastRecentEdge"`. + Note that counterintuitively `"OldestEdge"` sorting is not equivalent to the reverse of `"NewestEdge"` sorting, it is + equivalent to the reverse of `"LeastOldEdge"`. Similarly, `"NewestEdge"` is the reverse of `"LeastRecentEdge"`. -* `"RuleOrdering"`: similarly to `"OldestEdge"` greedily chooses edges from the beginning of the list, however unlike `"OldestEdge"` which would pick the oldest edge with *any* available matches, it chooses edges in the order the left-hand side of (any) rule is written. The difference is best demonstrated in an example: +* `"RuleOrdering"`: similarly to `"OldestEdge"` greedily chooses edges from the beginning of the list, however + unlike `"OldestEdge"` which would pick the oldest edge with *any* available matches, it chooses edges in the order the + left-hand side of (any) rule is written. The difference is best demonstrated in an example: ```wl In[] := WolframModel[{{x, y}, {y, z}} -> {}, @@ -81,21 +99,32 @@ Possible sorting criteria are: Out[] = {{{1, {1, 3} -> {}}}, {{1, {2, 4} -> {}}}} ``` - Note how `"RuleOrdering"` has selected the second edge first because it matches the first rule input while the first edge does not. + Note how `"RuleOrdering"` has selected the second edge first because it matches the first rule input while the first + edge does not. - In this case, a specific ordered sequence of edges is guaranteed to be matched (including its permutation). However, multiple matches might still be possible if multiple rules exist which match that sequence. + In this case, a specific ordered sequence of edges is guaranteed to be matched (including its permutation). However, + multiple matches might still be possible if multiple rules exist which match that sequence. * `"ReverseRuleOrdering"`: as the name suggests, this is just the reverse of `"RuleOrdering"`. -* `"RuleIndex"`: this simply means it attempts to match the first rule first, and only if no matches to the first rule are possible, it goes to the second rule, and so on. +* `"RuleIndex"`: this simply means it attempts to match the first rule first, and only if no matches to the first rule + are possible, it goes to the second rule, and so on. * `"ReverseRuleIndex"`: similar to `"RuleIndex"`, but reversed as the name suggests. -* `"Random"`: selects a single match uniformly at random. It is possible to do that efficiently because the C++ implementation of `WolframModel` (the only one that supports `"EventOrderingFunction"`) keeps track of all possible matches at any point during the evolution. `"Random"` is guaranteed to select a single match, so the remaining sorting criteria are ignored. It can also be omitted because the random event is always chosen if provided sorting criteria are insufficient. The seeding can be controlled with [`SeedRandom`](https://reference.wolfram.com/language/ref/SeedRandom.html). However, the result does depend on your platform (Mac/Linux/Windows) and the specific build (version) of *SetReplace*. +* `"Random"`: selects a single match uniformly at random. It is possible to do that efficiently because the C++ + implementation of `WolframModel` (the only one that supports `"EventOrderingFunction"`) keeps track of all possible + matches at any point during the evolution. `"Random"` is guaranteed to select a single match, so the remaining sorting + criteria are ignored. It can also be omitted because the random event is always chosen if provided sorting criteria + are insufficient. The seeding can be controlled + with [`SeedRandom`](https://reference.wolfram.com/language/ref/SeedRandom.html). However, the result does depend on + your platform (Mac/Linux/Windows) and the specific build (version) of *SetReplace*. -* `"Any"`: the chosen match is undefined. It can select any match, leading to nondeterministic and undefined evolution order. In some cases, it has better performance than "Random". +* `"Any"`: the chosen match is undefined. It can select any match, leading to nondeterministic and undefined evolution + order. In some cases, it has better performance than "Random". -As a neat example, here is the output of all individual sorting criteria (default sorting criteria are appended to disambiguate): +As a neat example, here is the output of all individual sorting criteria (default sorting criteria are appended to +disambiguate): ```wl In[] := WolframModel[{{{1, 2}, {1, 3}, {1, 4}} -> {{5, 6}, {6, 7}, {7, 5}, {5, diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/EventSelectionFunction.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/EventSelectionFunction.md index cbaf189dd..49dedbe5b 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/EventSelectionFunction.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/EventSelectionFunction.md @@ -2,18 +2,18 @@ # "EventSelectionFunction" -**`EventSelectionFunction`** allows one to evaluate multiway systems. -Currently, three values are supported, `"GlobalSpacelike"`, `"MultiwaySpacelike"` and `None`. +**`EventSelectionFunction`** allows one to evaluate multiway systems. Currently, three values are +supported, `"GlobalSpacelike"`, `"MultiwaySpacelike"` and `None`. `"GlobalSpacelike"` is the default, and is the single-way evolution. "Spacelike" refers to relationships between expressions, and "global" means each expression is only used once in an -event, so there is always a global state in which all expressions are pairwise spacelike. -Note that one can obtain different evolutions in this case depending on [the ordering function](EventOrderingFunction.md). +event, so there is always a global state in which all expressions are pairwise spacelike. Note that one can obtain +different evolutions in this case depending on [the ordering function](EventOrderingFunction.md). -`"MultiwaySpacelike"` evolution is the multiway version of `"GlobalSpacelike"`. -Essentially, it evolves it for all possible ordering functions and combines the result to a single evolution object. -It achieves that by not disabling expressions after they were used. -Only spacelike separated expressions are matched for any given event, however, so every individual expression of the +`"MultiwaySpacelike"` evolution is the multiway version of `"GlobalSpacelike"`. Essentially, it evolves it for all +possible ordering functions and combines the result to a single evolution object. It achieves that by not disabling +expressions after they were used. Only spacelike separated expressions are matched for any given event, however, so +every individual expression of the `"MultiwaySpacelike"` evolution can be obtained with a particular choice of the event ordering function. (It does not imply that it can actually be done in *SetReplace* as only few ordering functions are implemented at this time.) @@ -28,8 +28,8 @@ In[] := WolframModel[{{1, 2}, {2, 3}} -> {{1, 3}}, {{1, 2}, {2, 3}, {2, 4}}, In this example we used the default `"GlobalSpacelike"` selection function, and the evolution terminated after a single -event, because the expression `{1, 2}` was used, and it could not be reused to be matched with `{2, 4}`. -However, let's look at what `"EventSelectionFunction" -> "MultiwaySpacelike"` will do: +event, because the expression `{1, 2}` was used, and it could not be reused to be matched with `{2, 4}`. However, let's +look at what `"EventSelectionFunction" -> "MultiwaySpacelike"` will do: ```wl In[] := WolframModel[{{1, 2}, {2, 3}} -> {{1, 3}}, {{1, 2}, {2, 3}, {2, 4}}, @@ -64,8 +64,8 @@ In[] := WolframModel[{{{1, 2}, {2, 3}} -> {{1, 2, 3}}, -However, `"EventSelectionFunction" -> None` also matches expressions that are branchlike and timelike. -So, further evolution will be generated in the previous example: +However, `"EventSelectionFunction" -> None` also matches expressions that are branchlike and timelike. So, further +evolution will be generated in the previous example: ```wl In[] := WolframModel[{{{1, 2}, {2, 3}} -> {{1, 2, 3}}, diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/IncludeBoundaryEvents.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/IncludeBoundaryEvents.md index 26f5bce09..4926759a1 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/IncludeBoundaryEvents.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/IncludeBoundaryEvents.md @@ -2,9 +2,13 @@ # "IncludeBoundaryEvents" -**`"IncludeBoundaryEvents"`** allows one to include "fake" initial and final events in properties such as [`"ExpressionsEventsGraph"`](../Properties/CausalGraphs.md). It does not affect the evolution itself and does not affect the evolution object. It has 4 settings: [`None`](https://reference.wolfram.com/language/ref/None.html), `"Initial"`, `"Final"` and [`All`](https://reference.wolfram.com/language/ref/All.html). +**`"IncludeBoundaryEvents"`** allows one to include "fake" initial and final events in properties such +as [`"ExpressionsEventsGraph"`](../Properties/CausalGraphs.md). It does not affect the evolution itself and does not +affect the evolution object. It has 4 settings: [`None`](https://reference.wolfram.com/language/ref/None.html) +, `"Initial"`, `"Final"` and [`All`](https://reference.wolfram.com/language/ref/All.html). -Here is an example of an [`"ExpressionsEventsGraph"`](../Properties/CausalGraphs.md) with the initial and final "events" included: +Here is an example of an [`"ExpressionsEventsGraph"`](../Properties/CausalGraphs.md) with the initial and final "events" +included: ```wl In[] := WolframModel[<|"PatternRules" -> {a_, b_} :> a + b|>, diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/IncludePartialGenerations.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/IncludePartialGenerations.md index 037acf499..7d5fb42a2 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/IncludePartialGenerations.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/IncludePartialGenerations.md @@ -2,7 +2,9 @@ # "IncludePartialGenerations" -In case partial generations were produced, they can be automatically dropped by setting **`"IncludePartialGenerations"`** to [`False`](https://reference.wolfram.com/language/ref/False.html). Compare for instance +In case partial generations were produced, they can be automatically dropped by +setting **`"IncludePartialGenerations"`** to [`False`](https://reference.wolfram.com/language/ref/False.html). Compare +for instance ```wl In[] := WolframModel[{{1, 2}} -> {{1, 3}, {1, 3}, {3, 2}}, diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/Method.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/Method.md index f63fabc65..52f60dc08 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/Method.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/Method.md @@ -2,16 +2,26 @@ # Method -There are two implementations (**`Method`** s) available: one written in Wolfram Language (`Method -> "Symbolic"`), one in C++ (`Method -> "LowLevel"`). +There are two implementations (**`Method`** s) available: one written in Wolfram Language (`Method -> "Symbolic"`), one +in C++ (`Method -> "LowLevel"`). -The Wolfram Language implementation permutes the left-hand sides of the rules in all possible ways and uses [`Replace`](https://reference.wolfram.com/language/ref/Replace.html) a specified number of times to perform evolution. This implementation works well for small graphs and small rule inputs, but it slows down with the number of edges in the graph and has exponential complexity in rule size. +The Wolfram Language implementation permutes the left-hand sides of the rules in all possible ways and +uses [`Replace`](https://reference.wolfram.com/language/ref/Replace.html) a specified number of times to perform +evolution. This implementation works well for small graphs and small rule inputs, but it slows down with the number of +edges in the graph and has exponential complexity in rule size. -The C++ implementation, on the other hand, keeps an index of all possible rule matches and updates it after every replacement. The reindexing algorithm looks only at the local region of the graph close to the rewrite site. Thus time complexity does not depend on the graph size as long as vertex degrees are small. The downside is that it has exponential complexity (both in time and memory) in the vertex degrees. Currently, it also does not work for non-local rules (i.e., rule inputs that do not form a connected hypergraph) and rules that are not hypergraph rules (i.e., pattern rules that have non-trivial nesting or conditions). +The C++ implementation, on the other hand, keeps an index of all possible rule matches and updates it after every +replacement. The reindexing algorithm looks only at the local region of the graph close to the rewrite site. Thus time +complexity does not depend on the graph size as long as vertex degrees are small. The downside is that it has +exponential complexity (both in time and memory) in the vertex degrees. Currently, it also does not work for non-local +rules (i.e., rule inputs that do not form a connected hypergraph) and rules that are not hypergraph rules (i.e., pattern +rules that have non-trivial nesting or conditions). The C++ implementation is used by default for supported systems and is particularly useful if: * Vertex degrees are expected to be small. -* Evolution needs to be done for a large number of steps `> 100`, it is possible to produce states with up to a million edges or more. +* Evolution needs to be done for a large number of steps `> 100`, it is possible to produce states with up to a million + edges or more. It should not be used, however, if vertex degrees can grow large. For example @@ -36,4 +46,5 @@ In[] := AbsoluteTiming[ Wolfram Language implementation should be used if: * A large number of small rules with unknown behavior needs to be simulated for a small number of steps. -* Vertex degrees are expected to be large, rules are non-local, or pattern rules with non-trivial nesting or conditions are used. +* Vertex degrees are expected to be large, rules are non-local, or pattern rules with non-trivial nesting or conditions + are used. diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/TimeConstraint.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/TimeConstraint.md index c029a80e5..20e93f440 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/TimeConstraint.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/TimeConstraint.md @@ -2,7 +2,8 @@ # TimeConstraint -**`TimeConstraint`** option allows one to stop the evolution early. If an evolution object is requested, it will return a partial result, otherwise, it will just give [`$Aborted`](https://reference.wolfram.com/language/ref/$Aborted.html): +**`TimeConstraint`** option allows one to stop the evolution early. If an evolution object is requested, it will return +a partial result, otherwise, it will just give [`$Aborted`](https://reference.wolfram.com/language/ref/$Aborted.html): ```wl In[] := WolframModel[{{1, 2}} -> {{1, 3}, {1, 3}, {3, 2}}, diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/VertexNamingFunction.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/VertexNamingFunction.md index b74c72028..b4a902b1f 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/VertexNamingFunction.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/VertexNamingFunction.md @@ -2,9 +2,13 @@ # "VertexNamingFunction" -**`"VertexNamingFunction"`** controls the names chosen for vertices, particularly the newly created ones. It can take three values: [`None`](https://reference.wolfram.com/language/ref/None.html), [`Automatic`](https://reference.wolfram.com/language/ref/Automatic.html), and [`All`](https://reference.wolfram.com/language/ref/All.html). +**`"VertexNamingFunction"`** controls the names chosen for vertices, particularly the newly created ones. It can take +three values: [`None`](https://reference.wolfram.com/language/ref/None.html) +, [`Automatic`](https://reference.wolfram.com/language/ref/Automatic.html), +and [`All`](https://reference.wolfram.com/language/ref/All.html). -[`None`](https://reference.wolfram.com/language/ref/None.html) does not do anything, the vertices in the initial condition are left as-is, and the newly created vertices use symbol names as, i.e., `Module[{v}, v]` could generate: +[`None`](https://reference.wolfram.com/language/ref/None.html) does not do anything, the vertices in the initial +condition are left as-is, and the newly created vertices use symbol names as, i.e., `Module[{v}, v]` could generate: ```wl In[] := WolframModel[{{1, 2}} -> {{1, 3}, {1, 3}, {3, 2}}, @@ -15,7 +19,9 @@ Out[] = {{{v1, v1}}, {{v1, v256479}, {v1, v256479}, {v256479, v1}}, {{v1, v256482}, {v256482, v1}}} ``` -[`All`](https://reference.wolfram.com/language/ref/All.html) renames all vertices as sequential integers, including the ones in the the initial condition, and including ones manually generated in [pattern rules](../WolframModelAndWolframModelEvolutionObject.md#pattern-rules): +[`All`](https://reference.wolfram.com/language/ref/All.html) renames all vertices as sequential integers, including the +ones in the the initial condition, and including ones manually generated +in [pattern rules](../WolframModelAndWolframModelEvolutionObject.md#pattern-rules): ```wl In[] := WolframModel[{{1, 2}} -> {{1, 3}, {1, 3}, {3, 2}}, @@ -24,7 +30,9 @@ Out[] = {{{1, 1}}, {{1, 2}, {1, 2}, {2, 1}}, {{1, 3}, {1, 3}, {3, 2}, {1, 4}, {1, 4}, {4, 2}, {2, 5}, {2, 5}, {5, 1}}} ``` -[`Automatic`](https://reference.wolfram.com/language/ref/Automatic.html) only renames newly created vertices with non-previously-used integers, and leaves the initial condition as-is. It does nothing in the case of [pattern rules](../WolframModelAndWolframModelEvolutionObject.md#pattern-rules). +[`Automatic`](https://reference.wolfram.com/language/ref/Automatic.html) only renames newly created vertices with +non-previously-used integers, and leaves the initial condition as-is. It does nothing in the case +of [pattern rules](../WolframModelAndWolframModelEvolutionObject.md#pattern-rules). ```wl In[] := WolframModel[{{1, 2}} -> {{1, 3}, {1, 3}, {3, 2}}, diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/AllEdgesThroughoutEvolution.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/AllEdgesThroughoutEvolution.md index 50c4b645c..54d7cd3ef 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/AllEdgesThroughoutEvolution.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/AllEdgesThroughoutEvolution.md @@ -2,9 +2,12 @@ # All Edges throughout Evolution -**`"AllEventsEdgesList"`** (aka `"AllExpressions"`) returns the list of edges throughout evolution. This is distinct from a catenated [`"StateList"`](States.md), as the edge does not appear twice if it moved from one generation to the next without being involved in an event. +**`"AllEventsEdgesList"`** (aka `"AllExpressions"`) returns the list of edges throughout evolution. This is distinct +from a catenated [`"StateList"`](States.md), as the edge does not appear twice if it moved from one generation to the +next without being involved in an event. -Compare for instance the output of [`"StatesList"`](States.md) for a system where only one replacement is made per generation: +Compare for instance the output of [`"StatesList"`](States.md) for a system where only one replacement is made per +generation: ```wl In[] := WolframModel[<|"PatternRules" -> {x_?OddQ, y_} :> x + y|>, @@ -22,4 +25,5 @@ Out[] = {1, 2, 4, 6, 3, 7, 13} Note how 4 and 6 only appear once in the list. -Edge indices from `"AllEventsEdgesList"` are used in various other properties such as [`"AllEventsList"`](Events.md) and [`"EventsStatesList"`](EventsAndStates.md). +Edge indices from `"AllEventsEdgesList"` are used in various other properties such as [`"AllEventsList"`](Events.md) +and [`"EventsStatesList"`](EventsAndStates.md). diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/CausalGraphs.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/CausalGraphs.md index 755a76687..c7c941834 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/CausalGraphs.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/CausalGraphs.md @@ -2,11 +2,16 @@ # Causal Graphs -An event **A** *causes* an event **B** if there exists an expression (set element) created by **A** and destroyed by **B**. If we then consider all such relationships between events, we create a **`"CausalGraph"`**. In a causal graph, vertices correspond to events, and edges correspond to the set elements (aka spatial edges). +An event **A** *causes* an event **B** if there exists an expression (set element) created by **A** and destroyed by ** +B**. If we then consider all such relationships between events, we create a **`"CausalGraph"`**. In a causal graph, +vertices correspond to events, and edges correspond to the set elements (aka spatial edges). -To make it even more explicit, we have another property, **`"ExpressionsEventsGraph"`**. In this graph, there are two types of vertices corresponding to events and expressions, and edges correspond to a given expression being an input or an output of a given event. +To make it even more explicit, we have another property, **`"ExpressionsEventsGraph"`**. In this graph, there are two +types of vertices corresponding to events and expressions, and edges correspond to a given expression being an input or +an output of a given event. -For example, if we consider our simple arithmetic model `{a_, b_} :> a + b` starting from `{3, 8, 8, 8, 2, 10, 0, 9, 7}` we get an expressions-events graph which quite clearly describes what's going on: +For example, if we consider our simple arithmetic model `{a_, b_} :> a + b` starting from `{3, 8, 8, 8, 2, 10, 0, 9, 7}` +we get an expressions-events graph which quite clearly describes what's going on: ```wl In[] := WolframModel[<|"PatternRules" -> {a_, b_} :> a + b|>, @@ -25,7 +30,8 @@ In[] := WolframModel[<|"PatternRules" -> {a_, b_} :> a + b|>, -Here is an example for a hypergraph model (admittedly considerably harder to understand). Multiedges correspond to situations where multiple set elements were both created and destroyed by the same pair of events: +Here is an example for a hypergraph model (admittedly considerably harder to understand). Multiedges correspond to +situations where multiple set elements were both created and destroyed by the same pair of events: ```wl In[] := WolframModel[{{1, 2, 3}, {4, 5, 6}, {1, 4}} -> @@ -36,7 +42,8 @@ In[] := WolframModel[{{1, 2, 3}, {4, 5, 6}, {1, 4}} -> -**`"LayeredCausalGraph"`** generates the same graph but layers events generation-by-generation. For example, in our arithmetic causal graph, note how it's arranged differently from an example above: +**`"LayeredCausalGraph"`** generates the same graph but layers events generation-by-generation. For example, in our +arithmetic causal graph, note how it's arranged differently from an example above: ```wl In[] := WolframModel[<|"PatternRules" -> {a_, b_} :> a + b|>, @@ -45,7 +52,9 @@ In[] := WolframModel[<|"PatternRules" -> {a_, b_} :> a + b|>, -Note how slices through the expressions-events graph correspond to states returned by [`"StatesList"`](States.md). Pay attention to intersections of the slices with edges as well, as they correspond to unused expressions from previous generations that remain in the state: +Note how slices through the expressions-events graph correspond to states returned by [`"StatesList"`](States.md). Pay +attention to intersections of the slices with edges as well, as they correspond to unused expressions from previous +generations that remain in the state: ```wl In[] := With[{evolution = @@ -66,7 +75,9 @@ Out[] = {{3, 8, 8, 8, 2, 10, 0, 9, 7}, {7, 11, 16, 12, 9}, {9, 18, 28}, {28, 27}, {55}} ``` -`"ExpressionsEventsGraph"` is particularly useful for multiway systems, as it allows one to immediately see multiway branching. For example, here the expression-vertex `{2}` has the out-degree of 2, which indicates it was used in two conflicting events, which indicates multiway branching: +`"ExpressionsEventsGraph"` is particularly useful for multiway systems, as it allows one to immediately see multiway +branching. For example, here the expression-vertex `{2}` has the out-degree of 2, which indicates it was used in two +conflicting events, which indicates multiway branching: ```wl In[] := WolframModel[{{1}, {1, 2}} -> {{2}}, {{1}, {1, 2}, {2, 3}, {2, 4}}, @@ -77,7 +88,13 @@ In[] := WolframModel[{{1}, {1, 2}} -> {{2}}, {{1}, {1, 2}, {2, 3}, {2, 4}}, -`"CausalGraph"`, `"LayeredCausalGraph"` and `"ExpressionsEventsGraph"` properties all accept [`Graph`](https://reference.wolfram.com/language/ref/Graph.html) options, as was demonstrated above with [`VertexLabels`](https://reference.wolfram.com/language/ref/VertexLabels.html). Some options have special behavior for the [`Automatic`](https://reference.wolfram.com/language/ref/Automatic.html) value, i.e., `VertexLabels -> Automatic` in `"ExpressionsEventsGraph"` displays the contents of expressions, which are not the vertex names in that graph (as there can be multiple expressions with the same contents). `VertexLabels -> "Index"`, on the other hand, displays the vertex indices of both expressions and events in the graph: +`"CausalGraph"`, `"LayeredCausalGraph"` and `"ExpressionsEventsGraph"` properties all +accept [`Graph`](https://reference.wolfram.com/language/ref/Graph.html) options, as was demonstrated above +with [`VertexLabels`](https://reference.wolfram.com/language/ref/VertexLabels.html). Some options have special behavior +for the [`Automatic`](https://reference.wolfram.com/language/ref/Automatic.html) value, +i.e., `VertexLabels -> Automatic` in `"ExpressionsEventsGraph"` displays the contents of expressions, which are not the +vertex names in that graph (as there can be multiple expressions with the same contents). `VertexLabels -> "Index"`, on +the other hand, displays the vertex indices of both expressions and events in the graph: ```wl In[] := WolframModel[{{{x, y}, {x, z}} -> {{x, z}, {x, w}, {y, w}, {z, w}}}, diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/CreatorAndDestroyerEvents.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/CreatorAndDestroyerEvents.md index 0027febe1..c1fb82b96 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/CreatorAndDestroyerEvents.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/CreatorAndDestroyerEvents.md @@ -2,7 +2,9 @@ # Creator and Destroyer Events -An event is said to *destroy* the edges in its input, and *create* the edges in its output. Creator and destroyer events for each edge can be obtained with **`"EdgeCreatorEventIndices"`** (aka `"CreatorEvents"`) and **`"EdgeDestroyerEventsIndices"`** properties. +An event is said to *destroy* the edges in its input, and *create* the edges in its output. Creator and destroyer events +for each edge can be obtained with **`"EdgeCreatorEventIndices"`** (aka `"CreatorEvents"`) +and **`"EdgeDestroyerEventsIndices"`** properties. As an example, for a simple rule that splits each edge in two, one can see that edges are created in pairs: @@ -23,9 +25,13 @@ Out[] = {{1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {12}, {}, {}, {}, {}} ``` -Here 0 refers to the initial state. Note the format is different for creator and destroyer events. That is because each edge has a unique creator event, but can have multiple destroyer events in [multiway systems](../Options/EventSelectionFunction.md). +Here 0 refers to the initial state. Note the format is different for creator and destroyer events. That is because each +edge has a unique creator event, but can have multiple destroyer events +in [multiway systems](../Options/EventSelectionFunction.md). -There is another property, **`"EdgeDestroyerEventIndices"`** (aka `"DestroyerEvents"`), left for compatibility reasons, which has the same format as **`"EdgeCreatorEventIndices"`**. However, it does not work for [multiway systems](../Options/EventSelectionFunction.md). +There is another property, **`"EdgeDestroyerEventIndices"`** (aka `"DestroyerEvents"`), left for compatibility reasons, +which has the same format as **`"EdgeCreatorEventIndices"`**. However, it does not work +for [multiway systems](../Options/EventSelectionFunction.md). ```wl In[] := WolframModel[{{1, 2}} -> {{1, 3}, {3, 2}}, diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/EdgeAndEventGenerations.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/EdgeAndEventGenerations.md index 5e8bcde90..679d58ac4 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/EdgeAndEventGenerations.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/EdgeAndEventGenerations.md @@ -2,7 +2,8 @@ # Edge and Event Generations -**`"EdgeGenerationsList"`** (aka `"ExpressionGenerations"`) yields the list of generation numbers (numbers of predecessor layers) for each edge in [`"AllEventsEdgesList"`](AllEdgesThroughoutEvolution.md): +**`"EdgeGenerationsList"`** (aka `"ExpressionGenerations"`) yields the list of generation numbers (numbers of +predecessor layers) for each edge in [`"AllEventsEdgesList"`](AllEdgesThroughoutEvolution.md): ```wl In[] := WolframModel[{{1, 2}, {1, 3}, {1, 4}} -> @@ -12,7 +13,8 @@ Out[] = {0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5} ``` - **`"AllEventsGenerationsList"`** (aka `"EventGenerations"`) gives the same for events. The generation of an event is defined as the generation of edges it produces as output. Here edges of different generations are colored differently: +**`"AllEventsGenerationsList"`** (aka `"EventGenerations"`) gives the same for events. The generation of an event is +defined as the generation of edges it produces as output. Here edges of different generations are colored differently: ```wl In[] := With[{ @@ -30,7 +32,8 @@ In[] := With[{ -Event and expression generations correspond to layers in [`"LayeredCausalGraph"`](CausalGraphs.md) and [`"ExpressionsEventsGraph"`](CausalGraphs.md): +Event and expression generations correspond to layers in [`"LayeredCausalGraph"`](CausalGraphs.md) +and [`"ExpressionsEventsGraph"`](CausalGraphs.md): ```wl In[] := WolframModel[{{1, 2}, {1, 3}, {1, 4}} -> diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/ElementCountLists.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/ElementCountLists.md index fe8156a99..64bf555af 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/ElementCountLists.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/ElementCountLists.md @@ -2,7 +2,8 @@ # Element Count Lists -**`"VertexCountList"`** and **`"EdgeCountList"`** return counts of vertices and edges respectively in each state of [`"StatesList"`](States.md). They are useful to see how quickly a particular system grows: +**`"VertexCountList"`** and **`"EdgeCountList"`** return counts of vertices and edges respectively in each state +of [`"StatesList"`](States.md). They are useful to see how quickly a particular system grows: ```wl In[] := WolframModel[{{1, 2, 3}, {2, 4, 5}} -> diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/EventCounts.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/EventCounts.md index 50f250ae6..b57db5d10 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/EventCounts.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/EventCounts.md @@ -2,9 +2,12 @@ # Event Counts -**`"AllEventsCount"`** (aka `"EventsCount"`) returns the overall number of events throughout the evolution (the [`Length`](https://reference.wolfram.com/language/ref/Length.html) of [`"AllEventsList"`](Events.md)). +**`"AllEventsCount"`** (aka `"EventsCount"`) returns the overall number of events throughout the evolution ( +the [`Length`](https://reference.wolfram.com/language/ref/Length.html) of [`"AllEventsList"`](Events.md)). -**`"GenerationEventsCountList"`** gives the number of events per each generation ([`Length`](https://reference.wolfram.com/language/ref/Length.html) mapped over [`"GenerationEventsList"`](Events.md)): +**`"GenerationEventsCountList"`** gives the number of events per each +generation ([`Length`](https://reference.wolfram.com/language/ref/Length.html) mapped +over [`"GenerationEventsList"`](Events.md)): ```wl In[] := WolframModel[{{1, 2}} -> {{1, 3}, {1, 3}, {3, 2}}, diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/Events.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/Events.md index a15bc70eb..40b91a3c0 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/Events.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/Events.md @@ -2,7 +2,9 @@ # Events -**`"AllEventsList"`** (aka `"EventsList"`) and **`"GenerationEventsList"`** both return all replacement events throughout the evolution. The only difference is how the events are arranged. `"AllEventsList"` returns the flat list of all events, whereas `"GenerationEventsList"` splits them into sublists for each generation: +**`"AllEventsList"`** (aka `"EventsList"`) and **`"GenerationEventsList"`** both return all replacement events +throughout the evolution. The only difference is how the events are arranged. `"AllEventsList"` returns the flat list of +all events, whereas `"GenerationEventsList"` splits them into sublists for each generation: ```wl In[] := WolframModel[{{1, 2}} -> {{3, 4}, {3, 1}, {4, 1}, {2, 4}}, diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/EventsAndStates.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/EventsAndStates.md index 71d636248..23e7bcfd1 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/EventsAndStates.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/EventsAndStates.md @@ -2,7 +2,9 @@ # Events and States -**`"EventsStatesList"`** just produces a list of `{event, state}` pairs, where state is the complete state right after this event is applied. Events are the same as generated by [`"AllEventsList"`](Events.md), and the states are represented as edge indices as in [`"AllEventsStatesEdgeIndicesList"`](StatesAsEdgeIndices.md): +**`"EventsStatesList"`** just produces a list of `{event, state}` pairs, where state is the complete state right after +this event is applied. Events are the same as generated by [`"AllEventsList"`](Events.md), and the states are +represented as edge indices as in [`"AllEventsStatesEdgeIndicesList"`](StatesAsEdgeIndices.md): ```wl In[] := WolframModel[{{1, 2}} -> {{3, 4}, {3, 1}, {4, 1}, {2, 4}}, diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/ExpressionSeparations.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/ExpressionSeparations.md index 45296b683..0e4270379 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/ExpressionSeparations.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/ExpressionSeparations.md @@ -6,9 +6,10 @@ Expressions can be related in different ways to one another depending on the cau graph. There are three fundamental cases, the separation between two expressions can be: + * spacelike -- the expressions were produced (directly or indirectly) by a single event; * branchlike -- the expressions were produced (directly or indirectly) by multiple events that matched the same -expression; + expression; * timelike -- the expressions are causally related, one produced or was produced by another. The expressions `{2, 3}` and `{3, 4}` here are spacelike, branchlike and timelike separated respectively: @@ -26,12 +27,11 @@ In[] := Framed[WolframModel[<|"PatternRules" -> #|>, {{1, 2}}, Infinity, One might be tempted to assume that spacelike separated expressions can always be 'assembled' to produce a possible -history for a singleway system. -For match-all evolution, however, this is not the case. -Match-all rules can match two branchlike separated expressions, something that is never possible for singleway systems. -If such events produce spacelike separated results, then we will obtain spacelike separated expressions that can be -assembled into global states which *do not* correspond to any singleway evolution state. -See expressions `{4, 5}` and `{5, 6}` in the following picture: +history for a singleway system. For match-all evolution, however, this is not the case. Match-all rules can match two +branchlike separated expressions, something that is never possible for singleway systems. If such events produce +spacelike separated results, then we will obtain spacelike separated expressions that can be assembled into global +states which *do not* correspond to any singleway evolution state. See expressions `{4, 5}` and `{5, 6}` in the +following picture: ```wl In[] := WolframModel[<| @@ -44,9 +44,8 @@ In[] := WolframModel[<| Further, branchlike separation takes precedence over spacelike separation, and timelike separation takes precedence over -both. -As such, expressions `{v, f, 1}` and `{v, f, 2}` here are branchlike separated because one of their common ancestors is -an expression even though the other one is an event: +both. As such, expressions `{v, f, 1}` and `{v, f, 2}` here are branchlike separated because one of their common +ancestors is an expression even though the other one is an event: ```wl In[] := WolframModel[<|"PatternRules" -> {{{v, i}} -> {{v, 1}, {v, 2}}, @@ -61,6 +60,7 @@ In[] := WolframModel[<|"PatternRules" -> {{{v, i}} -> {{v, 1}, {v, 2}}, Specifically, the general algorithm for computing the separation between two expressions `A` and `B` in an expressions-events graph is: + 1. Compute the past causal cones of both `A` and `B`. 2. Compute the intersection between the causal cones. 3. Take all vertices with out-degree zero (the future boundary of the intersection). @@ -68,8 +68,8 @@ expressions-events graph is: 5. If any vertices on the boundary are expression-vertices, they are branchlike separated. 6. Otherwise, if all vertices on the boundary are event-vertices, they are spacelike separated. -One can compute that separation using **`"ExpressionsSeparation"`** property. -It takes two arguments, which are the indices of expressions from [`"AllEventsEdgesList"`](AllEdgesThroughoutEvolution.md): +One can compute that separation using **`"ExpressionsSeparation"`** property. It takes two arguments, which are the +indices of expressions from [`"AllEventsEdgesList"`](AllEdgesThroughoutEvolution.md): ```wl In[] := WolframModel[<|"PatternRules" -> {{{v, i}} -> {{v, 1}, {v, 2}}, diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/FeatureVector.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/FeatureVector.md index fb882ef04..3538979f1 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/FeatureVector.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/FeatureVector.md @@ -2,7 +2,9 @@ # FeatureVector -**`"FeatureVector"`** computes some features of the [`WolframModel`](/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md) evolution. For now, it only computes properties associated with the causal graph `g`: +**`"FeatureVector"`** computes some features of +the [`WolframModel`](/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md) +evolution. For now, it only computes properties associated with the causal graph `g`: ```wl In[] := WolframModel[{{x, y}, {x, z}} -> {{x, z}, {x, w}, {y, w}, {z, w}}, {{0, 0}, {0, 0}}, 5]["FeatureVector"] @@ -10,10 +12,17 @@ Out[] = {22, 42, 0, 2, 2, 2, 6, 6} ``` The list of properties is: -- [`VertexCount`](https://reference.wolfram.com/language/ref/VertexCount.html): The number of vertices in the causal graph. Related to the [total number of events](/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/EventCounts.md) -- [`EdgeCount`](https://reference.wolfram.com/language/ref/EdgeCount.html): The number of edges in the causal graph. Related to the [total number of expressions](/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/TotalElementCounts.md) -- [`VertexConnectivity`](https://reference.wolfram.com/language/ref/VertexConnectivity.html): The smallest number of vertices whose deletion from `g` disconnects `g`. This is computed on the undirected version of the causal graph. -- [`VertexDegree`](https://reference.wolfram.com/language/ref/VertexDegree.html) Quantiles: The quantiles 0, 0.25, 0.50, 0.75, 1 of the vertex degrees distribution. + +- [`VertexCount`](https://reference.wolfram.com/language/ref/VertexCount.html): The number of vertices in the causal + graph. Related to + the [total number of events](/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/EventCounts.md) +- [`EdgeCount`](https://reference.wolfram.com/language/ref/EdgeCount.html): The number of edges in the causal graph. + Related to + the [total number of expressions](/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/TotalElementCounts.md) +- [`VertexConnectivity`](https://reference.wolfram.com/language/ref/VertexConnectivity.html): The smallest number of + vertices whose deletion from `g` disconnects `g`. This is computed on the undirected version of the causal graph. +- [`VertexDegree`](https://reference.wolfram.com/language/ref/VertexDegree.html) Quantiles: The quantiles 0, 0.25, 0.50, + 0.75, 1 of the vertex degrees distribution. This property is useful for applying machine learning to Wolfram Models explorations. diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/FinalElementCounts.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/FinalElementCounts.md index 59a4a5b31..735b883ad 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/FinalElementCounts.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/FinalElementCounts.md @@ -2,9 +2,13 @@ # Final Element Counts -**`FinalDistinctElementsCount`** (aka `"AtomsCountFinal"`) and **`FinalEdgeCount`** (aka `"ExpressionsCountFinal"`) are similar to corresponding [`*List`](ElementCountLists.md) properties, except we don't have `"FinalVertexCount"` (we should have it and also `"DistinctElementsCountList"`, but they are not currently implemented). +**`FinalDistinctElementsCount`** (aka `"AtomsCountFinal"`) and **`FinalEdgeCount`** (aka `"ExpressionsCountFinal"`) are +similar to corresponding [`*List`](ElementCountLists.md) properties, except we don't have `"FinalVertexCount"` (we +should have it and also `"DistinctElementsCountList"`, but they are not currently implemented). -The difference is that [`"VertexCountList"`](ElementCountLists.md) counts expressions on level 2 in the states whereas `"FinalDistinctElementsCount"` counts all expressions matching `_ ? AtomQ` (on any level). The difference becomes apparent for edges that contain non-trivially nested lists. +The difference is that [`"VertexCountList"`](ElementCountLists.md) counts expressions on level 2 in the states +whereas `"FinalDistinctElementsCount"` counts all expressions matching `_ ? AtomQ` (on any level). The difference +becomes apparent for edges that contain non-trivially nested lists. For example, consider a rule that performs non-trivial nesting: @@ -31,4 +35,6 @@ In[] := WolframModel[<| Out[] = {{2}, {0}, {{3, -1}}} ``` -This state has 3 vertices (distinct level-2 expressions): `2`, `0`, and `{3, -1}`, but 4 atoms: `2`, `0`, `3`, and `-1`. This distinction does not usually come up in our models since vertices and atoms are usually the same things, but it is significant in exotic cases like this. +This state has 3 vertices (distinct level-2 expressions): `2`, `0`, and `{3, -1}`, but 4 atoms: `2`, `0`, `3`, and `-1`. +This distinction does not usually come up in our models since vertices and atoms are usually the same things, but it is +significant in exotic cases like this. diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/GenerationCounts.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/GenerationCounts.md index 93809aa30..bf032fbd5 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/GenerationCounts.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/GenerationCounts.md @@ -10,7 +10,11 @@ In[] := WolframModel[{{1, 2}} -> {{1, 3}, {1, 3}, {3, 2}}, {{1, 1}}, Out[] = 5 ``` -**`"CompleteGenerationsCount"`** yields the number of generations that are "completely done". That is, no more matches can be made involving this or earlier generations. If the default [evaluation order](../Options/EventOrderingFunction.md) is used, this can only be either the same as `"TotalGenerationsCount"` (if we just finished a step) or one less (if we are in the middle of a step). However, it gets much more interesting if a different event order is used. For a random evolution, for instance, one can get +**`"CompleteGenerationsCount"`** yields the number of generations that are "completely done". That is, no more matches +can be made involving this or earlier generations. If the +default [evaluation order](../Options/EventOrderingFunction.md) is used, this can only be either the same +as `"TotalGenerationsCount"` (if we just finished a step) or one less (if we are in the middle of a step). However, it +gets much more interesting if a different event order is used. For a random evolution, for instance, one can get ```wl In[] := WolframModel[{{1, 2}} -> {{1, 3}, {1, 3}, {3, 2}}, {{1, 1}}, @@ -19,11 +23,17 @@ In[] := WolframModel[{{1, 2}} -> {{1, 3}, {1, 3}, {3, 2}}, {{1, 1}}, -Note, in this case, only one generation is complete, and seven are partial. That happens because the states grow with each generation, so it becomes more likely for a random choice to pick an edge from a later generation. Thus earlier ones are left unevolved. +Note, in this case, only one generation is complete, and seven are partial. That happens because the states grow with +each generation, so it becomes more likely for a random choice to pick an edge from a later generation. Thus earlier +ones are left unevolved. -**`"PartialGenerationsCount"`** is simply a difference of `"TotalGenerationsCount"` and `"CompleteGenerationsCount"`, and **`"GenerationsCount"`** is equivalent to `{"CompleteGenerationsCount", "PartialGenerationsCount"}`. +**`"PartialGenerationsCount"`** is simply a difference of `"TotalGenerationsCount"` and `"CompleteGenerationsCount"`, +and **`"GenerationsCount"`** is equivalent to `{"CompleteGenerationsCount", "PartialGenerationsCount"}`. -**`"GenerationComplete"`** takes a generation number as an argument, and gives [`True`](https://reference.wolfram.com/language/ref/True.html) or [`False`](https://reference.wolfram.com/language/ref/False.html) depending on whether that particular generation is complete: +**`"GenerationComplete"`** takes a generation number as an argument, and +gives [`True`](https://reference.wolfram.com/language/ref/True.html) +or [`False`](https://reference.wolfram.com/language/ref/False.html) depending on whether that particular generation is +complete: ```wl In[] := WolframModel[{{1, 2}} -> {{1, 3}, {1, 3}, {3, 2}}, {{1, 1}}, diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/MultiwayQ.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/MultiwayQ.md index 0b3fa9422..f0857202a 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/MultiwayQ.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/MultiwayQ.md @@ -2,7 +2,8 @@ # MultiwayQ -**`"MultiwayQ"`** checks if a given evolution contains multiway branching, i.e., there is an expression used in multiple events. +**`"MultiwayQ"`** checks if a given evolution contains multiway branching, i.e., there is an expression used in multiple +events. ```wl In[] := EchoFunction[#["ExpressionsEventsGraph"] &][ @@ -18,8 +19,9 @@ In[] := EchoFunction[#["ExpressionsEventsGraph"] &][ Out[] = True ``` -Note that even if [`"EventSelectionFunction"`](/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/EventSelectionFunction.md) is set to allow multiway branching, the system might still be singleway if no overlapping matches occurred: - +Note that even +if [`"EventSelectionFunction"`](/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/EventSelectionFunction.md) +is set to allow multiway branching, the system might still be singleway if no overlapping matches occurred: ```wl In[] := EchoFunction[#["ExpressionsEventsGraph"] &][WolframModel[ diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/PlotsOfEvents.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/PlotsOfEvents.md index 71ef28f1f..57062f204 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/PlotsOfEvents.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/PlotsOfEvents.md @@ -2,7 +2,8 @@ # Plots of Events -The plotting function corresponding to [`"AllEventsStatesList"`](States.md) is more interesting than the other ones. **`"EventsStatesPlotsList"`** plots not only the states, but also the events that produced them: +The plotting function corresponding to [`"AllEventsStatesList"`](States.md) is more interesting than the other +ones. **`"EventsStatesPlotsList"`** plots not only the states, but also the events that produced them: ```wl In[] := WolframModel[{{1, 2, 3}, {4, 5, 6}, {1, 4}} -> diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/PlotsOfStates.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/PlotsOfStates.md index dd3e5b95e..9f6529a1d 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/PlotsOfStates.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/PlotsOfStates.md @@ -2,7 +2,8 @@ # Plots of States -Instead of explicitly calling [`HypergraphPlot`](../../HypergraphPlot.md), one can use short-hand properties **`"FinalStatePlot"`** and **`"StatesPlotsList"`**: +Instead of explicitly calling [`HypergraphPlot`](../../HypergraphPlot.md), one can use short-hand +properties **`"FinalStatePlot"`** and **`"StatesPlotsList"`**: ```wl In[] := WolframModel[{{1, 2, 3}, {4, 5, 6}, {1, 4}} -> @@ -22,7 +23,8 @@ In[] := WolframModel[{{1, 2, 3}, {4, 5, 6}, {1, 4}} -> -These properties take the same options as [`HypergraphPlot`](../../HypergraphPlot.md) (but one has to specify them in a call to the evolution object, not `WolframModel`): +These properties take the same options as [`HypergraphPlot`](../../HypergraphPlot.md) (but one has to specify them in a +call to the evolution object, not `WolframModel`): ```wl In[] := WolframModel[{{1, 2, 3}, {4, 5, 6}, {1, 4}} -> diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/RuleIndicesForEvents.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/RuleIndicesForEvents.md index 6ccb84765..c7af4647e 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/RuleIndicesForEvents.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/RuleIndicesForEvents.md @@ -2,7 +2,8 @@ # Rule Indices for Events -**`"AllEventsRuleIndices"`** returns which rule was used for each event (the same can be obtained by mapping [`First`](https://reference.wolfram.com/language/ref/First.html) over [`"AllEventsList"`](Events.md)): +**`"AllEventsRuleIndices"`** returns which rule was used for each event (the same can be obtained by +mapping [`First`](https://reference.wolfram.com/language/ref/First.html) over [`"AllEventsList"`](Events.md)): ```wl In[] := WolframModel[{{{1, 1, 2}} -> {{2, 2, 1}, {2, 3, 2}, {1, 2, 3}}, @@ -11,7 +12,9 @@ In[] := WolframModel[{{{1, 1, 2}} -> {{2, 2, 1}, {2, 3, 2}, {1, 2, 3}}, Out[] = {1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 2} ``` -A neat example of using `"AllEventsRuleIndices"` is coloring events in a causal graph according to the rule index. With this visualization, one can see, for instance, that the outputs of the second rule in the example above are never used in any further inputs: +A neat example of using `"AllEventsRuleIndices"` is coloring events in a causal graph according to the rule index. With +this visualization, one can see, for instance, that the outputs of the second rule in the example above are never used +in any further inputs: ```wl In[] := With[{ diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/Rules.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/Rules.md index c756ae445..3a90809a9 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/Rules.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/Rules.md @@ -11,4 +11,5 @@ In[] := WolframModel[<|"PatternRules" -> Out[] = <|"PatternRules" -> {{a_}} :> {{a + 1}, {a - 1}, {{a + 2, a - 2}}}|> ``` -This is useful for display in the information box of the evolution object, and if one needs to reproduce an evolution object, the input for which is no longer available. +This is useful for display in the information box of the evolution object, and if one needs to reproduce an evolution +object, the input for which is no longer available. diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/States.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/States.md index 010bb3ece..dce3467e9 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/States.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/States.md @@ -2,7 +2,8 @@ # States -These are the properties used to extract states at a particular moment in the evolution. They always return lists, but in the examples below, we plot them for clarity. +These are the properties used to extract states at a particular moment in the evolution. They always return lists, but +in the examples below, we plot them for clarity. **`"FinalState"`** (aka -1) yields the state obtained after all replacements of the evolution have been made: @@ -49,7 +50,8 @@ In[] := HypergraphPlot /@ WolframModel[{{1, 2, 3}, {4, 5, 6}, {1, 4}} -> -`"StatesList"` shows a compressed version of the evolution. To see how the state changes with each applied replacement, use **`"AllEventsStatesList"`**: +`"StatesList"` shows a compressed version of the evolution. To see how the state changes with each applied replacement, +use **`"AllEventsStatesList"`**: ```wl In[] := HypergraphPlot /@ WolframModel[{{1, 2, 3}, {4, 5, 6}, {1, 4}} -> @@ -73,4 +75,5 @@ In[] := HypergraphPlot @ WolframModel[{{1, 2, 3}, {4, 5, 6}, {1, 4}} -> -`"StateAfterEvent"` is equivalent to taking a corresponding part in `"AllEventsStatesList"`, but it is much faster to compute than the entire list. +`"StateAfterEvent"` is equivalent to taking a corresponding part in `"AllEventsStatesList"`, but it is much faster to +compute than the entire list. diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/StatesAsEdgeIndices.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/StatesAsEdgeIndices.md index ec9b1bff3..ec67fae23 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/StatesAsEdgeIndices.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/StatesAsEdgeIndices.md @@ -2,7 +2,8 @@ # States as Edge Indices -**`"AllEventsStatesEdgeIndicesList"`** is similar to [`"AllEventsStatesList"`](States.md), except instead of actual edges the list it returns contains the indices of edges from [`"AllEventsEdgesList"`](AllEdgesThroughoutEvolution.md): +**`"AllEventsStatesEdgeIndicesList"`** is similar to [`"AllEventsStatesList"`](States.md), except instead of actual +edges the list it returns contains the indices of edges from [`"AllEventsEdgesList"`](AllEdgesThroughoutEvolution.md): ```wl In[] := WolframModel[{{1, 2, 3}, {4, 5, 6}, {1, 4}} -> diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/TerminationReason.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/TerminationReason.md index 122cc2c24..8c56c250e 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/TerminationReason.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/TerminationReason.md @@ -2,16 +2,20 @@ # Termination Reason -**`"TerminationReason"`** shows why the evaluation of the model was stopped. It's particularly useful if multiple [stopping conditions](../WolframModelAndWolframModelEvolutionObject.md#step-limiters) are specified. +**`"TerminationReason"`** shows why the evaluation of the model was stopped. It's particularly useful if +multiple [stopping conditions](../WolframModelAndWolframModelEvolutionObject.md#step-limiters) are specified. All possible values are: -* `"MaxEvents"`, `"MaxGenerations"`, `"MaxVertices"`, `"MaxVertexDegree"` and `"MaxEdges"` correspond directly to [step limiters](../WolframModelAndWolframModelEvolutionObject.md#step-limiters). +* `"MaxEvents"`, `"MaxGenerations"`, `"MaxVertices"`, `"MaxVertexDegree"` and `"MaxEdges"` correspond directly + to [step limiters](../WolframModelAndWolframModelEvolutionObject.md#step-limiters). * `"FixedPoint"` means there were no more matches possible to rule inputs. * `"TimeConstraint"` could occur if a [`"TimeConstraint"`](../Options/TimeConstraint.md) option is used. -* `"Aborted"` would occur if the evaluation was manually interrupted (i.e., by pressing ⌘. on a Mac). In that case, a partially computed evolution object is returned. +* `"Aborted"` would occur if the evaluation was manually interrupted (i.e., by pressing ⌘. on a Mac). In that case, a + partially computed evolution object is returned. -As an example, in our arithmetic model a `"FixedPoint"` is reached (which is why we can use [`Infinity`](https://reference.wolfram.com/language/ref/Infinity.html) as the number of steps): +As an example, in our arithmetic model a `"FixedPoint"` is reached (which is why we can +use [`Infinity`](https://reference.wolfram.com/language/ref/Infinity.html) as the number of steps): ```wl In[] := WolframModel[<|"PatternRules" -> {a_, b_} :> a + b|>, diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/TotalElementCounts.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/TotalElementCounts.md index 7bfd8892f..dc112f380 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/TotalElementCounts.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/TotalElementCounts.md @@ -2,7 +2,10 @@ # Total Element Counts -**`"AllEventsDistinctElementsCount"`** (aka `"AtomsCountTotal"`) and **`"AllEventsEdgesCount"`** (aka `"ExpressionsCountTotal"`) are similar to [`"FinalDistinctElementsCount"`](FinalElementCounts.md) and [`"FinalEdgeCount"`](FinalElementCounts.md), except they count atoms and edges throughout the entire evolution instead of just in the final step. +**`"AllEventsDistinctElementsCount"`** (aka `"AtomsCountTotal"`) and **`"AllEventsEdgesCount"`** ( +aka `"ExpressionsCountTotal"`) are similar to [`"FinalDistinctElementsCount"`](FinalElementCounts.md) +and [`"FinalEdgeCount"`](FinalElementCounts.md), except they count atoms and edges throughout the entire evolution +instead of just in the final step. For instance, diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/Version.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/Version.md index c260e8b45..e1a6ebe3a 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/Version.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/Version.md @@ -2,11 +2,13 @@ # Version -**`"Version"`** returns the version of the data structure used in the evolution object. It will always be the same for the same version of *SetReplace*: +**`"Version"`** returns the version of the data structure used in the evolution object. It will always be the same for +the same version of *SetReplace*: ```wl In[] := WolframModel[1 -> 2, {1}]["Version"] Out[] = 2 ``` -Objects are automatically converted to the latest version when they are encountered by the newer version of *SetReplace*. +Objects are automatically converted to the latest version when they are encountered by the newer version of + *SetReplace*. diff --git a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md index 9de414c9b..06585b21b 100644 --- a/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md +++ b/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md @@ -2,9 +2,12 @@ # WolframModel and WolframModelEvolutionObject -[Rule Specification](#rule-specification) | [Automatic Initial State](#automatic-initial-state) | [Step Limiters](#step-limiters) | [Properties](#properties) | [Options](#options) +[Rule Specification](#rule-specification) | [Automatic Initial State](#automatic-initial-state) +| [Step Limiters](#step-limiters) | [Properties](#properties) | [Options](#options) -**`WolframModel`** is the primary function of the package. It provides tools for the generation and analysis of set substitution systems. It can compute many different properties of the evolution and has many different options, which we describe in the corresponding subsections. +**`WolframModel`** is the primary function of the package. It provides tools for the generation and analysis of set +substitution systems. It can compute many different properties of the evolution and has many different options, which we +describe in the corresponding subsections. The most basic way to call it is @@ -26,8 +29,13 @@ Note that this call is different from the [`SetReplace`](../SetReplace.md) funct * The order of arguments is switched, the rule goes first. * The rule is specified in the "anonymous" form ([`ToPatternRules`](../ToPatternRules.md) is done implicitly). -* The number of steps here is the number of generations, which is equivalent to steps of [`SetReplaceAll`](../SetReplace.md). Here each edge can have at most 10 generations of predecessors. -* The output is not a final state, but a **`WolframModelEvolutionObject`** containing the entire evolution (similar to [`SetReplaceList`](../SetReplace.md) but with additional information about the relationships between edges and the events that produced them. From the information field on that object, one can see that the evolution was done for 10 generations (i.e., the evolution did not terminate early), and 109 replacements (aka events) were made in total. More [properties](#properties) can be computed from an evolution object. +* The number of steps here is the number of generations, which is equivalent to steps + of [`SetReplaceAll`](../SetReplace.md). Here each edge can have at most 10 generations of predecessors. +* The output is not a final state, but a **`WolframModelEvolutionObject`** containing the entire evolution (similar + to [`SetReplaceList`](../SetReplace.md) but with additional information about the relationships between edges and the + events that produced them. From the information field on that object, one can see that the evolution was done for 10 + generations (i.e., the evolution did not terminate early), and 109 replacements (aka events) were made in total. + More [properties](#properties) can be computed from an evolution object. To see the information an evolution object contains, let's make one with a smaller number of generations: @@ -39,7 +47,8 @@ In[] := WolframModel[{{1, 2, 3}, {2, 4, 5}} -> -One can easily see its internal structure in its [`InputForm`](https://reference.wolfram.com/language/ref/InputForm.html): +One can easily see its internal structure in +its [`InputForm`](https://reference.wolfram.com/language/ref/InputForm.html): @@ -61,11 +70,18 @@ Out[] = WolframModelEvolutionObject[<| "EventGenerations" -> {0, 1, 2, 2, 3, 3}|>] ``` -The most important part of this [`Association`](https://reference.wolfram.com/language/ref/Association.html) is `"AtomLists"` which includes all set elements (aka expressions or edges) ever created throughout evolution. +The most important part of this [`Association`](https://reference.wolfram.com/language/ref/Association.html) +is `"AtomLists"` which includes all set elements (aka expressions or edges) ever created throughout evolution. -In this particular example, it begins with `{1, 2, 3}`, `{2, 4, 5}` and `{4, 6, 7}`, which is the initial set. It is then followed by `{5, 8, 1}`, `{8, 4, 2}` and `{4, 5, 3}` which are the edges created in the first replacement event (the new vertex `8` here is named with the first unused integer, see [`"VertexNamingFunction"`](Options/VertexNamingFunction.md) for details about naming). These edges are followed by four more triples of edges corresponding to the outputs of remaining events. +In this particular example, it begins with `{1, 2, 3}`, `{2, 4, 5}` and `{4, 6, 7}`, which is the initial set. It is +then followed by `{5, 8, 1}`, `{8, 4, 2}` and `{4, 5, 3}` which are the edges created in the first replacement event ( +the new vertex `8` here is named with the first unused integer, +see [`"VertexNamingFunction"`](Options/VertexNamingFunction.md) for details about naming). These edges are followed by +four more triples of edges corresponding to the outputs of remaining events. -`"AtomLists"` contains edges from all steps and is by itself insufficient to determine to which step a particular edge belongs. For example, `{5, 8, 1}` only appears in the result after a single step and `{7, 9, 8}` after two steps. Here we use [`"StatesList"`](Properties/States.md) property to demonstrate that: +`"AtomLists"` contains edges from all steps and is by itself insufficient to determine to which step a particular edge +belongs. For example, `{5, 8, 1}` only appears in the result after a single step and `{7, 9, 8}` after two steps. Here +we use [`"StatesList"`](Properties/States.md) property to demonstrate that: @@ -78,17 +94,30 @@ Out[] = {{{1, 2, 3}, {2, 4, 5}, {4, 6, 7}}, 1}, {12, 8, 10}, {8, 5, 4}}} ``` -Note that a set element is not duplicated in `"AtomLists"` if it exists in multiple steps. For example, `{6, 7, 2}` appears in the set after both two and three steps, but it only appears in `"AtomLists"` once because it was never used as an input during the 3rd step. +Note that a set element is not duplicated in `"AtomLists"` if it exists in multiple steps. For example, `{6, 7, 2}` +appears in the set after both two and three steps, but it only appears in `"AtomLists"` once because it was never used +as an input during the 3rd step. Other properties of the evolution object describe the relationships between edges and the features of the evolution: -* `"Version"` is the data format of the evolution object. This description is for version 2, which is the first version to support multiway systems. Version 1 does not have the `"Version"` key. The objects of older versions are automatically migrated when they are evaluated. +* `"Version"` is the data format of the evolution object. This description is for version 2, which is the first version + to support multiway systems. Version 1 does not have the `"Version"` key. The objects of older versions are + automatically migrated when they are evaluated. * `"Rules"` is an exact copy of the corresponding `WolframModel` argument. -* `"MaxCompleteGenerations"` shows the largest generation in which no matches are possible that only involve expressions of this or earlier generations. In this particular case, it is the same as the largest generation of any edge, but it might be different if a more elaborate [step specification](#step-limiters) is used. -* `"TerminationReason"` shows the reason evaluation was stopped. See the [`"TerminationReason"`](Properties/TerminationReason.md) property for more details. -* `"EventRuleIDs"` shows which rule was used for each event. It's rather boring in this particular case, as this example only has one rule. See [Rule Indices for Events](Properties/RuleIndicesForEvents.md) for a more interesting case. The first value, `0`, corresponds to the initial event, which is included in the evolution object but is omitted [by default](Options/IncludeBoundaryEvents.md) when computing [properties](#properties). -* `"EventInputs"` shows which edge indices from `"AtomLists"` were used in each event. The order corresponds to the input patterns of the rules. The first value, `{}`, again corresponds to the initial event. Note, the same index can appear multiple times in [multiway systems](Options/EventSelectionFunction.md). -* `"EventOutputs"` similarly shows which edge indices from `"AtomLists"` were produced by each event. There are no duplicates in these lists because events always generate new edges. +* `"MaxCompleteGenerations"` shows the largest generation in which no matches are possible that only involve expressions + of this or earlier generations. In this particular case, it is the same as the largest generation of any edge, but it + might be different if a more elaborate [step specification](#step-limiters) is used. +* `"TerminationReason"` shows the reason evaluation was stopped. See + the [`"TerminationReason"`](Properties/TerminationReason.md) property for more details. +* `"EventRuleIDs"` shows which rule was used for each event. It's rather boring in this particular case, as this example + only has one rule. See [Rule Indices for Events](Properties/RuleIndicesForEvents.md) for a more interesting case. The + first value, `0`, corresponds to the initial event, which is included in the evolution object but is + omitted [by default](Options/IncludeBoundaryEvents.md) when computing [properties](#properties). +* `"EventInputs"` shows which edge indices from `"AtomLists"` were used in each event. The order corresponds to the + input patterns of the rules. The first value, `{}`, again corresponds to the initial event. Note, the same index can + appear multiple times in [multiway systems](Options/EventSelectionFunction.md). +* `"EventOutputs"` similarly shows which edge indices from `"AtomLists"` were produced by each event. There are no + duplicates in these lists because events always generate new edges. * `"EventGenerations"` shows how many layers of predecessors a given event has. A specific property can be requested from an evolution object by supplying it as an argument to the object itself: @@ -99,7 +128,8 @@ A specific property can be requested from an evolution object by supplying it as Out[] = 109 ``` -[Properties](#properties) section describes and gives examples for each available property. The full list of them can also be obtained with the `"Properties"` property: +[Properties](#properties) section describes and gives examples for each available property. The full list of them can +also be obtained with the `"Properties"` property: @@ -150,7 +180,9 @@ In[] := WolframModel[{{1, 2, 3}, {2, 4, 5}} -> Out[] = {3, 4, 6, 8, 12, 18, 24, 36, 54, 76, 112} ``` -All properties available to use directly in `WolframModel` can be looked up in `$WolframModelProperties` (there are more properties here compared to the list above because some properties are available under multiple names, and only the canonical name is listed above): +All properties available to use directly in `WolframModel` can be looked up in `$WolframModelProperties` (there are more +properties here compared to the list above because some properties are available under multiple names, and only the +canonical name is listed above): ```wl In[] := $WolframModelProperties @@ -209,7 +241,8 @@ Out[] = {1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 2} ### Pattern Rules -Pattern rules (i.e., the kind of rules used in the [`SetReplace`](../SetReplace.md) function) can be specified as well. As an example, previously described call to [`SetReplaceList`](../SetReplace.md) can be reproduced as +Pattern rules (i.e., the kind of rules used in the [`SetReplace`](../SetReplace.md) function) can be specified as well. +As an example, previously described call to [`SetReplaceList`](../SetReplace.md) can be reproduced as ```wl In[] := WolframModel[<|"PatternRules" -> {a_, b_} :> a + b|>, @@ -227,7 +260,9 @@ Out[] = {{1, 1, 5, 3, 6}, {1, 3, 6, 4}, {6, 4, 2}, {2, 2}} ## Automatic Initial State -An initial state consisting of an appropriate number of (hyper) self-loops can be automatically produced for anonymous (non-pattern) rules. Here we evolve the system for 0 steps and ask the evolution object for the 0-th generation aka the initial state: +An initial state consisting of an appropriate number of (hyper) self-loops can be automatically produced for anonymous ( +non-pattern) rules. Here we evolve the system for 0 steps and ask the evolution object for the 0-th generation aka the +initial state: ```wl In[] := WolframModel[{{1, 2}, {1, 2}} -> {{3, 2}, {3, 2}, {2, 1}, {1, 3}}, @@ -244,7 +279,8 @@ In[] := WolframModel[{{{1, 2}, {1, 2}} -> Out[] = {{1, 1}, {1, 1}, {1, 1, 1}} ``` -Note that because different patterns can be matched to the same symbol, this initial state is guaranteed to match the rules at least once (no guarantees after that). +Note that because different patterns can be matched to the same symbol, this initial state is guaranteed to match the +rules at least once (no guarantees after that). ## Step Limiters @@ -260,7 +296,8 @@ In[] := WolframModel[{{1, 2, 3}, {4, 5, 6}, {2, 5}, {5, 2}} -> -Alternatively, an [`Association`](https://reference.wolfram.com/language/ref/Association.html) can be used to specify a more elaborate limiting condition: +Alternatively, an [`Association`](https://reference.wolfram.com/language/ref/Association.html) can be used to specify a +more elaborate limiting condition: ```wl In[] := WolframModel[{{1, 2, 3}, {4, 5, 6}, {2, 5}, {5, 2}} -> @@ -273,9 +310,13 @@ In[] := WolframModel[{{1, 2, 3}, {4, 5, 6}, {2, 5}, {5, 2}} -> -Note that the final state here is "less symmetric" because its last generation is incomplete (more on that [later](../UtilityFunctions/HypergraphAutomorphismGroup.md)). Such incomplete generations can be automatically trimmed by setting [`"IncludePartialGenerations" -> False`](Options/IncludePartialGenerations.md). +Note that the final state here is "less symmetric" because its last generation is incomplete (more on +that [later](../UtilityFunctions/HypergraphAutomorphismGroup.md)). Such incomplete generations can be automatically +trimmed by setting [`"IncludePartialGenerations" -> False`](Options/IncludePartialGenerations.md). -One can also see the presence of an incomplete generation by looking at the evolution object (note `5...6` which means 5 generations are complete, and 1 is not). Expanding the object's information, one can also see that in this particular case the evolution was terminated because `"MaxVertices"` (not `"MaxEvents"`) condition was reached: +One can also see the presence of an incomplete generation by looking at the evolution object (note `5...6` which means 5 +generations are complete, and 1 is not). Expanding the object's information, one can also see that in this particular +case the evolution was terminated because `"MaxVertices"` (not `"MaxEvents"`) condition was reached: ```wl In[] := WolframModel[{{1, 2, 3}, {4, 5, 6}, {2, 5}, {5, 2}} -> @@ -291,16 +332,26 @@ In[] := WolframModel[{{1, 2, 3}, {4, 5, 6}, {2, 5}, {5, 2}} -> All possible keys in that association are: * `"MaxEvents"`: limit the number of individual replacements (in the [`SetReplace`](../SetReplace.md) function meaning). -* `"MaxGenerations"`: limit the number of generations (steps in [`SetReplaceAll`](../SetReplace.md) meaning), same as specifying steps directly as a number in `WolframModel`. -* `"MaxVertices"`: limit the number of vertices in the *final* state only (the total count throughout evolution might be larger). This limit stops evolution if the next event, if applied, would put the state over the limit. Note once such an event is encountered, the evolution stops immediately even if other matches exist that would not put the vertex count over the limit. -* `"MaxVertexDegree"`: limit the number of final state edges in which any particular vertex is involved. Works in a similar way to `"MaxVertices"`. +* `"MaxGenerations"`: limit the number of generations (steps in [`SetReplaceAll`](../SetReplace.md) meaning), same as + specifying steps directly as a number in `WolframModel`. +* `"MaxVertices"`: limit the number of vertices in the *final* state only (the total count throughout evolution might be + larger). This limit stops evolution if the next event, if applied, would put the state over the limit. Note once such + an event is encountered, the evolution stops immediately even if other matches exist that would not put the vertex + count over the limit. +* `"MaxVertexDegree"`: limit the number of final state edges in which any particular vertex is involved. Works in a + similar way to `"MaxVertices"`. * `"MaxEdges"`: limit the number of edges (set elements) in the final state. Works similarly to `"MaxVertices"`. Any combination of these can be used, in which case the earliest triggered condition stops the evolution. -Note also that `"MaxGenerations"` works differently from the other limiters, as the matching algorithm would not even attempt to match edges with generations over the limit. Therefore unlike, i.e., `"MaxVertices"`, which would terminate the evolution immediately once the limit-violating event is attempted, `"MaxGenerations"` would keep "filling in" events for as long as possible until no further matches within allowed generations are possible. +Note also that `"MaxGenerations"` works differently from the other limiters, as the matching algorithm would not even +attempt to match edges with generations over the limit. Therefore unlike, i.e., `"MaxVertices"`, which would terminate +the evolution immediately once the limit-violating event is attempted, `"MaxGenerations"` would keep "filling in" events +for as long as possible until no further matches within allowed generations are possible. -It is also possible to set the step count to `Automatic`, in which case `WolframModel` tries to automatically pick a number of steps that showcases the evolution without taking too long. It stops the evolution sooner if the state grows quickly: +It is also possible to set the step count to `Automatic`, in which case `WolframModel` tries to automatically pick a +number of steps that showcases the evolution without taking too long. It stops the evolution sooner if the state grows +quickly: ```wl In[] := WolframModel[{{1, 2, 3}, {2, 4, 5}} -> {{5, 6, 1}, {6, 4, 2}, {4, 5, @@ -319,40 +370,42 @@ In[] := WolframModel[<|"PatternRules" -> {{a_, b_}} :> {{a + b, a - b}}|>, -Currently, it's equivalent to `<|"MaxEvents" -> 5000, "MaxVertices" -> 200|>`, setting `TimeConstraint -> 5` (it still returns values for all properties even if terminated due to time constraint), and `"IncludePartialGenerations" -> False`, but it may be adjusted in future updates. +Currently, it's equivalent to `<|"MaxEvents" -> 5000, "MaxVertices" -> 200|>`, setting `TimeConstraint -> 5` (it still +returns values for all properties even if terminated due to time constraint), and `"IncludePartialGenerations" -> False` +, but it may be adjusted in future updates. ## Properties -- [States](Properties/States.md) -- [Plots of States](Properties/PlotsOfStates.md) -- [Plots of Events](Properties/PlotsOfEvents.md) -- [All Edges throughout Evolution](Properties/AllEdgesThroughoutEvolution.md) -- [States as Edge Indices](Properties/StatesAsEdgeIndices.md) -- [Events](Properties/Events.md) -- [Events and States](Properties/EventsAndStates.md) -- [Creator and Destroyer Events](Properties/CreatorAndDestroyerEvents.md) -- [Causal Graphs](Properties/CausalGraphs.md) -- [Expression Separations](Properties/ExpressionSeparations.md) -- [MultiwayQ](Properties/MultiwayQ.md) -- [Rule Indices for Events](Properties/RuleIndicesForEvents.md) -- [Edge and Event Generations](Properties/EdgeAndEventGenerations.md) -- [Termination Reason](Properties/TerminationReason.md) -- [Generation Counts](Properties/GenerationCounts.md) -- [Event Counts](Properties/EventCounts.md) -- [Element Count Lists](Properties/ElementCountLists.md) -- [Final Element Counts](Properties/FinalElementCounts.md) -- [Total Element Counts](Properties/TotalElementCounts.md) -- [Rules](Properties/Rules.md) -- [Feature Vector](Properties/FeatureVector.md) -- [Version](Properties/Version.md) +* [States](Properties/States.md) +* [Plots of States](Properties/PlotsOfStates.md) +* [Plots of Events](Properties/PlotsOfEvents.md) +* [All Edges throughout Evolution](Properties/AllEdgesThroughoutEvolution.md) +* [States as Edge Indices](Properties/StatesAsEdgeIndices.md) +* [Events](Properties/Events.md) +* [Events and States](Properties/EventsAndStates.md) +* [Creator and Destroyer Events](Properties/CreatorAndDestroyerEvents.md) +* [Causal Graphs](Properties/CausalGraphs.md) +* [Expression Separations](Properties/ExpressionSeparations.md) +* [MultiwayQ](Properties/MultiwayQ.md) +* [Rule Indices for Events](Properties/RuleIndicesForEvents.md) +* [Edge and Event Generations](Properties/EdgeAndEventGenerations.md) +* [Termination Reason](Properties/TerminationReason.md) +* [Generation Counts](Properties/GenerationCounts.md) +* [Event Counts](Properties/EventCounts.md) +* [Element Count Lists](Properties/ElementCountLists.md) +* [Final Element Counts](Properties/FinalElementCounts.md) +* [Total Element Counts](Properties/TotalElementCounts.md) +* [Rules](Properties/Rules.md) +* [Feature Vector](Properties/FeatureVector.md) +* [Version](Properties/Version.md) ## Options -- ["VertexNamingFunction"](Options/VertexNamingFunction.md) -- ["IncludePartialGenerations"](Options/IncludePartialGenerations.md) -- ["IncludeBoundaryEvents"](Options/IncludeBoundaryEvents.md) -- ["EventOrderingFunction"](Options/EventOrderingFunction.md) -- ["EventSelectionFunction"](Options/EventSelectionFunction.md) -- ["EventDeduplication"](Options/EventDeduplication.md) -- [Method](Options/Method.md) -- [Time Constraint](Options/TimeConstraint.md) +* ["VertexNamingFunction"](Options/VertexNamingFunction.md) +* ["IncludePartialGenerations"](Options/IncludePartialGenerations.md) +* ["IncludeBoundaryEvents"](Options/IncludeBoundaryEvents.md) +* ["EventOrderingFunction"](Options/EventOrderingFunction.md) +* ["EventSelectionFunction"](Options/EventSelectionFunction.md) +* ["EventDeduplication"](Options/EventDeduplication.md) +* [Method](Options/Method.md) +* [Time Constraint](Options/TimeConstraint.md) diff --git a/README.md b/README.md index 79eddd442..7787eacc5 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,15 @@ [![Discord](https://img.shields.io/discord/761616685173309481?logo=Discord)](https://discord.setreplace.org) -[Wolfram Models as Set Substitution Systems](#wolfram-models-as-set-substitution-systems) | [Getting Started](#getting-started) | [Symbols and Functions](#symbols-and-functions) | [Physics](#physics) | [Acknowledgements](#acknowledgements) +[Wolfram Models as Set Substitution Systems](#wolfram-models-as-set-substitution-systems) +| [Getting Started](#getting-started) | [Symbols and Functions](#symbols-and-functions) | [Physics](#physics) +| [Acknowledgements](#acknowledgements) # Wolfram Models as Set Substitution Systems ## Set Substitution Systems -*SetReplace* is a [Wolfram Language](https://www.wolfram.com/language/) package for manipulating set substitution systems. To understand what a set substitution system does consider an unordered set of elements: +*SetReplace* is a [Wolfram Language](https://www.wolfram.com/language/) package for manipulating set substitution +systems. To understand what a set substitution system does consider an unordered set of elements: ```wl {1, 2, 5, 3, 6} @@ -25,7 +28,8 @@ In[] := SetReplace[{1, 2, 5, 3, 6}, {a_, b_} :> {a + b}] Out[] = {5, 3, 6, 3} ``` -Note that this is similar to [`SubsetReplace`](https://reference.wolfram.com/language/ref/SubsetReplace.html) function of Wolfram Language (introduced in version 12.1, it replaces all non-overlapping subsets at once by default): +Note that this is similar to [`SubsetReplace`](https://reference.wolfram.com/language/ref/SubsetReplace.html) function +of Wolfram Language (introduced in version 12.1, it replaces all non-overlapping subsets at once by default): ```wl In[] := SubsetReplace[{1, 2, 5, 3, 6}, {a_, b_} :> a + b] @@ -34,7 +38,8 @@ Out[] = {3, 8, 6} ## Wolfram Models -A more interesting case (which we call a Wolfram model) is one where the set elements are related to each other. Specifically, we can consider a set of ordered lists of atomic vertices; in other words, an ordered hypergraph. +A more interesting case (which we call a Wolfram model) is one where the set elements are related to each other. +Specifically, we can consider a set of ordered lists of atomic vertices; in other words, an ordered hypergraph. As an example consider a set: @@ -51,14 +56,18 @@ In[] := HypergraphPlot[{{1, 2, 3}, {2, 4, 5}, {4, 6, 7}}, -We can then have a rule which would pick a subset of these hyperedges related through common vertices (much like a join query) and replace them with something else: +We can then have a rule which would pick a subset of these hyperedges related through common vertices (much like a join +query) and replace them with something else: ```wl {{v1_, v2_, v3_}, {v2_, v4_, v5_}} :> Module[{v6}, {{v5, v6, v1}, {v6, v4, v2}, {v4, v5, v3}}] ``` -Note the [`Module`](https://reference.wolfram.com/language/ref/Module.html) on the right-hand side creates a new variable (vertex) which causes the hypergraph to grow. Due to optimizations, it's not always a [`Module`](https://reference.wolfram.com/language/ref/Module.html) that creates vertices, so its name may be different. After a single replacement we get this (the new vertex is v11): +Note the [`Module`](https://reference.wolfram.com/language/ref/Module.html) on the right-hand side creates a new +variable (vertex) which causes the hypergraph to grow. Due to optimizations, it's not always +a [`Module`](https://reference.wolfram.com/language/ref/Module.html) that creates vertices, so its name may be +different. After a single replacement we get this (the new vertex is v11): ```wl In[] := HypergraphPlot[SetReplace[{{1, 2, 3}, {2, 4, 5}, {4, 6, 7}}, @@ -99,12 +108,17 @@ Exploring the hypergraph models of this variety is the primary purpose of this p You only need three things to use *SetReplace*: * Windows, macOS 10.12+, or Linux. -* [Wolfram Language 12.1+](https://www.wolfram.com/language/) including [WolframScript](https://www.wolfram.com/wolframscript/). A free version is available as [Wolfram Engine](https://www.wolfram.com/engine/). -* A C++17 compiler to build the low-level part of the package. Instructions on how to set up a compiler to use in WolframScript are [here](https://reference.wolfram.com/language/CCompilerDriver/tutorial/SpecificCompilers.html#509267359). +* [Wolfram Language 12.1+](https://www.wolfram.com/language/) + including [WolframScript](https://www.wolfram.com/wolframscript/). A free version is available + as [Wolfram Engine](https://www.wolfram.com/engine/). +* A C++17 compiler to build the low-level part of the package. Instructions on how to set up a compiler to use in + WolframScript + are [here](https://reference.wolfram.com/language/CCompilerDriver/tutorial/SpecificCompilers.html#509267359). ## Build Instructions -For users who wish to make use of *SetReplace* functionality, and not modify the source code itself, we recommend simply building and installing the paclet. +For users who wish to make use of *SetReplace* functionality, and not modify the source code itself, we recommend simply +building and installing the paclet. To do this, run the following on the command line: @@ -115,88 +129,111 @@ cd ~/PATH-TO-CHECKOUT/SetReplace Please note that if you do not have GitLink installed, it will be installed for you. -Now that you have installed the *SetReplace* paclet, you should evaluate ``<< SetReplace` `` every time you start a fresh Mathematica session. This will load the paclet and bring the various functions into scope, so that you can call them. +Now that you have installed the *SetReplace* paclet, you should evaluate ``<< SetReplace` `` every time you start a +fresh Mathematica session. This will load the paclet and bring the various functions into scope, so that you can call +them. -For more info about doing development on the *SetReplace* codebase and the associated workflows, see the [Contributing guide](.github/CONTRIBUTING.md#building-in-place). +For more info about doing development on the *SetReplace* codebase and the associated workflows, see +the [Contributing guide](.github/CONTRIBUTING.md#building-in-place). ### C++17 -If, while building, you see an error message about C++17, make sure the C++ compiler you are using is up-to-date. If your default system compiler does not support C++17, you can choose a different one with environmental variables. The following, for instance, typically works on a Mac: +If, while building, you see an error message about C++17, make sure the C++ compiler you are using is up-to-date. If +your default system compiler does not support C++17, you can choose a different one with environmental variables. The +following, for instance, typically works on a Mac: ```bash COMPILER=CCompilerDriver\`ClangCompiler\`ClangCompiler COMPILER_INSTALLATION=/usr/bin ./install.wls ``` -Here `ClangCompiler` can be replaced with one of ``<< CCompilerDriver`; "Compiler" /. CCompilerDriver`CCompilers[Full]``, and `COMPILER_INSTALLATION` is a directory in which the compiler binary can be found. +Here `ClangCompiler` can be replaced with one of ``<< CCompilerDriver`; "Compiler" /. CCompilerDriver`CCompilers[Full]`` +, and `COMPILER_INSTALLATION` is a directory in which the compiler binary can be found. ## Contributing -Keep in mind that this is an active research project. While we try to keep the main functionality backward compatible, it might change in the future as we adjust our models and find better ways of analysis. Keep that in mind when building on top of *SetReplace*, and keep track of [git SHAs](Documentation/SymbolsAndFunctions/UtilityFunctions/BuildData.md) as you go. +Keep in mind that this is an active research project. While we try to keep the main functionality backward compatible, +it might change in the future as we adjust our models and find better ways of analysis. Keep that in mind when building +on top of *SetReplace*, and keep track of [git SHAs](Documentation/SymbolsAndFunctions/UtilityFunctions/BuildData.md) as +you go. -*SetReplace* is an open-source project, and everyone is welcome to contribute. Read our [contributing guidelines](.github/CONTRIBUTING.md) to get started. +*SetReplace* is an open-source project, and everyone is welcome to contribute. Read +our [contributing guidelines](.github/CONTRIBUTING.md) to get started. -We have a [Discord server](https://discord.setreplace.org). If you would like to contribute but have questions or don't know where to start, this is the perfect place! In addition to helping new contributors, we discuss feature and research ideas. So, if you are interested, please join! +We have a [Discord server](https://discord.setreplace.org). If you would like to contribute but have questions or don't +know where to start, this is the perfect place! In addition to helping new contributors, we discuss feature and research +ideas. So, if you are interested, please join! # Symbols and Functions -- [SetReplace\*](Documentation/SymbolsAndFunctions/SetReplace.md) -- [ToPatternRules](Documentation/SymbolsAndFunctions/ToPatternRules.md) -- [WolframModel and WolframModelEvolutionObject](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md) - - Properties - - [States](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/States.md) - - [Plots of States](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/PlotsOfStates.md) - - [Plots of Events](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/PlotsOfEvents.md) - - [All Edges throughout Evolution](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/AllEdgesThroughoutEvolution.md) - - [States as Edge Indices](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/StatesAsEdgeIndices.md) - - [Events](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/Events.md) - - [Events and States](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/EventsAndStates.md) - - [Creator and Destroyer Events](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/CreatorAndDestroyerEvents.md) - - [Causal Graphs](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/CausalGraphs.md) - - [Expression Separations](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/ExpressionSeparations.md) - - [MultiwayQ](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/MultiwayQ.md) - - [Rule Indices for Events](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/RuleIndicesForEvents.md) - - [Edge and Event Generations](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/EdgeAndEventGenerations.md) - - [Termination Reason](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/TerminationReason.md) - - [Generation Counts](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/GenerationCounts.md) - - [Event Counts](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/EventCounts.md) - - [Element Count Lists](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/ElementCountLists.md) - - [Final Element Counts](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/FinalElementCounts.md) - - [Total Element Counts](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/TotalElementCounts.md) - - [Rules](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/Rules.md) - - [Feature Vector](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/FeatureVector.md) - - [Version](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/Version.md) - - Options - - ["VertexNamingFunction"](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/VertexNamingFunction.md) - - ["IncludePartialGenerations"](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/IncludePartialGenerations.md) - - ["IncludeBoundaryEvents"](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/IncludeBoundaryEvents.md) - - ["EventOrderingFunction"](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/EventOrderingFunction.md) - - ["EventSelectionFunction"](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/EventSelectionFunction.md) - - ["EventDeduplication"](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/EventDeduplication.md) - - [Method](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/Method.md) - - [Time Constraint](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/TimeConstraint.md) -- [HypergraphPlot](Documentation/SymbolsAndFunctions/HypergraphPlot.md) -- [RulePlot of WolframModel](Documentation/SymbolsAndFunctions/RulePlotOfWolframModel.md) -- Utility Functions - - [IndexHypergraph](Documentation/SymbolsAndFunctions/UtilityFunctions/IndexHypergraph.md) - - [IsomorphicHypergraphQ](Documentation/SymbolsAndFunctions/UtilityFunctions/IsomorphicHypergraphQ.md) - - [HypergraphToGraph](Documentation/SymbolsAndFunctions/UtilityFunctions/HypergraphToGraph.md) - - [RandomHypergraph](Documentation/SymbolsAndFunctions/UtilityFunctions/RandomHypergraph.md) - - [Subhypergraph](Documentation/SymbolsAndFunctions/UtilityFunctions/Subhypergraph.md) - - [WolframModelRuleValue](Documentation/SymbolsAndFunctions/UtilityFunctions/WolframModelRuleValue.md) - - [GeneralizedGridGraph](Documentation/SymbolsAndFunctions/UtilityFunctions/GeneralizedGridGraph.md) - - [HypergraphAutomorphismGroup](Documentation/SymbolsAndFunctions/UtilityFunctions/HypergraphAutomorphismGroup.md) - - [HypergraphUnifications](Documentation/SymbolsAndFunctions/UtilityFunctions/HypergraphUnifications.md) - - [WolframPhysicsProjectStyleData](Documentation/SymbolsAndFunctions/UtilityFunctions/WolframPhysicsProjectStyleData.md) - - [Build Data](Documentation/SymbolsAndFunctions/UtilityFunctions/BuildData.md) +* [SetReplace\*](Documentation/SymbolsAndFunctions/SetReplace.md) +* [ToPatternRules](Documentation/SymbolsAndFunctions/ToPatternRules.md) +* [WolframModel and WolframModelEvolutionObject](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/WolframModelAndWolframModelEvolutionObject.md) + * Properties + * [States](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/States.md) + * [Plots of States](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/PlotsOfStates.md) + * [Plots of Events](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/PlotsOfEvents.md) + * [All Edges throughout Evolution](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/AllEdgesThroughoutEvolution.md) + * [States as Edge Indices](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/StatesAsEdgeIndices.md) + * [Events](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/Events.md) + * [Events and States](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/EventsAndStates.md) + * [Creator and Destroyer Events](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/CreatorAndDestroyerEvents.md) + * [Causal Graphs](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/CausalGraphs.md) + * [Expression Separations](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/ExpressionSeparations.md) + * [MultiwayQ](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/MultiwayQ.md) + * [Rule Indices for Events](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/RuleIndicesForEvents.md) + * [Edge and Event Generations](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/EdgeAndEventGenerations.md) + * [Termination Reason](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/TerminationReason.md) + * [Generation Counts](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/GenerationCounts.md) + * [Event Counts](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/EventCounts.md) + * [Element Count Lists](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/ElementCountLists.md) + * [Final Element Counts](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/FinalElementCounts.md) + * [Total Element Counts](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/TotalElementCounts.md) + * [Rules](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/Rules.md) + * [Feature Vector](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/FeatureVector.md) + * [Version](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/Version.md) + * Options + * ["VertexNamingFunction"](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/VertexNamingFunction.md) + * ["IncludePartialGenerations"](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/IncludePartialGenerations.md) + * ["IncludeBoundaryEvents"](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/IncludeBoundaryEvents.md) + * ["EventOrderingFunction"](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/EventOrderingFunction.md) + * ["EventSelectionFunction"](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/EventSelectionFunction.md) + * ["EventDeduplication"](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/EventDeduplication.md) + * [Method](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/Method.md) + * [Time Constraint](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Options/TimeConstraint.md) +* [HypergraphPlot](Documentation/SymbolsAndFunctions/HypergraphPlot.md) +* [RulePlot of WolframModel](Documentation/SymbolsAndFunctions/RulePlotOfWolframModel.md) +* Utility Functions + * [IndexHypergraph](Documentation/SymbolsAndFunctions/UtilityFunctions/IndexHypergraph.md) + * [IsomorphicHypergraphQ](Documentation/SymbolsAndFunctions/UtilityFunctions/IsomorphicHypergraphQ.md) + * [HypergraphToGraph](Documentation/SymbolsAndFunctions/UtilityFunctions/HypergraphToGraph.md) + * [RandomHypergraph](Documentation/SymbolsAndFunctions/UtilityFunctions/RandomHypergraph.md) + * [Subhypergraph](Documentation/SymbolsAndFunctions/UtilityFunctions/Subhypergraph.md) + * [WolframModelRuleValue](Documentation/SymbolsAndFunctions/UtilityFunctions/WolframModelRuleValue.md) + * [GeneralizedGridGraph](Documentation/SymbolsAndFunctions/UtilityFunctions/GeneralizedGridGraph.md) + * [HypergraphAutomorphismGroup](Documentation/SymbolsAndFunctions/UtilityFunctions/HypergraphAutomorphismGroup.md) + * [HypergraphUnifications](Documentation/SymbolsAndFunctions/UtilityFunctions/HypergraphUnifications.md) + * [WolframPhysicsProjectStyleData](Documentation/SymbolsAndFunctions/UtilityFunctions/WolframPhysicsProjectStyleData.md) + * [Build Data](Documentation/SymbolsAndFunctions/UtilityFunctions/BuildData.md) # Physics -A hypothesis is that spacetime at small scales is a network, and the fundamental law of physics is a system similar to the one this package implements. +A hypothesis is that spacetime at small scales is a network, and the fundamental law of physics is a system similar to +the one this package implements. -A slightly different version of this system was first introduced in *Stephen Wolfram*'s [A New Kind Of Science](https://www.wolframscience.com/nks/chap-9--fundamental-physics/). +A slightly different version of this system was first introduced in *Stephen Wolfram*' +s [A New Kind Of Science](https://www.wolframscience.com/nks/chap-9--fundamental-physics/). -You can find many more details about our physics results in *Stephen Wolfram*'s [Technical Introduction](https://www.wolframphysics.org/technical-introduction/), and *Jonathan Gorard*'s papers on [Relativity](https://www.wolframcloud.com/obj/wolframphysics/Documents/some-relativistic-and-gravitational-properties-of-the-wolfram-model.pdf) and [Quantum Mechanics](https://www.wolframcloud.com/obj/wolframphysics/Documents/some-quantum-mechanical-properties-of-the-wolfram-model.pdf). And there is much more on [wolframphysics.org](https://www.wolframphysics.org). +You can find many more details about our physics results in *Stephen Wolfram*' +s [Technical Introduction](https://www.wolframphysics.org/technical-introduction/), and *Jonathan Gorard*'s papers +on [Relativity](https://www.wolframcloud.com/obj/wolframphysics/Documents/some-relativistic-and-gravitational-properties-of-the-wolfram-model.pdf) +and [Quantum Mechanics](https://www.wolframcloud.com/obj/wolframphysics/Documents/some-quantum-mechanical-properties-of-the-wolfram-model.pdf) +. And there is much more on [wolframphysics.org](https://www.wolframphysics.org). # Acknowledgements -In additional to commit authors and reviewers, *Stephen Wolfram* has contributed to the API design of most functions, and *Jeremy Davis* has contributed to the visual style of [`HypergraphPlot`](Documentation/SymbolsAndFunctions/HypergraphPlot.md), [`RulePlot`](Documentation/SymbolsAndFunctions/RulePlotOfWolframModel.md) and [`"CausalGraph"`](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/CausalGraphs.md). +In additional to commit authors and reviewers, *Stephen Wolfram* has contributed to the API design of most functions, +and *Jeremy Davis* has contributed to the visual style +of [`HypergraphPlot`](Documentation/SymbolsAndFunctions/HypergraphPlot.md) +, [`RulePlot`](Documentation/SymbolsAndFunctions/RulePlotOfWolframModel.md) +and [`"CausalGraph"`](Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/CausalGraphs.md) +. diff --git a/Research/ConfluenceAndCausalInvariance/ConfluenceAndCausalInvariance.md b/Research/ConfluenceAndCausalInvariance/ConfluenceAndCausalInvariance.md index b7b02d3fd..ca25a0f79 100644 --- a/Research/ConfluenceAndCausalInvariance/ConfluenceAndCausalInvariance.md +++ b/Research/ConfluenceAndCausalInvariance/ConfluenceAndCausalInvariance.md @@ -3,9 +3,8 @@ ## Introduction There are claims made in the [Wolfram Physics Project](https://www.wolframphysics.org) about the equivalence of -confluence and causal invariance. -This note demonstrates that some of these claims are not correct. -For example, consider +confluence and causal invariance. This note demonstrates that some of these claims are not correct. For example, +consider [the glossary](https://www.wolframphysics.org/glossary/#CausalInvariance) on the project's website, which, [as of 10/30/2020](http://web.archive.org/web/20201030155847/https://www.wolframphysics.org/glossary/#CausalInvariance), says: @@ -17,7 +16,7 @@ says: > In a terminating system, causal invariance implies that whatever path is taken, the "answer" will always be the same. > **Confluence**: A simplified form of causal invariance considered in term rewriting systems such as ones that reach -> fixed points. + fixed points. However, the glossary does not explicitly define confluence, so we are going to use the [standard definition](https://en.wikipedia.org/wiki/Confluence_%28abstract_rewriting%29#General_case_and_theory) from @@ -36,8 +35,8 @@ We can summarize the statements above with the following definitions: > are isomorphic. Note that the definition above is only meaningful for terminating systems (i.e., the systems that always reach a -[`"FixedPoint"`](/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/TerminationReason.md), -a state during the evolution where no more matches can be made to its expressions). +[`"FixedPoint"`](/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/TerminationReason.md) +, a state during the evolution where no more matches can be made to its expressions). We can then define confluence as: @@ -56,8 +55,8 @@ We will not make any comments in this note about the physics claims made above. Before we get to specific examples, it's essential to understand the fundamental difference between these two properties. *Causal invariance* has to do with symmetries between evolution branches of -[expressions-events graphs](/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/CausalGraphs.md). -It requires that, even though the branches operate on different expressions, they have the same causal structure: +[expressions-events graphs](/Documentation/SymbolsAndFunctions/WolframModelAndWolframModelEvolutionObject/Properties/CausalGraphs.md) +. It requires that, even though the branches operate on different expressions, they have the same causal structure: