acj 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- acj-0.1.0/.github/workflows/wheels.yml +53 -0
- acj-0.1.0/.gitignore +53 -0
- acj-0.1.0/CMakeLists.txt +80 -0
- acj-0.1.0/Dockerfile +62 -0
- acj-0.1.0/Makefile +79 -0
- acj-0.1.0/PKG-INFO +16 -0
- acj-0.1.0/README.md +122 -0
- acj-0.1.0/examples/example_acj.py +108 -0
- acj-0.1.0/examples/example_crime_osm.py +250 -0
- acj-0.1.0/examples/example_crime_visualization.py +254 -0
- acj-0.1.0/examples/example_minkowski_osm.py +92 -0
- acj-0.1.0/examples/example_multimodal_evaluation.py +83 -0
- acj-0.1.0/examples/example_realtime.py +205 -0
- acj-0.1.0/examples/example_simplification.py +125 -0
- acj-0.1.0/examples/example_simplification_osm.py +246 -0
- acj-0.1.0/examples/example_simplification_visual.py +208 -0
- acj-0.1.0/flake.lock +27 -0
- acj-0.1.0/flake.nix +57 -0
- acj-0.1.0/pyproject.toml +33 -0
- acj-0.1.0/src/acj/__init__.py +46 -0
- acj-0.1.0/src/acj/algorithms/__init__.py +0 -0
- acj-0.1.0/src/acj/algorithms/graph.py +472 -0
- acj-0.1.0/src/acj/algorithms/map_index.py +204 -0
- acj-0.1.0/src/acj/algorithms/minkowski.py +91 -0
- acj-0.1.0/src/acj/core/CMakeLists.txt +42 -0
- acj-0.1.0/src/acj/core/__init__.py +3 -0
- acj-0.1.0/src/acj/core/network.py +105 -0
- acj-0.1.0/src/acj/core/semantics.py +51 -0
- acj-0.1.0/src/acj/core/src/bindings.cpp +65 -0
- acj-0.1.0/src/acj/core/src/graph_simplify.cpp +987 -0
- acj-0.1.0/src/acj/core/src/graph_simplify.hpp +43 -0
- acj-0.1.0/src/acj/core/src/spatial_index.cpp +147 -0
- acj-0.1.0/src/acj/core/src/spatial_index.hpp +17 -0
- acj-0.1.0/src/acj/core/src/types.hpp +81 -0
- acj-0.1.0/src/acj/data/__init__.py +0 -0
- acj-0.1.0/src/acj/data/io.py +219 -0
- acj-0.1.0/src/acj/evaluation/__init__.py +0 -0
- acj-0.1.0/src/acj/evaluation/base.py +28 -0
- acj-0.1.0/src/acj/evaluation/evaluators.py +53 -0
- acj-0.1.0/src/acj/evaluation/metrics.py +51 -0
- acj-0.1.0/src/acj/utils/__init__.py +0 -0
- acj-0.1.0/src/acj/utils/render.py +394 -0
- acj-0.1.0/tests/__init__.py +0 -0
- acj-0.1.0/tests/test_data.py +44 -0
- acj-0.1.0/tests/test_evaluation.py +45 -0
- acj-0.1.0/tests/test_network.py +34 -0
- acj-0.1.0/tests/test_parsers.py +55 -0
- acj-0.1.0/tests/test_semantics.py +58 -0
- acj-0.1.0/tests/test_simplification.py +81 -0
- acj-0.1.0/tests/test_spatial_index.py +82 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: Build Wheels
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
- develop
|
|
8
|
+
tags:
|
|
9
|
+
- 'v*'
|
|
10
|
+
pull_request:
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build_wheels:
|
|
14
|
+
name: Build wheels on ${{ matrix.os }}
|
|
15
|
+
runs-on: ${{ matrix.os }}
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- name: Set up Python
|
|
25
|
+
uses: actions/setup-python@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: '3.10'
|
|
28
|
+
|
|
29
|
+
# cibuildwheel automatically downloads the cibuildwheel docker images for linux
|
|
30
|
+
# and runs the build process across different python versions.
|
|
31
|
+
- name: Cache vcpkg installed packages
|
|
32
|
+
uses: actions/cache@v4
|
|
33
|
+
if: runner.os == 'Windows'
|
|
34
|
+
with:
|
|
35
|
+
path: C:\vcpkg\installed
|
|
36
|
+
key: ${{ runner.os }}-vcpkg-boost-full
|
|
37
|
+
restore-keys: |
|
|
38
|
+
${{ runner.os }}-vcpkg-
|
|
39
|
+
|
|
40
|
+
- name: Build wheels
|
|
41
|
+
uses: pypa/cibuildwheel@v2.22.0
|
|
42
|
+
env:
|
|
43
|
+
CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28
|
|
44
|
+
CIBW_BEFORE_ALL_LINUX: "dnf install -y gmp-devel mpfr-devel boost-devel"
|
|
45
|
+
CIBW_BEFORE_ALL_MACOS: "brew install gmp mpfr boost"
|
|
46
|
+
CIBW_ENVIRONMENT_MACOS: 'MACOSX_DEPLOYMENT_TARGET="15.0"'
|
|
47
|
+
CIBW_BEFORE_ALL_WINDOWS: "vcpkg install boost:x64-windows gmp:x64-windows mpfr:x64-windows"
|
|
48
|
+
CIBW_SKIP: "cp36-* cp37-* cp38-* pp* *-musllinux_* *i686* *win32*" # Omitir versiones muy viejas o 32 bits
|
|
49
|
+
|
|
50
|
+
- uses: actions/upload-artifact@v4
|
|
51
|
+
with:
|
|
52
|
+
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
|
|
53
|
+
path: ./wheelhouse/*.whl
|
acj-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Build artifacts
|
|
2
|
+
build/
|
|
3
|
+
*.so
|
|
4
|
+
*.o
|
|
5
|
+
*.a
|
|
6
|
+
*.dylib
|
|
7
|
+
|
|
8
|
+
# Python cache
|
|
9
|
+
__pycache__/
|
|
10
|
+
*.py[cod]
|
|
11
|
+
*$py.class
|
|
12
|
+
*.egg-info/
|
|
13
|
+
dist/
|
|
14
|
+
.eggs/
|
|
15
|
+
|
|
16
|
+
# Testing
|
|
17
|
+
.pytest_cache/
|
|
18
|
+
.coverage
|
|
19
|
+
htmlcov/
|
|
20
|
+
|
|
21
|
+
# IDEs
|
|
22
|
+
.vscode/
|
|
23
|
+
.idea/
|
|
24
|
+
*.swp
|
|
25
|
+
*.swo
|
|
26
|
+
*~
|
|
27
|
+
.env
|
|
28
|
+
|
|
29
|
+
# OS
|
|
30
|
+
.DS_Store
|
|
31
|
+
Thumbs.db
|
|
32
|
+
|
|
33
|
+
# CMake
|
|
34
|
+
CMakeCache.txt
|
|
35
|
+
CMakeFiles/
|
|
36
|
+
cmake_install.cmake
|
|
37
|
+
build/Makefile
|
|
38
|
+
*.cmake
|
|
39
|
+
|
|
40
|
+
# Keep only the main CMakeLists.txt files and root Makefile
|
|
41
|
+
!CMakeLists.txt
|
|
42
|
+
!acj/core/CMakeLists.txt
|
|
43
|
+
!Makefile
|
|
44
|
+
|
|
45
|
+
# ACJ specific
|
|
46
|
+
cache/
|
|
47
|
+
output/
|
|
48
|
+
*.tar.xz
|
|
49
|
+
|
|
50
|
+
# NixOs / direnv
|
|
51
|
+
.direnv/
|
|
52
|
+
.venv/
|
|
53
|
+
.envrc
|
acj-0.1.0/CMakeLists.txt
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.15)
|
|
2
|
+
project(acj_project LANGUAGES CXX)
|
|
3
|
+
|
|
4
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
5
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
6
|
+
|
|
7
|
+
if(NOT CMAKE_BUILD_TYPE)
|
|
8
|
+
set(CMAKE_BUILD_TYPE Release)
|
|
9
|
+
endif()
|
|
10
|
+
|
|
11
|
+
find_package(Python3 COMPONENTS Interpreter Development.Module REQUIRED)
|
|
12
|
+
find_package(pybind11 CONFIG REQUIRED)
|
|
13
|
+
|
|
14
|
+
# Use FetchContent to extract the local CGAL tarball during build
|
|
15
|
+
include(FetchContent)
|
|
16
|
+
FetchContent_Declare(
|
|
17
|
+
CGAL
|
|
18
|
+
URL https://github.com/CGAL/cgal/releases/download/v6.0.1/CGAL-6.0.1.tar.xz
|
|
19
|
+
)
|
|
20
|
+
FetchContent_Populate(CGAL)
|
|
21
|
+
|
|
22
|
+
# PATCH CGAL BUG in AABB_traits_2.h
|
|
23
|
+
file(READ "${cgal_SOURCE_DIR}/include/CGAL/AABB_traits_2.h" AABB_TRAITS_CONTENT)
|
|
24
|
+
string(REPLACE "bb,true)?" "bb)?" AABB_TRAITS_CONTENT "${AABB_TRAITS_CONTENT}")
|
|
25
|
+
file(WRITE "${cgal_SOURCE_DIR}/include/CGAL/AABB_traits_2.h" "${AABB_TRAITS_CONTENT}")
|
|
26
|
+
# CGAL is header-only from 5.0+, just add the include directories
|
|
27
|
+
add_library(CGAL::CGAL INTERFACE IMPORTED)
|
|
28
|
+
target_include_directories(CGAL::CGAL INTERFACE "${cgal_SOURCE_DIR}/include")
|
|
29
|
+
|
|
30
|
+
# Find Boost (strictly required by CGAL)
|
|
31
|
+
if(NOT WIN32)
|
|
32
|
+
find_package(Boost REQUIRED)
|
|
33
|
+
endif()
|
|
34
|
+
|
|
35
|
+
if(WIN32)
|
|
36
|
+
# === WINDOWS LOGIC ===
|
|
37
|
+
# Include vcpkg globally for gmp/mpfr and EXACTLY inject Boost include path like the experiment!
|
|
38
|
+
include_directories("C:/vcpkg/installed/x64-windows/include")
|
|
39
|
+
|
|
40
|
+
find_library(GMP_LIBRARY gmp PATHS "C:/vcpkg/installed/x64-windows/lib" NO_DEFAULT_PATH)
|
|
41
|
+
find_library(MPFR_LIBRARY mpfr PATHS "C:/vcpkg/installed/x64-windows/lib" NO_DEFAULT_PATH)
|
|
42
|
+
if(GMP_LIBRARY AND MPFR_LIBRARY)
|
|
43
|
+
target_link_libraries(CGAL::CGAL INTERFACE ${GMP_LIBRARY} ${MPFR_LIBRARY})
|
|
44
|
+
endif()
|
|
45
|
+
|
|
46
|
+
elseif(APPLE)
|
|
47
|
+
# === MACOS LOGIC ===
|
|
48
|
+
if(TARGET Boost::headers)
|
|
49
|
+
target_link_libraries(CGAL::CGAL INTERFACE Boost::headers)
|
|
50
|
+
elseif(TARGET Boost::boost)
|
|
51
|
+
target_link_libraries(CGAL::CGAL INTERFACE Boost::boost)
|
|
52
|
+
elseif(Boost_INCLUDE_DIRS)
|
|
53
|
+
target_include_directories(CGAL::CGAL INTERFACE "${Boost_INCLUDE_DIRS}")
|
|
54
|
+
endif()
|
|
55
|
+
|
|
56
|
+
find_library(GMP_LIBRARY gmp)
|
|
57
|
+
find_library(MPFR_LIBRARY mpfr)
|
|
58
|
+
if(GMP_LIBRARY AND MPFR_LIBRARY)
|
|
59
|
+
target_link_libraries(CGAL::CGAL INTERFACE ${GMP_LIBRARY} ${MPFR_LIBRARY})
|
|
60
|
+
endif()
|
|
61
|
+
|
|
62
|
+
else()
|
|
63
|
+
# === LINUX (UBUNTU) LOGIC ===
|
|
64
|
+
if(TARGET Boost::headers)
|
|
65
|
+
target_link_libraries(CGAL::CGAL INTERFACE Boost::headers)
|
|
66
|
+
elseif(TARGET Boost::boost)
|
|
67
|
+
target_link_libraries(CGAL::CGAL INTERFACE Boost::boost)
|
|
68
|
+
elseif(Boost_INCLUDE_DIRS)
|
|
69
|
+
target_include_directories(CGAL::CGAL INTERFACE "${Boost_INCLUDE_DIRS}")
|
|
70
|
+
endif()
|
|
71
|
+
|
|
72
|
+
find_library(GMP_LIBRARY gmp)
|
|
73
|
+
find_library(MPFR_LIBRARY mpfr)
|
|
74
|
+
if(GMP_LIBRARY AND MPFR_LIBRARY)
|
|
75
|
+
target_link_libraries(CGAL::CGAL INTERFACE ${GMP_LIBRARY} ${MPFR_LIBRARY})
|
|
76
|
+
endif()
|
|
77
|
+
endif()
|
|
78
|
+
|
|
79
|
+
add_compile_definitions(CGAL_DO_NOT_USE_BOOST_MP)
|
|
80
|
+
add_subdirectory(src/acj/core)
|
acj-0.1.0/Dockerfile
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
FROM ubuntu:jammy
|
|
2
|
+
|
|
3
|
+
ARG DEBIAN_FRONTEND=noninteractive
|
|
4
|
+
ARG uid
|
|
5
|
+
ARG gid
|
|
6
|
+
ARG user
|
|
7
|
+
ARG group
|
|
8
|
+
|
|
9
|
+
RUN apt-get update
|
|
10
|
+
RUN apt-get install -y tzdata
|
|
11
|
+
RUN apt-get upgrade -y
|
|
12
|
+
|
|
13
|
+
RUN echo 'alias ll="ls -l --color -a"' >> /root/.bashrc
|
|
14
|
+
|
|
15
|
+
RUN apt-get install -y python3 python3-pip python3-dev
|
|
16
|
+
RUN apt-get install -y build-essential cmake git pkg-config
|
|
17
|
+
RUN apt-get install -y pybind11-dev
|
|
18
|
+
|
|
19
|
+
RUN apt-get install -y xz-utils
|
|
20
|
+
RUN apt-get install -y g++
|
|
21
|
+
RUN apt-get install -y libboost-all-dev
|
|
22
|
+
RUN apt-get install -y libgmp-dev
|
|
23
|
+
RUN apt-get install -y libmpfr-dev
|
|
24
|
+
|
|
25
|
+
RUN apt-get install -y libcgal-dev
|
|
26
|
+
|
|
27
|
+
RUN mkdir -p /tmp/cgal
|
|
28
|
+
COPY CGAL-6.0.1.tar.xz /tmp/cgal/
|
|
29
|
+
RUN cd /tmp/cgal && tar -xf CGAL-6.0.1.tar.xz
|
|
30
|
+
RUN cd /tmp/cgal/CGAL-6.0.1 && mkdir -p build
|
|
31
|
+
RUN cd /tmp/cgal/CGAL-6.0.1/build && cmake ..
|
|
32
|
+
RUN cd /tmp/cgal/CGAL-6.0.1/build && make install
|
|
33
|
+
RUN rm -rf /tmp/cgal
|
|
34
|
+
|
|
35
|
+
RUN apt-get install -y libspatialindex-dev libgeos-dev libproj-dev
|
|
36
|
+
|
|
37
|
+
RUN apt-get install -y libgl1-mesa-glx libglib2.0-0 libsm6 libxrender1 libxext6 libfontconfig1
|
|
38
|
+
RUN apt-get install -y python3-pyqt5 python3-pyqt5.qtopengl
|
|
39
|
+
|
|
40
|
+
RUN rm -rf /var/lib/apt/lists/*
|
|
41
|
+
|
|
42
|
+
RUN mkdir -p /workspace
|
|
43
|
+
|
|
44
|
+
RUN groupadd -g ${gid} ${group} || true
|
|
45
|
+
RUN useradd -m -u ${uid} -g ${gid} -s /bin/bash ${user} || true
|
|
46
|
+
|
|
47
|
+
RUN echo 'alias ll="ls -l --color -a"' >> /home/${user}/.bashrc || true
|
|
48
|
+
|
|
49
|
+
RUN chown -R ${uid}:${gid} /workspace
|
|
50
|
+
|
|
51
|
+
USER ${user}
|
|
52
|
+
WORKDIR /workspace
|
|
53
|
+
|
|
54
|
+
COPY --chown=${user}:${group} . /workspace/
|
|
55
|
+
|
|
56
|
+
RUN pip3 install -r requirements.txt
|
|
57
|
+
|
|
58
|
+
RUN mkdir -p build
|
|
59
|
+
WORKDIR /workspace/build
|
|
60
|
+
RUN cmake .. && make -j$(nproc)
|
|
61
|
+
|
|
62
|
+
WORKDIR /workspace
|
acj-0.1.0/Makefile
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
.PHONY: build shell shell-user test example example-realtime example-simplification example-simplification-visual example-crime example-crime-osm example-simplification-osm example-minkowski-osm clean clean-all help
|
|
2
|
+
|
|
3
|
+
.DEFAULT_GOAL := help
|
|
4
|
+
|
|
5
|
+
help:
|
|
6
|
+
@echo "ACJ Library - Makefile Commands"
|
|
7
|
+
@echo "================================"
|
|
8
|
+
@echo ""
|
|
9
|
+
@echo "Main commands:"
|
|
10
|
+
@echo " make build - Build Docker image with all dependencies"
|
|
11
|
+
@echo " make test - Run ACJ library tests"
|
|
12
|
+
@echo ""
|
|
13
|
+
@echo "Examples with synthetic data:"
|
|
14
|
+
@echo " make example - Basic ACJ example"
|
|
15
|
+
@echo " make example-simplification-visual - Graph simplification demo (synthetic)"
|
|
16
|
+
@echo " make example-crime - Crime heatmap demo (synthetic)"
|
|
17
|
+
@echo ""
|
|
18
|
+
@echo "Examples with real OSM data (configurable city):"
|
|
19
|
+
@echo " make example-realtime - Real-time crime heatmap"
|
|
20
|
+
@echo " make example-simplification - Graph simplification comparison"
|
|
21
|
+
@echo " make example-minkowski-osm - Minkowski simplification (configurable location)"
|
|
22
|
+
@echo " make example-crime-osm - Crime heatmap (configurable location)"
|
|
23
|
+
@echo " make example-simplification-osm - Simplification (configurable location)"
|
|
24
|
+
@echo ""
|
|
25
|
+
@echo "Cleanup commands:"
|
|
26
|
+
@echo " make clean - Clean build artifacts"
|
|
27
|
+
@echo " make clean-all - Clean everything including Docker cache"
|
|
28
|
+
@echo ""
|
|
29
|
+
@echo "Development commands:"
|
|
30
|
+
@echo " make shell - Open Docker shell as root"
|
|
31
|
+
@echo " make shell-user - Open Docker shell as user"
|
|
32
|
+
|
|
33
|
+
# Build Docker image
|
|
34
|
+
build:
|
|
35
|
+
docker build -f Dockerfile -t ubuntu-acj:1 --build-arg uid="$(shell id -u)" --build-arg gid="$(shell id -g)" --build-arg user=dockeruser --build-arg group=dockergroup .
|
|
36
|
+
|
|
37
|
+
# Interactive shells
|
|
38
|
+
shell:
|
|
39
|
+
docker run -v $(shell pwd):/workspace -w /workspace -it ubuntu-acj:1 /bin/bash
|
|
40
|
+
|
|
41
|
+
shell-user:
|
|
42
|
+
docker run --user $(shell id -u):$(shell id -g) -v $(shell pwd):/workspace -w /workspace -it ubuntu-acj:1 /bin/bash
|
|
43
|
+
|
|
44
|
+
# ACJ Library commands (Actualizado para Arquitectura src/)
|
|
45
|
+
test: ## Run ACJ library test suite
|
|
46
|
+
docker run --user $(shell id -u):$(shell id -g) -v $(shell pwd):/workspace ubuntu-acj:1 sh -c "cd /workspace && mkdir -p build && cd build && cmake .. && make -j\$$(nproc) && cd .. && PYTHONPATH=/workspace/build:/workspace/src python3 -m pytest tests/ -v"
|
|
47
|
+
|
|
48
|
+
example: ## Run basic ACJ library example
|
|
49
|
+
docker run --user $(shell id -u):$(shell id -g) -v $(shell pwd):/workspace ubuntu-acj:1 sh -c "cd /workspace && mkdir -p build && cd build && cmake .. && make -j\$$(nproc) && cd .. && PYTHONPATH=/workspace/build:/workspace/src python3 examples/example_acj.py"
|
|
50
|
+
|
|
51
|
+
example-realtime: ## Run real-time interactive visualization with VisPy
|
|
52
|
+
docker run --user $(shell id -u):$(shell id -g) -v $(shell pwd):/workspace -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$$DISPLAY ubuntu-acj:1 sh -c "cd /workspace && mkdir -p build && cd build && cmake .. && make -j\$$(nproc) && cd .. && PYTHONPATH=/workspace/build:/workspace/src python3 examples/example_realtime.py"
|
|
53
|
+
|
|
54
|
+
example-simplification: ## Run graph simplification comparison
|
|
55
|
+
docker run --user $(shell id -u):$(shell id -g) -v $(shell pwd):/workspace -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$$DISPLAY ubuntu-acj:1 sh -c "cd /workspace && mkdir -p build && cd build && cmake .. && make -j\$$(nproc) && cd .. && PYTHONPATH=/workspace/build:/workspace/src python3 examples/example_simplification.py"
|
|
56
|
+
|
|
57
|
+
example-simplification-visual: ## Run visual graph simplification demo with interactive comparison
|
|
58
|
+
docker run --user $(shell id -u):$(shell id -g) -v $(shell pwd):/workspace -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$$DISPLAY ubuntu-acj:1 sh -c "cd /workspace && mkdir -p build && cd build && cmake .. && make -j\$$(nproc) && cd .. && PYTHONPATH=/workspace/build:/workspace/src python3 examples/example_simplification_visual.py"
|
|
59
|
+
|
|
60
|
+
example-crime: ## Run crime heatmap visualization demo with interactive comparison
|
|
61
|
+
docker run --user $(shell id -u):$(shell id -g) -v $(shell pwd):/workspace -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$$DISPLAY ubuntu-acj:1 sh -c "cd /workspace && mkdir -p build && cd build && cmake .. && make -j\$$(nproc) && cd .. && PYTHONPATH=/workspace/build:/workspace/src python3 examples/example_crime_visualization.py"
|
|
62
|
+
|
|
63
|
+
example-crime-osm: ## Run crime heatmap with real OSM data (configurable location)
|
|
64
|
+
docker run --user $(shell id -u):$(shell id -g) -v $(shell pwd):/workspace -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$$DISPLAY ubuntu-acj:1 sh -c "cd /workspace && mkdir -p build && cd build && cmake .. && make -j\$$(nproc) && cd .. && PYTHONPATH=/workspace/build:/workspace/src python3 examples/example_crime_osm.py"
|
|
65
|
+
|
|
66
|
+
example-simplification-osm: ## Run simplification comparison with real OSM data (configurable location)
|
|
67
|
+
docker run --user $(shell id -u):$(shell id -g) -v $(shell pwd):/workspace -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$$DISPLAY ubuntu-acj:1 sh -c "cd /workspace && mkdir -p build && cd build && cmake .. && make -j\$$(nproc) && cd .. && PYTHONPATH=/workspace/build:/workspace/src python3 examples/example_simplification_osm.py"
|
|
68
|
+
|
|
69
|
+
example-minkowski-osm: ## Run Minkowski simplification with real OSM data (configurable location)
|
|
70
|
+
docker run --user $(shell id -u):$(shell id -g) -v $(shell pwd):/workspace -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$$DISPLAY ubuntu-acj:1 sh -c "cd /workspace && mkdir -p build && cd build && cmake .. && make -j\$$(nproc) && cd .. && PYTHONPATH=/workspace/build:/workspace/src python3 examples/example_minkowski_osm.py"
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
# Cleanup
|
|
74
|
+
clean: ## Clean build artifacts
|
|
75
|
+
rm -rf build/ cache/ output/
|
|
76
|
+
|
|
77
|
+
clean-all: ## Clean everything including Docker cache
|
|
78
|
+
rm -rf build/ cache/ output/
|
|
79
|
+
docker rmi ubuntu-acj:1 || true
|
acj-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: acj
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Simplificacion de grafos urbanos y analisis de criminalidad
|
|
5
|
+
Author-Email: Alejandro <alejandro.calizaya@utec.edu.pe>, Cesar <cesar.perales@utec.edu.pe>, Jerimy <jerimy.sandoval@utec.edu.pe>
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Requires-Dist: pybind11
|
|
8
|
+
Requires-Dist: numpy
|
|
9
|
+
Requires-Dist: pandas
|
|
10
|
+
Requires-Dist: osmnx
|
|
11
|
+
Requires-Dist: vispy
|
|
12
|
+
Requires-Dist: PyQt5
|
|
13
|
+
Requires-Dist: pytest
|
|
14
|
+
Requires-Dist: geopandas
|
|
15
|
+
Requires-Dist: networkx
|
|
16
|
+
|
acj-0.1.0/README.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# ACJ: Urban Graph Acceleration & Simplification Framework
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
**ACJ** is a high-performance hybrid framework (C++/Python) designed for the semantic and topological simplification of large-scale urban networks. It safely decouples complex geometric operations from semantic data attributes, ensuring that metadata (e.g., speed limits, road names) survives massive graph reductions.
|
|
9
|
+
|
|
10
|
+
## System Architecture
|
|
11
|
+
|
|
12
|
+
The core philosophy of ACJ relies on treating `UrbanNetwork` as an invariant Registry/Proxy. Heavy geometric simplifications are sent to a highly optimized C++ core using CGAL. The core returns the simplified topology alongside strict lineage maps, which Python then uses to reconstruct and resolve semantic collisions.
|
|
13
|
+
|
|
14
|
+
```mermaid
|
|
15
|
+
graph TD
|
|
16
|
+
subgraph Inputs ["Multimodal Inputs"]
|
|
17
|
+
A1[OSMnx]
|
|
18
|
+
A2[DataFrames]
|
|
19
|
+
A3[Shapefiles]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
A1 -->|from_networkx| B
|
|
23
|
+
A2 -->|from_dataframe| B
|
|
24
|
+
A3 -->|Parsers| B
|
|
25
|
+
|
|
26
|
+
subgraph Python ["Python Layer"]
|
|
27
|
+
B[UrbanNetwork <br/> Registry/Proxy]
|
|
28
|
+
E[Semantic Resolution <br/> Metadata Fusion]
|
|
29
|
+
F[Metrics & Evaluator]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
subgraph Cpp ["C++ Core (CGAL/pybind11)"]
|
|
33
|
+
C[Raw Topology <br/> V, E matrices]
|
|
34
|
+
D[Geometric & Topological <br/> Simplification Algorithms]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
B -.->|Passes Topology| C
|
|
38
|
+
C --> D
|
|
39
|
+
D -.->|SimplificationResult <br/> Topology + Lineage Maps| E
|
|
40
|
+
B -.->|Passes Metadata| E
|
|
41
|
+
|
|
42
|
+
E -->|Resolved UrbanNetwork| F
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Installation Guide
|
|
46
|
+
|
|
47
|
+
### Prerequisites
|
|
48
|
+
You need a system with C++17 support, CMake, and the following libraries:
|
|
49
|
+
- **CGAL** (Computational Geometry Algorithms Library)
|
|
50
|
+
- **Boost**
|
|
51
|
+
- **pybind11**
|
|
52
|
+
|
|
53
|
+
On Ubuntu/Debian:
|
|
54
|
+
```bash
|
|
55
|
+
sudo apt-get update
|
|
56
|
+
sudo apt-get install cmake libcgal-dev libboost-all-dev
|
|
57
|
+
```
|
|
58
|
+
On Arch Linux:
|
|
59
|
+
```bash
|
|
60
|
+
sudo pacman -S cmake cgal boost pybind11
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Building the Package
|
|
64
|
+
We highly recommend setting up a virtual environment:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
python -m venv venv
|
|
68
|
+
source venv/bin/activate
|
|
69
|
+
pip install -U pip setuptools wheel
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Install the package in editable mode (which will trigger CMake build):
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pip install -e .
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Quick Start (E2E Pipeline)
|
|
79
|
+
|
|
80
|
+
This demonstrates the end-to-end pipeline: extracting raw data, parsing, executing a highly optimized topological simplification, and calculating compression metrics.
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
import osmnx as ox
|
|
84
|
+
from acj import UrbanNetwork, ACJTopologicalEvaluator
|
|
85
|
+
from acj import CompressionRatioMetric, SemanticSpeedDistortionMetric
|
|
86
|
+
|
|
87
|
+
# 1. Ingest Data (Raw Graph)
|
|
88
|
+
G = ox.graph_from_place("Barranco, Lima, Peru", network_type="drive")
|
|
89
|
+
|
|
90
|
+
# 2. Parse into Multimodal Registry
|
|
91
|
+
network = UrbanNetwork.from_networkx(G)
|
|
92
|
+
print("Initial:", network)
|
|
93
|
+
|
|
94
|
+
# 3. Setup Metrics and Evaluator
|
|
95
|
+
metrics = [CompressionRatioMetric(), SemanticSpeedDistortionMetric()]
|
|
96
|
+
evaluator = ACJTopologicalEvaluator(network, metrics)
|
|
97
|
+
|
|
98
|
+
# 4. Evaluate (C++ Topo Simplification + Semantic Resolution)
|
|
99
|
+
results = evaluator.evaluate()
|
|
100
|
+
|
|
101
|
+
print("Results:", results)
|
|
102
|
+
print("Simplified:", evaluator.simplified_network)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Module Structure (API Reference)
|
|
106
|
+
|
|
107
|
+
### `acj.core` (The Heart of the Framework)
|
|
108
|
+
This module acts as the central orchestrator for data decoupling.
|
|
109
|
+
- **`UrbanNetwork`**: The fundamental data structure of the library. It stores raw network topologies in heavily optimized Pandas DataFrames alongside dictionaries of semantic metadata. Supports multimodal ingestion from `NetworkX`, `osmnx`, or arbitrary DataFrames.
|
|
110
|
+
- **`resolve_semantics()`**: The pure Python metadata fusion engine. When a graph is collapsed by C++, this function takes the topological lineage map and automatically resolves semantic collisions (e.g., averaging max speeds or concatenating street names) to keep information loss at 0.
|
|
111
|
+
|
|
112
|
+
### `acj.algorithms` (Python Wrappers & Indexing)
|
|
113
|
+
- **`graph` / `minkowski`**: Wrappers for invoking our low-level C++ simplification procedures. Here you'll find interfaces for topological simplifications, geometric clustering, Minkowski-sum reductions, and more.
|
|
114
|
+
- **`MapIndex`**: An advanced spatial querying interface wrapping CGAL spatial trees, enabling fast nearest-neighbor point-to-graph assignments (essential for crime mapping or event correlation on large networks).
|
|
115
|
+
|
|
116
|
+
### `acj.data` (Data Binding & IO)
|
|
117
|
+
- **`SimplificationResult`**: The critical struct generated and bound directly from pybind11. It holds the new `GraphData` topology alongside `.node_lineage` and `.edge_lineage` dictionaries linking new entities back to their original IDs.
|
|
118
|
+
- **`GraphData`**: Internal lightweight wrapper handling node/edge validations before passing arrays down to C++.
|
|
119
|
+
|
|
120
|
+
### `acj.evaluation` (Research & Metrics Engine)
|
|
121
|
+
- **`BaseEvaluator` / `ACJTopologicalEvaluator`**: Automates the simplification lifecycle. These evaluators accept a raw `UrbanNetwork`, inject it into C++ for reduction, apply the semantic resolution layer, and systematically test the results against predefined metrics.
|
|
122
|
+
- **`CompressionRatioMetric` / `SemanticSpeedDistortionMetric`**: Pluggable metrics allowing researchers to quantitatively evaluate exactly how much data is compressed and what percentage of the semantic truth (like speed distributions) is distorted during network abstraction.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Example usage of the ACJ library.
|
|
3
|
+
|
|
4
|
+
This example demonstrates how to:
|
|
5
|
+
1. Load graph data from pandas DataFrames
|
|
6
|
+
2. Create a MapIndex for spatial queries
|
|
7
|
+
3. Assign points to nearest graph endpoints (nodes)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import sys
|
|
11
|
+
import os
|
|
12
|
+
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
|
|
13
|
+
|
|
14
|
+
import acj
|
|
15
|
+
import pandas as pd
|
|
16
|
+
import numpy as np
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def main():
|
|
20
|
+
print("=" * 70)
|
|
21
|
+
print("ACJ Library - Example Usage")
|
|
22
|
+
print("=" * 70)
|
|
23
|
+
print()
|
|
24
|
+
|
|
25
|
+
# Step 1: Create sample graph data (simple street network)
|
|
26
|
+
print("[1/4] Creating sample graph data...")
|
|
27
|
+
print()
|
|
28
|
+
|
|
29
|
+
nodes = pd.DataFrame({
|
|
30
|
+
'node_id': [0, 1, 2, 3, 4],
|
|
31
|
+
'x': [0.0, 100.0, 200.0, 300.0, 150.0],
|
|
32
|
+
'y': [0.0, 0.0, 100.0, 0.0, 100.0]
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
segments = pd.DataFrame({
|
|
36
|
+
'segment_id': [0, 1, 2, 3],
|
|
37
|
+
'node_start': [0, 1, 2, 3],
|
|
38
|
+
'node_end': [1, 2, 4, 4],
|
|
39
|
+
'x1': [0.0, 100.0, 200.0, 300.0],
|
|
40
|
+
'y1': [0.0, 0.0, 100.0, 0.0],
|
|
41
|
+
'x2': [100.0, 200.0, 150.0, 150.0],
|
|
42
|
+
'y2': [0.0, 100.0, 100.0, 100.0]
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
print(f" Nodes: {len(nodes)}")
|
|
46
|
+
print(f" Segments: {len(segments)}")
|
|
47
|
+
print()
|
|
48
|
+
|
|
49
|
+
# Step 2: Load graph using ACJ
|
|
50
|
+
print("[2/4] Loading graph data...")
|
|
51
|
+
graph = acj.load_graph(nodes, segments)
|
|
52
|
+
print(f" Graph loaded: {graph}")
|
|
53
|
+
print()
|
|
54
|
+
|
|
55
|
+
# Step 3: Create MapIndex
|
|
56
|
+
print("[3/4] Building spatial index...")
|
|
57
|
+
map_index = acj.MapIndex(graph)
|
|
58
|
+
print(f" MapIndex created: {map_index}")
|
|
59
|
+
print()
|
|
60
|
+
|
|
61
|
+
# Step 4: Create sample points (e.g., crime locations)
|
|
62
|
+
print("[4/4] Assigning sample points to nearest nodes...")
|
|
63
|
+
print()
|
|
64
|
+
|
|
65
|
+
points = pd.DataFrame({
|
|
66
|
+
'point_id': [0, 1, 2, 3, 4],
|
|
67
|
+
'x': [10.0, 105.0, 195.0, 290.0, 155.0],
|
|
68
|
+
'y': [5.0, 10.0, 95.0, 5.0, 90.0],
|
|
69
|
+
'crime_type': ['robbery', 'assault', 'theft', 'vandalism', 'burglary']
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
print("Sample points to assign:")
|
|
73
|
+
print(points)
|
|
74
|
+
print()
|
|
75
|
+
|
|
76
|
+
# Perform assignment
|
|
77
|
+
print("Performing endpoint assignment...")
|
|
78
|
+
assignments = map_index.assign_to_endpoints(points)
|
|
79
|
+
|
|
80
|
+
print()
|
|
81
|
+
print("Assignment results:")
|
|
82
|
+
print(assignments[['point_id', 'crime_type', 'assigned_node_id', 'distance']])
|
|
83
|
+
print()
|
|
84
|
+
|
|
85
|
+
# Summary statistics
|
|
86
|
+
print("=" * 70)
|
|
87
|
+
print("Summary Statistics")
|
|
88
|
+
print("=" * 70)
|
|
89
|
+
print(f"Total points assigned: {len(assignments)}")
|
|
90
|
+
print(f"Average distance: {assignments['distance'].mean():.2f} meters")
|
|
91
|
+
print(f"Max distance: {assignments['distance'].max():.2f} meters")
|
|
92
|
+
print(f"Min distance: {assignments['distance'].min():.2f} meters")
|
|
93
|
+
print()
|
|
94
|
+
|
|
95
|
+
# Distribution by node
|
|
96
|
+
print("Points per node:")
|
|
97
|
+
node_counts = assignments['assigned_node_id'].value_counts().sort_index()
|
|
98
|
+
for node_id, count in node_counts.items():
|
|
99
|
+
print(f" Node {node_id}: {count} points")
|
|
100
|
+
print()
|
|
101
|
+
|
|
102
|
+
print("=" * 70)
|
|
103
|
+
print("Example completed successfully!")
|
|
104
|
+
print("=" * 70)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
if __name__ == "__main__":
|
|
108
|
+
main()
|