first commit
This commit is contained in:
commit
5012a7e2b6
68 changed files with 1445 additions and 0 deletions
8
.idea/.gitignore
vendored
Normal file
8
.idea/.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
28
.idea/Graphs.iml
Normal file
28
.idea/Graphs.iml
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="FacetManager">
|
||||||
|
<facet type="django" name="Django">
|
||||||
|
<configuration>
|
||||||
|
<option name="rootFolder" value="$MODULE_DIR$" />
|
||||||
|
<option name="settingsModule" value="Graphs/settings.py" />
|
||||||
|
<option name="manageScript" value="$MODULE_DIR$/manage.py" />
|
||||||
|
<option name="environment" value="<map/>" />
|
||||||
|
<option name="doNotUseTestRunner" value="false" />
|
||||||
|
<option name="trackFilePattern" value="migrations" />
|
||||||
|
</configuration>
|
||||||
|
</facet>
|
||||||
|
</component>
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
<component name="TemplatesService">
|
||||||
|
<option name="TEMPLATE_CONFIGURATION" value="Django" />
|
||||||
|
<option name="TEMPLATE_FOLDERS">
|
||||||
|
<list>
|
||||||
|
<option value="$MODULE_DIR$/templates" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</module>
|
12
.idea/dataSources.xml
Normal file
12
.idea/dataSources.xml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||||
|
<data-source source="LOCAL" name="db" uuid="0fa9eba3-0541-4f73-9641-aa1e25dcaa32">
|
||||||
|
<driver-ref>sqlite.xerial</driver-ref>
|
||||||
|
<synchronize>true</synchronize>
|
||||||
|
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||||
|
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/db.sqlite3</jdbc-url>
|
||||||
|
<working-dir>$ProjectFileDir$</working-dir>
|
||||||
|
</data-source>
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/inspectionProfiles/Project_Default.xml
Normal file
6
.idea/inspectionProfiles/Project_Default.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
</profile>
|
||||||
|
</component>
|
6
.idea/inspectionProfiles/profiles_settings.xml
Normal file
6
.idea/inspectionProfiles/profiles_settings.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
7
.idea/misc.xml
Normal file
7
.idea/misc.xml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Black">
|
||||||
|
<option name="sdkName" value="Poetry (Graphs) (2)" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Poetry (Graphs) (2)" project-jdk-type="Python SDK" />
|
||||||
|
</project>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/Graphs.iml" filepath="$PROJECT_DIR$/.idea/Graphs.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/ruff.xml
Normal file
6
.idea/ruff.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="RuffConfigService">
|
||||||
|
<option name="globalRuffExecutablePath" value="$USER_HOME$/.local/bin/ruff" />
|
||||||
|
</component>
|
||||||
|
</project>
|
0
Graphs/__init__.py
Normal file
0
Graphs/__init__.py
Normal file
BIN
Graphs/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
Graphs/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
Graphs/__pycache__/settings.cpython-310.pyc
Normal file
BIN
Graphs/__pycache__/settings.cpython-310.pyc
Normal file
Binary file not shown.
BIN
Graphs/__pycache__/urls.cpython-310.pyc
Normal file
BIN
Graphs/__pycache__/urls.cpython-310.pyc
Normal file
Binary file not shown.
BIN
Graphs/__pycache__/wsgi.cpython-310.pyc
Normal file
BIN
Graphs/__pycache__/wsgi.cpython-310.pyc
Normal file
Binary file not shown.
16
Graphs/asgi.py
Normal file
16
Graphs/asgi.py
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
"""
|
||||||
|
ASGI config for Graphs project.
|
||||||
|
|
||||||
|
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.asgi import get_asgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Graphs.settings')
|
||||||
|
|
||||||
|
application = get_asgi_application()
|
125
Graphs/settings.py
Normal file
125
Graphs/settings.py
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
"""
|
||||||
|
Django settings for Graphs project.
|
||||||
|
|
||||||
|
Generated by 'django-admin startproject' using Django 4.2.5.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/4.2/topics/settings/
|
||||||
|
|
||||||
|
For the full list of settings and their values, see
|
||||||
|
https://docs.djangoproject.com/en/4.2/ref/settings/
|
||||||
|
"""
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
|
||||||
|
# Quick-start development settings - unsuitable for production
|
||||||
|
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
|
||||||
|
|
||||||
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
|
SECRET_KEY = 'django-insecure-_d+6%0z5*@jzz-wkemhw-qe5$pa_jv)vq4&oc=(5$-n0#oosso'
|
||||||
|
|
||||||
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
|
DEBUG = True
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = []
|
||||||
|
|
||||||
|
|
||||||
|
# Application definition
|
||||||
|
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
'django.contrib.admin',
|
||||||
|
'django.contrib.auth',
|
||||||
|
'django.contrib.contenttypes',
|
||||||
|
'django.contrib.sessions',
|
||||||
|
'django.contrib.messages',
|
||||||
|
'django.contrib.staticfiles',
|
||||||
|
'src.apps.SrcConfig',
|
||||||
|
]
|
||||||
|
|
||||||
|
MIDDLEWARE = [
|
||||||
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
|
]
|
||||||
|
|
||||||
|
ROOT_URLCONF = 'Graphs.urls'
|
||||||
|
|
||||||
|
TEMPLATES = [
|
||||||
|
{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'DIRS': [BASE_DIR / 'templates']
|
||||||
|
,
|
||||||
|
'APP_DIRS': True,
|
||||||
|
'OPTIONS': {
|
||||||
|
'context_processors': [
|
||||||
|
'django.template.context_processors.debug',
|
||||||
|
'django.template.context_processors.request',
|
||||||
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
WSGI_APPLICATION = 'Graphs.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
|
# Database
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
'NAME': BASE_DIR / 'db.sqlite3',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Password validation
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Internationalization
|
||||||
|
# https://docs.djangoproject.com/en/4.2/topics/i18n/
|
||||||
|
|
||||||
|
LANGUAGE_CODE = 'en-us'
|
||||||
|
|
||||||
|
TIME_ZONE = 'UTC'
|
||||||
|
|
||||||
|
USE_I18N = True
|
||||||
|
|
||||||
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
|
# Static files (CSS, JavaScript, Images)
|
||||||
|
# https://docs.djangoproject.com/en/4.2/howto/static-files/
|
||||||
|
|
||||||
|
STATIC_URL = 'static/'
|
||||||
|
|
||||||
|
# Default primary key field type
|
||||||
|
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
||||||
|
|
||||||
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
11
Graphs/urls.py
Normal file
11
Graphs/urls.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
from src.views import IndexView, TypeView, InfoView
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('admin/', admin.site.urls),
|
||||||
|
path('', IndexView.as_view(), name='index'),
|
||||||
|
path('<str:type>/', TypeView.as_view(), name='type'),
|
||||||
|
path('<str:type>/<int:info>/', InfoView.as_view(), name='info'),
|
||||||
|
]
|
16
Graphs/wsgi.py
Normal file
16
Graphs/wsgi.py
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
"""
|
||||||
|
WSGI config for Graphs project.
|
||||||
|
|
||||||
|
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Graphs.settings')
|
||||||
|
|
||||||
|
application = get_wsgi_application()
|
BIN
__pycache__/manage.cpython-310.pyc
Normal file
BIN
__pycache__/manage.cpython-310.pyc
Normal file
Binary file not shown.
BIN
db.sqlite3
Normal file
BIN
db.sqlite3
Normal file
Binary file not shown.
22
manage.py
Executable file
22
manage.py
Executable file
|
@ -0,0 +1,22 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
"""Django's command-line utility for administrative tasks."""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Run administrative tasks."""
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Graphs.settings')
|
||||||
|
try:
|
||||||
|
from django.core.management import execute_from_command_line
|
||||||
|
except ImportError as exc:
|
||||||
|
raise ImportError(
|
||||||
|
"Couldn't import Django. Are you sure it's installed and "
|
||||||
|
"available on your PYTHONPATH environment variable? Did you "
|
||||||
|
"forget to activate a virtual environment?"
|
||||||
|
) from exc
|
||||||
|
execute_from_command_line(sys.argv)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
144
poetry.lock
generated
Normal file
144
poetry.lock
generated
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "asgiref"
|
||||||
|
version = "3.8.1"
|
||||||
|
description = "ASGI specs, helper code, and adapters"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47"},
|
||||||
|
{file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""}
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "django"
|
||||||
|
version = "4.2.20"
|
||||||
|
description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "Django-4.2.20-py3-none-any.whl", hash = "sha256:213381b6e4405f5c8703fffc29cd719efdf189dec60c67c04f76272b3dc845b9"},
|
||||||
|
{file = "Django-4.2.20.tar.gz", hash = "sha256:92bac5b4432a64532abb73b2ac27203f485e40225d2640a7fbef2b62b876e789"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
asgiref = ">=3.6.0,<4"
|
||||||
|
sqlparse = ">=0.3.1"
|
||||||
|
tzdata = {version = "*", markers = "sys_platform == \"win32\""}
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
argon2 = ["argon2-cffi (>=19.1.0)"]
|
||||||
|
bcrypt = ["bcrypt"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "networkx"
|
||||||
|
version = "3.4.2"
|
||||||
|
description = "Python package for creating and manipulating graphs and networks"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.10"
|
||||||
|
files = [
|
||||||
|
{file = "networkx-3.4.2-py3-none-any.whl", hash = "sha256:df5d4365b724cf81b8c6a7312509d0c22386097011ad1abe274afd5e9d3bbc5f"},
|
||||||
|
{file = "networkx-3.4.2.tar.gz", hash = "sha256:307c3669428c5362aab27c8a1260aa8f47c4e91d3891f48be0141738d8d053e1"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
default = ["matplotlib (>=3.7)", "numpy (>=1.24)", "pandas (>=2.0)", "scipy (>=1.10,!=1.11.0,!=1.11.1)"]
|
||||||
|
developer = ["changelist (==0.5)", "mypy (>=1.1)", "pre-commit (>=3.2)", "rtoml"]
|
||||||
|
doc = ["intersphinx-registry", "myst-nb (>=1.1)", "numpydoc (>=1.8.0)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.15)", "sphinx (>=7.3)", "sphinx-gallery (>=0.16)", "texext (>=0.6.7)"]
|
||||||
|
example = ["cairocffi (>=1.7)", "contextily (>=1.6)", "igraph (>=0.11)", "momepy (>=0.7.2)", "osmnx (>=1.9)", "scikit-learn (>=1.5)", "seaborn (>=0.13)"]
|
||||||
|
extra = ["lxml (>=4.6)", "pydot (>=3.0.1)", "pygraphviz (>=1.14)", "sympy (>=1.10)"]
|
||||||
|
test = ["pytest (>=7.2)", "pytest-cov (>=4.0)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "numpy"
|
||||||
|
version = "1.26.4"
|
||||||
|
description = "Fundamental package for array computing in Python"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
files = [
|
||||||
|
{file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"},
|
||||||
|
{file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"},
|
||||||
|
{file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"},
|
||||||
|
{file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"},
|
||||||
|
{file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"},
|
||||||
|
{file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"},
|
||||||
|
{file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"},
|
||||||
|
{file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"},
|
||||||
|
{file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"},
|
||||||
|
{file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"},
|
||||||
|
{file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"},
|
||||||
|
{file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"},
|
||||||
|
{file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"},
|
||||||
|
{file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"},
|
||||||
|
{file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"},
|
||||||
|
{file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"},
|
||||||
|
{file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"},
|
||||||
|
{file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"},
|
||||||
|
{file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"},
|
||||||
|
{file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"},
|
||||||
|
{file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"},
|
||||||
|
{file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"},
|
||||||
|
{file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"},
|
||||||
|
{file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"},
|
||||||
|
{file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"},
|
||||||
|
{file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"},
|
||||||
|
{file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"},
|
||||||
|
{file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"},
|
||||||
|
{file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"},
|
||||||
|
{file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"},
|
||||||
|
{file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"},
|
||||||
|
{file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"},
|
||||||
|
{file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"},
|
||||||
|
{file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"},
|
||||||
|
{file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"},
|
||||||
|
{file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sqlparse"
|
||||||
|
version = "0.5.3"
|
||||||
|
description = "A non-validating SQL parser."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "sqlparse-0.5.3-py3-none-any.whl", hash = "sha256:cf2196ed3418f3ba5de6af7e82c694a9fbdbfecccdfc72e281548517081f16ca"},
|
||||||
|
{file = "sqlparse-0.5.3.tar.gz", hash = "sha256:09f67787f56a0b16ecdbde1bfc7f5d9c3371ca683cfeaa8e6ff60b4807ec9272"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
dev = ["build", "hatch"]
|
||||||
|
doc = ["sphinx"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typing-extensions"
|
||||||
|
version = "4.12.2"
|
||||||
|
description = "Backported and Experimental Type Hints for Python 3.8+"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
|
||||||
|
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tzdata"
|
||||||
|
version = "2025.1"
|
||||||
|
description = "Provider of IANA time zone data"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2"
|
||||||
|
files = [
|
||||||
|
{file = "tzdata-2025.1-py2.py3-none-any.whl", hash = "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639"},
|
||||||
|
{file = "tzdata-2025.1.tar.gz", hash = "sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
lock-version = "2.0"
|
||||||
|
python-versions = "^3.10"
|
||||||
|
content-hash = "cf0c35bc75496d42ca7e5bae99bc0636ca80a3235326d52974de95a1169f310c"
|
17
pyproject.toml
Normal file
17
pyproject.toml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
[tool.poetry]
|
||||||
|
name = "graphs"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = ""
|
||||||
|
authors = ["KUB0570 <nikola.kubeczkova.st@vsb.cz>"]
|
||||||
|
readme = "README.md"
|
||||||
|
|
||||||
|
[tool.poetry.dependencies]
|
||||||
|
python = "^3.10"
|
||||||
|
django = "^4.2.5"
|
||||||
|
numpy = "^1.26.3"
|
||||||
|
networkx = "^3.2.1"
|
||||||
|
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["poetry-core"]
|
||||||
|
build-backend = "poetry.core.masonry.api"
|
0
src/__init__.py
Normal file
0
src/__init__.py
Normal file
BIN
src/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
src/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/admin.cpython-310.pyc
Normal file
BIN
src/__pycache__/admin.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/apps.cpython-310.pyc
Normal file
BIN
src/__pycache__/apps.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/models.cpython-310.pyc
Normal file
BIN
src/__pycache__/models.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/views.cpython-310.pyc
Normal file
BIN
src/__pycache__/views.cpython-310.pyc
Normal file
Binary file not shown.
24
src/admin.py
Normal file
24
src/admin.py
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# from django.contrib import admin
|
||||||
|
# from src.models import Graph, Vertex, Arc
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# @admin.register(Graph)
|
||||||
|
# class GraphAdmin(admin.ModelAdmin):
|
||||||
|
# list_display = [
|
||||||
|
# "graph_type",
|
||||||
|
# "antimagic",
|
||||||
|
# "strong",
|
||||||
|
# "vertex",
|
||||||
|
# "arc"
|
||||||
|
# ]
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# @admin.register(Vertex)
|
||||||
|
# class VertexAdmin(admin.ModelAdmin):
|
||||||
|
# list_display = ["graph", "in_weight", "out_weight", "label"]
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# @admin.register(Arc)
|
||||||
|
# class ArcAdmin(admin.ModelAdmin):
|
||||||
|
# list_display = ["vertex_in", "vertex_out", "label"]
|
||||||
|
#
|
6
src/apps.py
Normal file
6
src/apps.py
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class SrcConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'src'
|
0
src/management/__init__.py
Normal file
0
src/management/__init__.py
Normal file
BIN
src/management/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
src/management/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
0
src/management/commands/__init__.py
Normal file
0
src/management/commands/__init__.py
Normal file
BIN
src/management/commands/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
src/management/commands/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/management/commands/__pycache__/core.cpython-310.pyc
Normal file
BIN
src/management/commands/__pycache__/core.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/management/commands/__pycache__/create_cycle.cpython-310.pyc
Normal file
BIN
src/management/commands/__pycache__/create_cycle.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/management/commands/__pycache__/create_graph.cpython-310.pyc
Normal file
BIN
src/management/commands/__pycache__/create_graph.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/management/commands/__pycache__/create_path.cpython-310.pyc
Normal file
BIN
src/management/commands/__pycache__/create_path.cpython-310.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/management/commands/__pycache__/default.cpython-310.pyc
Normal file
BIN
src/management/commands/__pycache__/default.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/management/commands/__pycache__/path.cpython-310.pyc
Normal file
BIN
src/management/commands/__pycache__/path.cpython-310.pyc
Normal file
Binary file not shown.
BIN
src/management/commands/__pycache__/visualizate.cpython-310.pyc
Normal file
BIN
src/management/commands/__pycache__/visualizate.cpython-310.pyc
Normal file
Binary file not shown.
21
src/management/commands/core.py
Normal file
21
src/management/commands/core.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
from src.models import Arc
|
||||||
|
|
||||||
|
|
||||||
|
def create_arc(vertex_in, vertex_out, arc_num, label=None):
|
||||||
|
Arc.objects.create(
|
||||||
|
vertex_in=vertex_in,
|
||||||
|
vertex_out=vertex_out,
|
||||||
|
label=label
|
||||||
|
)
|
||||||
|
return arc_num+1
|
||||||
|
|
||||||
|
|
||||||
|
def get_arc(first, second, n, idx):
|
||||||
|
if Arc.objects.filter(vertex_out=first, vertex_in=second).exists():
|
||||||
|
arc = Arc.objects.get(vertex_out=first, vertex_in=second)
|
||||||
|
else:
|
||||||
|
arc = Arc.objects.get(vertex_out=second, vertex_in=first)
|
||||||
|
first = second
|
||||||
|
arc.label = n + idx
|
||||||
|
arc.save()
|
||||||
|
return first
|
116
src/management/commands/create_cycle.py
Normal file
116
src/management/commands/create_cycle.py
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.db import transaction
|
||||||
|
|
||||||
|
from src.management.commands.default import delete_graphs
|
||||||
|
from src.management.commands.core import create_arc, get_arc
|
||||||
|
from src.models import Graph, Vertex, Arc
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument('min', type=int)
|
||||||
|
parser.add_argument('max', type=int)
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
delete_graphs(Graph.CYCLE)
|
||||||
|
|
||||||
|
min = options['min']
|
||||||
|
max = options['max']
|
||||||
|
|
||||||
|
s_time = time.time()
|
||||||
|
for n in range(min, max + 1):
|
||||||
|
start_time = time.time()
|
||||||
|
self.create_cycle(n)
|
||||||
|
end_time = time.time()
|
||||||
|
elapsed_time = end_time - start_time
|
||||||
|
|
||||||
|
print("Čas trvání", n, "vrcholů:", elapsed_time, "sekund")
|
||||||
|
|
||||||
|
e_time = time.time()
|
||||||
|
eed_time = e_time - s_time
|
||||||
|
|
||||||
|
print("Celkový čas trvání:", eed_time, "sekund")
|
||||||
|
|
||||||
|
def create_cycle(self, n):
|
||||||
|
with transaction.atomic():
|
||||||
|
for i in range(2 ** n):
|
||||||
|
binary_number = bin(i)[2:].zfill(n)
|
||||||
|
if binary_number[:2] not in ['01', '10']:
|
||||||
|
continue
|
||||||
|
graph = self.create_graph(binary_number)
|
||||||
|
vertex = None
|
||||||
|
vertices = Vertex.objects.filter(graph=graph)
|
||||||
|
vertices_list = []
|
||||||
|
|
||||||
|
for num, v in enumerate(vertices):
|
||||||
|
vertices_list.append(v)
|
||||||
|
if v.max_degree == 2 and not vertex:
|
||||||
|
vertex = v
|
||||||
|
|
||||||
|
right = vertices_list.index(vertex)
|
||||||
|
left = vertices_list.index(vertex)-1
|
||||||
|
section = True
|
||||||
|
|
||||||
|
right_ark = vertices_list[right % n]
|
||||||
|
left_ark = vertices_list[right % n]
|
||||||
|
for idx in range(n):
|
||||||
|
location = (right % n) if section else left
|
||||||
|
now = vertices_list[location]
|
||||||
|
now.index = idx + 1
|
||||||
|
now.save()
|
||||||
|
if section:
|
||||||
|
if right_ark != now:
|
||||||
|
right_ark = get_arc(first=right_ark, second=now, n=n, idx=idx)
|
||||||
|
right += 1
|
||||||
|
else:
|
||||||
|
left_ark = get_arc(first=left_ark, second=now, n=n, idx=idx)
|
||||||
|
left -= 1
|
||||||
|
|
||||||
|
if now.max_degree == 2:
|
||||||
|
section = not section
|
||||||
|
|
||||||
|
if Arc.objects.filter(vertex_out=right_ark, vertex_in=left_ark).exists():
|
||||||
|
arc = Arc.objects.get(vertex_out=right_ark, vertex_in=left_ark)
|
||||||
|
else:
|
||||||
|
arc = Arc.objects.get(vertex_out=left_ark, vertex_in=right_ark)
|
||||||
|
arc.label = n + n
|
||||||
|
arc.save()
|
||||||
|
|
||||||
|
sorted_vertices = sorted(vertices_list, key=lambda vertex: (vertex.max_degree, vertex.index))
|
||||||
|
for num, v in enumerate(sorted_vertices):
|
||||||
|
v.label = num + 1
|
||||||
|
v.save()
|
||||||
|
|
||||||
|
graph.update()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_graph(binary_number):
|
||||||
|
prev_vertex = None
|
||||||
|
first_vertex = None
|
||||||
|
first_bit = None
|
||||||
|
arc_num = 1
|
||||||
|
graph = Graph.objects.create(
|
||||||
|
graph_type=Graph.CYCLE,
|
||||||
|
binary=binary_number,
|
||||||
|
)
|
||||||
|
|
||||||
|
for j, bit in enumerate(binary_number):
|
||||||
|
vertex = Vertex.objects.create(graph=graph, label=j + 1)
|
||||||
|
if prev_vertex:
|
||||||
|
arc_num = create_arc(
|
||||||
|
vertex_in=prev_vertex if bit == '0' else vertex,
|
||||||
|
vertex_out=vertex if bit == '0' else prev_vertex,
|
||||||
|
arc_num=arc_num
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
first_vertex = vertex
|
||||||
|
first_bit = bit
|
||||||
|
prev_vertex = vertex
|
||||||
|
create_arc(
|
||||||
|
vertex_in=prev_vertex if first_bit == '0' else first_vertex,
|
||||||
|
vertex_out=first_vertex if first_bit == '0' else prev_vertex,
|
||||||
|
arc_num=arc_num
|
||||||
|
)
|
||||||
|
return graph
|
||||||
|
|
31
src/management/commands/create_graph.py
Normal file
31
src/management/commands/create_graph.py
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
|
from src.management.commands.default import (
|
||||||
|
delete_graphs,
|
||||||
|
GRAPHS
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument('graph', nargs='+', type=str)
|
||||||
|
parser.add_argument('--min', type=int, default=3)
|
||||||
|
parser.add_argument('--max', type=int, default=5)
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
delete_graphs("all")
|
||||||
|
graphs = options['graph']
|
||||||
|
min = options['min']
|
||||||
|
max = options['max']
|
||||||
|
|
||||||
|
component = None
|
||||||
|
for graph in graphs:
|
||||||
|
component = GRAPHS[graph](component)
|
||||||
|
|
||||||
|
for n in range(min, max + 1):
|
||||||
|
for i in range(2 ** (n - 1)):
|
||||||
|
binary_number = bin(i)[2:].zfill(n)
|
||||||
|
|
||||||
|
if i >= 2 ** (n - 1) / 2 - 1:
|
||||||
|
break
|
||||||
|
|
108
src/management/commands/create_path.py
Normal file
108
src/management/commands/create_path.py
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.db import transaction
|
||||||
|
from django.db.models import Count, Max, F, OuterRef, Subquery, ExpressionWrapper, IntegerField
|
||||||
|
from django.db.models.functions import Coalesce
|
||||||
|
|
||||||
|
from src.management.commands.default import delete_graphs
|
||||||
|
from src.management.commands.core import create_arc
|
||||||
|
from src.models import Graph, Vertex, Arc
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument('min', type=int)
|
||||||
|
parser.add_argument('max', type=int)
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
delete_graphs("all")
|
||||||
|
|
||||||
|
min = options['min']
|
||||||
|
max = options['max']
|
||||||
|
|
||||||
|
s_time = time.time()
|
||||||
|
for n in range(min, max + 1):
|
||||||
|
start_time = time.time()
|
||||||
|
self.create_path(n)
|
||||||
|
end_time = time.time()
|
||||||
|
elapsed_time = end_time - start_time
|
||||||
|
|
||||||
|
print("Čas trvání", n, "vrcholů:", elapsed_time, "sekund")
|
||||||
|
e_time = time.time()
|
||||||
|
eed_time = e_time - s_time
|
||||||
|
|
||||||
|
print("Celkový čas trvání:", eed_time, "sekund")
|
||||||
|
|
||||||
|
def create_path(self, n):
|
||||||
|
with transaction.atomic():
|
||||||
|
for i in range(2 ** (n-1)):
|
||||||
|
binary_number = bin(i)[2:].zfill(n)
|
||||||
|
graph = self.create_graph(n, binary_number)
|
||||||
|
|
||||||
|
arc_count_in_subquery = (
|
||||||
|
Arc.objects
|
||||||
|
.filter(vertex_in=OuterRef('pk'))
|
||||||
|
.values('vertex_in')
|
||||||
|
.annotate(arc_count_in=Count('label'))
|
||||||
|
.values('arc_count_in')
|
||||||
|
.order_by('-arc_count_in')
|
||||||
|
[:1]
|
||||||
|
)
|
||||||
|
|
||||||
|
arc_count_out_subquery = (
|
||||||
|
Arc.objects
|
||||||
|
.filter(vertex_out=OuterRef('pk'))
|
||||||
|
.values('vertex_out')
|
||||||
|
.annotate(arc_count_out=Count('label'))
|
||||||
|
.values('arc_count_out')
|
||||||
|
.order_by('-arc_count_out')
|
||||||
|
[:1]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Získání maximálního počtu arků pro každý vrchol
|
||||||
|
vertices = (
|
||||||
|
Vertex.objects
|
||||||
|
.filter(graph=graph)
|
||||||
|
.annotate(arc_count_in=Coalesce(Subquery(arc_count_in_subquery, output_field=IntegerField()), 0))
|
||||||
|
.annotate(arc_count_out=Coalesce(Subquery(arc_count_out_subquery, output_field=IntegerField()), 0))
|
||||||
|
.annotate(max_arc_count=ExpressionWrapper(
|
||||||
|
Max(F('arc_count_in'), F('arc_count_out')),
|
||||||
|
output_field=IntegerField()
|
||||||
|
))
|
||||||
|
.order_by('max_arc_count', 'label')
|
||||||
|
)
|
||||||
|
for num, v in enumerate(vertices):
|
||||||
|
v.label = num + 1
|
||||||
|
v.save()
|
||||||
|
graph.update()
|
||||||
|
|
||||||
|
if i >= 2 ** (n - 1) / 2 - 1:
|
||||||
|
break
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_graph(n, binary_number):
|
||||||
|
prev_vertex = None
|
||||||
|
arc_num = 0
|
||||||
|
graph = Graph.objects.create(
|
||||||
|
graph_type=Graph.PATH,
|
||||||
|
binary=binary_number[1:],
|
||||||
|
)
|
||||||
|
|
||||||
|
for j, bit in enumerate(binary_number):
|
||||||
|
vertex = Vertex.objects.create(graph=graph, index=j + 1)
|
||||||
|
if prev_vertex:
|
||||||
|
arc_num = create_arc(
|
||||||
|
vertex_in=prev_vertex if bit == '0' else vertex,
|
||||||
|
vertex_out=vertex if bit == '0' else prev_vertex,
|
||||||
|
arc_num=arc_num,
|
||||||
|
label=n + arc_num
|
||||||
|
)
|
||||||
|
prev_vertex = vertex
|
||||||
|
return graph
|
||||||
|
|
||||||
|
|
||||||
|
# for i in range(2 ** (n - 1)):
|
||||||
|
# binary_number = bin(i)[2:].zfill(n)
|
||||||
|
#
|
||||||
|
# if i >= 2 ** (n - 1) / 2 - 1:
|
||||||
|
# break
|
97
src/management/commands/create_tadpole.py
Normal file
97
src/management/commands/create_tadpole.py
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.db import transaction
|
||||||
|
|
||||||
|
from src.management.commands.default import delete_graphs, count_change
|
||||||
|
from src.management.commands.core import create_arc, get_arc
|
||||||
|
from src.models import Graph, Vertex, Arc
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument('min_n', type=int)
|
||||||
|
parser.add_argument('max_n', type=int)
|
||||||
|
parser.add_argument('min_m', type=int)
|
||||||
|
parser.add_argument('max_m', type=int)
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
delete_graphs("all")
|
||||||
|
|
||||||
|
min_n = options['min_n']
|
||||||
|
max_n = options['max_n']
|
||||||
|
min_m = options['min_m']
|
||||||
|
max_m = options['max_m']
|
||||||
|
for n in range(min_n, max_n + 1):
|
||||||
|
for m in range(min_m, max_m + 1):
|
||||||
|
self.create_tadpole(n, m)
|
||||||
|
|
||||||
|
def create_tadpole(self, n, m):
|
||||||
|
with transaction.atomic():
|
||||||
|
for i in range(1, (2 ** n)):
|
||||||
|
for j in range(1, (2 ** m)):
|
||||||
|
binary_number_n = bin(i)[2:].zfill(n)
|
||||||
|
binary_number_m = bin(j)[2:].zfill(m)
|
||||||
|
|
||||||
|
print(binary_number_n, binary_number_m)
|
||||||
|
graph = self.create_graph(binary_number_n, binary_number_m)
|
||||||
|
if graph:
|
||||||
|
graph.update()
|
||||||
|
|
||||||
|
def create_graph(self, binary_number_n, binary_number_m):
|
||||||
|
length = len(binary_number_n+binary_number_m)
|
||||||
|
graph = Graph.objects.create(
|
||||||
|
graph_type=Graph.TADPOLE,
|
||||||
|
binary=binary_number_n + binary_number_m,
|
||||||
|
)
|
||||||
|
|
||||||
|
a = count_change(binary_number_n+binary_number_n[0]) + count_change(binary_number_m)
|
||||||
|
if binary_number_n[0] == binary_number_m[0] and binary_number_n[-1] != binary_number_m[0]:
|
||||||
|
return self.max_degree_3(binary_number_n, binary_number_m, graph, length, a)
|
||||||
|
else:
|
||||||
|
return self.max_degree_2()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def max_degree_3(binary_number_n, binary_number_m, graph, length, a):
|
||||||
|
arc_num = 1
|
||||||
|
labeling = [i for i in range(1, length + 1)]
|
||||||
|
label = length - a + 1
|
||||||
|
labeling.remove(label)
|
||||||
|
prev_vertex = vertex3 = Vertex.objects.create(graph=graph, label=label)
|
||||||
|
for j, bit in enumerate(binary_number_n):
|
||||||
|
vertex = vertex3 if j == len(binary_number_n) - 1 else Vertex.objects.create(graph=graph)
|
||||||
|
arc_num = create_arc(
|
||||||
|
vertex_in=prev_vertex if bit == '0' else vertex,
|
||||||
|
vertex_out=vertex if bit == '0' else prev_vertex,
|
||||||
|
arc_num=arc_num,
|
||||||
|
label=arc_num + length
|
||||||
|
)
|
||||||
|
prev_vertex = vertex
|
||||||
|
|
||||||
|
prev_vertex = vertex3
|
||||||
|
for j, bit in enumerate(binary_number_m):
|
||||||
|
vertex = Vertex.objects.create(graph=graph)
|
||||||
|
arc_num = create_arc(
|
||||||
|
vertex_in=prev_vertex if bit == '0' else vertex,
|
||||||
|
vertex_out=vertex if bit == '0' else prev_vertex,
|
||||||
|
arc_num=arc_num,
|
||||||
|
label=arc_num + length
|
||||||
|
)
|
||||||
|
prev_vertex = vertex
|
||||||
|
|
||||||
|
vertices = Vertex.objects.filter(graph=graph)
|
||||||
|
for vertex in vertices:
|
||||||
|
if vertex.max_degree == 2:
|
||||||
|
label = min([x for x in labeling if x > (length - a + 1)])
|
||||||
|
labeling.remove(label)
|
||||||
|
vertex.label = label
|
||||||
|
vertex.save()
|
||||||
|
if vertex.max_degree == 1:
|
||||||
|
label = min([x for x in labeling if x < (length - a + 1)])
|
||||||
|
labeling.remove(label)
|
||||||
|
vertex.label = label
|
||||||
|
vertex.save()
|
||||||
|
return graph
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def max_degree_2():
|
||||||
|
return None
|
||||||
|
|
55
src/management/commands/default.py
Normal file
55
src/management/commands/default.py
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
from src.management.commands.path import path
|
||||||
|
from src.models import Graph, Vertex, Arc
|
||||||
|
|
||||||
|
|
||||||
|
def delete_graphs(type_of_graph):
|
||||||
|
if type_of_graph == "all":
|
||||||
|
Graph.objects.all().delete()
|
||||||
|
Vertex.objects.all().delete()
|
||||||
|
Arc.objects.all().delete()
|
||||||
|
else:
|
||||||
|
Graph.objects.filter(graph_type=type_of_graph).delete()
|
||||||
|
Vertex.objects.filter(graph__graph_type=type_of_graph).delete()
|
||||||
|
Arc.objects.filter(vertex_in__graph__graph_type=type_of_graph).delete()
|
||||||
|
|
||||||
|
|
||||||
|
def count_change(binary_number):
|
||||||
|
change = 0
|
||||||
|
actual_bit = binary_number[0]
|
||||||
|
|
||||||
|
for bit in binary_number:
|
||||||
|
if bit != actual_bit:
|
||||||
|
change += 1
|
||||||
|
actual_bit = bit
|
||||||
|
return change
|
||||||
|
|
||||||
|
|
||||||
|
def create_path(n, binary_number, graph=None):
|
||||||
|
if graph:
|
||||||
|
return path()
|
||||||
|
return print("new path")
|
||||||
|
|
||||||
|
|
||||||
|
def create_cycle(graph=None):
|
||||||
|
if graph:
|
||||||
|
return print("cycle")
|
||||||
|
return print("new cycle")
|
||||||
|
|
||||||
|
|
||||||
|
# def create_tadpole(graph=None):
|
||||||
|
# if graph:
|
||||||
|
# return print("tadpole")
|
||||||
|
# return print("new tadpole")
|
||||||
|
|
||||||
|
|
||||||
|
GRAPHS = {
|
||||||
|
Graph.CYCLE: create_cycle,
|
||||||
|
Graph.PATH: create_path,
|
||||||
|
# Graph.TADPOLE: create_tadpole,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# def unite_graph(function, graph=None):
|
||||||
|
# if graph:
|
||||||
|
# return function(graph)
|
||||||
|
# return function()
|
74
src/management/commands/path.py
Normal file
74
src/management/commands/path.py
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
from django.db import transaction
|
||||||
|
from django.db.models import OuterRef, Count, Subquery, ExpressionWrapper, IntegerField, F, Max
|
||||||
|
from django.db.models.functions import Coalesce
|
||||||
|
|
||||||
|
from src.management.commands.core import create_arc
|
||||||
|
from src.models import Arc, Vertex, Graph
|
||||||
|
|
||||||
|
|
||||||
|
def path(n, binary_number):
|
||||||
|
with transaction.atomic():
|
||||||
|
graph = create_path(n, binary_number)
|
||||||
|
|
||||||
|
arc_count_in_subquery = (
|
||||||
|
Arc.objects
|
||||||
|
.filter(vertex_in=OuterRef('pk'))
|
||||||
|
.values('vertex_in')
|
||||||
|
.annotate(arc_count_in=Count('label'))
|
||||||
|
.values('arc_count_in')
|
||||||
|
.order_by('-arc_count_in')
|
||||||
|
[:1]
|
||||||
|
)
|
||||||
|
|
||||||
|
arc_count_out_subquery = (
|
||||||
|
Arc.objects
|
||||||
|
.filter(vertex_out=OuterRef('pk'))
|
||||||
|
.values('vertex_out')
|
||||||
|
.annotate(arc_count_out=Count('label'))
|
||||||
|
.values('arc_count_out')
|
||||||
|
.order_by('-arc_count_out')
|
||||||
|
[:1]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Získání maximálního počtu arků pro každý vrchol
|
||||||
|
vertices = (
|
||||||
|
Vertex.objects
|
||||||
|
.filter(graph=graph)
|
||||||
|
.annotate(arc_count_in=Coalesce(Subquery(arc_count_in_subquery, output_field=IntegerField()), 0))
|
||||||
|
.annotate(arc_count_out=Coalesce(Subquery(arc_count_out_subquery, output_field=IntegerField()), 0))
|
||||||
|
.annotate(max_arc_count=ExpressionWrapper(
|
||||||
|
Max(F('arc_count_in'), F('arc_count_out')),
|
||||||
|
output_field=IntegerField()
|
||||||
|
))
|
||||||
|
.order_by('max_arc_count', 'label')
|
||||||
|
)
|
||||||
|
for num, v in enumerate(vertices):
|
||||||
|
v.label = num + 1
|
||||||
|
v.save()
|
||||||
|
graph.update()
|
||||||
|
|
||||||
|
|
||||||
|
def create_path(n, binary_number, graph=None):
|
||||||
|
prev_vertex = None
|
||||||
|
arc_num = 0
|
||||||
|
if graph:
|
||||||
|
graph.components += 1
|
||||||
|
graph.graph_type = Graph.UNITED
|
||||||
|
graph.save()
|
||||||
|
else:
|
||||||
|
graph = Graph.objects.create(
|
||||||
|
graph_type=Graph.PATH,
|
||||||
|
binary=binary_number[1:],
|
||||||
|
)
|
||||||
|
|
||||||
|
for j, bit in enumerate(binary_number):
|
||||||
|
vertex = Vertex.objects.create(graph=graph, index=j + 1)
|
||||||
|
if prev_vertex:
|
||||||
|
arc_num = create_arc(
|
||||||
|
vertex_in=prev_vertex if bit == '0' else vertex,
|
||||||
|
vertex_out=vertex if bit == '0' else prev_vertex,
|
||||||
|
arc_num=arc_num,
|
||||||
|
label=n + arc_num
|
||||||
|
)
|
||||||
|
prev_vertex = vertex
|
||||||
|
return graph
|
67
src/management/commands/visualizate.py
Normal file
67
src/management/commands/visualizate.py
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import networkx as nx
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from src.models import Graph, Vertex, Arc
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument('id', type=int)
|
||||||
|
# parser.add_argument('graph_type', type=str)
|
||||||
|
# parser.add_argument('binary', type=str)
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
id = options['id']
|
||||||
|
# graph_type = options['graph_type']
|
||||||
|
# binary = options['binary']
|
||||||
|
|
||||||
|
graph = Graph.objects.filter(
|
||||||
|
# graph_type=graph_type, binary=binary
|
||||||
|
id=id
|
||||||
|
).first()
|
||||||
|
|
||||||
|
if not graph:
|
||||||
|
return
|
||||||
|
|
||||||
|
vertices = Vertex.objects.filter(graph=graph)
|
||||||
|
arcs = Arc.objects.filter(vertex_in__graph=graph)
|
||||||
|
|
||||||
|
adjacency_matrix = np.zeros((len(vertices), len(vertices)))
|
||||||
|
|
||||||
|
for arc in arcs:
|
||||||
|
adjacency_matrix[arc.vertex_in.index - 1][arc.vertex_out.index - 1] = 1
|
||||||
|
adjacency_matrix[arc.vertex_out.index - 1][arc.vertex_in.index - 1] = 1
|
||||||
|
|
||||||
|
# Create a degree matrix
|
||||||
|
degree_matrix = np.diag(np.sum(adjacency_matrix, axis=1))
|
||||||
|
|
||||||
|
# Create Laplacian matrix
|
||||||
|
laplacian_matrix = degree_matrix - adjacency_matrix
|
||||||
|
|
||||||
|
# Calculate eigenvalues and eigenvectors of the Laplacian matrix
|
||||||
|
eigenvalues, eigenvectors = np.linalg.eigh(laplacian_matrix)
|
||||||
|
|
||||||
|
# Get the second smallest eigenvector (the smallest is constant)
|
||||||
|
second_smallest_eigenvector = eigenvectors[:, 1]
|
||||||
|
|
||||||
|
# Use the eigenvector values as x, y coordinates for visualization
|
||||||
|
x_coordinates = second_smallest_eigenvector.real
|
||||||
|
y_coordinates = eigenvectors[:, 2].real # You can choose a different eigenvector if needed
|
||||||
|
|
||||||
|
# Visualize the graph using matplotlib
|
||||||
|
plt.scatter(x_coordinates, y_coordinates, c='blue', s=100)
|
||||||
|
for i, vertex in enumerate(vertices):
|
||||||
|
plt.text(x_coordinates[i], y_coordinates[i], str(vertex.index))
|
||||||
|
|
||||||
|
# Draw lines between connected vertices
|
||||||
|
for arc in arcs:
|
||||||
|
index_in = arc.vertex_in.index - 1
|
||||||
|
index_out = arc.vertex_out.index - 1
|
||||||
|
plt.plot([x_coordinates[index_in], x_coordinates[index_out]],
|
||||||
|
[y_coordinates[index_in], y_coordinates[index_out]],
|
||||||
|
color='gray', linestyle='-', linewidth=1)
|
||||||
|
|
||||||
|
plt.title('Graph Visualization with Edges using Laplacian Eigenmaps')
|
||||||
|
plt.show()
|
45
src/migrations/0001_initial.py
Normal file
45
src/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# Generated by Django 4.2.5 on 2024-01-29 16:19
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Graph',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('graph_type', models.CharField(choices=[('cycle', 'cycle'), ('path', 'path')], max_length=8)),
|
||||||
|
('arcs', models.CharField(blank=True, max_length=128, null=True)),
|
||||||
|
('arc_binary', models.IntegerField(blank=True, null=True)),
|
||||||
|
('antimagic', models.BooleanField(default=False)),
|
||||||
|
('super', models.BooleanField(default=False)),
|
||||||
|
('strict', models.BooleanField(default=False)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Vertex',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('index', models.IntegerField(blank=True, default=0, null=True)),
|
||||||
|
('label', models.IntegerField(blank=True, default=0, null=True)),
|
||||||
|
('graph', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vertices', to='src.graph')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Arc',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('label', models.IntegerField(blank=True, default=0, null=True)),
|
||||||
|
('vertex_in', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='in_arcs', to='src.vertex')),
|
||||||
|
('vertex_out', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='out_arcs', to='src.vertex')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
18
src/migrations/0002_alter_graph_arc_binary.py
Normal file
18
src/migrations/0002_alter_graph_arc_binary.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 4.2.5 on 2024-01-29 18:43
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('src', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='graph',
|
||||||
|
name='arc_binary',
|
||||||
|
field=models.CharField(blank=True, max_length=2048, null=True),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Generated by Django 4.2.5 on 2024-01-29 18:46
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('src', '0002_alter_graph_arc_binary'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='graph',
|
||||||
|
old_name='arc_binary',
|
||||||
|
new_name='binary',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='graph',
|
||||||
|
name='arcs',
|
||||||
|
),
|
||||||
|
]
|
18
src/migrations/0004_graph_components.py
Normal file
18
src/migrations/0004_graph_components.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 4.2.5 on 2024-03-05 10:52
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('src', '0003_rename_arc_binary_graph_binary_remove_graph_arcs'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='graph',
|
||||||
|
name='components',
|
||||||
|
field=models.IntegerField(default=1),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Generated by Django 4.2.5 on 2024-04-25 07:11
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('src', '0004_graph_components'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='graph',
|
||||||
|
old_name='strict',
|
||||||
|
new_name='strong',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='graph',
|
||||||
|
name='super',
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='graph',
|
||||||
|
name='graph_type',
|
||||||
|
field=models.CharField(choices=[('cycle', 'cycle'), ('path', 'path'), ('tadpole', 'tadpole'), ('united', 'united')], max_length=8),
|
||||||
|
),
|
||||||
|
]
|
0
src/migrations/__init__.py
Normal file
0
src/migrations/__init__.py
Normal file
BIN
src/migrations/__pycache__/0001_initial.cpython-310.pyc
Normal file
BIN
src/migrations/__pycache__/0001_initial.cpython-310.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
src/migrations/__pycache__/0004_graph_components.cpython-310.pyc
Normal file
BIN
src/migrations/__pycache__/0004_graph_components.cpython-310.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/migrations/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
src/migrations/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
100
src/models.py
Normal file
100
src/models.py
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class Graph(models.Model):
|
||||||
|
CYCLE = "cycle"
|
||||||
|
PATH = "path"
|
||||||
|
TADPOLE = "tadpole"
|
||||||
|
UNITED = "united"
|
||||||
|
|
||||||
|
GRAPHS = (
|
||||||
|
(CYCLE, "cycle"),
|
||||||
|
(PATH, "path"),
|
||||||
|
(TADPOLE, "tadpole"),
|
||||||
|
(UNITED, "united")
|
||||||
|
)
|
||||||
|
|
||||||
|
graph_type = models.CharField(max_length=8, choices=GRAPHS)
|
||||||
|
binary = models.CharField(max_length=2048, blank=True, null=True)
|
||||||
|
components = models.IntegerField(default=1)
|
||||||
|
|
||||||
|
antimagic = models.BooleanField(default=False)
|
||||||
|
strong = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def vertex_count(self):
|
||||||
|
return self.vertices.filter(graph=self).count()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def arc_count(self):
|
||||||
|
return self.vertices.filter(in_arcs__isnull=False).count()
|
||||||
|
# return Arc.objects.filter(vertex_in__graph=self).count()
|
||||||
|
|
||||||
|
def get_properties(self):
|
||||||
|
return {
|
||||||
|
'vertex': self.vertex_count,
|
||||||
|
'arc': self.arc_count,
|
||||||
|
}
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
vertices = self.vertices.all()
|
||||||
|
in_weight = []
|
||||||
|
out_weight = []
|
||||||
|
labels = []
|
||||||
|
|
||||||
|
for vertex in vertices:
|
||||||
|
labels.append(vertex.label)
|
||||||
|
in_weight.append(vertex.in_weight)
|
||||||
|
out_weight.append(vertex.out_weight)
|
||||||
|
|
||||||
|
self.antimagic = len(in_weight) == len(set(in_weight)) and len(out_weight) == len(set(out_weight))
|
||||||
|
self.strong = len(in_weight + out_weight) == len(set(in_weight + out_weight))
|
||||||
|
self.save()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.graph_type}, {self.vertex_count};{self.arc_count}"
|
||||||
|
|
||||||
|
|
||||||
|
class Vertex(models.Model):
|
||||||
|
graph = models.ForeignKey(Graph, on_delete=models.CASCADE, blank=True, null=True, related_name="vertices")
|
||||||
|
index = models.IntegerField(default=0, null=True, blank=True)
|
||||||
|
label = models.IntegerField(default=0, null=True, blank=True)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def max_degree(self):
|
||||||
|
sum_in = self.in_arcs.all().count()
|
||||||
|
sum_out = self.out_arcs.all().count()
|
||||||
|
# in_arcs = Arc.objects.filter(vertex_in=self)
|
||||||
|
# sum_in = sum(1 for _ in in_arcs)
|
||||||
|
# out_arcs = Arc.objects.filter(vertex_out=self)
|
||||||
|
# sum_out = sum(1 for _ in out_arcs)
|
||||||
|
return sum_in if sum_in > sum_out else sum_out
|
||||||
|
|
||||||
|
@property
|
||||||
|
def in_weight(self):
|
||||||
|
in_arcs = Arc.objects.filter(vertex_in=self)
|
||||||
|
return self.label + sum(arc.label for arc in in_arcs)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def out_weight(self):
|
||||||
|
out_arcs = Arc.objects.filter(vertex_out=self)
|
||||||
|
return self.label + sum(arc.label for arc in out_arcs)
|
||||||
|
|
||||||
|
def get_properties(self):
|
||||||
|
return {
|
||||||
|
'in_weight': self.in_weight,
|
||||||
|
'out_weight': self.out_weight,
|
||||||
|
'max_degree': self.max_degree,
|
||||||
|
}
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.id}, {self.label}, {self.index}"
|
||||||
|
|
||||||
|
|
||||||
|
class Arc(models.Model):
|
||||||
|
vertex_in = models.ForeignKey(Vertex, on_delete=models.CASCADE, related_name='in_arcs')
|
||||||
|
vertex_out = models.ForeignKey(Vertex, on_delete=models.CASCADE, related_name='out_arcs')
|
||||||
|
label = models.IntegerField(default=0, null=True, blank=True)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.id}, ({self.vertex_in.label}, {self.vertex_out.label}) {self.label}"
|
3
src/tests.py
Normal file
3
src/tests.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
37
src/views.py
Normal file
37
src/views.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
from django.views.generic import TemplateView
|
||||||
|
|
||||||
|
from src.models import Graph, Vertex, Arc
|
||||||
|
|
||||||
|
|
||||||
|
class IndexView(TemplateView):
|
||||||
|
template_name = "index.html"
|
||||||
|
|
||||||
|
def get_context_data(self):
|
||||||
|
return {
|
||||||
|
"graphs": [Graph.CYCLE, Graph.PATH],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TypeView(TemplateView):
|
||||||
|
template_name = "type.html"
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
return {
|
||||||
|
"kwargs": kwargs,
|
||||||
|
"graphs": Graph.objects.filter(
|
||||||
|
graph_type=kwargs.get("type")
|
||||||
|
).order_by("binary"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class InfoView(TemplateView):
|
||||||
|
template_name = "info.html"
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
graph = Graph.objects.get(id=kwargs.get("info"))
|
||||||
|
return {
|
||||||
|
"arcs": Arc.objects.filter(vertex_in__graph=graph).order_by("id"),
|
||||||
|
"vertices": Vertex.objects.filter(graph=graph).order_by("id"),
|
||||||
|
"graph": graph,
|
||||||
|
"type_name": graph.graph_type,
|
||||||
|
}
|
14
templates/index.html
Normal file
14
templates/index.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Beeebooo</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{% for graph in graphs %}
|
||||||
|
<div>
|
||||||
|
<a href="{% url "type" type=graph %}">{{ graph }}</a>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</body>
|
||||||
|
</html>
|
98
templates/info.html
Normal file
98
templates/info.html
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h3>INFO</h3>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Vrcholy</th>
|
||||||
|
<th>Arky</th>
|
||||||
|
<th>Binary</th>
|
||||||
|
|
||||||
|
<th>Antimagic</th>
|
||||||
|
<th>Super</th>
|
||||||
|
<th>Strict</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ graph.get_properties.vertex }}</td>
|
||||||
|
<td>{{ graph.get_properties.arc }}</td>
|
||||||
|
<td>{{ graph.binary }}</td>
|
||||||
|
|
||||||
|
<td>{% if graph.antimagic %}{{ graph.antimagic }}{% else %}---{% endif %}</td>
|
||||||
|
<td>{% if graph.strong %}{{ graph.strong }}{% else %}---{% endif %}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
{% for arc in arcs %}
|
||||||
|
{% if forloop.last and type_name == "cyklus" %}
|
||||||
|
{% if arc.vertex_out.id > arc.vertex_in.id %}
|
||||||
|
({{ arc.vertex_out.label }})--{{ arc.label }}-->({{ arc.vertex_in.label }})
|
||||||
|
{% else %}
|
||||||
|
({{ arc.vertex_in.label }})<--{{ arc.label }}--({{ arc.vertex_out.label }})
|
||||||
|
{% endif %}
|
||||||
|
{% elif forloop.last and type_name == "cesta" %}
|
||||||
|
{% if arc.vertex_out.id > arc.vertex_in.id %}
|
||||||
|
({{ arc.vertex_out.label }})--{{ arc.label }}-->({{ arc.vertex_in.label }})
|
||||||
|
{% else %}
|
||||||
|
({{ arc.vertex_in.label }})<--{{ arc.label }}--({{ arc.vertex_out.label }})
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
{% if arc.vertex_out.id > arc.vertex_in.id %}
|
||||||
|
({{ arc.vertex_in.label }})<--{{ arc.label }}--
|
||||||
|
{% else %}
|
||||||
|
({{ arc.vertex_out.label }})--{{ arc.label }}-->
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
<br>
|
||||||
|
{% for vertex in vertices %}
|
||||||
|
{{ vertex.get_properties.in_weight }} --------
|
||||||
|
{% endfor %}
|
||||||
|
<br>
|
||||||
|
{% for vertex in vertices %}
|
||||||
|
{{ vertex.get_properties.out_weight }} --------
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Arky</h3>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>OUT</th>
|
||||||
|
<th>IN</th>
|
||||||
|
<th>Váha</th>
|
||||||
|
</tr>
|
||||||
|
{% for arc in arcs %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ arc.vertex_out.label }}</td>
|
||||||
|
<td>{{ arc.vertex_in.label }}</td>
|
||||||
|
<td>{{ arc.label }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
<h3>Váhy</h3>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Váha</th>
|
||||||
|
<th>index</th>
|
||||||
|
<th>m_d</th>
|
||||||
|
<th>OUT</th>
|
||||||
|
<th>IN</th>
|
||||||
|
</tr>
|
||||||
|
{% for vertex in vertices %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ vertex.label }}</td>
|
||||||
|
<td>{{ vertex.index }}</td>
|
||||||
|
<td>{{ vertex.get_properties.max_degree }}</td>
|
||||||
|
<td>{{ vertex.get_properties.out_weight }}</td>
|
||||||
|
<td>{{ vertex.get_properties.in_weight }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
32
templates/type.html
Normal file
32
templates/type.html
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Ahoj</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>-></th>
|
||||||
|
<th>Vrcholy</th>
|
||||||
|
<th>Arky</th>
|
||||||
|
<th>Binary</th>
|
||||||
|
|
||||||
|
<th>Antimagic</th>
|
||||||
|
<th>Super</th>
|
||||||
|
<th>Strict</th>
|
||||||
|
</tr>
|
||||||
|
{% for graph in graphs %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{% url "info" type=kwargs.type info=graph.id %}">o</a></td>
|
||||||
|
<td>{{ graph.get_properties.vertex }}</td>
|
||||||
|
<td>{{ graph.get_properties.arc }}</td>
|
||||||
|
<td>{{ graph.binary }}</td>
|
||||||
|
|
||||||
|
<td>{% if graph.antimagic %}{{ graph.antimagic }}{% else %}---{% endif %}</td>
|
||||||
|
<td>{% if graph.strong %}{{ graph.strong }}{% else %}---{% endif %}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in a new issue