diff --git a/docs/bits/keyword/letting_domain.md b/docs/bits/keyword/letting_domain.md index 8389c0e57..10039f1f8 100644 --- a/docs/bits/keyword/letting_domain.md +++ b/docs/bits/keyword/letting_domain.md @@ -14,9 +14,9 @@ Types of domains: - [integer](https://github.com/conjure-cp/conjure/blob/main/docs/bits/type/L_int.md) - [enumerated](https://github.com/conjure-cp/conjure/blob/main/docs/bits/keyword/new_type_enum.md) - [unnamed](https://github.com/conjure-cp/conjure/blob/main/docs/bits/type/unnamed.md) -- [tuple](...) +- [tuple](https://github.com/conjure-cp/conjure/blob/main/docs/bits/type/L_tuple.md) - [record](...) -- [variant](...) +- [variant](https://github.com/conjure-cp/conjure/blob/main/docs/bits/type/L_variant.md) - [matrix](https://github.com/conjure-cp/conjure/blob/main/docs/bits/type/matrix.md) - [set](...) - [multi-set](...) diff --git a/docs/bits/type/L_variant.md b/docs/bits/type/L_variant.md new file mode 100644 index 000000000..f9059b8eb --- /dev/null +++ b/docs/bits/type/L_variant.md @@ -0,0 +1,17 @@ +# variant + +Similar to a [record](https://github.com/conjure-cp/conjure/blob/main/docs/bits/type/L_record.md) but can only be 1 value, of 1 domain at a time. It is also like a [tagged union](https://en.wikipedia.org/wiki/Tagged_union). + +It is defined by + +``` +letting be domain variant {} +``` + +as shown [here](https://github.com/conjure-cp/conjure/blob/main/docs/notebooks/letting_domain.ipynb) + +Like [records](https://github.com/conjure-cp/conjure/blob/main/docs/bits/type/L_record.md), you can refer to a domain using +```[lebel]``` +as demonstrated [here](https://github.com/conjure-cp/conjure/blob/main/docs/notebooks/VariantDomains.ipynb). + +Read more about variants [here](https://conjure.readthedocs.io/en/latest/essence.html#variant-domains). \ No newline at end of file diff --git a/docs/notebooks/VariantDomains.ipynb b/docs/notebooks/VariantDomains.ipynb new file mode 100644 index 000000000..2da92596d --- /dev/null +++ b/docs/notebooks/VariantDomains.ipynb @@ -0,0 +1,225 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"Open" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "XO6lij_rd8Mu" + }, + "source": [ + "## Variant" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 133 + }, + "id": "nBQDiwTSbPNq", + "outputId": "7ce395a9-ac86-409d-fe1d-43238b9fdf76" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Installing Conjure version v2.5.1 and Conjure Notebook version v0.0.10...\n", + "Downloading...\n", + "Conjure: The Automated Constraint Modelling Tool\n", + "Release version 2.5.1\n", + "Repository version a9cbc2e (2023-11-07 23:44:00 +0000)\n" + ] + }, + { + "data": { + "application/javascript": "\"use strict\";\n\nCodeMirror.defineMode(\"text/conjure\", function (config) {\n\n var isOperatorChar = /[+\\-*=<>%^\\/]/;\n\n var keywords = {\n \"forall\": true,\n \"allDifferent\": true,\n \"allDiff\": true,\n \"alldifferent_except\": true,\n \"dim\": true,\n \"toSet\": true,\n \"toMSet\": true,\n \"toRelation\": true,\n \"maximising\": true,\n \"minimising\": true,\n \"forAll\": true,\n \"exists\": true,\n \"toInt\": true,\n \"sum\": true,\n \"be\": true,\n \"bijective\": true,\n \"bool\": true,\n \"by\": true,\n \"complete\": true,\n \"defined\": true,\n \"domain\": true,\n \"in\": true,\n \"or\": true,\n \"and\": true,\n \"false\": true,\n \"find\": true,\n \"from\": true,\n \"function\": true,\n \"given\": true,\n \"image\": true,\n \"indexed\": true,\n \"injective\": true,\n \"int\": true,\n \"intersect\": true,\n \"freq\": true,\n \"lambda\": true,\n \"language\": true,\n \"letting\": true,\n \"matrix\": true,\n \"maxNumParts\": true,\n \"maxOccur\": true,\n \"maxPartSize\": true,\n \"maxSize\": true,\n \"minNumParts\": true,\n \"minOccur\": true,\n \"minPartSize\": true,\n \"minSize\": true,\n \"mset\": true,\n \"numParts\": true,\n \"of\": true,\n \"partial\": true,\n \"partition\": true,\n \"partSize\": true,\n \"preImage\": true,\n \"quantifier\": true,\n \"range\": true,\n \"regular\": true,\n \"relation\": true,\n \"representation\": true,\n \"set\": true,\n \"size\": true,\n \"subset\": true,\n \"subsetEq\": true,\n \"such\": true,\n \"supset\": true,\n \"supsetEq\": true,\n \"surjective\": true,\n \"that\": true,\n \"together\": true,\n \"enum\": true,\n \"total\": true,\n \"true\": true,\n \"new\": true,\n \"type\": true,\n \"tuple\": true,\n \"union\": true,\n \"where\": true,\n \"branching\": true,\n \"on\": true\n }; \n var punc = \":;,.(){}[]\";\n\n function tokenBase(stream, state) {\n var ch = stream.next();\n if (ch == '\"') {\n state.tokenize.push(tokenString);\n return tokenString(stream, state);\n }\n if (/[\\d\\.]/.test(ch)) {\n if (ch == \".\") {\n stream.match(/^[0-9]+([eE][\\-+]?[0-9]+)?/);\n } else if (ch == \"0\") {\n stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/);\n } else {\n stream.match(/^[0-9]*\\.?[0-9]*([eE][\\-+]?[0-9]+)?/);\n }\n return \"number\";\n }\n if (ch == \"/\") {\n if (stream.eat(\"*\")) {\n state.tokenize.push(tokenComment);\n return tokenComment(stream, state);\n }\n }\n if (ch == \"$\") {\n stream.skipToEnd();\n return \"comment\";\n }\n if (isOperatorChar.test(ch)) {\n stream.eatWhile(isOperatorChar);\n return \"operator\";\n }\n if (punc.indexOf(ch) > -1) {\n return \"punctuation\";\n }\n stream.eatWhile(/[\\w\\$_\\xa1-\\uffff]/);\n var cur = stream.current();\n \n if (keywords.propertyIsEnumerable(cur)) {\n return \"keyword\";\n }\n return \"variable\";\n }\n\n function tokenComment(stream, state) {\n var maybeEnd = false, ch;\n while (ch = stream.next()) {\n if (ch == \"/\" && maybeEnd) {\n state.tokenize.pop();\n break;\n }\n maybeEnd = (ch == \"*\");\n }\n return \"comment\";\n }\n\n function tokenUntilClosingParen() {\n var depth = 0;\n return function (stream, state, prev) {\n var inner = tokenBase(stream, state, prev);\n console.log(\"untilClosing\", inner, stream.current());\n if (inner == \"punctuation\") {\n if (stream.current() == \"(\") {\n ++depth;\n } else if (stream.current() == \")\") {\n if (depth == 0) {\n stream.backUp(1)\n state.tokenize.pop()\n return state.tokenize[state.tokenize.length - 1](stream, state)\n } else {\n --depth;\n }\n }\n }\n return inner;\n }\n }\n\n function tokenString(stream, state) {\n var escaped = false, next, end = false;\n while ((next = stream.next()) != null) {\n if (next == '(' && escaped) {\n state.tokenize.push(tokenUntilClosingParen());\n return \"string\";\n }\n if (next == '\"' && !escaped) { end = true; break; }\n escaped = !escaped && next == \"\\\\\";\n }\n if (end || !escaped)\n state.tokenize.pop();\n return \"string\";\n }\n\n return {\n startState: function (basecolumn) {\n return {\n tokenize: []\n };\n },\n\n token: function (stream, state) {\n if (stream.eatSpace()) return null;\n var style = (state.tokenize[state.tokenize.length - 1] || tokenBase)(stream, state);\n console.log(\"token\", style);\n return style;\n },\n\n blockCommentStart: \"/*\",\n blockCommentEnd: \"*/\",\n lineComment: \"$\"\n };\n});\n\n\nCodeMirror.defineMIME(\"text/conjure\", \"text/conjure\");\n\nrequire(['notebook/js/codecell'], function (codecell) {\n codecell.CodeCell.options_default.highlight_modes['magic_text/conjure'] = { 'reg': [/%?%conjure/] };\n Jupyter.notebook.events.one('kernel_ready.Kernel', function () {\n Jupyter.notebook.get_cells().map(function (cell) {\n if (cell.cell_type == 'code') { cell.auto_highlight(); }\n });\n });\n});\n\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "Conjure extension is loaded - run `%conjure_help`" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "!source <(curl -s https://raw.githubusercontent.com/conjure-cp/conjure-notebook/v0.0.10/scripts/install-colab.sh)\n", + "%load_ext conjure" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "RvHDe8GffDxX" + }, + "source": [ + "Similar to records, but a member of a variant domain contains a value for only one of the components of the variant. Also similar to [tagged unions](https://en.wikipedia.org/wiki/Tagged_union)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 317 + }, + "id": "khS3LB5AfLKh", + "outputId": "f9d8c128-f086-416d-fd38-7f1e050cf5f5" + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "```json\n", + "{}\n", + "```" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| Statistic | Value |\n", + "|:-|-:|\n", + "| SolverTotalTime | 0.000 |\n", + "| SavileRowClauseOut | 0 |\n", + "| SavileRowTotalTime | 0.088 |\n", + "| SolverFailures | 0 |\n", + "| SolverSatisfiable | 1 |\n", + "| SavileRowTimeOut | 0 |\n", + "| SolverTimeOut | 0 |\n", + "| SolverNodes | 1 |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%%conjure\n", + "letting x be domain\n", + " variant\n", + " { a : int(1..3)\n", + " , b : bool\n", + " }" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "J_7VE8yvi41c" + }, + "source": [ + "They can be indexed, in a similar way too. They can be referred to by the label in square brackets. (but only one value at a time)." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 365 + }, + "id": "f1DEFXcEg2Qe", + "outputId": "99ba1414-36d4-425e-8e88-a5e52c870666" + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "## Solution 1" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "```json\n", + "[{\"y\": {\"a\": 1}}, {\"y\": {\"a\": 2}}, {\"y\": {\"a\": 3}}, {\"y\": {\"b\": false}}]\n", + "```" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| Statistic | Value |\n", + "|:-|-:|\n", + "| SolverTotalTime | 0.000 |\n", + "| SavileRowClauseOut | 0 |\n", + "| SavileRowTotalTime | 0.092 |\n", + "| SolverFailures | 4 |\n", + "| SolverSatisfiable | 1 |\n", + "| SavileRowTimeOut | 0 |\n", + "| SolverTimeOut | 0 |\n", + "| SolverNodes | 4 |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%%conjure+ --number-of-solutions=all\n", + "find y: x such that (y[a] = 1) \\/ (y[b] = false)" + ] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +}