├── .gitignore ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── assets └── logo.png ├── config.yml ├── entrypoint.sh └── examples └── base.sql /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | postgresql-proxy -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | #################################### 2 | # HyperC DB # 3 | # Let Computers Think on Their Own # 4 | #################################### 5 | 6 | 7 | FROM ubuntu:20.04 8 | WORKDIR /build 9 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y python3.8 python3-pip python-setuptools git software-properties-common wget build-essential lsb-release 10 | RUN sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' && wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - && apt-get update 11 | RUN DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential libreadline-dev zlib1g-dev flex bison libxml2-dev libxslt-dev libssl-dev libxml2-utils xsltproc 12 | 13 | ENV PGVER 14.0 14 | # RUN wget https://ftp.postgresql.org/pub/source/v12.3/postgresql-$PGVER.tar.gz && tar -zxvf postgresql-$PGVER.tar.gz 15 | 16 | RUN wget https://ftp.postgresql.org/pub/source/v14.0/postgresql-$PGVER.tar.bz2 && tar xvf postgresql-$PGVER.tar.bz2 17 | RUN mkdir -p /opt/hyperc/postgres && cd postgresql-$PGVER && ./configure --prefix=/opt/hyperc/postgres --with-python && make -j16 && make install 18 | 19 | RUN apt install -y sudo 20 | ENV PGHOME /opt/hyperc/db 21 | RUN mkdir $PGHOME && useradd postgres && chown postgres:postgres $PGHOME && sudo -u postgres /opt/hyperc/postgres/bin/initdb -D $PGHOME/data 22 | 23 | #################################### 24 | # Build complete. Stage 2. 25 | 26 | FROM ubuntu:20.04 27 | ENV PGVER 14.0 28 | ENV PGHOME /opt/hyperc/db 29 | COPY --from=0 /opt /opt 30 | WORKDIR /opt/hyperc 31 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y sudo python3.8 python3-pip python-setuptools git software-properties-common wget 32 | RUN sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' && wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - && apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y $(apt-cache depends postgresql | grep Depends | sed "s/.*ends:\ //" | tr '\n' ' ') 33 | RUN chown -R postgres:postgres $PGHOME 34 | RUN add-apt-repository ppa:pypy/ppa && apt-get update && apt-get install -y pypy3 35 | 36 | RUN mkdir -p /var/lib/postgresql && cd /var/lib/postgresql && pip install virtualenv && virtualenv -p python3.8 .local && . .local/bin/activate && pip install downward_ch openpyxl flask formulas schedula sqlalchemy gspread==3.6.0 google-api-python-client google_auth_oauthlib flask msal PyYAML==5.4.1 psycopg2-binary logzero 37 | # RUN mkdir /opt/hyperc/examples 38 | RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y locales unzip 39 | RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \ 40 | dpkg-reconfigure --frontend=noninteractive locales && \ 41 | update-locale LANG=en_US.UTF-8 42 | ENV LANG en_US.UTF-8 43 | ENV LANGUAGE en_US:en 44 | ENV LC_ALL en_US.UTF-8 45 | RUN cd /var/lib/postgresql && . .local/bin/activate && cd /tmp && git clone -b python38 https://github.com/grandrew/pyclips && cd pyclips && wget -q -O clips.zip 'https://downloads.sourceforge.net/project/clipsrules/CLIPS/6.31/clips_core_source_631.zip?r=https%3A%2F%2Fsourceforge.net%2Fprojects%2Fclipsrules%2Ffiles%2FCLIPS%2F6.31%2Fclips_core_source_631.zip%2Fdownload&ts=1554816443' && unzip ./clips.zip && patch -d./clips_core_source_631/core -p0 < mergestats.patch && CLIPS_SRC=clips_core_source_631/core python ./setup.py build && CLIPS_SRC=clips_core_source_631/core python ./setup.py install 46 | RUN cd /var/lib/postgresql && . .local/bin/activate && pip install networkx==2.6.3 sympy==1.9 attrs sklearn matplotlib 47 | RUN cd /var/lib/postgresql && . .local/bin/activate && pip install git+https://github.com/hyperc-ai/hyperc && pip install git+https://github.com/hyperc-ai/hyper-etable && echo rebuild8 48 | RUN cd /var/lib/postgresql && . .local/bin/activate && pip install git+https://github.com/grandrew/sklearn-compiledtrees@pypy-ffi 49 | RUN mkdir /var/cache/hyperc && chmod 777 /var/cache/hyperc 50 | RUN cd /opt/hyperc && git clone --depth=6 https://github.com/hyperc-ai/hyperc-psql-proxy && mkdir /etc/hyperc && cp hyperc-psql-proxy/config.yml.example /etc/hyperc/config.yml && echo rebuild16 51 | COPY config.yml /etc/hyperc/config.yml 52 | RUN mkdir /var/log/postgresql-proxy && chown postgres /var/log/postgresql-proxy 53 | COPY examples/base.sql /opt/hyperc/examples/base.sql 54 | RUN sudo -u postgres /opt/hyperc/postgres/bin/pg_ctl -D $PGHOME/data -l $PGHOME/logfile start && cd /var/lib/postgresql && sudo -u postgres bash -c ". .local/bin/activate && python3 /opt/hyperc/hyperc-psql-proxy/proxy.py /etc/hyperc/config.yml &" && sleep 1 && /opt/hyperc/postgres/bin/psql -d template1 -U postgres -c "CREATE USER pguser WITH PASSWORD '123';" -c "CREATE DATABASE testdb WITH TEMPLATE = template0 ENCODING = 'UTF8';" -c "GRANT ALL PRIVILEGES ON DATABASE testdb to pguser;" && PGPASSWORD=123 /opt/hyperc/postgres/bin/psql -h localhost --port=8493 -d testdb -U pguser -f /opt/hyperc/examples/base.sql && sudo -u postgres /opt/hyperc/postgres/bin/pg_ctl -D $PGHOME/data -l $PGHOME/logfile stop && pkill -f python3 55 | 56 | COPY entrypoint.sh /entrypoint.sh 57 | CMD ["/entrypoint.sh"] 58 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | docker build -t hypercdb/hypercdb:latest . 3 | 4 | push: 5 | docker push hypercdb/hypercdb:latest 6 | 7 | login: 8 | docker login 9 | 10 | develop: 11 | rm -rf ./postgresql-proxy 12 | # git clone --depth=1 ../etable/postgresql-proxy postgresql-proxy 13 | rsync -av ../etable/postgresql-proxy ./ --exclude .git --exclude *.log 14 | docker build -f ./Dockerfile.devel -t hypercdb-devel . 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 |

4 | logo 5 |

HyperC
Planning Database

6 |

7 | 8 | ## About HyperCDB 9 | 10 | HyperC Planning Database enables processing of data and business rules with autonomous algorithms. HyperCDB finds best-effort-optimal plans in retail, logistics, robotics, IT infrastructure and others using action schema defined with an easy domain-independent language. 11 | 12 | HyperCDB reads stored PostgreSQL procedures written in Python and applies only relevant of them repeatedly to reach a desired end state. It achieves this by gradually lowering the logic order of defined procedures to selected grounded states. The math behind HyperC lies in realms of [AI planning](https://en.wikipedia.org/wiki/Automated_planning_and_scheduling), [automatic proof](https://en.wikipedia.org/wiki/Automated_theorem_proving) and [type theory](https://en.wikipedia.org/wiki/Type_theory). 13 | 14 | ## Transitional Database vs. Transactional Database 15 | 16 | HyperCDB is a transitional, or planning database. This means that instead of blindly accepting an `UPDATE` to the stored data, HyperCDB calculates if it is possible to reach the new proposed state using the allowed transitions. This transitional property is useful in several scenarios: 17 | 18 | - Validating every change to the data to be in compliance with defined business process 19 | - Generating missing data and performing consistency healing automatically 20 | - Planning restocking, checking manufacturing timings, allocating workforce, etc. 21 | - Rebalancing cloud clusters with complex resource dependencies and constraints 22 | - Robotic motion planning for 3D printers, cutters, and multi-axis robots 23 | - Automatic website design 24 | - Creating spacecraft launch sequences 25 | - etc. 26 | 27 | ## Getting Started with HyperCDB 28 | 29 | ### Installation 30 | 31 | ``` 32 | docker run -p 8493:8493 hypercdb/hypercdb 33 | ``` 34 | 35 | Then connect to the database using [pgAdmin](https://www.pgadmin.org/) or your favorite PostgreSQL admin tool. Demo project user is `pguser` and password is `123`. 36 | 37 | To run with persistent data, use: 38 | 39 | ``` 40 | docker run --name hyperc -p 8493:8493 -v :/opt/hyperc/db/data hypercdb/hypercdb 41 | ``` 42 | 43 | ### Create your first plan 44 | 45 | HyperCDB docker image comes with a demo database with vehicles in `trucks` table and map defined in `location_adjacency` table. 46 | 47 | To create a plan for the trucks to move, issue the `TRANSIT` query: 48 | 49 | ``` 50 | $ psql -h localhost --port 8493 -U pguser testdb 51 | ``` 52 | 53 | ```SQL 54 | testdb=> SELECT * FROM trucks; 55 | name | odometer | location 56 | ---------+----------+---------- 57 | Truck 2 | 0 | Office 58 | Truck 1 | 0 | Home 59 | 60 | testdb=> TRANSIT UPDATE trucks SET location = 'Office'; 61 | 62 | step_num | proc_name 63 | -----------+------------- 64 | 0 | move_truck 65 | 1 | move_truck 66 | ... 67 | 68 | testdb=> SELECT * FROM trucks; 69 | name | odometer | location 70 | ---------+----------+---------- 71 | Truck 2 | 0 | Office 72 | Truck 1 | 7 | Office 73 | 74 | ``` 75 | 76 | `TRANSIT` queries tell HyperC to calculate transition plan instead of 'just' accepting the change. You will also notice that `odometer` reading was updated automatically, as `move_truck` procedure was also counting mileage at every execution. 77 | 78 | ## Preparing Database From Scratch 79 | 80 | ### Initializing database 81 | 82 | HyperCDB requires special table `hc_plan` and procedure `hyperc_transit` to be initialized in the database so you must always explicitly issue this command: 83 | 84 | ```SQL 85 | TRANSIT INIT; 86 | ``` 87 | 88 | You must be connected to correct database before issuing `TRANSIT INIT`. 89 | 90 | ### Creating tables 91 | 92 | Creating tables works exactly the same as in any PostgreSQL database with additional requirement that all tables must have `PRIMARY KEY` defined: 93 | 94 | ```SQL 95 | CREATE TABLE public.trucks ( 96 | name character varying(50) PRIMARY KEY NOT NULL, 97 | odometer integer, 98 | location character varying(50) NOT NULL 99 | ); 100 | ``` 101 | 102 | ### Creating transition procedures 103 | 104 | All transition procedures must have language `'hyperc'` and define one or more input parameters. Column names must be all capital letters in current edition of HyperCDB procedure language: 105 | 106 | ```SQL 107 | CREATE PROCEDURE move_truck(t trucks, l location_adjacency) 108 | LANGUAGE 'hyperc' 109 | AS $BODY$ 110 | 111 | assert t.LOCATION == l.LOC_A 112 | t.LOCATION = l.LOC_B 113 | t.ODOMETER += l.DISTANCE 114 | 115 | $BODY$; 116 | ``` 117 | 118 | Procedure `move_truck(t truck, l location_adjacency)` takes two rows as input: any row from `trucks` table as local variable `t` and any row from `location_adjacency` table with local name `l`. Additional information on defining stored procedures can be found in [PostgreSQL manual](https://www.postgresql.org/docs/14/sql-createprocedure.html). 119 | 120 | HyperC will automatically define which rows have the best match to reach end state in least steps. 121 | 122 | The body of the procedure is defined in Python-like dialect: 123 | 124 | ```python 125 | assert t.LOCATION == l.LOC_A 126 | t.LOCATION = l.LOC_B 127 | t.ODOMETER += l.DISTANCE 128 | ``` 129 | 130 | The first line, `assert t.LOCATION == l.LOC_A` means that only such two rows (`t` from `trucks` and `l` from `location_adjacency`) that have equal values in columns `location` and `loc_a` respectively can be used in this procedure. The business logic behind this assertion is that we want to 'JOIN' tables `trucks` and `location_adjacency` by columns `LOCATION` and `LOC_A` because the truck can only move to the next adjacent location, defined in columns `LOC_A` and `LOC_B` in locations adjacency map table. 131 | 132 | The second and third lines define the effects of the procedure: updating location of the truck to next hop from the table, and increasing the odometer. 133 | 134 | ## Documentation 135 | 136 | HyperCDB is based on [PostgreSQL database v.14](https://www.postgresql.org/docs/14/index.html) and most functions of the database work as expected. 137 | 138 | The HyperC Planning Database extends SQL language with the `TRANSIT *` set of commands: 139 | 140 | --- 141 | 142 | ``` 143 | TRANSIT INIT 144 | ``` 145 | 146 | Prepares the database for planning function. 147 | 148 | --- 149 | 150 | ``` 151 | [ EXPLAIN [ TO table_name1[.column], table_name2, ... ]] TRANSIT UPDATE table_name 152 | SET { column = { expression | DEFAULT } | 153 | ( column [, ...] ) = ( { expression | DEFAULT } [, ...] ) } [, ...] 154 | [ WHERE condition ] 155 | ``` 156 | 157 | `TRANSIT UPDATE` initiates transition to the state defined by UPDATE statement with familiar SQL syntax of [UPDATE](https://www.postgresql.org/docs/14/sql-update.html). It returns the table of the plan with unique plan_id that can be remembered and used to query `hc_plan` table to recall this plan at any later time. 158 | 159 | `EXPLAIN TRANSIT ...` - initiates calculation of the plan, stores and outputs the plan table but does not do any actual updates to the state. 160 | 161 | `EXPLAIN TO *table_name*, ... TRANSIT ...` - instructs the solver to only write down changes to tables (and possibly columns) specified after `TO` keyword. 162 | 163 | Examples: 164 | 165 | Calculate transition plan but only write down `odometer` reading, leaving truck at its original location: 166 | 167 | ```SQL 168 | EXPLAIN TO trucks.odometer TRANSIT UPDATE trucks SET location = 'Office'; 169 | ``` 170 | 171 | --- 172 | 173 | ### hc_plan table 174 | 175 | HyperCDB defines a special table `hc_plan` to incrementally store all plans with called procedure names and input/output parameters in JSONB objects. 176 | 177 | The purpose of hc_plan table is to easily extract additional information from the plans like tracing the truck travel path, measuring fuel consumption, etc. When TRANSIT command completes it outputs back to the user connection the table with plan summary where plan_id can be extracted and remembered by the client application. 178 | 179 | # Status 180 | 181 | HyperC in under active development. It is used in several production environments but has scalability limitations that are being addressed using various machine learning techniques. 182 | 183 | # Support 184 | 185 | HyperCDB is supported by HyperC team. Feel free to write at andrew@hyperc.com. 186 | -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperc-ai/hypercdb/8e62d1ffac394ebafb2812b97495f2dfe647e98b/assets/logo.png -------------------------------------------------------------------------------- /config.yml: -------------------------------------------------------------------------------- 1 | plugins: 2 | - hyperc 3 | 4 | settings: 5 | log-level: info 6 | intercept-log: /var/log/postgresql-proxy/intercept.log 7 | general-log: /var/log/postgresql-proxy/general.log 8 | 9 | instances: 10 | - listen: 11 | name: proxy 12 | host: 0.0.0.0 13 | port: 8493 14 | redirect: 15 | name: postgresql 16 | host: 127.0.0.1 17 | port: 5432 18 | intercept: 19 | commands: 20 | queries: 21 | - plugin: hyperc 22 | function: rewrite_query 23 | connects: 24 | responses: 25 | -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | PGHOME=/opt/hyperc/db 3 | PGDATA=$PGHOME/data 4 | 5 | if [ -z "$(ls -A $PGDATA)" ]; then 6 | echo "Initializing empty datadir" 7 | chown -R postgres:postgres $PGHOME && sudo -u postgres /opt/hyperc/postgres/bin/initdb -D $PGDATA 8 | sudo -u postgres /opt/hyperc/postgres/bin/pg_ctl -D $PGHOME/data -l $PGHOME/logfile start 9 | PASSWD=`< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c8` 10 | sudo -u postgres psql -h /tmp -c "ALTER USER postgres WITH PASSWORD '$PASSWD';" 11 | cd /var/lib/postgresql && sudo -u postgres bash -c ". .local/bin/activate && python3 /opt/hyperc/hyperc-psql-proxy/proxy.py /etc/hyperc/config.yml &" && sleep 1 && /opt/hyperc/postgres/bin/psql -d template1 -U postgres -c "CREATE USER pguser WITH PASSWORD '123';" -c "CREATE DATABASE testdb WITH TEMPLATE = template0 ENCODING = 'UTF8';" -c "GRANT ALL PRIVILEGES ON DATABASE testdb to pguser;" && PGPASSWORD=123 /opt/hyperc/postgres/bin/psql -h localhost --port=8493 -d testdb -U pguser -f /opt/hyperc/examples/base.sql 12 | echo "--- User 'postgres' password is '$PASSWD'" 13 | echo "!!! Don't forget to delete DEMO databse 'testdb' and DEMO user 'pguser'!" 14 | echo "--- DEMO database 'testdb' initialized with user 'pguser' password '123'" 15 | sleep infinity 16 | else 17 | sudo -u postgres /opt/hyperc/postgres/bin/pg_ctl -D $PGHOME/data -l $PGHOME/logfile start 18 | while true; do 19 | sudo -u postgres bash -c "cd /var/lib/postgresql && . .local/bin/activate && python3 /opt/hyperc/hyperc-psql-proxy/proxy.py /etc/hyperc/config.yml" 20 | done; 21 | fi 22 | 23 | 24 | -------------------------------------------------------------------------------- /examples/base.sql: -------------------------------------------------------------------------------- 1 | -- 2 | -- PostgreSQL database dump 3 | -- 4 | TRANSIT INIT; 5 | 6 | -- Dumped from database version 12.8 (Ubuntu 12.8-1.pgdg20.04+1) 7 | -- Dumped by pg_dump version 14.0 (Ubuntu 14.0-1.pgdg20.04+1) 8 | 9 | -- Started on 2021-10-27 08:44:08 PDT 10 | 11 | SET statement_timeout = 0; 12 | SET lock_timeout = 0; 13 | SET idle_in_transaction_session_timeout = 0; 14 | SET client_encoding = 'UTF8'; 15 | SET standard_conforming_strings = on; 16 | SELECT pg_catalog.set_config('search_path', '', false); 17 | SET check_function_bodies = false; 18 | SET xmloption = content; 19 | SET client_min_messages = warning; 20 | SET row_security = off; 21 | 22 | -- 23 | -- TOC entry 3015 (class 1262 OID 16385) 24 | -- Name: testdb; Type: DATABASE; Schema: -; Owner: postgres 25 | -- 26 | 27 | \connect testdb 28 | 29 | SET statement_timeout = 0; 30 | SET lock_timeout = 0; 31 | SET idle_in_transaction_session_timeout = 0; 32 | SET client_encoding = 'UTF8'; 33 | SET standard_conforming_strings = on; 34 | SELECT pg_catalog.set_config('search_path', '', false); 35 | SET check_function_bodies = false; 36 | SET xmloption = content; 37 | SET client_min_messages = warning; 38 | SET row_security = off; 39 | 40 | SET default_tablespace = ''; 41 | 42 | SET default_table_access_method = heap; 43 | 44 | -- 45 | -- TOC entry 208 (class 1259 OID 16446) 46 | -- Name: location_adjacency; Type: TABLE; Schema: public; Owner: pguser 47 | -- 48 | 49 | CREATE TABLE public.location_adjacency ( 50 | user_id integer NOT NULL, 51 | loc_a character varying(50) NOT NULL, 52 | loc_b character varying(50) NOT NULL, 53 | distance integer NOT NULL 54 | ); 55 | 56 | 57 | ALTER TABLE public.location_adjacency OWNER TO pguser; 58 | 59 | -- 60 | -- TOC entry 206 (class 1259 OID 16436) 61 | -- Name: trucks; Type: TABLE; Schema: public; Owner: pguser 62 | -- 63 | 64 | CREATE TABLE public.trucks ( 65 | user_id integer NOT NULL, 66 | name character varying(50) PRIMARY KEY NOT NULL, 67 | odometer integer, 68 | location character varying(50) NOT NULL 69 | ); 70 | 71 | 72 | ALTER TABLE public.trucks OWNER TO pguser; 73 | 74 | -- 75 | -- TOC entry 212 (class 1255 OID 16453) 76 | -- Name: move_truck_p(public.trucks, public.location_adjacency); Type: PROCEDURE; Schema: public; Owner: pguser 77 | -- 78 | 79 | CREATE PROCEDURE public.move_truck_p(t public.trucks, l public.location_adjacency) 80 | LANGUAGE hyperc 81 | AS $$ 82 | assert t.LOCATION == l.LOC_A 83 | t.LOCATION = l.LOC_B 84 | t.ODOMETER += l.DISTANCE 85 | $$; 86 | 87 | 88 | ALTER PROCEDURE public.move_truck_p(t public.trucks, l public.location_adjacency) OWNER TO pguser; 89 | 90 | -- 91 | -- TOC entry 211 (class 1259 OID 32869) 92 | -- Name: drivers; Type: TABLE; Schema: public; Owner: pguser 93 | -- 94 | 95 | CREATE TABLE public.drivers ( 96 | name character varying(50), 97 | location character varying(50) 98 | ); 99 | 100 | 101 | ALTER TABLE public.drivers OWNER TO pguser; 102 | 103 | -- 104 | -- TOC entry 207 (class 1259 OID 16444) 105 | -- Name: location_adjacency_user_id_seq; Type: SEQUENCE; Schema: public; Owner: pguser 106 | -- 107 | 108 | CREATE SEQUENCE public.location_adjacency_user_id_seq 109 | AS integer 110 | START WITH 1 111 | INCREMENT BY 1 112 | NO MINVALUE 113 | NO MAXVALUE 114 | CACHE 1; 115 | 116 | 117 | ALTER TABLE public.location_adjacency_user_id_seq OWNER TO pguser; 118 | 119 | -- 120 | -- TOC entry 3019 (class 0 OID 0) 121 | -- Dependencies: 207 122 | -- Name: location_adjacency_user_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: pguser 123 | -- 124 | 125 | ALTER SEQUENCE public.location_adjacency_user_id_seq OWNED BY public.location_adjacency.user_id; 126 | 127 | 128 | -- 129 | -- TOC entry 205 (class 1259 OID 16434) 130 | -- Name: trucks_user_id_seq; Type: SEQUENCE; Schema: public; Owner: pguser 131 | -- 132 | 133 | CREATE SEQUENCE public.trucks_user_id_seq 134 | AS integer 135 | START WITH 1 136 | INCREMENT BY 1 137 | NO MINVALUE 138 | NO MAXVALUE 139 | CACHE 1; 140 | 141 | 142 | ALTER TABLE public.trucks_user_id_seq OWNER TO pguser; 143 | 144 | -- 145 | -- TOC entry 3020 (class 0 OID 0) 146 | -- Dependencies: 205 147 | -- Name: trucks_user_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: pguser 148 | -- 149 | 150 | ALTER SEQUENCE public.trucks_user_id_seq OWNED BY public.trucks.user_id; 151 | 152 | -- 153 | -- TOC entry 2860 (class 2604 OID 16449) 154 | -- Name: location_adjacency user_id; Type: DEFAULT; Schema: public; Owner: pguser 155 | -- 156 | 157 | ALTER TABLE ONLY public.location_adjacency ALTER COLUMN user_id SET DEFAULT nextval('public.location_adjacency_user_id_seq'::regclass); 158 | 159 | 160 | -- 161 | -- TOC entry 2859 (class 2604 OID 16439) 162 | -- Name: trucks user_id; Type: DEFAULT; Schema: public; Owner: pguser 163 | -- 164 | 165 | ALTER TABLE ONLY public.trucks ALTER COLUMN user_id SET DEFAULT nextval('public.trucks_user_id_seq'::regclass); 166 | 167 | 168 | -- 169 | -- TOC entry 3006 (class 0 OID 16446) 170 | -- Dependencies: 208 171 | -- Data for Name: location_adjacency; Type: TABLE DATA; Schema: public; Owner: pguser 172 | -- 173 | 174 | INSERT INTO public.location_adjacency (user_id, loc_a, loc_b, distance) VALUES (1, 'Home', '1st JCT', 2); 175 | INSERT INTO public.location_adjacency (user_id, loc_a, loc_b, distance) VALUES (2, '1st JCT', 'Willows', 3); 176 | INSERT INTO public.location_adjacency (user_id, loc_a, loc_b, distance) VALUES (3, 'Willows', 'Office', 2); 177 | 178 | 179 | -- 180 | -- TOC entry 3004 (class 0 OID 16436) 181 | -- Dependencies: 206 182 | -- Data for Name: trucks; Type: TABLE DATA; Schema: public; Owner: pguser 183 | -- 184 | 185 | INSERT INTO public.trucks (user_id, name, odometer, location) VALUES (2, 'Truck 2', 0, 'Office'); 186 | INSERT INTO public.trucks (user_id, name, odometer, location) VALUES (1, 'Truck 1', 0, 'Home'); 187 | 188 | 189 | -- 190 | -- TOC entry 3023 (class 0 OID 0) 191 | -- Dependencies: 207 192 | -- Name: location_adjacency_user_id_seq; Type: SEQUENCE SET; Schema: public; Owner: pguser 193 | -- 194 | 195 | SELECT pg_catalog.setval('public.location_adjacency_user_id_seq', 3, true); 196 | 197 | 198 | -- 199 | -- TOC entry 3024 (class 0 OID 0) 200 | -- Dependencies: 205 201 | -- Name: trucks_user_id_seq; Type: SEQUENCE SET; Schema: public; Owner: pguser 202 | -- 203 | 204 | SELECT pg_catalog.setval('public.trucks_user_id_seq', 2, true); 205 | 206 | -- 207 | -- TOC entry 2874 (class 2606 OID 16451) 208 | -- Name: location_adjacency location_adjacency_pkey; Type: CONSTRAINT; Schema: public; Owner: pguser 209 | -- 210 | 211 | ALTER TABLE ONLY public.location_adjacency 212 | ADD CONSTRAINT location_adjacency_pkey PRIMARY KEY (user_id); 213 | 214 | 215 | -- 216 | -- TOC entry 2870 (class 2606 OID 16443) 217 | -- Name: trucks trucks_name_key; Type: CONSTRAINT; Schema: public; Owner: pguser 218 | -- 219 | 220 | ALTER TABLE ONLY public.trucks 221 | ADD CONSTRAINT trucks_name_key UNIQUE (name); 222 | --------------------------------------------------------------------------------