├── .github └── workflows │ ├── publish-test.yml │ └── publish.yml ├── .gitignore ├── .gitmodules ├── .travis.yml ├── C++ ├── PyEvolutionModel.hpp ├── PyMLNetwork.hpp ├── main.cpp ├── py_functions.hpp ├── py_functions1.cpp ├── py_functions2.cpp ├── pycpp_utils.cpp └── pycpp_utils.hpp ├── CMakeLists.txt ├── DESCRIPTION.md ├── LICENSE ├── MANIFEST.in ├── NEWS ├── README.md ├── pyproject.toml ├── setup.py ├── tutorial ├── README.md ├── example1.txt ├── example2.txt ├── example_igraph1.dat ├── example_igraph2.dat ├── py_multinet.ipynb ├── py_multinet.pdf └── py_multinet.pptx └── uunet ├── __init__.py ├── data ├── aucs.mpx ├── bankwiring.mpx ├── book.mpx ├── florentine.mpx ├── monastery.mpx └── tailorshop.mpx └── multinet.py /.github/workflows/publish-test.yml: -------------------------------------------------------------------------------- 1 | name: build package and upload to TestPyPI 2 | 3 | on: [workflow_dispatch] 4 | 5 | jobs: 6 | build_sdist: 7 | name: Build source dist 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout library 11 | uses: actions/checkout@v4 12 | with: 13 | submodules: true 14 | 15 | - name: Set up Python 16 | uses: actions/setup-python@v5 17 | 18 | - name: Install dependencies 19 | run: python -m pip install build twine 20 | 21 | - name: Build 22 | run: python -m build --sdist 23 | 24 | - name: Check metadata 25 | run: python -m twine check dist/* 26 | 27 | - uses: actions/upload-artifact@v4 28 | with: 29 | name: cibw-sdist 30 | path: dist/*.tar.gz 31 | 32 | 33 | build_wheels: 34 | name: Wheels on ${{ matrix.os }} 35 | runs-on: ${{ matrix.os }} 36 | strategy: 37 | fail-fast: false 38 | matrix: 39 | os: [ubuntu-latest, macos-13, macos-14] 40 | steps: 41 | - name: Checkout library 42 | uses: actions/checkout@v4 43 | with: 44 | submodules: true 45 | 46 | - name: Set up Python 47 | uses: actions/setup-python@v5 48 | with: 49 | python-version: 3.8 50 | if: runner.os == 'macOS' && runner.arch == 'ARM64' 51 | 52 | - name: Install cibuildwheel 53 | run: python -m pip install cibuildwheel==2.19.2 54 | 55 | - name: Build wheels 56 | run: python -m cibuildwheel --output-dir wheelhouse 57 | env: 58 | CIBW_ENVIRONMENT: MACOSX_DEPLOYMENT_TARGET=10.13 59 | #CIBW_REPAIR_WHEEL_COMMAND_MACOS: DYLD_LIBRARY_PATH=$REPAIR_LIBRARY_PATH delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel} 60 | #CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: "pip install delvewheel && delvewheel repair --add-path . -vv -w {dest_dir} {wheel}" 61 | 62 | - uses: actions/upload-artifact@v4 63 | with: 64 | name: cibw-wheels-${{ matrix.os }} 65 | path: wheelhouse/*.whl 66 | 67 | build_windows_wheels: 68 | name: Wheels on windows-latest ${{ matrix.py_version }} 69 | runs-on: windows-latest 70 | strategy: 71 | fail-fast: false 72 | matrix: 73 | py_version: ['3.8', '3.9', '3.10', '3.11', '3.12'] 74 | 75 | steps: 76 | - name: Checkout library 77 | uses: actions/checkout@v4 78 | with: 79 | submodules: true 80 | 81 | - name: Set up Python 82 | uses: actions/setup-python@v5 83 | with: 84 | python-version: ${{ matrix.py_version }} 85 | 86 | - run: python -m pip wheel . 87 | 88 | - run: mkdir wheelhouse && Move-Item uunet*.whl wheelhouse/ 89 | 90 | - uses: actions/upload-artifact@v4 91 | with: 92 | name: cibw-wheels-win-${{ matrix.py_version }} 93 | path: wheelhouse/*.whl 94 | 95 | 96 | pypi-publish-test: 97 | name: upload release to TestPyPI 98 | needs: 99 | - build_sdist 100 | - build_wheels 101 | - build_windows_wheels 102 | runs-on: ubuntu-latest 103 | environment: release-test 104 | permissions: 105 | id-token: write 106 | steps: 107 | - name: Download artifact 108 | uses: actions/download-artifact@v4 109 | with: 110 | pattern: cibw-* 111 | path: dist 112 | merge-multiple: true 113 | - name: Publish 114 | uses: pypa/gh-action-pypi-publish@release/v1 115 | with: 116 | repository-url: https://test.pypi.org/legacy/ 117 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: build package and upload to PyPI 2 | 3 | on: [workflow_dispatch] 4 | 5 | jobs: 6 | build_sdist: 7 | name: Build source dist 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout library 11 | uses: actions/checkout@v4 12 | with: 13 | submodules: true 14 | 15 | - name: Set up Python 16 | uses: actions/setup-python@v5 17 | 18 | - name: Install dependencies 19 | run: python -m pip install build twine 20 | 21 | - name: Build 22 | run: python -m build --sdist 23 | 24 | - name: Check metadata 25 | run: python -m twine check dist/* 26 | 27 | - uses: actions/upload-artifact@v4 28 | with: 29 | name: cibw-sdist 30 | path: dist/*.tar.gz 31 | 32 | 33 | build_wheels: 34 | name: Wheels on ${{ matrix.os }} 35 | runs-on: ${{ matrix.os }} 36 | strategy: 37 | fail-fast: false 38 | matrix: 39 | os: [ubuntu-latest, macos-13, macos-14] 40 | steps: 41 | - name: Checkout library 42 | uses: actions/checkout@v4 43 | with: 44 | submodules: true 45 | 46 | - name: Set up Python 47 | uses: actions/setup-python@v5 48 | with: 49 | python-version: 3.8 50 | if: runner.os == 'macOS' && runner.arch == 'ARM64' 51 | 52 | - name: Install cibuildwheel 53 | run: python -m pip install cibuildwheel==2.19.2 54 | 55 | - name: Build wheels 56 | run: python -m cibuildwheel --output-dir wheelhouse 57 | env: 58 | CIBW_ENVIRONMENT: MACOSX_DEPLOYMENT_TARGET=10.13 59 | 60 | - uses: actions/upload-artifact@v4 61 | with: 62 | name: cibw-wheels-${{ matrix.os }} 63 | path: wheelhouse/*.whl 64 | 65 | build_windows_wheels: 66 | name: Wheels on windows-latest ${{ matrix.py_version }} 67 | runs-on: windows-latest 68 | strategy: 69 | fail-fast: false 70 | matrix: 71 | py_version: ['3.8', '3.9', '3.10', '3.11', '3.12'] 72 | 73 | steps: 74 | - name: Checkout library 75 | uses: actions/checkout@v4 76 | with: 77 | submodules: true 78 | 79 | - name: Set up Python 80 | uses: actions/setup-python@v5 81 | with: 82 | python-version: ${{ matrix.py_version }} 83 | 84 | - run: python -m pip wheel . 85 | 86 | - run: mkdir wheelhouse && Move-Item uunet*.whl wheelhouse/ 87 | 88 | - uses: actions/upload-artifact@v4 89 | with: 90 | name: cibw-wheels-win-${{ matrix.py_version }} 91 | path: wheelhouse/*.whl 92 | 93 | 94 | pypi-publish: 95 | name: upload release to PyPI 96 | needs: 97 | - build_sdist 98 | - build_wheels 99 | - build_windows_wheels 100 | runs-on: ubuntu-latest 101 | environment: release 102 | permissions: 103 | id-token: write 104 | steps: 105 | - name: Download artifact 106 | uses: actions/download-artifact@v4 107 | with: 108 | pattern: cibw-* 109 | path: dist 110 | merge-multiple: true 111 | - name: Publish 112 | uses: pypa/gh-action-pypi-publish@release/v1 113 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | build 3 | dist 4 | uunet.egg-info/ 5 | __pycache__/ 6 | ve*/ 7 | ^PyPI*txt 8 | ^TestPyPI*txt 9 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ext/uunet"] 2 | path = ext/uunet 3 | url = https://github.com/uuinfolab/uunet.git 4 | [submodule "ext/pybind11"] 5 | path = ext/pybind11 6 | url = https://github.com/pybind/pybind11 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: linux 2 | dist: focal 3 | language: python 4 | 5 | jobs: 6 | include: 7 | # perform a linux build 8 | # - services: docker 9 | # perform a linux ARMv8 build 10 | # - services: docker 11 | # arch: arm64 12 | # perform a linux PPC64LE build 13 | # - services: docker 14 | # arch: ppc64le 15 | # perform a linux S390X build 16 | # - services: docker 17 | # arch: s390x 18 | # and a mac build 19 | # - os: osx 20 | # language: shell 21 | # and a windows build 22 | - os: windows 23 | language: shell 24 | before_install: 25 | - choco upgrade python -y --version 3.8.6 26 | - export PATH="/c/Python38:/c/Python38/Scripts:$PATH" 27 | # make sure it's on PATH as 'python3' 28 | - ln -s /c/Python38/python.exe /c/Python38/python3.exe 29 | 30 | env: 31 | global: 32 | - TRAVIS_PYTHON_VERSION="3.8" 33 | - CIBW_BUILD="cp38-*" 34 | - CIBW_BUILD_VERBOSITY=3 35 | - BUILD_OUTPUT_PATH="$(uname | perl -ne 'print lc')-uunet-wheels" 36 | 37 | 38 | 39 | install: 40 | - python3 -m pip install cibuildwheel==1.11.0 41 | #2.0.0a2 42 | 43 | script: 44 | - cibuildwheel --output-dir $BUILD_OUTPUT_PATH 45 | - echo "OK" 46 | -------------------------------------------------------------------------------- /C++/PyEvolutionModel.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef UU_MULTINET_PYEVOLUTIONMODEL_H_ 3 | #define UU_MULTINET_PYEVOLUTIONMODEL_H_ 4 | 5 | #include "networks/MultilayerNetwork.hpp" 6 | #include "generation/EvolutionModel.hpp" 7 | #include 8 | #include 9 | 10 | class PyEvolutionModel 11 | { 12 | private: 13 | std::shared_ptr> ptr; 14 | std::string desc; 15 | 16 | public: 17 | std::string 18 | description( 19 | ) const 20 | { 21 | return desc; 22 | } 23 | 24 | PyEvolutionModel( 25 | std::shared_ptr> ptr, 26 | const std::string& description 27 | ) : ptr(ptr), desc(description) {} 28 | 29 | uu::net::EvolutionModel* 30 | get_model() const 31 | { 32 | return ptr.get(); 33 | } 34 | }; 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /C++/PyMLNetwork.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef UU_MULTINET_PYMLNETWORK_H_ 3 | #define UU_MULTINET_PYMLNETWORK_H_ 4 | 5 | #include "networks/MultilayerNetwork.hpp" 6 | 7 | class PyMLNetwork 8 | { 9 | private: 10 | std::shared_ptr ptr; 11 | 12 | public: 13 | 14 | std::string 15 | name( 16 | ) const 17 | { 18 | return ptr->name; 19 | } 20 | 21 | PyMLNetwork(std::shared_ptr ptr) : ptr(ptr) 22 | { 23 | // @todo check not null? 24 | } 25 | 26 | uu::net::MultilayerNetwork* 27 | get_mlnet() const 28 | { 29 | return ptr.get(); 30 | } 31 | 32 | }; 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /C++/py_functions.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from r_functions.h 3 | * 4 | * Created on: 2020-04-14 5 | * Author: matteomagnani 6 | * Version: 0.0.1 7 | */ 8 | 9 | #ifndef _PY_FUNCTIONS_H_ 10 | #define _PY_FUNCTIONS_H_ 11 | 12 | #include 13 | #include 14 | #include "PyMLNetwork.hpp" 15 | #include "PyEvolutionModel.hpp" 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | namespace py = pybind11; 22 | 23 | 24 | // CREATION AND STORAGE 25 | 26 | PyMLNetwork 27 | emptyMultilayer( 28 | const std::string& name 29 | ); 30 | 31 | 32 | 33 | PyMLNetwork 34 | readMultilayer( 35 | const std::string& input_file, 36 | const std::string& name, 37 | bool vertex_aligned 38 | ); 39 | 40 | 41 | void 42 | writeMultilayer( 43 | const PyMLNetwork& mnet, 44 | const std::string& output_file, 45 | const std::string& format, 46 | const py::list& layer_names, 47 | char sep, 48 | bool merge_actors, 49 | bool all_actors 50 | ); 51 | 52 | // Evolution 53 | 54 | PyEvolutionModel 55 | ba_evolution_model( 56 | size_t m0, 57 | size_t m 58 | ); 59 | 60 | PyEvolutionModel 61 | er_evolution_model( 62 | size_t n 63 | ); 64 | 65 | PyMLNetwork 66 | growMultiplex( 67 | size_t num_actors, 68 | long num_of_steps, 69 | const py::list& evolution_model, 70 | const py::list& pr_internal_event, 71 | const py::list& pr_external_event, 72 | const py::list& dependency 73 | ); 74 | 75 | py::dict 76 | generateCommunities( 77 | const std::string& type, 78 | size_t num_actors, 79 | size_t num_layers, 80 | size_t num_communities, 81 | size_t overlap, 82 | const py::list& pr_internal, 83 | const py::list& pr_external 84 | ); 85 | 86 | // INFORMATION ON NETWORKS 87 | 88 | py::list 89 | layers( 90 | const PyMLNetwork& mnet 91 | ); 92 | 93 | py::dict 94 | actors( 95 | const PyMLNetwork& mnet, 96 | const py::list& layer_names, 97 | bool add_attributes = false 98 | ); 99 | 100 | py::dict 101 | vertices( 102 | const PyMLNetwork& mnet, 103 | const py::list& layer_names, 104 | bool add_attributes = false 105 | ); 106 | 107 | py::dict 108 | edges( 109 | const PyMLNetwork& mnet, 110 | const py::list& layer_names1, 111 | const py::list& layer_names2, 112 | bool add_attributes = false 113 | ); 114 | 115 | py::dict 116 | edges_idx( 117 | const PyMLNetwork& rmnet 118 | ); 119 | 120 | size_t 121 | numLayers( 122 | const PyMLNetwork& mnet 123 | ); 124 | 125 | size_t 126 | numActors( 127 | const PyMLNetwork& mnet, 128 | const py::list& layers 129 | ); 130 | 131 | size_t 132 | numNodes( 133 | const PyMLNetwork& mnet, 134 | const py::list& layers 135 | ); 136 | 137 | size_t 138 | numEdges( 139 | const PyMLNetwork& mnet, 140 | const py::list& layer_names1, 141 | const py::list& layer_names2 142 | ); 143 | 144 | py::dict 145 | isDirected( 146 | const PyMLNetwork& mnet, 147 | const py::list& layer_names1, 148 | const py::list& layer_names2 149 | ); 150 | 151 | std::unordered_set 152 | actor_neighbors( 153 | const PyMLNetwork& rmnet, 154 | const std::string& actor_name, 155 | const py::list& layer_names, 156 | const std::string& mode_name 157 | ); 158 | 159 | std::unordered_set 160 | actor_xneighbors( 161 | const PyMLNetwork& rmnet, 162 | const std::string& actor_name, 163 | const py::list& layer_names, 164 | const std::string& mode_name 165 | ); 166 | 167 | 168 | // NETWORK MANIPULATION 169 | 170 | void 171 | addLayers( 172 | PyMLNetwork& rmnet, 173 | const py::list& layer_names, 174 | const py::list& directed 175 | ); 176 | 177 | void 178 | addActors( 179 | PyMLNetwork& rmnet, 180 | const py::list& actor_names 181 | ); 182 | 183 | void 184 | addNodes( 185 | PyMLNetwork& rmnet, 186 | const py::dict& vertices 187 | ); 188 | 189 | void 190 | addEdges( 191 | PyMLNetwork& rmnet, 192 | const py::dict& edges); 193 | 194 | void 195 | setDirected( 196 | const PyMLNetwork&, 197 | const py::dict& directionalities 198 | ); 199 | 200 | void 201 | deleteLayers( 202 | PyMLNetwork& rmnet, 203 | const py::list& layer_names 204 | ); 205 | 206 | void 207 | deleteActors( 208 | PyMLNetwork& rmnet, 209 | const py::list& actor_names 210 | ); 211 | 212 | void 213 | deleteNodes( 214 | PyMLNetwork& rmnet, 215 | const py::dict& vertices 216 | ); 217 | 218 | void 219 | deleteEdges( 220 | PyMLNetwork& rmnet, 221 | const py::dict& edges 222 | ); 223 | 224 | 225 | 226 | void 227 | newAttributes( 228 | PyMLNetwork& rmnet, 229 | const py::list& attribute_names, 230 | const std::string& type, 231 | const std::string& target, 232 | const std::string& layer_name, 233 | const std::string& layer_name1, 234 | const std::string& layer_name2 235 | ); 236 | 237 | py::dict 238 | getAttributes( 239 | const PyMLNetwork&, 240 | const std::string& target 241 | ); 242 | 243 | py::dict 244 | getValues( 245 | const PyMLNetwork& rmnet, 246 | const std::string& attribute_name, 247 | const py::dict& actor_names, 248 | const py::dict& vertex_matrix, 249 | const py::dict& edge_matrix 250 | ); 251 | 252 | 253 | void 254 | setValues( 255 | PyMLNetwork& rmnet, 256 | const std::string& attribute_name, 257 | const py::dict& actor_names, 258 | const py::dict& vertex_matrix, 259 | const py::dict& edge_matrix, 260 | const py::list& values 261 | ); 262 | 263 | 264 | // TRANSFORMATION 265 | 266 | void 267 | flatten( 268 | PyMLNetwork& rmnet, 269 | const std::string& new_layer, 270 | const py::list& layer_names, 271 | const std::string& method, 272 | bool force_directed, 273 | bool all_actors 274 | ); 275 | 276 | void 277 | project( 278 | PyMLNetwork& rmnet, 279 | const std::string& new_layer, 280 | const std::string& layer1, 281 | const std::string& layer2, 282 | const std::string& method 283 | ); 284 | 285 | // MEASURES 286 | 287 | py::list 288 | degree_ml( 289 | const PyMLNetwork&, 290 | const py::list& actor_names, 291 | const py::list& layer_names, 292 | const std::string& type 293 | ); 294 | 295 | 296 | py::list 297 | degree_deviation_ml( 298 | const PyMLNetwork&, 299 | const py::list& actor_names, 300 | const py::list& layer_names, 301 | const std::string& type 302 | ); 303 | 304 | py::list 305 | neighborhood_ml( 306 | const PyMLNetwork& mnet, 307 | const py::list& actor_names, 308 | const py::list& layer_names, 309 | const std::string& type 310 | ); 311 | 312 | py::list 313 | xneighborhood_ml( 314 | const PyMLNetwork& mnet, 315 | const py::list& actor_names, 316 | const py::list& layer_names, 317 | const std::string& type 318 | ); 319 | 320 | 321 | py::list 322 | connective_redundancy_ml( 323 | const PyMLNetwork& mnet, 324 | const py::list& actor_names, 325 | const py::list& layer_names, 326 | const std::string& type 327 | ); 328 | 329 | py::list 330 | relevance_ml( 331 | const PyMLNetwork& mnet, 332 | const py::list& actor_names, 333 | const py::list& layer_names, 334 | const std::string& type 335 | ); 336 | 337 | py::list 338 | xrelevance_ml( 339 | const PyMLNetwork& mnet, 340 | const py::list& actor_names, 341 | const py::list& layer_names, 342 | const std::string& type 343 | ); 344 | 345 | double 346 | summary_ml( 347 | const PyMLNetwork&, 348 | const std::string& layer, 349 | const std::string& method, 350 | const std::string& type 351 | ); 352 | 353 | py::list 354 | comparison_ml( 355 | const PyMLNetwork&, 356 | const py::list& layer_names, 357 | const std::string& method, 358 | const std::string& type, 359 | int K 360 | ); 361 | 362 | 363 | 364 | py::dict 365 | distance_ml(const PyMLNetwork& mnet, 366 | const std::string& from, 367 | const py::list& to, 368 | const std::string& method); 369 | 370 | 371 | // CLUSTERING 372 | 373 | py::dict 374 | cliquepercolation_ml( 375 | const PyMLNetwork& rmnet, 376 | int k, 377 | int m 378 | ); 379 | 380 | 381 | py::dict 382 | infomap_ml( 383 | const PyMLNetwork& mnet, 384 | bool overlapping, 385 | bool directed, 386 | bool include_self_links 387 | ); 388 | 389 | py::dict 390 | flat_ec( 391 | const PyMLNetwork& mnet 392 | ); 393 | 394 | py::dict 395 | flat_nw( 396 | const PyMLNetwork& mnet 397 | ); 398 | 399 | py::dict 400 | mdlp( 401 | const PyMLNetwork& mnet 402 | ); 403 | 404 | py::dict 405 | glouvain_ml( 406 | const PyMLNetwork&, 407 | double gamma, 408 | double omega 409 | ); 410 | 411 | py::dict 412 | abacus_ml( 413 | const PyMLNetwork&, 414 | int min_actors, 415 | int min_layers 416 | ); 417 | 418 | double 419 | nmi( 420 | const PyMLNetwork& rmnet, 421 | const py::dict& com1, 422 | const py::dict& com2 423 | ); 424 | 425 | double 426 | omega( 427 | const PyMLNetwork& rmnet, 428 | const py::dict& com1, 429 | const py::dict& com2 430 | ); 431 | 432 | 433 | double 434 | modularity_ml( 435 | const PyMLNetwork& rmnet, 436 | const py::dict& com, double gamma, 437 | double omega 438 | ); 439 | 440 | /* 441 | List 442 | to_list( 443 | const py::dict& cs, 444 | const PyMLNetwork& mnet 445 | ); 446 | */ 447 | 448 | // Layout 449 | 450 | py::dict 451 | multiforce_ml( 452 | const PyMLNetwork& mnet, 453 | const py::list& w_in, 454 | const py::list& w_out, 455 | const py::list& gravity, 456 | int iterations 457 | ); 458 | 459 | py::dict 460 | circular_ml( 461 | const PyMLNetwork& mnet 462 | ); 463 | 464 | 465 | /* 466 | 467 | // SPREADING 468 | // NumericMatrix sir(const PyMLNetwork& mnet, double beta, int tau, long num_iterations); 469 | 470 | */ 471 | 472 | py::dict 473 | toNetworkxNodeDict( 474 | const PyMLNetwork& rmnet 475 | ); 476 | 477 | py::dict 478 | toNetworkxEdgeDict( 479 | const PyMLNetwork& rmnet 480 | ); 481 | 482 | #endif 483 | -------------------------------------------------------------------------------- /C++/py_functions2.cpp: -------------------------------------------------------------------------------- 1 | // @todo check dict field existence 2 | 3 | #include 4 | #include 5 | #include "py_functions.hpp" 6 | #include "pycpp_utils.hpp" 7 | 8 | #include "operations/union.hpp" 9 | #include "operations/project.hpp" 10 | #include "community/glouvain2.hpp" 11 | #include "community/abacus.hpp" 12 | #include "community/infomap.hpp" 13 | #include "community/flat.hpp" 14 | #include "community/mlp.hpp" 15 | #include "community/mlcpm.hpp" 16 | #include "community/modularity.hpp" 17 | #include "community/nmi.hpp" 18 | #include "community/omega_index.hpp" 19 | #include "measures/degree_ml.hpp" 20 | #include "measures/relevance.hpp" 21 | #include "measures/redundancy.hpp" 22 | #include "measures/layer.hpp" 23 | #include "measures/distance.hpp" 24 | #include "core/propertymatrix/summarization.hpp" 25 | #include "layout/multiforce.hpp" 26 | #include "layout/circular.hpp" 27 | 28 | 29 | using M = uu::net::MultilayerNetwork; 30 | using G = uu::net::Network; 31 | 32 | 33 | 34 | 35 | 36 | // TRANSFORMATION 37 | 38 | void 39 | flatten( 40 | PyMLNetwork& rmnet, 41 | const std::string& new_layer_name, 42 | const py::list& layer_names, 43 | const std::string& method, 44 | bool force_directed, 45 | bool all_actors 46 | ) 47 | { 48 | 49 | // @todo 50 | if (all_actors) 51 | { 52 | throw std::runtime_error("option to include all actors not currently implemented"); 53 | } 54 | 55 | auto mnet = rmnet.get_mlnet(); 56 | 57 | auto layers = resolve_layers_unordered(mnet,layer_names); 58 | 59 | bool directed = force_directed; 60 | 61 | if (!force_directed) 62 | { 63 | for (auto layer: layers) 64 | { 65 | if (layer->is_directed()) 66 | { 67 | directed = true; 68 | break; 69 | } 70 | } 71 | } 72 | 73 | auto edge_directionality = directed?uu::net::EdgeDir::DIRECTED:uu::net::EdgeDir::UNDIRECTED; 74 | 75 | 76 | auto target = mnet->layers()->add(new_layer_name, edge_directionality, uu::net::LoopMode::ALLOWED); 77 | target->edges()->attr()->add("weight", uu::core::AttributeType::DOUBLE); 78 | 79 | if (method=="weighted") 80 | { 81 | uu::net::weighted_graph_union(layers.begin(),layers.end(),target,"weight"); 82 | } 83 | 84 | else if (method=="or") 85 | { 86 | // todo replace with new union 87 | for (auto g=layers.begin(); g!=layers.end(); ++g) 88 | { 89 | uu::net::graph_add(*g, target); 90 | } 91 | } 92 | 93 | else 94 | { 95 | throw std::runtime_error("Unexpected value: method"); 96 | } 97 | } 98 | 99 | 100 | void project( 101 | PyMLNetwork& rmnet, 102 | const std::string& new_layer, 103 | const std::string& layer_name1, 104 | const std::string& layer_name2, 105 | const std::string& method) 106 | { 107 | auto mnet = rmnet.get_mlnet(); 108 | auto layer1 = mnet->layers()->get(layer_name1); 109 | auto layer2 = mnet->layers()->get(layer_name2); 110 | if (!layer1 || !layer2) 111 | throw std::runtime_error("Layer not found"); 112 | if (method=="clique") 113 | { 114 | auto target_ptr = mnet->layers()->add(new_layer, uu::net::EdgeDir::UNDIRECTED, uu::net::LoopMode::ALLOWED); 115 | uu::net::project_unweighted(mnet, layer1, layer2, target_ptr); 116 | } 117 | else throw std::runtime_error("Unexpected value: method"); 118 | } 119 | 120 | // MEASURES 121 | 122 | py::list 123 | degree_ml( 124 | const PyMLNetwork& rmnet, 125 | const py::list& actor_names, 126 | const py::list& layer_names, 127 | const std::string& type 128 | ) 129 | { 130 | auto mnet = rmnet.get_mlnet(); 131 | 132 | auto actors = resolve_actors(mnet,actor_names); 133 | auto layers = resolve_layers_unordered(mnet,layer_names); 134 | py::list res; 135 | 136 | for (auto actor: actors) 137 | { 138 | long deg = 0; 139 | auto mode = resolve_mode(type); 140 | deg = degree(layers.begin(), layers.end(), actor, mode); 141 | 142 | if (deg==0) 143 | { 144 | // check if the actor is missing from all layer_names 145 | bool is_missing = true; 146 | 147 | for (auto layer: layers) 148 | { 149 | if (layer->vertices()->contains(actor)) 150 | { 151 | is_missing = false; 152 | } 153 | } 154 | 155 | if (is_missing) 156 | { 157 | res.append(NAN); 158 | } 159 | 160 | else 161 | { 162 | res.append(0); 163 | } 164 | } 165 | 166 | else 167 | { 168 | res.append(deg); 169 | } 170 | } 171 | 172 | return res; 173 | } 174 | 175 | 176 | py::list 177 | degree_deviation_ml( 178 | const PyMLNetwork& rmnet, 179 | const py::list& actor_names, 180 | const py::list& layer_names, 181 | const std::string& type) 182 | { 183 | auto mnet = rmnet.get_mlnet(); 184 | 185 | auto actors = resolve_actors(mnet,actor_names); 186 | auto layers = resolve_layers_unordered(mnet,layer_names); 187 | py::list res; 188 | 189 | for (auto actor: actors) 190 | { 191 | double deg = 0; 192 | auto mode = resolve_mode(type); 193 | deg = degree_deviation(layers.begin(), layers.end(), actor, mode); 194 | 195 | if (deg==0) 196 | { 197 | // check if the actor is missing from all layer_names 198 | bool is_missing = true; 199 | 200 | for (auto layer: layers) 201 | { 202 | if (layer->vertices()->contains(actor)) 203 | { 204 | is_missing = false; 205 | } 206 | } 207 | 208 | if (is_missing) 209 | { 210 | res.append(NAN); 211 | } 212 | 213 | else 214 | { 215 | res.append(0); 216 | } 217 | } 218 | 219 | else 220 | { 221 | res.append(deg); 222 | } 223 | } 224 | 225 | return res; 226 | } 227 | 228 | 229 | py::list 230 | neighborhood_ml( 231 | const PyMLNetwork& rmnet, 232 | const py::list& actor_names, 233 | const py::list& layer_names, 234 | const std::string& type 235 | ) 236 | { 237 | auto mnet = rmnet.get_mlnet(); 238 | 239 | auto actors = resolve_actors(mnet,actor_names); 240 | auto layers = resolve_layers_unordered(mnet,layer_names); 241 | py::list res; 242 | 243 | for (auto actor: actors) 244 | { 245 | long neigh = 0; 246 | auto mode = resolve_mode(type); 247 | neigh = neighbors(layers.begin(), layers.end(), actor, mode).size(); 248 | 249 | if (neigh==0) 250 | { 251 | // check if the actor is missing from all layer_names 252 | bool is_missing = true; 253 | 254 | for (auto layer: layers) 255 | { 256 | if (layer->vertices()->contains(actor)) 257 | { 258 | is_missing = false; 259 | } 260 | } 261 | 262 | if (is_missing) 263 | { 264 | res.append(NAN); 265 | } 266 | 267 | else 268 | { 269 | res.append(0); 270 | } 271 | } 272 | 273 | else 274 | { 275 | res.append(neigh); 276 | } 277 | } 278 | 279 | return res; 280 | } 281 | 282 | 283 | 284 | py::list 285 | xneighborhood_ml( 286 | const PyMLNetwork& rmnet, 287 | const py::list& actor_names, 288 | const py::list& layer_names, 289 | const std::string& type) 290 | { 291 | auto mnet = rmnet.get_mlnet(); 292 | 293 | auto actors = resolve_actors(mnet,actor_names); 294 | auto layers = resolve_layers_unordered(mnet,layer_names); 295 | py::list res; 296 | 297 | for (auto actor: actors) 298 | { 299 | long neigh = 0; 300 | auto mode = resolve_mode(type); 301 | neigh = xneighbors(mnet, layers.begin(), layers.end(), actor, mode).size(); 302 | 303 | if (neigh==0) 304 | { 305 | // check if the actor is missing from all layer_names 306 | bool is_missing = true; 307 | 308 | for (auto layer: layers) 309 | { 310 | if (layer->vertices()->contains(actor)) 311 | { 312 | is_missing = false; 313 | } 314 | } 315 | 316 | if (is_missing) 317 | { 318 | res.append(NAN); 319 | } 320 | 321 | else 322 | { 323 | res.append(0); 324 | } 325 | } 326 | 327 | else 328 | { 329 | res.append(neigh); 330 | } 331 | } 332 | 333 | return res; 334 | } 335 | 336 | py::list 337 | connective_redundancy_ml( 338 | const PyMLNetwork& rmnet, 339 | const py::list& actor_names, 340 | const py::list& layer_names, 341 | const std::string& type) 342 | { 343 | auto mnet = rmnet.get_mlnet(); 344 | 345 | auto actors = resolve_actors(mnet,actor_names); 346 | auto layers = resolve_layers_unordered(mnet,layer_names); 347 | py::list res; 348 | double cr = 0; 349 | 350 | for (auto actor: actors) 351 | { 352 | auto mode = resolve_mode(type); 353 | 354 | cr = uu::net::connective_redundancy(mnet, layers.begin(), layers.end(), actor, mode); 355 | 356 | if (cr==0) 357 | { 358 | // check if the actor is missing from all layer_names 359 | bool is_missing = true; 360 | 361 | for (auto layer: layers) 362 | { 363 | if (layer->vertices()->contains(actor)) 364 | { 365 | is_missing = false; 366 | } 367 | } 368 | 369 | if (is_missing) 370 | { 371 | res.append(NAN); 372 | } 373 | 374 | else 375 | { 376 | res.append(0); 377 | } 378 | } 379 | 380 | else 381 | { 382 | res.append(cr); 383 | } 384 | } 385 | 386 | return res; 387 | } 388 | 389 | py::list 390 | relevance_ml( 391 | const PyMLNetwork& rmnet, 392 | const py::list& actor_names, 393 | const py::list& layer_names, 394 | const std::string& type) 395 | { 396 | auto mnet = rmnet.get_mlnet(); 397 | 398 | auto actors = resolve_actors(mnet,actor_names); 399 | auto layers = resolve_layers_unordered(mnet,layer_names); 400 | py::list res; 401 | 402 | for (auto actor: actors) 403 | { 404 | double rel = 0; 405 | auto mode = resolve_mode(type); 406 | rel = uu::net::relevance(mnet, layers.begin(), layers.end(), actor, mode); 407 | 408 | if (rel==0) 409 | { 410 | // check if the actor is missing from all layer_names 411 | bool is_missing = true; 412 | 413 | for (auto layer: layers) 414 | { 415 | if (layer->vertices()->contains(actor)) 416 | { 417 | is_missing = false; 418 | } 419 | } 420 | 421 | if (is_missing) 422 | { 423 | res.append(NAN); 424 | } 425 | 426 | else 427 | { 428 | res.append(0); 429 | } 430 | } 431 | 432 | else 433 | { 434 | res.append(rel); 435 | } 436 | } 437 | 438 | return res; 439 | } 440 | 441 | 442 | py::list 443 | xrelevance_ml( 444 | const PyMLNetwork& rmnet, 445 | const py::list& actor_names, 446 | const py::list& layer_names, 447 | const std::string& type) 448 | { 449 | auto mnet = rmnet.get_mlnet(); 450 | 451 | auto actors = resolve_actors(mnet,actor_names); 452 | auto layers = resolve_layers_unordered(mnet,layer_names); 453 | 454 | py::list res; 455 | 456 | for (auto actor: actors) 457 | { 458 | double rel = 0; 459 | auto mode = resolve_mode(type); 460 | rel = uu::net::xrelevance(mnet, layers.begin(), layers.end(), actor, mode); 461 | 462 | if (rel==0) 463 | { 464 | // check if the actor is missing from all layer_names 465 | bool is_missing = true; 466 | 467 | for (auto layer: layers) 468 | { 469 | if (layer->vertices()->contains(actor)) 470 | { 471 | is_missing = false; 472 | } 473 | } 474 | 475 | if (is_missing) 476 | { 477 | res.append(NAN); 478 | } 479 | 480 | else 481 | { 482 | res.append(0); 483 | } 484 | } 485 | 486 | else 487 | { 488 | res.append(rel); 489 | } 490 | } 491 | 492 | return res; 493 | } 494 | 495 | 496 | py::list 497 | comparison_ml( 498 | const PyMLNetwork& rmnet, 499 | const py::list& layer_names, 500 | const std::string& method, 501 | const std::string& type, 502 | int K 503 | ) 504 | { 505 | 506 | auto mnet = rmnet.get_mlnet(); 507 | std::vector layers = resolve_layers(mnet,layer_names); 508 | std::vector values; 509 | 510 | for (size_t i=0; i P = uu::net::actor_existence_property_matrix(mnet); 521 | 522 | for (size_t j=0; j(P,layers[i],layers[j])); 527 | } 528 | } 529 | } 530 | 531 | else if (method=="coverage.actors") 532 | { 533 | uu::core::PropertyMatrix P = uu::net::actor_existence_property_matrix(mnet); 534 | 535 | for (size_t j=0; j(P,layers[i],layers[j])); 540 | } 541 | } 542 | } 543 | 544 | else if (method=="kulczynski2.actors") 545 | { 546 | uu::core::PropertyMatrix P = uu::net::actor_existence_property_matrix(mnet); 547 | 548 | for (size_t j=0; j(P,layers[i],layers[j])); 553 | } 554 | } 555 | } 556 | 557 | else if (method=="sm.actors") 558 | { 559 | uu::core::PropertyMatrix P = uu::net::actor_existence_property_matrix(mnet); 560 | 561 | for (size_t j=0; j(P,layers[i],layers[j])); 566 | } 567 | } 568 | } 569 | 570 | else if (method=="rr.actors") 571 | { 572 | uu::core::PropertyMatrix P = uu::net::actor_existence_property_matrix(mnet); 573 | 574 | for (size_t j=0; j(P,layers[i],layers[j])); 579 | } 580 | } 581 | } 582 | 583 | else if (method=="hamann.actors") 584 | { 585 | uu::core::PropertyMatrix P = uu::net::actor_existence_property_matrix(mnet); 586 | 587 | for (size_t j=0; j(P,layers[i],layers[j])); 592 | } 593 | } 594 | } 595 | 596 | else if (method=="jaccard.edges") 597 | { 598 | auto P = uu::net::edge_existence_property_matrix(mnet); 599 | 600 | for (size_t j=0; j, const uu::net::Network*>(P,layers[i],layers[j])); 605 | } 606 | } 607 | } 608 | 609 | else if (method=="coverage.edges") 610 | { 611 | auto P = uu::net::edge_existence_property_matrix(mnet); 612 | 613 | for (size_t j=0; j, const uu::net::Network*>(P,layers[i],layers[j])); 618 | } 619 | } 620 | } 621 | 622 | else if (method=="kulczynski2.edges") 623 | { 624 | auto P = uu::net::edge_existence_property_matrix(mnet); 625 | 626 | for (size_t j=0; j, const uu::net::Network*>(P,layers[i],layers[j])); 631 | } 632 | } 633 | } 634 | 635 | else if (method=="sm.edges") 636 | { 637 | auto P = uu::net::edge_existence_property_matrix(mnet); 638 | 639 | for (size_t j=0; j, const uu::net::Network*>(P,layers[i],layers[j])); 644 | } 645 | } 646 | } 647 | 648 | else if (method=="rr.edges") 649 | { 650 | auto P = uu::net::edge_existence_property_matrix(mnet); 651 | 652 | for (size_t j=0; j, const uu::net::Network*>(P,layers[i],layers[j])); 657 | } 658 | } 659 | } 660 | 661 | else if (method=="hamann.edges") 662 | { 663 | auto P = uu::net::edge_existence_property_matrix(mnet); 664 | 665 | for (size_t j=0; j, const uu::net::Network*>(P,layers[i],layers[j])); 670 | } 671 | } 672 | } 673 | 674 | else if (method=="jaccard.triangles") 675 | { 676 | uu::core::PropertyMatrix P = uu::net::triangle_existence_property_matrix(mnet); 677 | 678 | for (size_t j=0; j(P,layers[i],layers[j])); 683 | } 684 | } 685 | } 686 | 687 | else if (method=="coverage.triangles") 688 | { 689 | uu::core::PropertyMatrix P = uu::net::triangle_existence_property_matrix(mnet); 690 | 691 | for (size_t j=0; j(P,layers[i],layers[j])); 696 | } 697 | } 698 | } 699 | 700 | else if (method=="kulczynski2.triangles") 701 | { 702 | uu::core::PropertyMatrix P = uu::net::triangle_existence_property_matrix(mnet); 703 | 704 | for (size_t j=0; j(P,layers[i],layers[j])); 709 | } 710 | } 711 | } 712 | 713 | else if (method=="sm.triangles") 714 | { 715 | uu::core::PropertyMatrix P = uu::net::triangle_existence_property_matrix(mnet); 716 | 717 | for (size_t j=0; j(P,layers[i],layers[j])); 722 | } 723 | } 724 | } 725 | 726 | else if (method=="rr.triangles") 727 | { 728 | uu::core::PropertyMatrix P = uu::net::triangle_existence_property_matrix(mnet); 729 | 730 | for (size_t j=0; j(P,layers[i],layers[j])); 735 | } 736 | } 737 | } 738 | 739 | else if (method=="hamann.triangles") 740 | { 741 | uu::core::PropertyMatrix P = uu::net::triangle_existence_property_matrix(mnet); 742 | 743 | for (size_t j=0; j(P,layers[i],layers[j])); 748 | } 749 | } 750 | } 751 | 752 | else if (method=="dissimilarity.degree") 753 | { 754 | auto mode = resolve_mode(type); 755 | uu::core::PropertyMatrix P = uu::net::actor_degree_property_matrix(mnet,mode); 756 | 757 | if (K<=0) 758 | { 759 | K=std::ceil(std::log2(P.num_structures) + 1); 760 | } 761 | 762 | for (size_t j=0; j(P,layers[i],layers[j],K)); 767 | } 768 | } 769 | } 770 | 771 | else if (method=="KL.degree") 772 | { 773 | auto mode = resolve_mode(type); 774 | uu::core::PropertyMatrix P = uu::net::actor_degree_property_matrix(mnet,mode); 775 | 776 | if (K<=0) 777 | { 778 | K=std::ceil(std::log2(P.num_structures) + 1); 779 | } 780 | 781 | for (size_t j=0; j(P,layers[i],layers[j],K)); 786 | } 787 | } 788 | } 789 | 790 | else if (method=="jeffrey.degree") 791 | { 792 | auto mode = resolve_mode(type); 793 | uu::core::PropertyMatrix P = uu::net::actor_degree_property_matrix(mnet,mode); 794 | 795 | if (K<=0) 796 | { 797 | K=std::ceil(std::log2(P.num_structures) + 1); 798 | } 799 | 800 | for (size_t j=0; j(P,layers[i],layers[j],K)); 805 | } 806 | } 807 | } 808 | 809 | else if (method=="pearson.degree") 810 | { 811 | auto mode = resolve_mode(type); 812 | uu::core::PropertyMatrix P = uu::net::actor_degree_property_matrix(mnet,mode); 813 | 814 | for (size_t j=0; j(P,layers[i],layers[j])); 819 | } 820 | } 821 | } 822 | 823 | else if (method=="rho.degree") 824 | { 825 | auto mode = resolve_mode(type); 826 | uu::core::PropertyMatrix P = uu::net::actor_degree_property_matrix(mnet,mode); 827 | P.rankify(); 828 | 829 | for (size_t j=0; j(P,layers[i],layers[j])); 834 | } 835 | } 836 | } 837 | 838 | else 839 | { 840 | throw std::runtime_error("Unexpected value: method parameter"); 841 | } 842 | 843 | /* 844 | if (layer_names.size()==0) 845 | { 846 | py::list names; 847 | 848 | for (auto l: layers) 849 | { 850 | names.append(l->name); 851 | } 852 | 853 | for (size_t i=0; ilayers()->get(layer_name); 896 | 897 | if (!layer) 898 | { 899 | throw std::runtime_error("no layer named " + layer_name); 900 | } 901 | 902 | auto mode = resolve_mode(type); 903 | uu::core::PropertyMatrix P = uu::net::actor_degree_property_matrix(mnet,mode); 904 | 905 | if (method=="min.degree") 906 | { 907 | return uu::core::min(P,layer); 908 | } 909 | 910 | else if (method=="max.degree") 911 | { 912 | return uu::core::max(P,layer); 913 | } 914 | 915 | else if (method=="sum.degree") 916 | { 917 | return uu::core::sum(P,layer); 918 | } 919 | 920 | else if (method=="mean.degree") 921 | { 922 | return uu::core::mean(P,layer); 923 | } 924 | 925 | else if (method=="sd.degree") 926 | { 927 | return uu::core::sd(P,layer); 928 | } 929 | 930 | else if (method=="skewness.degree") 931 | { 932 | return uu::core::skew(P,layer); 933 | } 934 | 935 | else if (method=="kurtosis.degree") 936 | { 937 | return uu::core::kurt(P,layer); 938 | } 939 | 940 | else if (method=="entropy.degree") 941 | { 942 | return uu::core::entropy(P,layer); 943 | } 944 | 945 | else if (method=="CV.degree") 946 | { 947 | return uu::core::CV(P,layer); 948 | } 949 | 950 | else if (method=="jarque.bera.degree") 951 | { 952 | return uu::core::jarque_bera(P,layer); 953 | } 954 | 955 | else 956 | { 957 | throw std::runtime_error("Unexpected value: method parameter"); 958 | } 959 | 960 | return 0; 961 | } 962 | 963 | 964 | 965 | py::dict 966 | distance_ml( 967 | const PyMLNetwork& rmnet, 968 | const std::string& from_actor, 969 | const py::list& to_actors, 970 | const std::string& method 971 | ) 972 | { 973 | auto mnet = rmnet.get_mlnet(); 974 | std::vector actors_to = resolve_actors(mnet,to_actors); 975 | auto actor_from = mnet->actors()->get(from_actor); 976 | 977 | py::dict res; 978 | 979 | if (!actor_from) 980 | { 981 | throw std::runtime_error("no actor named " + from_actor); 982 | } 983 | 984 | if (method=="multiplex") 985 | { 986 | auto dists = uu::net::pareto_distance(mnet, actor_from); 987 | 988 | py::list from, to; 989 | std::vector lengths; 990 | 991 | for (size_t i=0; ilayers()->size(); i++) 992 | { 993 | py::list v; 994 | lengths.push_back(v); 995 | } 996 | 997 | for (auto actor: actors_to) 998 | { 999 | for (auto d: dists[actor]) 1000 | { 1001 | from.append(from_actor); 1002 | to.append(actor->name); 1003 | 1004 | for (size_t i=0; ilayers()->size(); i++) 1005 | { 1006 | lengths[i].append(d.length(mnet->layers()->at(i))); 1007 | } 1008 | } 1009 | } 1010 | 1011 | res["from"] = from; 1012 | res["to"] = to; 1013 | 1014 | for (size_t i=0; ilayers()->size(); i++) 1015 | { 1016 | res[mnet->layers()->at(i)->name.c_str()] = lengths[i]; 1017 | } 1018 | } 1019 | 1020 | else 1021 | { 1022 | throw std::runtime_error("Unexpected value: method"); 1023 | } 1024 | 1025 | return res; 1026 | } 1027 | 1028 | 1029 | /* 1030 | NumericMatrix sir_ml( 1031 | const PyMLNetwork& rmnet, double beta, int tau, long num_iterations) { 1032 | auto mnet = rmnet.get_mlnet(); 1033 | matrix stats = sir(mnet, beta, tau, num_iterations); 1034 | 1035 | NumericMatrix res(3,num_iterations+1); 1036 | 1037 | py::list colnames(0); 1038 | py::list rownames(3); 1039 | rownames(0) = "S"; 1040 | rownames(1) = "I"; 1041 | rownames(2) = "R"; 1042 | res.attr("dimnames") = List::create(rownames, colnames); 1043 | 1044 | for (size_t i=0; i<3; i++) { 1045 | for (long j=0; j(mnet, omega, gamma); 1079 | 1080 | return to_dataframe(com_struct.get()); 1081 | } 1082 | 1083 | py::dict 1084 | infomap_ml(const PyMLNetwork& rmnet, 1085 | bool overlapping, 1086 | bool directed, 1087 | bool include_self_links 1088 | ) 1089 | { 1090 | auto mnet = rmnet.get_mlnet(); 1091 | 1092 | try 1093 | { 1094 | auto com_struct = uu::net::infomap(mnet, overlapping, directed, include_self_links); 1095 | return to_dataframe(com_struct.get()); 1096 | } 1097 | 1098 | catch (std::exception& e) 1099 | { 1100 | py::print("[Warning] could not run external library: " + std::string(e.what())); 1101 | py::print("Returning empty community set."); 1102 | } 1103 | 1104 | auto com_struct = std::make_unique>(); 1105 | return to_dataframe(com_struct.get()); 1106 | } 1107 | 1108 | py::dict 1109 | abacus_ml( 1110 | const PyMLNetwork& rmnet, 1111 | int min_actors, 1112 | int min_layers 1113 | ) 1114 | { 1115 | auto mnet = rmnet.get_mlnet(); 1116 | 1117 | try 1118 | { 1119 | auto com_struct = uu::net::abacus(mnet, min_actors, min_layers); 1120 | return to_dataframe(com_struct.get()); 1121 | } 1122 | 1123 | catch (std::exception& e) 1124 | { 1125 | py::print("[Warning] could not run external library: " + std::string(e.what())); 1126 | py::print("Returning empty community set."); 1127 | } 1128 | 1129 | auto com_struct = std::make_unique>(); 1130 | return to_dataframe(com_struct.get()); 1131 | 1132 | } 1133 | 1134 | py::dict 1135 | flat_ec( 1136 | const PyMLNetwork& rmnet 1137 | ) 1138 | { 1139 | auto mnet = rmnet.get_mlnet(); 1140 | 1141 | auto com_struct = uu::net::flat_ec(mnet); 1142 | return to_dataframe(com_struct.get()); 1143 | } 1144 | 1145 | py::dict 1146 | flat_nw( 1147 | const PyMLNetwork& rmnet 1148 | ) 1149 | { 1150 | auto mnet = rmnet.get_mlnet(); 1151 | 1152 | auto com_struct = uu::net::flat_nw(mnet); 1153 | return to_dataframe(com_struct.get()); 1154 | } 1155 | 1156 | py::dict 1157 | mdlp( 1158 | const PyMLNetwork& rmnet 1159 | ) 1160 | { 1161 | auto mnet = rmnet.get_mlnet(); 1162 | 1163 | auto com_struct = uu::net::mlp(mnet); 1164 | return to_dataframe(com_struct.get()); 1165 | } 1166 | 1167 | 1168 | double 1169 | modularity_ml( 1170 | const PyMLNetwork& rmnet, 1171 | const py::dict& com, 1172 | double gamma, 1173 | double omega 1174 | ) 1175 | { 1176 | auto mnet = rmnet.get_mlnet(); 1177 | auto communities = to_communities(com, mnet); 1178 | return uu::net::modularity(mnet, communities.get(), omega); 1179 | } 1180 | 1181 | double 1182 | nmi( 1183 | const PyMLNetwork& rmnet, 1184 | const py::dict& com1, 1185 | const py::dict& com2 1186 | ) 1187 | { 1188 | size_t num_vertices = numNodes(rmnet, py::list()); 1189 | auto mnet = rmnet.get_mlnet(); 1190 | auto c1 = to_communities(com1, mnet); 1191 | auto c2 = to_communities(com2, mnet); 1192 | return uu::net::nmi(c1.get(), c2.get(), num_vertices); 1193 | } 1194 | 1195 | double 1196 | omega( 1197 | const PyMLNetwork& rmnet, 1198 | const py::dict& com1, 1199 | const py::dict& com2 1200 | ) 1201 | { 1202 | size_t num_vertices = numNodes(rmnet, py::list()); 1203 | auto mnet = rmnet.get_mlnet(); 1204 | auto c1 = to_communities(com1, mnet); 1205 | auto c2 = to_communities(com2, mnet); 1206 | return uu::net::omega_index(c1.get(), c2.get(), num_vertices); 1207 | } 1208 | 1209 | /* 1210 | List 1211 | to_list( 1212 | const py::dict& cs, 1213 | const PyMLNetwork& rmnet 1214 | ) 1215 | { 1216 | auto mnet = rmnet.get_mlnet(); 1217 | 1218 | // stores at which index vertices start in a layer 1219 | std::unordered_map offset; 1220 | size_t num_vertices = 0; 1221 | 1222 | for (auto layer: *mnet->layers()) 1223 | { 1224 | offset[layer] = num_vertices; 1225 | num_vertices += layer->vertices()->size(); 1226 | } 1227 | 1228 | 1229 | std::map > > list; 1230 | py::list cs_actor = cs["actor"]; 1231 | py::list cs_layer = cs["layer"]; 1232 | py::list cs_cid = cs["cid"]; 1233 | 1234 | for (size_t i=0; ilayers()->get(std::string(cs_layer[i])); 1238 | 1239 | if (!layer) 1240 | { 1241 | throw std::runtime_error("cannot find layer " + std::string(cs_layer[i]) + " (community structure not compatible with this network?)"); 1242 | } 1243 | 1244 | int l = mnet->layers()->index_of(layer); 1245 | auto actor = mnet->actors()->get(std::string(cs_actor[i])); 1246 | 1247 | if (!actor) 1248 | { 1249 | throw std::runtime_error("cannot find actor " + std::string(cs_actor[i]) + " (community structure not compatible with this network?)"); 1250 | } 1251 | 1252 | int vertex_idx = layer->vertices()->index_of(actor); 1253 | 1254 | if (vertex_idx==-1) 1255 | { 1256 | throw std::runtime_error("cannot find vertex " + std::string(cs_actor[i]) + "::" + std::string(cs_layer[i]) + " (community structure not compatible with this network?)"); 1257 | } 1258 | 1259 | int n = vertex_idx+offset[layer]+1; 1260 | list[comm_id][l].append(n); 1261 | } 1262 | 1263 | List res = List::create(); 1264 | 1265 | for (auto clist: list) 1266 | { 1267 | for (auto llist: clist.second) 1268 | { 1269 | res.append(List::create(res["cid"]=clist.first, res["lid"]=llist.first, res["aid"]=llist.second)); 1270 | } 1271 | } 1272 | 1273 | return res; 1274 | } 1275 | */ 1276 | 1277 | // LAYOUT 1278 | 1279 | py::dict 1280 | multiforce_ml( 1281 | const PyMLNetwork& rmnet, 1282 | const py::list& w_in, 1283 | const py::list& w_inter, 1284 | const py::list& gravity, 1285 | int iterations 1286 | ) 1287 | { 1288 | auto mnet = rmnet.get_mlnet(); 1289 | std::unordered_map weight_in, weight_inter, weight_gr; 1290 | auto layers = mnet->layers(); 1291 | 1292 | if (w_in.size()==1) 1293 | { 1294 | for (size_t i=0; isize(); i++) 1295 | { 1296 | weight_in[layers->at(i)] = w_in[0].cast(); 1297 | } 1298 | } 1299 | 1300 | else if (w_in.size()==layers->size()) 1301 | { 1302 | for (size_t i=0; isize(); i++) 1303 | { 1304 | weight_in[layers->at(i)] = w_in[i].cast(); 1305 | } 1306 | } 1307 | 1308 | else 1309 | { 1310 | throw std::runtime_error("wrong dimension: internal weights (should contain 1 or num.layers.ml weights)"); 1311 | } 1312 | 1313 | if (w_inter.size()==1) 1314 | { 1315 | for (size_t i=0; isize(); i++) 1316 | { 1317 | weight_inter[layers->at(i)] = w_inter[0].cast(); 1318 | } 1319 | } 1320 | 1321 | else if (w_inter.size()==layers->size()) 1322 | { 1323 | for (size_t i=0; isize(); i++) 1324 | { 1325 | weight_inter[layers->at(i)] = w_inter[i].cast(); 1326 | } 1327 | } 1328 | 1329 | else 1330 | { 1331 | throw std::runtime_error("wrong dimension: external weights (should contain 1 or num.layers.ml weights)"); 1332 | } 1333 | 1334 | if (gravity.size()==1) 1335 | { 1336 | for (size_t i=0; isize(); i++) 1337 | { 1338 | weight_gr[layers->at(i)] = gravity[0].cast(); 1339 | } 1340 | } 1341 | 1342 | else if (gravity.size()==layers->size()) 1343 | { 1344 | for (size_t i=0; isize(); i++) 1345 | { 1346 | weight_gr[layers->at(i)] = gravity[i].cast(); 1347 | } 1348 | } 1349 | 1350 | else 1351 | { 1352 | throw std::runtime_error("wrong dimension: gravity (should contain 1 or num.layers.ml weights)"); 1353 | } 1354 | 1355 | auto coord = uu::net::multiforce(mnet, 10, 10, weight_in, weight_inter, weight_gr, iterations); 1356 | 1357 | std::unordered_map offset; 1358 | size_t num_rows = 0; 1359 | 1360 | for (auto layer: *mnet->layers()) 1361 | { 1362 | num_rows += layer->vertices()->size(); 1363 | } 1364 | 1365 | py::list actor_n; 1366 | py::list layer_n; 1367 | py::list x_n; 1368 | py::list y_n; 1369 | py::list z_n; 1370 | 1371 | for (auto l: *mnet->layers()) 1372 | { 1373 | for (auto a: *l->vertices()) 1374 | { 1375 | 1376 | auto n = std::make_pair(a, l); 1377 | actor_n.append(a->name); 1378 | layer_n.append(l->name); 1379 | auto c = coord.at(n); 1380 | x_n.append(c.x); 1381 | y_n.append(c.y); 1382 | z_n.append(c.z); 1383 | } 1384 | } 1385 | 1386 | py::dict vertices; 1387 | vertices["actor"]=actor_n; 1388 | vertices["layer"]=layer_n; 1389 | vertices["x"]=x_n; 1390 | vertices["y"]=y_n; 1391 | vertices["z"]=z_n; 1392 | 1393 | return vertices; 1394 | } 1395 | 1396 | 1397 | py::dict 1398 | circular_ml( 1399 | const PyMLNetwork& rmnet) 1400 | { 1401 | auto mnet = rmnet.get_mlnet(); 1402 | 1403 | auto coord = uu::net::circular(mnet, 10.0); 1404 | 1405 | std::unordered_map offset; 1406 | size_t num_rows = 0; 1407 | 1408 | for (auto layer: *mnet->layers()) 1409 | { 1410 | num_rows += layer->vertices()->size(); 1411 | } 1412 | 1413 | py::list actor_n; 1414 | py::list layer_n; 1415 | py::list x_n; 1416 | py::list y_n; 1417 | py::list z_n; 1418 | 1419 | for (auto l: *mnet->layers()) 1420 | { 1421 | for (auto a: *l->vertices()) 1422 | { 1423 | 1424 | auto n = std::make_pair(a, l); 1425 | actor_n.append(a->name); 1426 | layer_n.append(l->name); 1427 | auto c = coord.at(n); 1428 | x_n.append(c.x); 1429 | y_n.append(c.y); 1430 | z_n.append(c.z); 1431 | } 1432 | } 1433 | 1434 | 1435 | py::dict vertices; 1436 | vertices["actor"]=actor_n; 1437 | vertices["layer"]=layer_n; 1438 | vertices["x"]=x_n; 1439 | vertices["y"]=y_n; 1440 | vertices["z"]=z_n; 1441 | 1442 | return vertices; 1443 | } 1444 | 1445 | py::dict 1446 | toNetworkxEdgeDict( 1447 | const PyMLNetwork& rmnet 1448 | ) 1449 | { 1450 | auto mnet = rmnet.get_mlnet(); 1451 | 1452 | py::dict res; 1453 | for (auto l: *mnet->layers()) 1454 | { 1455 | py::dict layer_dict; 1456 | 1457 | for (auto v: *l->vertices()) 1458 | { 1459 | layer_dict[v->name.c_str()] = py::dict(); 1460 | } 1461 | 1462 | auto edge_attrs = l->edges()->attr(); 1463 | for (auto e: *l->edges()) 1464 | { 1465 | py::dict attr_values; 1466 | for (auto attr: *edge_attrs) 1467 | { 1468 | switch (attr->type) 1469 | { 1470 | case uu::core::AttributeType::NUMERIC: 1471 | case uu::core::AttributeType::DOUBLE: 1472 | attr_values[attr->name.c_str()] = edge_attrs->get_double(e,attr->name).value; 1473 | break; 1474 | 1475 | case uu::core::AttributeType::STRING: 1476 | attr_values[attr->name.c_str()] = edge_attrs->get_string(e,attr->name).value; 1477 | break; 1478 | 1479 | case uu::core::AttributeType::TIME: 1480 | case uu::core::AttributeType::TEXT: 1481 | case uu::core::AttributeType::INTEGER: 1482 | case uu::core::AttributeType::INTEGERSET: 1483 | case uu::core::AttributeType::DOUBLESET: 1484 | case uu::core::AttributeType::STRINGSET: 1485 | case uu::core::AttributeType::TIMESET: 1486 | break; 1487 | } 1488 | } 1489 | layer_dict[e->v1->name.c_str()][e->v2->name.c_str()] = attr_values; 1490 | } 1491 | res[l->name.c_str()] = layer_dict; 1492 | } 1493 | return res; 1494 | } 1495 | 1496 | py::dict 1497 | toNetworkxNodeDict( 1498 | const PyMLNetwork& rmnet 1499 | ) 1500 | { 1501 | auto mnet = rmnet.get_mlnet(); 1502 | 1503 | py::dict res; 1504 | for (auto l: *mnet->layers()) 1505 | { 1506 | py::dict layer_dict; 1507 | auto node_attrs = l->vertices()->attr(); 1508 | for (auto v: *l->vertices()) 1509 | { 1510 | py::dict attr_values; 1511 | 1512 | // actor atributes 1513 | auto actor_attr = mnet->actors()->attr(); 1514 | for (auto attr: *actor_attr) 1515 | { 1516 | switch (attr->type) 1517 | { 1518 | case uu::core::AttributeType::NUMERIC: 1519 | case uu::core::AttributeType::DOUBLE: 1520 | attr_values[attr->name.c_str()] = actor_attr->get_double(v,attr->name).value; 1521 | break; 1522 | 1523 | case uu::core::AttributeType::STRING: 1524 | attr_values[attr->name.c_str()] = actor_attr->get_string(v,attr->name).value; 1525 | break; 1526 | 1527 | case uu::core::AttributeType::TIME: 1528 | case uu::core::AttributeType::TEXT: 1529 | case uu::core::AttributeType::INTEGER: 1530 | case uu::core::AttributeType::INTEGERSET: 1531 | case uu::core::AttributeType::DOUBLESET: 1532 | case uu::core::AttributeType::STRINGSET: 1533 | case uu::core::AttributeType::TIMESET: 1534 | break; 1535 | } 1536 | } 1537 | 1538 | // vertex atributes 1539 | auto node_attrs = l->vertices()->attr(); 1540 | for (auto attr: *node_attrs) 1541 | { 1542 | switch (attr->type) 1543 | { 1544 | case uu::core::AttributeType::NUMERIC: 1545 | case uu::core::AttributeType::DOUBLE: 1546 | attr_values[(l->name + ":" + attr->name).c_str()] = node_attrs->get_double(v,attr->name).value; 1547 | break; 1548 | 1549 | case uu::core::AttributeType::STRING: 1550 | attr_values[(l->name + ":" + attr->name).c_str()] = node_attrs->get_string(v,attr->name).value; 1551 | break; 1552 | 1553 | case uu::core::AttributeType::TIME: 1554 | case uu::core::AttributeType::TEXT: 1555 | case uu::core::AttributeType::INTEGER: 1556 | case uu::core::AttributeType::INTEGERSET: 1557 | case uu::core::AttributeType::DOUBLESET: 1558 | case uu::core::AttributeType::STRINGSET: 1559 | case uu::core::AttributeType::TIMESET: 1560 | break; 1561 | } 1562 | } 1563 | 1564 | layer_dict[v->name.c_str()] = attr_values; 1565 | } 1566 | res[l->name.c_str()] = layer_dict; 1567 | } 1568 | return res; 1569 | } 1570 | 1571 | -------------------------------------------------------------------------------- /C++/pycpp_utils.cpp: -------------------------------------------------------------------------------- 1 | #include "pycpp_utils.hpp" 2 | #include "objects/MLVertex.hpp" 3 | #include 4 | #include 5 | 6 | // @todo check dictionaries have the right fields 7 | 8 | std::vector 9 | resolve_const_layers( 10 | const uu::net::MultilayerNetwork* mnet, 11 | const py::list& names 12 | ) 13 | { 14 | size_t result_size = names.size()?names.size():mnet->layers()->size(); 15 | std::vector res(result_size); 16 | 17 | if (names.size()==0) 18 | { 19 | size_t i=0; 20 | for (auto layer: *mnet->layers()) 21 | { 22 | res[i] = layer; 23 | i++; 24 | } 25 | } 26 | 27 | else 28 | { 29 | size_t i=0; 30 | for (py::handle obj: names) 31 | { 32 | std::string name = obj.attr("__str__")().cast(); 33 | auto layer = mnet->layers()->get(name); 34 | 35 | if (!layer) 36 | { 37 | throw std::runtime_error("cannot find layer " + name); 38 | } 39 | 40 | res[i] = layer; 41 | i++; 42 | } 43 | } 44 | 45 | return res; 46 | } 47 | 48 | std::vector 49 | resolve_layers( 50 | uu::net::MultilayerNetwork* mnet, 51 | const py::list& names 52 | ) 53 | { 54 | size_t result_size = names.size()?names.size():mnet->layers()->size(); 55 | std::vector res(result_size); 56 | 57 | if (names.size()==0) 58 | { 59 | size_t i=0; 60 | for (auto layer: *mnet->layers()) 61 | { 62 | res[i] = layer; 63 | i++; 64 | } 65 | } 66 | 67 | else 68 | { 69 | size_t i=0; 70 | for (py::handle obj: names) 71 | { 72 | std::string name = obj.attr("__str__")().cast(); 73 | auto layer = mnet->layers()->get(name); 74 | 75 | if (!layer) 76 | { 77 | throw std::runtime_error("cannot find layer " + name); 78 | } 79 | 80 | res[i] = layer; 81 | i++; 82 | } 83 | } 84 | 85 | return res; 86 | } 87 | 88 | std::unordered_set 89 | resolve_layers_unordered( 90 | uu::net::MultilayerNetwork* mnet, 91 | const py::list& names 92 | ) 93 | { 94 | std::unordered_set res; 95 | 96 | if (names.size()==0) 97 | { 98 | for (auto layer: *mnet->layers()) 99 | { 100 | res.insert(layer); 101 | } 102 | } 103 | 104 | else 105 | { 106 | for (py::handle obj: names) 107 | { 108 | std::string name = obj.attr("__str__")().cast(); 109 | auto layer = mnet->layers()->get(name); 110 | 111 | if (!layer) 112 | { 113 | throw std::runtime_error("cannot find layer " + name); 114 | } 115 | 116 | res.insert(layer); 117 | } 118 | } 119 | 120 | return res; 121 | } 122 | 123 | 124 | 125 | std::unordered_set 126 | resolve_const_layers_unordered( 127 | const uu::net::MultilayerNetwork* mnet, 128 | const py::list& names 129 | ) 130 | { 131 | std::unordered_set res; 132 | 133 | if (names.size()==0) 134 | { 135 | for (auto layer: *mnet->layers()) 136 | { 137 | res.insert(layer); 138 | } 139 | } 140 | 141 | else 142 | { 143 | for (py::handle obj: names) 144 | { 145 | std::string name = obj.attr("__str__")().cast(); 146 | auto layer = mnet->layers()->get(name); 147 | 148 | if (!layer) 149 | { 150 | throw std::runtime_error("cannot find layer " + name); 151 | } 152 | 153 | res.insert(layer); 154 | } 155 | } 156 | 157 | return res; 158 | } 159 | 160 | 161 | std::vector 162 | resolve_actors( 163 | const uu::net::MultilayerNetwork* mnet, 164 | const py::list& names 165 | ) 166 | { 167 | int result_size = names.size()?names.size():mnet->actors()->size(); 168 | std::vector res(result_size); 169 | 170 | if (names.size()==0) 171 | { 172 | size_t i = 0; 173 | 174 | for (auto actor: *mnet->actors()) 175 | { 176 | res[i] = actor; 177 | i++; 178 | } 179 | } 180 | 181 | else 182 | { 183 | size_t i = 0; 184 | for (py::handle obj: names) 185 | { 186 | std::string name = obj.attr("__str__")().cast(); 187 | auto actor = mnet->actors()->get(name); 188 | 189 | if (!actor) 190 | { 191 | throw std::runtime_error("cannot find actor " + name); 192 | } 193 | 194 | res[i] = actor; 195 | i++; 196 | } 197 | } 198 | 199 | return res; 200 | } 201 | 202 | std::unordered_set 203 | resolve_actors_unordered( 204 | const uu::net::MultilayerNetwork* mnet, 205 | const py::list& names 206 | ) 207 | { 208 | std::unordered_set res; 209 | 210 | if (names.size()==0) 211 | { 212 | for (auto actor: *mnet->actors()) 213 | { 214 | res.insert(actor); 215 | } 216 | } 217 | 218 | else 219 | { 220 | for (py::handle obj: names) 221 | { 222 | std::string name = obj.attr("__str__")().cast(); 223 | 224 | auto actor = mnet->actors()->get(name); 225 | 226 | if (!actor) 227 | { 228 | throw std::runtime_error("cannot find actor " + name); 229 | } 230 | 231 | res.insert(actor); 232 | } 233 | } 234 | 235 | return res; 236 | } 237 | 238 | std::vector> 239 | resolve_const_vertices( 240 | const uu::net::MultilayerNetwork* mnet, 241 | const py::dict& vertex_matrix 242 | ) 243 | { 244 | std::vector a = vertex_matrix["actor"].cast>(); 245 | std::vector l = vertex_matrix["layer"].cast>(); 246 | 247 | if (a.size() != l.size()) 248 | { 249 | throw std::runtime_error("actors and layers should have the same length"); 250 | } 251 | std::vector> res(a.size()); 252 | 253 | for (size_t i=0; iactors()->get(a.at(i)); 256 | 257 | if (!actor) 258 | { 259 | throw std::runtime_error("cannot find actor " + a.at(i)); 260 | } 261 | 262 | auto layer = mnet->layers()->get(l.at(i)); 263 | 264 | if (!layer) 265 | { 266 | throw std::runtime_error("cannot find layer " + l.at(i)); 267 | } 268 | 269 | int vertex = layer->vertices()->index_of(actor); 270 | 271 | if (vertex == -1) 272 | { 273 | throw std::runtime_error("cannot find actor " + actor->name + " on layer " + layer->name); 274 | } 275 | 276 | res[i] = std::make_pair(actor, layer); 277 | } 278 | 279 | return res; 280 | } 281 | 282 | std::vector> 283 | resolve_vertices( 284 | uu::net::MultilayerNetwork* mnet, 285 | const py::dict& vertex_matrix 286 | ) 287 | { 288 | std::vector a = vertex_matrix["actor"].cast>(); 289 | std::vector l = vertex_matrix["layer"].cast>(); 290 | 291 | if (a.size() != l.size()) 292 | { 293 | throw std::runtime_error("actors and layers should have the same length"); 294 | } 295 | std::vector> res(a.size()); 296 | 297 | for (size_t i=0; iactors()->get(a.at(i)); 300 | 301 | if (!actor) 302 | { 303 | throw std::runtime_error("cannot find actor " + a.at(i)); 304 | } 305 | 306 | auto layer = mnet->layers()->get(l.at(i)); 307 | 308 | if (!layer) 309 | { 310 | throw std::runtime_error("cannot find layer " + l.at(i)); 311 | } 312 | 313 | int vertex = layer->vertices()->index_of(actor); 314 | 315 | if (vertex == -1) 316 | { 317 | throw std::runtime_error("cannot find actor " + actor->name + " on layer " + layer->name); 318 | } 319 | 320 | res[i] = std::make_pair(actor, layer); 321 | } 322 | 323 | return res; 324 | } 325 | 326 | std::vector> 327 | resolve_const_edges( 328 | const uu::net::MultilayerNetwork* mnet, 329 | const py::dict& edges 330 | ) 331 | { 332 | std::vector a_from = edges["from_actor"].cast>(); 333 | std::vector l_from = edges["from_layer"].cast>(); 334 | std::vector a_to = edges["to_actor"].cast>(); 335 | std::vector l_to = edges["to_layer"].cast>(); 336 | 337 | if ((a_from.size() != l_from.size()) || (a_from.size() != a_to.size()) || (a_from.size() != l_to.size())) 338 | { 339 | throw std::runtime_error("all lists should have the same length"); 340 | } 341 | 342 | std::vector> res(a_from.size()); 343 | 344 | for (size_t i=0; iactors()->get(std::string(a_from.at(i))); 347 | 348 | if (!actor1) 349 | { 350 | throw std::runtime_error("cannot find actor " + std::string(a_from.at(i))); 351 | } 352 | 353 | auto actor2 = mnet->actors()->get(std::string(a_to.at(i))); 354 | 355 | if (!actor2) 356 | { 357 | throw std::runtime_error("cannot find actor " + std::string(a_to.at(i))); 358 | } 359 | 360 | auto layer1 = mnet->layers()->get(std::string(l_from.at(i))); 361 | 362 | if (!layer1) 363 | { 364 | throw std::runtime_error("cannot find layer " + std::string(l_from.at(i))); 365 | } 366 | 367 | auto layer2 = mnet->layers()->get(std::string(l_to.at(i))); 368 | 369 | if (!layer2) 370 | { 371 | throw std::runtime_error("cannot find layer " + std::string(l_to.at(i))); 372 | } 373 | 374 | if (layer1 == layer2) 375 | { 376 | auto edge = layer1->edges()->get(actor1, actor2); 377 | 378 | if (!edge) 379 | { 380 | throw std::runtime_error("cannot find edge from " + actor1->to_string() + " to " 381 | + actor2->to_string() + " on layer " + layer1->name); 382 | } 383 | 384 | res[i] = std::tuple(actor1, layer1, actor2, layer2); 385 | 386 | } 387 | 388 | else 389 | { 390 | auto edge = mnet->interlayer_edges()->get(actor1, layer1, actor2, layer2); 391 | 392 | if (!edge) 393 | { 394 | throw std::runtime_error("cannot find edge from " + actor1->to_string() + " on layer " + 395 | layer1->name + " to " + actor2->to_string() + " on layer " + layer2->name); 396 | } 397 | 398 | res[i] = std::tuple(actor1, layer1, actor2, layer2); 399 | 400 | } 401 | } 402 | 403 | return res; 404 | } 405 | 406 | std::vector> 407 | resolve_edges( 408 | uu::net::MultilayerNetwork* mnet, 409 | const py::dict& edges 410 | ) 411 | { 412 | std::vector a_from = edges["from_actor"].cast>(); 413 | std::vector l_from = edges["from_layer"].cast>(); 414 | std::vector a_to = edges["to_actor"].cast>(); 415 | std::vector l_to = edges["to_layer"].cast>(); 416 | 417 | if ((a_from.size() != l_from.size()) || (a_from.size() != a_to.size()) || (a_from.size() != l_to.size())) 418 | { 419 | throw std::runtime_error("all lists should have the same length"); 420 | } 421 | 422 | std::vector> res(a_from.size()); 423 | 424 | for (size_t i=0; iactors()->get(std::string(a_from.at(i))); 427 | 428 | if (!actor1) 429 | { 430 | throw std::runtime_error("cannot find actor " + std::string(a_from.at(i))); 431 | } 432 | 433 | auto actor2 = mnet->actors()->get(std::string(a_to.at(i))); 434 | 435 | if (!actor2) 436 | { 437 | throw std::runtime_error("cannot find actor " + std::string(a_to.at(i))); 438 | } 439 | 440 | auto layer1 = mnet->layers()->get(std::string(l_from.at(i))); 441 | 442 | if (!layer1) 443 | { 444 | throw std::runtime_error("cannot find layer " + std::string(l_from.at(i))); 445 | } 446 | 447 | auto layer2 = mnet->layers()->get(std::string(l_to.at(i))); 448 | 449 | if (!layer2) 450 | { 451 | throw std::runtime_error("cannot find layer " + std::string(l_to.at(i))); 452 | } 453 | 454 | if (layer1 == layer2) 455 | { 456 | auto edge = layer1->edges()->get(actor1, actor2); 457 | 458 | if (!edge) 459 | { 460 | throw std::runtime_error("cannot find edge from " + actor1->to_string() + " to " 461 | + actor2->to_string() + " on layer " + layer1->name); 462 | } 463 | 464 | res[i] = std::tuple(actor1, layer1, actor2, layer2); 465 | 466 | } 467 | 468 | else 469 | { 470 | auto edge = mnet->interlayer_edges()->get(actor1, layer1, actor2, layer2); 471 | 472 | if (!edge) 473 | { 474 | throw std::runtime_error("cannot find edge from " + actor1->to_string() + " on layer " + 475 | layer1->name + " to " + actor2->to_string() + " on layer " + layer2->name); 476 | } 477 | 478 | res[i] = std::tuple(actor1, layer1, actor2, layer2); 479 | 480 | } 481 | } 482 | 483 | return res; 484 | } 485 | 486 | 487 | 488 | uu::net::EdgeMode 489 | resolve_mode( 490 | const std::string& mode 491 | ) 492 | { 493 | if (mode=="all") 494 | { 495 | return uu::net::EdgeMode::INOUT; 496 | } 497 | 498 | else if (mode=="in") 499 | { 500 | return uu::net::EdgeMode::IN; 501 | } 502 | 503 | else if (mode=="out") 504 | { 505 | return uu::net::EdgeMode::OUT; 506 | } 507 | 508 | throw std::runtime_error("unexpected value: edge mode " + mode); 509 | 510 | return uu::net::EdgeMode::INOUT; // never reaches here 511 | } 512 | 513 | py::dict 514 | to_dataframe( 515 | uu::net::CommunityStructure* cs 516 | ) 517 | { 518 | 519 | py::list actor, layer, community_id; 520 | 521 | int comm_id=0; 522 | 523 | for (auto com: *cs) 524 | { 525 | for (auto pair: *com) 526 | { 527 | actor.append(pair.v->name); 528 | layer.append(pair.c->name); 529 | community_id.append(comm_id); 530 | } 531 | 532 | comm_id++; 533 | } 534 | 535 | py::dict res; 536 | res["actor"] = actor; 537 | res["layer"] = layer; 538 | res["cid"] = community_id; 539 | 540 | 541 | return res; 542 | } 543 | 544 | std::unique_ptr> 545 | to_communities( 546 | const py::dict& com, 547 | const uu::net::MultilayerNetwork* mnet 548 | ) 549 | { 550 | std::vector cs_actor = com["actor"].cast>();; 551 | std::vector cs_layer = com["layer"].cast>();; 552 | std::vector cs_cid = com["cid"].cast>();; 553 | 554 | if ((cs_actor.size() != cs_layer.size()) || (cs_layer.size() != cs_cid.size())) 555 | { 556 | throw std::runtime_error("all lists should have the same length"); 557 | } 558 | 559 | std::unordered_map> result; 560 | 561 | for (size_t i=0; ilayers()->get(std::string(cs_layer[i])); 564 | if (!layer) throw std::runtime_error("cannot find layer " + std::string(cs_layer[i]) + " (community structure not compatible with this network?)"); 565 | auto actor = mnet->actors()->get(std::string(cs_actor[i])); 566 | if (!actor) throw std::runtime_error("cannot find actor " + std::string(cs_actor[i]) + " (community structure not compatible with this network?)"); 567 | 568 | result[comm_id].push_back(uu::net::MLVertex(actor,layer)); 569 | 570 | } 571 | 572 | 573 | // build community structure 574 | 575 | auto communities = std::make_unique>(); 576 | 577 | for (auto pair: result) 578 | { 579 | auto c = std::make_unique>(); 580 | 581 | for (auto vertex_layer_pair: pair.second) 582 | { 583 | c->add(vertex_layer_pair); 584 | } 585 | 586 | communities->add(std::move(c)); 587 | } 588 | 589 | return communities; 590 | } 591 | 592 | 593 | -------------------------------------------------------------------------------- /C++/pycpp_utils.hpp: -------------------------------------------------------------------------------- 1 | #ifndef UU_MULTINET_PYCPP_UTILS_H_ 2 | #define UU_MULTINET_PYCPP_UTILS_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "community/CommunityStructure.hpp" 9 | #include "objects/Vertex.hpp" 10 | #include "objects/Edge.hpp" 11 | #include "networks/Network.hpp" 12 | #include "community/Community.hpp" 13 | #include "networks/MultilayerNetwork.hpp" 14 | 15 | namespace py = pybind11; 16 | 17 | std::vector 18 | resolve_const_layers( 19 | const uu::net::MultilayerNetwork* mnet, 20 | const py::list& names 21 | ); 22 | 23 | std::vector 24 | resolve_layers( 25 | uu::net::MultilayerNetwork* mnet, 26 | const py::list& names 27 | ); 28 | 29 | std::unordered_set 30 | resolve_layers_unordered( 31 | uu::net::MultilayerNetwork* mnet, 32 | const py::list& names 33 | ); 34 | 35 | std::unordered_set 36 | resolve_const_layers_unordered( 37 | const uu::net::MultilayerNetwork* mnet, 38 | const py::list& names 39 | ); 40 | 41 | std::vector 42 | resolve_actors( 43 | const uu::net::MultilayerNetwork* mnet, 44 | const py::list& names 45 | ); 46 | 47 | std::unordered_set 48 | resolve_actors_unordered( 49 | const uu::net::MultilayerNetwork* mnet, 50 | const py::list& names 51 | ); 52 | 53 | std::vector> 54 | resolve_const_vertices( 55 | const uu::net::MultilayerNetwork* mnet, 56 | const py::dict& vertex_matrix 57 | ); 58 | 59 | std::vector> 60 | resolve_const_edges( 61 | const uu::net::MultilayerNetwork* mnet, 62 | const py::dict& edge_matrix 63 | ); 64 | 65 | std::vector> 66 | resolve_vertices( 67 | uu::net::MultilayerNetwork* mnet, 68 | const py::dict& vertex_matrix 69 | ); 70 | 71 | std::vector> 72 | resolve_edges( 73 | uu::net::MultilayerNetwork* mnet, 74 | const py::dict& edge_matrix 75 | ); 76 | 77 | uu::net::EdgeMode 78 | resolve_mode( 79 | const std::string& mode 80 | ); 81 | 82 | py::dict 83 | to_dataframe( 84 | uu::net::CommunityStructure* cs 85 | ); 86 | 87 | std::unique_ptr> 88 | to_communities( 89 | const py::dict& com, 90 | const uu::net::MultilayerNetwork* mnet 91 | ); 92 | 93 | 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.0 FATAL_ERROR) 2 | project(uunet LANGUAGES C CXX) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 6 | set(CMAKE_CXX_EXTENSIONS OFF) 7 | 8 | # Choosing compiler (clang has preference). 9 | if (CMAKE_CXX_COMPILER MATCHES ".*clang.*" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") 10 | set (CMAKE_COMPILER_IS_CLANGXX 1) 11 | endif() 12 | 13 | #set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O2 -fno-inline -std=c++17") 14 | #set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Iext/eclat/eclat/src -Iext/uunet/ext/eclat/tract/src -Iext/uunet/ext/eclat/math/src -Iext/uunet/ext/eclat/util/src -Iext/uunet/ext/eclat/apriori/src") 15 | #set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Iext/uunet/src -Iext/uunet/ext/boost -Iext/uunet/ext/eclat/eclat/src -Iext/uunet/ext/eclat/tract/src -Iext/uunet/ext/eclat/math/src -Iext/uunet/ext/eclat/util/src -Iext/uunet/ext/eclat/apriori/src -Iext/uunet/ext/infomap") 16 | #set (CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} -DNS_INFOMAP -DONLY_C_LOCALE=1") 17 | 18 | if (APPLE) 19 | set(CMAKE_INSTALL_RPATH @loader_path) 20 | else() 21 | set(CMAKE_INSTALL_RPATH "$ORIGIN") 22 | endif() 23 | 24 | add_subdirectory(ext/pybind11) 25 | #add_subdirectory(ext/uunet) 26 | 27 | file (GLOB_RECURSE SOURCES C++/*cpp ext/uunet/ext/eclat/*.c ext/uunet/ext/infomap/*.cpp ext/uunet/src/*cpp) 28 | #file (GLOB_RECURSE SOURCES C++/*cpp) 29 | pybind11_add_module(_multinet MODULE ${SOURCES}) 30 | #target_link_libraries(_multinet PRIVATE libuunet.dll) 31 | #target_link_libraries(_multinet PRIVATE uunet) 32 | target_include_directories (_multinet PRIVATE 33 | ext/uunet/ext/eclat/eclat/src 34 | ext/uunet/ext/eclat/tract/src 35 | ext/uunet/ext/eclat/math/src 36 | ext/uunet/ext/eclat/util/src 37 | ext/uunet/ext/eclat/apriori/src 38 | ext/uunet/ext/infomap 39 | ext/uunet/ext/boost 40 | ext/uunet/src) 41 | 42 | add_definitions(-DNS_INFOMAP -DONLY_C_LOCALE=1) 43 | -------------------------------------------------------------------------------- /DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | This is the Python version of the _multinet_ library for the analysis of multilayer networks, first released for the R framework in January 2017 on CRAN. _multinet_ is developed by the Uppsala University Information Laboratory (UU InfoLab - https://uuinfolab.github.io) 2 | 3 | 4 | - **Tutorial:** https://github.com/uuinfolab/py_multinet/tree/master/tutorial 5 | 6 | - **Source:** https://github.com/uuinfolab/py_multinet 7 | - **R version:** https://github.com/uuinfolab/r_multinet 8 | - **C++ library:** https://github.com/uuinfolab/uunet 9 | - **Bug reports:** https://github.com/uuinfolab/py_multinet/issues 10 | 11 | A simple example 12 | -------------- 13 | 14 | Find the degree of an actor on two layers: 15 | 16 | >>> import uunet.multinet as ml 17 | >>> m = ml.data("aucs") 18 | >>> ml.degree(m, actors = ['U54'], layers = ['leisure', 'facebook']) 19 | [18] 20 | 21 | Install 22 | ------- 23 | 24 | Install the latest version of uunet: 25 | 26 | $ python -m pip install uunet 27 | 28 | Notes: 29 | 30 | - Python >= 3.8 is required 31 | - The package is not compatible with conda 32 | 33 | Credits 34 | ------- 35 | 36 | This library was originally based on the book: Multilayer Social Networks, by Dickison, Magnani & Rossi, Cambridge University Press (2016). The methods contained in the library and described in the book have been developed by many different authors: extensive references are available in the book, and in the documentation of each function we indicate the main reference we have followed for the implementation. For some methods developed after the book was published we give references to the corresponding literature. 37 | 38 | The package uses functions from eclat , for association rule mining, Infomap , for the Infomap community detection method, and Howard Hinnant's date and time library . The code from these libraries has been included in our source package, and may not be the latest version released by the authors. 39 | 40 | License 41 | ------- 42 | 43 | Released under the GNU General Public Licence. 44 | 45 | Contact: Matteo Magnani 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include DESCRIPTION LICENSE NEWS uunet/data/*.mpx 2 | global-include CMakeLists.txt VERSION *.cmake *.cpp *.hpp *.ipp *.c *.h 3 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | # version 2.2.2 2 | 3 | - Fixed duplicate multilayer edges in writing function. 4 | 5 | # version 2.2.1 6 | 7 | - Fixed I/O bugs. 8 | 9 | # version 2.2 10 | 11 | - Added resolution parameter and weights to generalised Louvain. 12 | 13 | - Fixed set_values() to allow multiple actors to be specified. 14 | 15 | - Small updates to documentation. 16 | 17 | - Updated layer degree correlation: the correlation is now computed on the degree, not the number of neighbours. That is, if a vertex V has two incident edges V -> U and V <- U, its degree with mode INOUT is 2 (it was previously 1, as the neighbour is the same). 18 | 19 | - Updated clique percolation: fixed a missing duplicate check (potentially leading to redundant sub-communities being returned) and now automatically discarding directionality if executed on a directed graph. 20 | 21 | # version 2.1 22 | 23 | - Added pyproject.toml configuration 24 | 25 | # version 2.0 26 | 27 | - Aligned interface of actors() with R version, now returning a dictionary 28 | - get_values() and set_values() require a dictionary also for actors 29 | - added the option to add attribute values to actors(), vertices(), and edges() 30 | 31 | # version 1.1.4 32 | 33 | - Fixed bug on get_edges (could swap layers) 34 | 35 | # version 1.1.3 36 | 37 | - Fixed bug on get_values when applied to edges (did not return the values) 38 | - Updated license 39 | 40 | # version 1.1.2 41 | 42 | - values2graphics supports up to 12 distinct values (not included in previous version) 43 | 44 | # version 1.1.1 45 | 46 | - values2graphics supports up to 12 distinct values 47 | - Fixed bug in generate_communities (was returning only with input "pep") 48 | 49 | # version 1.1 50 | 51 | - Updated description 52 | 53 | # version 1.0 54 | 55 | - The multilayer network data structure has been re-implemented using multilayer cubes 56 | - Actors must exist on at least one layer 57 | - Removed actor Pucci from florentine data, not being present in any layer 58 | - Added generate_communities, to create simple community structures 59 | - Added flat_ec, flat_nw and mdlp clustering algorithms 60 | - Added nmi and omega_index evaluation functions 61 | 62 | # version 0.10 63 | 64 | - New default: loops are allowed. 65 | 66 | # version 0.9 67 | 68 | - Added project() 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # multinet library (python version) 2 | 3 | This repository contains the python version of the _multinet_ library for the analysis of multilayer networks, first released for the R framework in January 2017 on CRAN. 4 | 5 | The library is available on PyPI (the Python Package Index), and can be installed using _pip_. This repository is mainly useful if you want to develop the library. 6 | 7 | This library was originally based on the book: Multilayer Social Networks, by Dickison, Magnani & Rossi, Cambridge University Press (2016). The methods contained in the library and described in the book have been developed by many different authors: extensive references are available in the book, and in the documentation of each function we indicate the main reference we have followed for the implementation. For some methods developed after the book was published we give references to the corresponding literature. 8 | 9 | ## Requirements 10 | 11 | * python >= 3.8 12 | 13 | ## Installation 14 | 15 | pip install uunet 16 | 17 | (this provides the module: uunet.multinet) 18 | 19 | ## Usage 20 | 21 | In the directory `tutorial/` you find example code covering most of the functions in the library. Documentation for all functions can be obtained from Python using `help()`. 22 | 23 | 24 | ## Contribute 25 | 26 | To modify the library, one should consider that a large part of its code is written in C++ and comes from the [uunet repository](https://github.com/uuinfolab/uunet). 27 | 28 | If you only want to modify the functions written in python, this can be done directly in this repository. These functions are in uunet/multinet.py. 29 | 30 | After modifying the functions, you can install the new version running pip from the directory where setup-py is located (this requires the setuptools module and the environment needed to recompile uunet): 31 | 32 | ```sh 33 | python -m pip install . 34 | ``` 35 | 36 | The directory C++/ contains the files exporting C++ functions from uunet to python, using ext/pybind11. These functions can also be updated directly in this repository: 37 | 38 | - main.cpp contains the definitions of the python functions implemented in C++. 39 | - py_functions.cpp contains the functions referenced in main.cpp, themselves calling functions from uunet. 40 | - pycpp_utils.cpp contains some utility functions automating some common tasks used in py_functions.cpp. 41 | 42 | If you need to modify any of the files in the directories eclat/, infomap/ and src/, they are imported from uunet and should modified the [uunet repository](https://github.com/uuinfolab/uunet). One can then get the latest code from uunet by running: 43 | 44 | ```sh 45 | git submodule update --remote --merge 46 | ``` 47 | 48 | This command loads the latest code from uunet into ext/. 49 | 50 | The repository has two workflows, publish-test and publish, generating source distribution and wheels and uploading them respectively to TestPyPI and PyPI. For PyPI we use .devN as a suffix for the library version, that is used under development with publish-test. When a new stable release is ready, publish is run on the master branch without .devN. 51 | 52 | ## Contact 53 | 54 | For any inquiries regarding this repository you can contact . 55 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools","cmake>=3.20"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "uunet" 7 | version= "2.2.2" 8 | authors = [ 9 | {name = "Matteo Magnani", email = "matteo.magnani@it.uu.se"} 10 | ] 11 | description = "Python porting of the multinet library" 12 | readme = "DESCRIPTION.md" 13 | requires-python = ">=3.8" 14 | keywords = ["network analysis","multilayer"] 15 | license = {text = "Apache 2.0"} 16 | classifiers = [ 17 | "Programming Language :: Python :: 3", 18 | "License :: OSI Approved :: Apache Software License", 19 | "Operating System :: OS Independent" 20 | ] 21 | dependencies = [ 22 | "networkx", 23 | "matplotlib" 24 | ] 25 | 26 | [options] 27 | include_package_data = "true" 28 | zip_safe = "true" 29 | 30 | [project.urls] 31 | homepage = "https://github.com/uuinfolab/py_multinet" 32 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import sys 4 | import platform 5 | import sysconfig 6 | import subprocess 7 | import setuptools 8 | 9 | from setuptools import setup, Extension 10 | from setuptools.command.build_ext import build_ext 11 | from distutils.version import LooseVersion 12 | 13 | 14 | class CMakeExtension(Extension): 15 | def __init__(self, name, sourcedir=''): 16 | Extension.__init__(self, name, sources=[]) 17 | self.sourcedir = os.path.abspath(sourcedir) 18 | 19 | 20 | class CMakeBuild(build_ext): 21 | def run(self): 22 | try: 23 | out = subprocess.check_output(['cmake', '--version']) 24 | except OSError: 25 | raise RuntimeError("CMake must be installed to build the following extensions: " + 26 | ", ".join(e.name for e in self.extensions)) 27 | 28 | if platform.system() == "Windows": 29 | cmake_version = LooseVersion(re.search(r'version\s*([\d.]+)', out.decode()).group(1)) 30 | if cmake_version < '3.20': 31 | raise RuntimeError("CMake >= 3.20 is required") 32 | 33 | for ext in self.extensions: 34 | self.build_extension(ext) 35 | 36 | def build_extension(self, ext): 37 | extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name))) 38 | cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir, 39 | '-DPYTHON_EXECUTABLE=' + sys.executable, 40 | '-DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=True'] 41 | 42 | cfg = 'Debug' if self.debug else 'Release' 43 | build_args = ['--config', cfg] 44 | 45 | # Pile all .so in one place and use $ORIGIN as RPATH // by Sergei Izmailov 46 | cmake_args += ["-DCMAKE_BUILD_WITH_INSTALL_RPATH=TRUE"] 47 | 48 | if platform.system() == "Windows": 49 | print('Windows!') 50 | cmake_args += ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir)] 51 | # cmake_args += ['-G \"Unix Makefiles\"'] 52 | if sys.maxsize > 2**32: 53 | cmake_args += ['-A', 'x64'] 54 | build_args += ['--', '/m'] 55 | print(cmake_args) 56 | elif sys.platform == 'darwin': 57 | #macosx_target_ver = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') 58 | #if macosx_target_ver and 'MACOSX_DEPLOYMENT_TARGET' not in os.environ: 59 | # print(f'-DCMAKE_OSX_DEPLOYMENT_TARGET={macosx_target_ver}') 60 | #cmake_args.append(f'-DCMAKE_OSX_DEPLOYMENT_TARGET={macosx_target_ver}') 61 | cmake_args.append(f'-DCMAKE_OSX_DEPLOYMENT_TARGET=10.13') 62 | 63 | osx_arch = platform.machine() 64 | cmake_args.append(f'-DCMAKE_OSX_ARCHITECTURES={osx_arch}') 65 | else: 66 | cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg] 67 | build_args += ['--', '-j2'] 68 | 69 | env = os.environ.copy() 70 | env['CXXFLAGS'] = '{} -DVERSION_INFO=\\"{}\\"'.format(env.get('CXXFLAGS', ''), 71 | self.distribution.get_version()) 72 | if not os.path.exists(self.build_temp): 73 | os.makedirs(self.build_temp) 74 | subprocess.check_call(['cmake', ext.sourcedir] + cmake_args, cwd=self.build_temp, env=env) 75 | subprocess.check_call(['cmake', '--build', '.'] + build_args, cwd=self.build_temp) 76 | 77 | from subprocess import CalledProcessError 78 | 79 | print('Running setup') 80 | 81 | try: 82 | setup( 83 | ext_modules=[CMakeExtension('uunet._multinet')], 84 | cmdclass=dict(build_ext=CMakeBuild), 85 | packages=['uunet','uunet.data'] 86 | ) 87 | except CalledProcessError: 88 | print('Failed to build extension') 89 | 90 | 91 | -------------------------------------------------------------------------------- /tutorial/README.md: -------------------------------------------------------------------------------- 1 | # Learning material 2 | 3 | This folder contains: 4 | 5 | * a jupyter notebook (with additional example files used in the notebook) 6 | * a pdf generated from the notebook 7 | * powerpoint slides 8 | 9 | ## Usage 10 | 11 | This is a possible and typical way to use the notebook: 12 | 13 | Create a virtual environment (using Python at least version 3.8): 14 | 15 | python -m venv multinet 16 | 17 | To activate it, on linux/mac: 18 | 19 | source multinet/bin/activate 20 | 21 | On Windows: 22 | 23 | multinet\Scripts\activate.bat 24 | 25 | Then install the following: 26 | 27 | pip install uunet --upgrade 28 | pip install pandas 29 | pip install matplotlib 30 | pip install jupyter 31 | 32 | To check that you have the latest version, you can execute: 33 | 34 | pip show uunet 35 | 36 | And you should see: Version: 1.1.2. Then you can run: 37 | 38 | ipython kernel install --name "multinet" --user 39 | jupyter-notebook 40 | 41 | from this directory. When you open the notebook you should choose the kernel called `multinet`. 42 | 43 | Please notice that: 44 | 45 | * you need Python version 3.8 or higher. 46 | * the pip package is not compatible with conda. 47 | 48 | All the material can be freely reused[1] and modified[2]. 49 | 50 | All inquiries can be sent to 51 | 52 | [1] please acknowledge the original source 53 | [2] please make sure that your changes are not attributed to us 54 | -------------------------------------------------------------------------------- /tutorial/example1.txt: -------------------------------------------------------------------------------- 1 | a1,a2,layer1 2 | a2,a3,layer1 3 | a1,a4,layer1 4 | a2,a5,layer1 5 | a5,a1,layer2 6 | a1,a6,layer2 7 | a6,a2,layer2 8 | a2,a3,layer2 9 | -------------------------------------------------------------------------------- /tutorial/example2.txt: -------------------------------------------------------------------------------- 1 | #VERSION 2 | 3.0 3 | 4 | #TYPE 5 | multiplex 6 | 7 | #LAYERS 8 | research, UNDIRECTED 9 | twitter, DIRECTED 10 | 11 | #ACTOR ATTRIBUTES 12 | affiliation,STRING 13 | 14 | #VERTEX ATTRIBUTES 15 | twitter, num_tweets, NUMERIC 16 | 17 | #EDGE ATTRIBUTES 18 | research, num_publications, NUMERIC 19 | 20 | #ACTORS 21 | Luca,ITU 22 | Matteo,UU 23 | Davide,UU 24 | 25 | #VERTICES 26 | Luca,twitter,53 27 | Matteo,twitter,13 28 | 29 | #EDGES 30 | Luca,Matteo,research,9 31 | Davide,Matteo,research,7 32 | Luca,Matteo,twitter 33 | -------------------------------------------------------------------------------- /tutorial/example_igraph1.dat: -------------------------------------------------------------------------------- 1 | A B 2 | A C 3 | B C 4 | -------------------------------------------------------------------------------- /tutorial/example_igraph2.dat: -------------------------------------------------------------------------------- 1 | A C 2 | -------------------------------------------------------------------------------- /tutorial/py_multinet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uuinfolab/py_multinet/042862952cf90db856dc081df247817acee75e54/tutorial/py_multinet.pdf -------------------------------------------------------------------------------- /tutorial/py_multinet.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uuinfolab/py_multinet/042862952cf90db856dc081df247817acee75e54/tutorial/py_multinet.pptx -------------------------------------------------------------------------------- /uunet/__init__.py: -------------------------------------------------------------------------------- 1 | """Root module""" 2 | -------------------------------------------------------------------------------- /uunet/data/aucs.mpx: -------------------------------------------------------------------------------- 1 | #ACTOR ATTRIBUTES 2 | group,STRING 3 | role,STRING 4 | 5 | #ACTORS 6 | U1,G1,Associate 7 | U3,G2,Postdoc 8 | U4,G2/G3,Admin 9 | U6,G4,PhD 10 | U10,G1,Postdoc 11 | U13,G3,Postdoc 12 | U14,G1,PhD 13 | U17,G5,PhD 14 | U18,G2,PhD 15 | U19,G1,PhD 16 | U21,G4,Associate 17 | U22,G6,PhD 18 | U23,G1,PhD 19 | U26,G6,Associate 20 | U29,G5,Postdoc 21 | U32,G5,Professor 22 | U33,NA,Admin 23 | U37,G4,PhD 24 | U41,G6,PhD 25 | U42,G6,PhD 26 | U47,G2,PhD 27 | U48,G3,PhD 28 | U49,G6,PhD 29 | U53,G7,PhD 30 | U54,G2,Postdoc 31 | U59,G7,PhD 32 | U62,G2,Postdoc 33 | U63,NA,Admin 34 | U65,G7,PhD 35 | U67,G4,Admin 36 | U68,G3,PhD 37 | U69,G4,Postdoc 38 | U71,NA,NA 39 | U72,G7,PhD 40 | U73,G1,PhD 41 | U76,G2,PhD 42 | U79,G2,PhD 43 | U86,NA,Professor 44 | U90,G2,PhD 45 | U91,G7,Postdoc 46 | U92,G3,PhD 47 | U97,G4,Admin 48 | U99,G2,PhD 49 | U102,NA,Emeritus 50 | U106,G6,PhD 51 | U107,G5,Postdoc 52 | U109,G2,Phd (visiting) 53 | U110,G7,Professor 54 | U112,G3,PhD 55 | U113,G7,PhD 56 | U118,G6,Associate 57 | U123,G2/G6,Admin 58 | U124,G2,PhD 59 | U126,G4,Postdoc 60 | U130,G2,Professor 61 | U134,G3,Postdoc 62 | U138,G7,Postdoc 63 | U139,NA,Associate 64 | U140,G8,Assistant 65 | U141,G3,PhD 66 | U142,G3,PhD 67 | 68 | #EDGES 69 | U102,U139,lunch 70 | U102,U33,lunch 71 | U106,U107,facebook 72 | U106,U118,coauthor 73 | U106,U118,leisure 74 | U106,U118,lunch 75 | U106,U118,work 76 | U106,U123,facebook 77 | U106,U123,work 78 | U106,U1,facebook 79 | U106,U21,facebook 80 | U106,U22,lunch 81 | U106,U26,lunch 82 | U106,U26,work 83 | U106,U29,facebook 84 | U106,U32,facebook 85 | U106,U41,leisure 86 | U106,U41,lunch 87 | U106,U41,work 88 | U106,U42,lunch 89 | U106,U49,lunch 90 | U106,U59,facebook 91 | U106,U97,lunch 92 | U107,U106,facebook 93 | U107,U124,facebook 94 | U107,U139,work 95 | U107,U17,leisure 96 | U107,U17,lunch 97 | U107,U17,work 98 | U107,U29,facebook 99 | U107,U29,lunch 100 | U107,U29,work 101 | U107,U32,facebook 102 | U107,U32,leisure 103 | U107,U32,lunch 104 | U107,U32,work 105 | U107,U71,facebook 106 | U107,U71,work 107 | U107,U86,work 108 | U107,U91,leisure 109 | U109,U124,facebook 110 | U109,U124,lunch 111 | U109,U126,leisure 112 | U109,U126,lunch 113 | U109,U130,work 114 | U109,U134,lunch 115 | U109,U18,facebook 116 | U109,U18,lunch 117 | U109,U3,lunch 118 | U109,U47,facebook 119 | U109,U47,lunch 120 | U109,U54,facebook 121 | U109,U54,leisure 122 | U109,U54,lunch 123 | U109,U54,work 124 | U109,U62,lunch 125 | U109,U62,work 126 | U109,U76,facebook 127 | U109,U76,leisure 128 | U109,U76,lunch 129 | U109,U79,facebook 130 | U109,U79,lunch 131 | U109,U90,leisure 132 | U109,U90,lunch 133 | U109,U99,lunch 134 | U10,U130,work 135 | U10,U139,work 136 | U10,U13,leisure 137 | U10,U142,facebook 138 | U10,U142,leisure 139 | U10,U14,lunch 140 | U10,U14,work 141 | U10,U19,lunch 142 | U10,U19,work 143 | U10,U1,coauthor 144 | U10,U1,facebook 145 | U10,U1,leisure 146 | U10,U1,lunch 147 | U10,U1,work 148 | U10,U23,work 149 | U10,U37,leisure 150 | U10,U4,facebook 151 | U10,U54,facebook 152 | U10,U54,leisure 153 | U10,U73,leisure 154 | U10,U73,work 155 | U10,U91,facebook 156 | U110,U113,facebook 157 | U110,U113,leisure 158 | U110,U113,lunch 159 | U110,U113,work 160 | U110,U123,work 161 | U110,U126,leisure 162 | U110,U126,lunch 163 | U110,U126,work 164 | U110,U130,lunch 165 | U110,U138,coauthor 166 | U110,U138,leisure 167 | U110,U138,work 168 | U110,U142,facebook 169 | U110,U26,work 170 | U110,U32,facebook 171 | U110,U32,work 172 | U110,U33,work 173 | U110,U4,facebook 174 | U110,U53,coauthor 175 | U110,U53,lunch 176 | U110,U53,work 177 | U110,U59,facebook 178 | U110,U59,leisure 179 | U110,U59,lunch 180 | U110,U59,work 181 | U110,U65,leisure 182 | U110,U67,facebook 183 | U110,U67,leisure 184 | U110,U67,work 185 | U110,U71,facebook 186 | U110,U71,work 187 | U110,U72,lunch 188 | U110,U72,work 189 | U110,U79,facebook 190 | U110,U79,work 191 | U110,U91,coauthor 192 | U110,U91,facebook 193 | U110,U91,leisure 194 | U110,U91,lunch 195 | U110,U91,work 196 | U110,U97,coauthor 197 | U112,U48,lunch 198 | U112,U4,lunch 199 | U112,U4,work 200 | U112,U65,facebook 201 | U112,U68,lunch 202 | U112,U68,work 203 | U112,U76,facebook 204 | U113,U110,facebook 205 | U113,U110,leisure 206 | U113,U110,lunch 207 | U113,U110,work 208 | U113,U126,lunch 209 | U113,U138,leisure 210 | U113,U138,lunch 211 | U113,U138,work 212 | U113,U59,facebook 213 | U113,U65,facebook 214 | U113,U65,leisure 215 | U113,U67,facebook 216 | U113,U67,lunch 217 | U113,U67,work 218 | U113,U69,facebook 219 | U113,U72,lunch 220 | U113,U91,facebook 221 | U113,U91,leisure 222 | U113,U91,work 223 | U118,U106,coauthor 224 | U118,U106,leisure 225 | U118,U106,lunch 226 | U118,U106,work 227 | U118,U123,work 228 | U118,U22,lunch 229 | U118,U26,lunch 230 | U118,U26,work 231 | U118,U33,work 232 | U118,U41,coauthor 233 | U118,U41,leisure 234 | U118,U41,lunch 235 | U118,U41,work 236 | U118,U42,lunch 237 | U118,U49,lunch 238 | U118,U67,work 239 | U118,U71,work 240 | U118,U90,work 241 | U118,U97,work 242 | U123,U106,facebook 243 | U123,U106,work 244 | U123,U110,work 245 | U123,U118,work 246 | U123,U124,work 247 | U123,U130,facebook 248 | U123,U130,work 249 | U123,U139,work 250 | U123,U142,facebook 251 | U123,U142,work 252 | U123,U17,work 253 | U123,U18,work 254 | U123,U22,work 255 | U123,U26,work 256 | U123,U32,facebook 257 | U123,U33,lunch 258 | U123,U33,work 259 | U123,U3,work 260 | U123,U42,facebook 261 | U123,U42,work 262 | U123,U47,facebook 263 | U123,U47,work 264 | U123,U49,facebook 265 | U123,U49,work 266 | U123,U4,facebook 267 | U123,U4,lunch 268 | U123,U4,work 269 | U123,U54,work 270 | U123,U62,work 271 | U123,U63,lunch 272 | U123,U63,work 273 | U123,U67,facebook 274 | U123,U67,lunch 275 | U123,U67,work 276 | U123,U71,facebook 277 | U123,U71,lunch 278 | U123,U71,work 279 | U123,U76,work 280 | U123,U79,lunch 281 | U123,U79,work 282 | U123,U90,work 283 | U123,U91,facebook 284 | U123,U97,work 285 | U123,U99,work 286 | U124,U107,facebook 287 | U124,U109,facebook 288 | U124,U109,lunch 289 | U124,U123,work 290 | U124,U126,leisure 291 | U124,U126,lunch 292 | U124,U130,facebook 293 | U124,U130,work 294 | U124,U134,facebook 295 | U124,U18,facebook 296 | U124,U18,leisure 297 | U124,U1,work 298 | U124,U3,facebook 299 | U124,U47,facebook 300 | U124,U47,lunch 301 | U124,U4,work 302 | U124,U54,facebook 303 | U124,U69,facebook 304 | U124,U6,facebook 305 | U124,U76,facebook 306 | U124,U79,facebook 307 | U124,U91,facebook 308 | U124,U91,leisure 309 | U124,U99,leisure 310 | U124,U99,lunch 311 | U126,U109,leisure 312 | U126,U109,lunch 313 | U126,U110,leisure 314 | U126,U110,lunch 315 | U126,U110,work 316 | U126,U113,lunch 317 | U126,U124,leisure 318 | U126,U124,lunch 319 | U126,U138,lunch 320 | U126,U21,leisure 321 | U126,U21,lunch 322 | U126,U29,leisure 323 | U126,U37,lunch 324 | U126,U54,leisure 325 | U126,U54,lunch 326 | U126,U59,lunch 327 | U126,U67,work 328 | U126,U69,leisure 329 | U126,U69,lunch 330 | U126,U69,work 331 | U126,U6,lunch 332 | U126,U72,lunch 333 | U126,U90,leisure 334 | U126,U90,lunch 335 | U126,U91,leisure 336 | U126,U91,lunch 337 | U126,U97,lunch 338 | U130,U109,work 339 | U130,U10,work 340 | U130,U110,lunch 341 | U130,U123,facebook 342 | U130,U123,work 343 | U130,U124,facebook 344 | U130,U124,work 345 | U130,U134,coauthor 346 | U130,U134,facebook 347 | U130,U134,lunch 348 | U130,U134,work 349 | U130,U142,facebook 350 | U130,U18,coauthor 351 | U130,U18,facebook 352 | U130,U18,work 353 | U130,U1,work 354 | U130,U26,work 355 | U130,U32,facebook 356 | U130,U32,lunch 357 | U130,U32,work 358 | U130,U3,facebook 359 | U130,U47,coauthor 360 | U130,U47,facebook 361 | U130,U47,work 362 | U130,U4,facebook 363 | U130,U4,lunch 364 | U130,U4,work 365 | U130,U54,work 366 | U130,U62,work 367 | U130,U67,facebook 368 | U130,U76,coauthor 369 | U130,U76,facebook 370 | U130,U76,work 371 | U130,U79,facebook 372 | U130,U79,lunch 373 | U130,U79,work 374 | U130,U86,lunch 375 | U130,U99,coauthor 376 | U130,U99,work 377 | U134,U109,lunch 378 | U134,U124,facebook 379 | U134,U130,coauthor 380 | U134,U130,facebook 381 | U134,U130,lunch 382 | U134,U130,work 383 | U134,U13,lunch 384 | U134,U48,lunch 385 | U134,U4,lunch 386 | U134,U4,work 387 | U134,U54,lunch 388 | U134,U62,lunch 389 | U134,U76,lunch 390 | U134,U79,lunch 391 | U134,U90,lunch 392 | U134,U92,lunch 393 | U134,U99,lunch 394 | U134,U99,work 395 | U138,U110,coauthor 396 | U138,U110,leisure 397 | U138,U110,work 398 | U138,U113,leisure 399 | U138,U113,lunch 400 | U138,U113,work 401 | U138,U126,lunch 402 | U138,U67,work 403 | U138,U72,leisure 404 | U138,U72,lunch 405 | U138,U91,leisure 406 | U138,U91,work 407 | U139,U102,lunch 408 | U139,U107,work 409 | U139,U10,work 410 | U139,U123,work 411 | U139,U14,work 412 | U139,U19,work 413 | U139,U1,work 414 | U139,U26,work 415 | U139,U29,work 416 | U139,U67,work 417 | U139,U71,work 418 | U139,U97,work 419 | U13,U10,leisure 420 | U13,U134,lunch 421 | U13,U142,lunch 422 | U13,U48,coauthor 423 | U13,U48,work 424 | U13,U4,lunch 425 | U13,U4,work 426 | U13,U54,work 427 | U13,U92,work 428 | U140,U26,work 429 | U140,U71,work 430 | U141,U48,lunch 431 | U141,U4,lunch 432 | U141,U4,work 433 | U141,U68,leisure 434 | U141,U68,lunch 435 | U141,U68,work 436 | U141,U92,lunch 437 | U142,U10,facebook 438 | U142,U10,leisure 439 | U142,U110,facebook 440 | U142,U123,facebook 441 | U142,U123,work 442 | U142,U130,facebook 443 | U142,U13,lunch 444 | U142,U37,leisure 445 | U142,U42,facebook 446 | U142,U42,leisure 447 | U142,U47,facebook 448 | U142,U4,facebook 449 | U142,U4,lunch 450 | U142,U4,work 451 | U142,U54,facebook 452 | U142,U67,facebook 453 | U142,U68,coauthor 454 | U142,U68,leisure 455 | U142,U68,work 456 | U142,U79,facebook 457 | U142,U91,facebook 458 | U14,U10,lunch 459 | U14,U10,work 460 | U14,U139,work 461 | U14,U17,leisure 462 | U14,U17,lunch 463 | U14,U17,work 464 | U14,U19,leisure 465 | U14,U19,lunch 466 | U14,U19,work 467 | U14,U1,leisure 468 | U14,U1,lunch 469 | U14,U1,work 470 | U14,U23,leisure 471 | U14,U23,lunch 472 | U14,U23,work 473 | U14,U29,lunch 474 | U14,U32,lunch 475 | U14,U32,work 476 | U14,U71,work 477 | U14,U73,leisure 478 | U14,U73,lunch 479 | U14,U73,work 480 | U17,U107,leisure 481 | U17,U107,lunch 482 | U17,U107,work 483 | U17,U123,work 484 | U17,U14,leisure 485 | U17,U14,lunch 486 | U17,U14,work 487 | U17,U23,leisure 488 | U17,U23,lunch 489 | U17,U23,work 490 | U17,U29,lunch 491 | U17,U29,work 492 | U17,U32,lunch 493 | U17,U32,work 494 | U17,U73,leisure 495 | U17,U73,lunch 496 | U17,U73,work 497 | U17,U91,leisure 498 | U18,U109,facebook 499 | U18,U109,lunch 500 | U18,U123,work 501 | U18,U124,facebook 502 | U18,U124,leisure 503 | U18,U130,coauthor 504 | U18,U130,facebook 505 | U18,U130,work 506 | U18,U3,facebook 507 | U18,U3,lunch 508 | U18,U47,facebook 509 | U18,U54,facebook 510 | U18,U54,lunch 511 | U18,U62,leisure 512 | U18,U62,lunch 513 | U18,U62,work 514 | U18,U76,coauthor 515 | U18,U76,facebook 516 | U18,U76,leisure 517 | U18,U76,lunch 518 | U18,U79,facebook 519 | U18,U79,lunch 520 | U18,U90,lunch 521 | U18,U99,leisure 522 | U18,U99,lunch 523 | U19,U10,lunch 524 | U19,U10,work 525 | U19,U139,work 526 | U19,U14,leisure 527 | U19,U14,lunch 528 | U19,U14,work 529 | U19,U1,lunch 530 | U19,U1,work 531 | U19,U23,leisure 532 | U19,U23,lunch 533 | U19,U23,work 534 | U19,U54,work 535 | U19,U71,work 536 | U19,U73,leisure 537 | U19,U73,lunch 538 | U19,U73,work 539 | U1,U106,facebook 540 | U1,U10,coauthor 541 | U1,U10,facebook 542 | U1,U10,leisure 543 | U1,U10,lunch 544 | U1,U10,work 545 | U1,U124,work 546 | U1,U130,work 547 | U1,U139,work 548 | U1,U14,leisure 549 | U1,U14,lunch 550 | U1,U14,work 551 | U1,U19,lunch 552 | U1,U19,work 553 | U1,U23,leisure 554 | U1,U23,lunch 555 | U1,U23,work 556 | U1,U26,leisure 557 | U1,U26,work 558 | U1,U29,facebook 559 | U1,U29,lunch 560 | U1,U32,facebook 561 | U1,U32,lunch 562 | U1,U32,work 563 | U1,U71,facebook 564 | U1,U71,work 565 | U1,U73,leisure 566 | U1,U73,lunch 567 | U1,U73,work 568 | U1,U79,facebook 569 | U1,U79,work 570 | U21,U106,facebook 571 | U21,U126,leisure 572 | U21,U126,lunch 573 | U21,U33,work 574 | U21,U37,lunch 575 | U21,U67,facebook 576 | U21,U67,lunch 577 | U21,U67,work 578 | U21,U69,facebook 579 | U21,U69,lunch 580 | U21,U6,facebook 581 | U21,U6,lunch 582 | U21,U97,lunch 583 | U22,U106,lunch 584 | U22,U118,lunch 585 | U22,U123,work 586 | U22,U26,coauthor 587 | U22,U26,lunch 588 | U22,U26,work 589 | U22,U41,lunch 590 | U22,U41,work 591 | U22,U42,leisure 592 | U22,U42,lunch 593 | U22,U42,work 594 | U22,U49,lunch 595 | U22,U49,work 596 | U23,U10,work 597 | U23,U14,leisure 598 | U23,U14,lunch 599 | U23,U14,work 600 | U23,U17,leisure 601 | U23,U17,lunch 602 | U23,U17,work 603 | U23,U19,leisure 604 | U23,U19,lunch 605 | U23,U19,work 606 | U23,U1,leisure 607 | U23,U1,lunch 608 | U23,U1,work 609 | U23,U73,leisure 610 | U23,U73,lunch 611 | U23,U73,work 612 | U26,U106,lunch 613 | U26,U106,work 614 | U26,U110,work 615 | U26,U118,lunch 616 | U26,U118,work 617 | U26,U123,work 618 | U26,U130,work 619 | U26,U139,work 620 | U26,U140,work 621 | U26,U1,leisure 622 | U26,U1,work 623 | U26,U22,coauthor 624 | U26,U22,lunch 625 | U26,U22,work 626 | U26,U32,work 627 | U26,U33,work 628 | U26,U41,lunch 629 | U26,U42,lunch 630 | U26,U42,work 631 | U26,U49,lunch 632 | U26,U49,work 633 | U26,U71,work 634 | U26,U79,work 635 | U26,U97,work 636 | U29,U106,facebook 637 | U29,U107,facebook 638 | U29,U107,lunch 639 | U29,U107,work 640 | U29,U126,leisure 641 | U29,U139,work 642 | U29,U14,lunch 643 | U29,U17,lunch 644 | U29,U17,work 645 | U29,U1,facebook 646 | U29,U1,lunch 647 | U29,U32,coauthor 648 | U29,U32,facebook 649 | U29,U32,leisure 650 | U29,U32,lunch 651 | U29,U32,work 652 | U29,U91,facebook 653 | U32,U106,facebook 654 | U32,U107,facebook 655 | U32,U107,leisure 656 | U32,U107,lunch 657 | U32,U107,work 658 | U32,U110,facebook 659 | U32,U110,work 660 | U32,U123,facebook 661 | U32,U130,facebook 662 | U32,U130,lunch 663 | U32,U130,work 664 | U32,U14,lunch 665 | U32,U14,work 666 | U32,U17,lunch 667 | U32,U17,work 668 | U32,U1,facebook 669 | U32,U1,lunch 670 | U32,U1,work 671 | U32,U26,work 672 | U32,U29,coauthor 673 | U32,U29,facebook 674 | U32,U29,leisure 675 | U32,U29,lunch 676 | U32,U29,work 677 | U32,U4,facebook 678 | U32,U67,facebook 679 | U32,U71,facebook 680 | U32,U73,lunch 681 | U32,U73,work 682 | U32,U86,work 683 | U32,U91,facebook 684 | U32,U97,work 685 | U33,U102,lunch 686 | U33,U110,work 687 | U33,U118,work 688 | U33,U123,lunch 689 | U33,U123,work 690 | U33,U21,work 691 | U33,U26,work 692 | U33,U4,lunch 693 | U33,U4,work 694 | U33,U63,lunch 695 | U33,U63,work 696 | U33,U67,lunch 697 | U33,U67,work 698 | U33,U71,lunch 699 | U33,U71,work 700 | U37,U10,leisure 701 | U37,U126,lunch 702 | U37,U142,leisure 703 | U37,U21,lunch 704 | U37,U67,lunch 705 | U37,U67,work 706 | U37,U69,lunch 707 | U37,U6,lunch 708 | U37,U97,lunch 709 | U3,U109,lunch 710 | U3,U123,work 711 | U3,U124,facebook 712 | U3,U130,facebook 713 | U3,U18,facebook 714 | U3,U18,lunch 715 | U3,U47,facebook 716 | U3,U54,facebook 717 | U3,U54,leisure 718 | U3,U54,lunch 719 | U3,U62,lunch 720 | U3,U76,facebook 721 | U3,U76,lunch 722 | U3,U79,facebook 723 | U3,U79,lunch 724 | U3,U90,leisure 725 | U3,U90,lunch 726 | U3,U90,work 727 | U41,U106,leisure 728 | U41,U106,lunch 729 | U41,U106,work 730 | U41,U118,coauthor 731 | U41,U118,leisure 732 | U41,U118,lunch 733 | U41,U118,work 734 | U41,U22,lunch 735 | U41,U22,work 736 | U41,U26,lunch 737 | U41,U42,lunch 738 | U42,U106,lunch 739 | U42,U118,lunch 740 | U42,U123,facebook 741 | U42,U123,work 742 | U42,U142,facebook 743 | U42,U142,leisure 744 | U42,U22,leisure 745 | U42,U22,lunch 746 | U42,U22,work 747 | U42,U26,lunch 748 | U42,U26,work 749 | U42,U41,lunch 750 | U42,U47,lunch 751 | U42,U49,facebook 752 | U42,U49,leisure 753 | U42,U49,lunch 754 | U42,U79,facebook 755 | U42,U79,leisure 756 | U42,U79,work 757 | U47,U109,facebook 758 | U47,U109,lunch 759 | U47,U123,facebook 760 | U47,U123,work 761 | U47,U124,facebook 762 | U47,U124,lunch 763 | U47,U130,coauthor 764 | U47,U130,facebook 765 | U47,U130,work 766 | U47,U142,facebook 767 | U47,U18,facebook 768 | U47,U3,facebook 769 | U47,U42,lunch 770 | U47,U4,facebook 771 | U47,U54,facebook 772 | U47,U62,work 773 | U47,U76,facebook 774 | U47,U76,leisure 775 | U47,U79,facebook 776 | U47,U79,lunch 777 | U47,U99,coauthor 778 | U47,U99,lunch 779 | U47,U99,work 780 | U48,U112,lunch 781 | U48,U134,lunch 782 | U48,U13,coauthor 783 | U48,U13,work 784 | U48,U141,lunch 785 | U48,U4,lunch 786 | U48,U4,work 787 | U48,U68,lunch 788 | U48,U69,work 789 | U48,U92,lunch 790 | U49,U106,lunch 791 | U49,U118,lunch 792 | U49,U123,facebook 793 | U49,U123,work 794 | U49,U22,lunch 795 | U49,U22,work 796 | U49,U26,lunch 797 | U49,U26,work 798 | U49,U42,facebook 799 | U49,U42,leisure 800 | U49,U42,lunch 801 | U4,U10,facebook 802 | U4,U110,facebook 803 | U4,U112,lunch 804 | U4,U112,work 805 | U4,U123,facebook 806 | U4,U123,lunch 807 | U4,U123,work 808 | U4,U124,work 809 | U4,U130,facebook 810 | U4,U130,lunch 811 | U4,U130,work 812 | U4,U134,lunch 813 | U4,U134,work 814 | U4,U13,lunch 815 | U4,U13,work 816 | U4,U141,lunch 817 | U4,U141,work 818 | U4,U142,facebook 819 | U4,U142,lunch 820 | U4,U142,work 821 | U4,U32,facebook 822 | U4,U33,lunch 823 | U4,U33,work 824 | U4,U47,facebook 825 | U4,U48,lunch 826 | U4,U48,work 827 | U4,U54,facebook 828 | U4,U54,work 829 | U4,U63,lunch 830 | U4,U63,work 831 | U4,U67,facebook 832 | U4,U67,leisure 833 | U4,U67,lunch 834 | U4,U67,work 835 | U4,U68,lunch 836 | U4,U68,work 837 | U4,U71,facebook 838 | U4,U71,lunch 839 | U4,U71,work 840 | U4,U76,facebook 841 | U4,U76,work 842 | U4,U79,work 843 | U4,U90,work 844 | U4,U91,facebook 845 | U4,U92,lunch 846 | U4,U92,work 847 | U4,U97,lunch 848 | U4,U97,work 849 | U4,U99,work 850 | U53,U110,coauthor 851 | U53,U110,lunch 852 | U53,U110,work 853 | U53,U59,lunch 854 | U53,U65,lunch 855 | U53,U72,coauthor 856 | U53,U72,lunch 857 | U53,U91,coauthor 858 | U53,U91,leisure 859 | U53,U91,lunch 860 | U53,U91,work 861 | U54,U109,facebook 862 | U54,U109,leisure 863 | U54,U109,lunch 864 | U54,U109,work 865 | U54,U10,facebook 866 | U54,U10,leisure 867 | U54,U123,work 868 | U54,U124,facebook 869 | U54,U126,leisure 870 | U54,U126,lunch 871 | U54,U130,work 872 | U54,U134,lunch 873 | U54,U13,work 874 | U54,U142,facebook 875 | U54,U18,facebook 876 | U54,U18,lunch 877 | U54,U19,work 878 | U54,U3,facebook 879 | U54,U3,leisure 880 | U54,U3,lunch 881 | U54,U47,facebook 882 | U54,U4,facebook 883 | U54,U4,work 884 | U54,U62,lunch 885 | U54,U76,facebook 886 | U54,U76,leisure 887 | U54,U76,lunch 888 | U54,U79,facebook 889 | U54,U79,leisure 890 | U54,U79,lunch 891 | U54,U79,work 892 | U54,U90,leisure 893 | U54,U90,lunch 894 | U54,U90,work 895 | U54,U91,leisure 896 | U59,U106,facebook 897 | U59,U110,facebook 898 | U59,U110,leisure 899 | U59,U110,lunch 900 | U59,U110,work 901 | U59,U113,facebook 902 | U59,U126,lunch 903 | U59,U53,lunch 904 | U59,U65,leisure 905 | U59,U65,lunch 906 | U59,U67,facebook 907 | U59,U67,lunch 908 | U59,U67,work 909 | U59,U72,leisure 910 | U59,U72,lunch 911 | U59,U91,facebook 912 | U59,U91,leisure 913 | U59,U91,lunch 914 | U59,U91,work 915 | U62,U109,lunch 916 | U62,U109,work 917 | U62,U123,work 918 | U62,U130,work 919 | U62,U134,lunch 920 | U62,U18,leisure 921 | U62,U18,lunch 922 | U62,U18,work 923 | U62,U3,lunch 924 | U62,U47,work 925 | U62,U54,lunch 926 | U62,U76,leisure 927 | U62,U76,lunch 928 | U62,U76,work 929 | U62,U79,lunch 930 | U62,U90,lunch 931 | U63,U123,lunch 932 | U63,U123,work 933 | U63,U33,lunch 934 | U63,U33,work 935 | U63,U4,lunch 936 | U63,U4,work 937 | U63,U67,lunch 938 | U63,U67,work 939 | U63,U71,lunch 940 | U63,U71,work 941 | U63,U79,lunch 942 | U65,U110,leisure 943 | U65,U112,facebook 944 | U65,U113,facebook 945 | U65,U113,leisure 946 | U65,U53,lunch 947 | U65,U59,leisure 948 | U65,U59,lunch 949 | U65,U67,lunch 950 | U65,U67,work 951 | U65,U72,leisure 952 | U65,U72,lunch 953 | U65,U72,work 954 | U65,U79,facebook 955 | U65,U79,leisure 956 | U65,U91,facebook 957 | U65,U91,leisure 958 | U65,U91,lunch 959 | U65,U91,work 960 | U67,U110,facebook 961 | U67,U110,leisure 962 | U67,U110,work 963 | U67,U113,facebook 964 | U67,U113,lunch 965 | U67,U113,work 966 | U67,U118,work 967 | U67,U123,facebook 968 | U67,U123,lunch 969 | U67,U123,work 970 | U67,U126,work 971 | U67,U130,facebook 972 | U67,U138,work 973 | U67,U139,work 974 | U67,U142,facebook 975 | U67,U21,facebook 976 | U67,U21,lunch 977 | U67,U21,work 978 | U67,U32,facebook 979 | U67,U33,lunch 980 | U67,U33,work 981 | U67,U37,lunch 982 | U67,U37,work 983 | U67,U4,facebook 984 | U67,U4,leisure 985 | U67,U4,lunch 986 | U67,U4,work 987 | U67,U59,facebook 988 | U67,U59,lunch 989 | U67,U59,work 990 | U67,U63,lunch 991 | U67,U63,work 992 | U67,U65,lunch 993 | U67,U65,work 994 | U67,U69,facebook 995 | U67,U69,work 996 | U67,U6,facebook 997 | U67,U6,work 998 | U67,U71,facebook 999 | U67,U71,lunch 1000 | U67,U71,work 1001 | U67,U72,lunch 1002 | U67,U72,work 1003 | U67,U91,facebook 1004 | U67,U91,lunch 1005 | U67,U91,work 1006 | U67,U97,work 1007 | U68,U112,lunch 1008 | U68,U112,work 1009 | U68,U141,leisure 1010 | U68,U141,lunch 1011 | U68,U141,work 1012 | U68,U142,coauthor 1013 | U68,U142,leisure 1014 | U68,U142,work 1015 | U68,U48,lunch 1016 | U68,U4,lunch 1017 | U68,U4,work 1018 | U68,U92,lunch 1019 | U69,U113,facebook 1020 | U69,U124,facebook 1021 | U69,U126,leisure 1022 | U69,U126,lunch 1023 | U69,U126,work 1024 | U69,U21,facebook 1025 | U69,U21,lunch 1026 | U69,U37,lunch 1027 | U69,U48,work 1028 | U69,U67,facebook 1029 | U69,U67,work 1030 | U69,U6,facebook 1031 | U69,U6,lunch 1032 | U69,U72,lunch 1033 | U69,U91,facebook 1034 | U69,U91,leisure 1035 | U69,U97,lunch 1036 | U6,U124,facebook 1037 | U6,U126,lunch 1038 | U6,U21,facebook 1039 | U6,U21,lunch 1040 | U6,U37,lunch 1041 | U6,U67,facebook 1042 | U6,U67,work 1043 | U6,U69,facebook 1044 | U6,U69,lunch 1045 | U6,U71,work 1046 | U6,U90,leisure 1047 | U6,U90,lunch 1048 | U6,U97,lunch 1049 | U71,U107,facebook 1050 | U71,U107,work 1051 | U71,U110,facebook 1052 | U71,U110,work 1053 | U71,U118,work 1054 | U71,U123,facebook 1055 | U71,U123,lunch 1056 | U71,U123,work 1057 | U71,U139,work 1058 | U71,U140,work 1059 | U71,U14,work 1060 | U71,U19,work 1061 | U71,U1,facebook 1062 | U71,U1,work 1063 | U71,U26,work 1064 | U71,U32,facebook 1065 | U71,U33,lunch 1066 | U71,U33,work 1067 | U71,U4,facebook 1068 | U71,U4,lunch 1069 | U71,U4,work 1070 | U71,U63,lunch 1071 | U71,U63,work 1072 | U71,U67,facebook 1073 | U71,U67,lunch 1074 | U71,U67,work 1075 | U71,U6,work 1076 | U71,U79,facebook 1077 | U71,U97,lunch 1078 | U71,U97,work 1079 | U72,U110,lunch 1080 | U72,U110,work 1081 | U72,U113,lunch 1082 | U72,U126,lunch 1083 | U72,U138,leisure 1084 | U72,U138,lunch 1085 | U72,U53,coauthor 1086 | U72,U53,lunch 1087 | U72,U59,leisure 1088 | U72,U59,lunch 1089 | U72,U65,leisure 1090 | U72,U65,lunch 1091 | U72,U65,work 1092 | U72,U67,lunch 1093 | U72,U67,work 1094 | U72,U69,lunch 1095 | U72,U91,coauthor 1096 | U72,U91,leisure 1097 | U72,U91,lunch 1098 | U72,U91,work 1099 | U73,U10,leisure 1100 | U73,U10,work 1101 | U73,U14,leisure 1102 | U73,U14,lunch 1103 | U73,U14,work 1104 | U73,U17,leisure 1105 | U73,U17,lunch 1106 | U73,U17,work 1107 | U73,U19,leisure 1108 | U73,U19,lunch 1109 | U73,U19,work 1110 | U73,U1,leisure 1111 | U73,U1,lunch 1112 | U73,U1,work 1113 | U73,U23,leisure 1114 | U73,U23,lunch 1115 | U73,U23,work 1116 | U73,U32,lunch 1117 | U73,U32,work 1118 | U73,U79,leisure 1119 | U76,U109,facebook 1120 | U76,U109,leisure 1121 | U76,U109,lunch 1122 | U76,U112,facebook 1123 | U76,U123,work 1124 | U76,U124,facebook 1125 | U76,U130,coauthor 1126 | U76,U130,facebook 1127 | U76,U130,work 1128 | U76,U134,lunch 1129 | U76,U18,coauthor 1130 | U76,U18,facebook 1131 | U76,U18,leisure 1132 | U76,U18,lunch 1133 | U76,U3,facebook 1134 | U76,U3,lunch 1135 | U76,U47,facebook 1136 | U76,U47,leisure 1137 | U76,U4,facebook 1138 | U76,U4,work 1139 | U76,U54,facebook 1140 | U76,U54,leisure 1141 | U76,U54,lunch 1142 | U76,U62,leisure 1143 | U76,U62,lunch 1144 | U76,U62,work 1145 | U76,U79,facebook 1146 | U76,U79,leisure 1147 | U76,U79,lunch 1148 | U76,U90,leisure 1149 | U76,U90,lunch 1150 | U76,U99,lunch 1151 | U79,U109,facebook 1152 | U79,U109,lunch 1153 | U79,U110,facebook 1154 | U79,U110,work 1155 | U79,U123,lunch 1156 | U79,U123,work 1157 | U79,U124,facebook 1158 | U79,U130,facebook 1159 | U79,U130,lunch 1160 | U79,U130,work 1161 | U79,U134,lunch 1162 | U79,U142,facebook 1163 | U79,U18,facebook 1164 | U79,U18,lunch 1165 | U79,U1,facebook 1166 | U79,U1,work 1167 | U79,U26,work 1168 | U79,U3,facebook 1169 | U79,U3,lunch 1170 | U79,U42,facebook 1171 | U79,U42,leisure 1172 | U79,U42,work 1173 | U79,U47,facebook 1174 | U79,U47,lunch 1175 | U79,U4,work 1176 | U79,U54,facebook 1177 | U79,U54,leisure 1178 | U79,U54,lunch 1179 | U79,U54,work 1180 | U79,U62,lunch 1181 | U79,U63,lunch 1182 | U79,U65,facebook 1183 | U79,U65,leisure 1184 | U79,U71,facebook 1185 | U79,U73,leisure 1186 | U79,U76,facebook 1187 | U79,U76,leisure 1188 | U79,U76,lunch 1189 | U79,U90,leisure 1190 | U79,U90,lunch 1191 | U79,U91,facebook 1192 | U79,U99,leisure 1193 | U79,U99,lunch 1194 | U79,U99,work 1195 | U86,U107,work 1196 | U86,U130,lunch 1197 | U86,U32,work 1198 | U90,U109,leisure 1199 | U90,U109,lunch 1200 | U90,U118,work 1201 | U90,U123,work 1202 | U90,U126,leisure 1203 | U90,U126,lunch 1204 | U90,U134,lunch 1205 | U90,U18,lunch 1206 | U90,U3,leisure 1207 | U90,U3,lunch 1208 | U90,U3,work 1209 | U90,U4,work 1210 | U90,U54,leisure 1211 | U90,U54,lunch 1212 | U90,U54,work 1213 | U90,U62,lunch 1214 | U90,U6,leisure 1215 | U90,U6,lunch 1216 | U90,U76,leisure 1217 | U90,U76,lunch 1218 | U90,U79,leisure 1219 | U90,U79,lunch 1220 | U90,U91,leisure 1221 | U91,U107,leisure 1222 | U91,U10,facebook 1223 | U91,U110,coauthor 1224 | U91,U110,facebook 1225 | U91,U110,leisure 1226 | U91,U110,lunch 1227 | U91,U110,work 1228 | U91,U113,facebook 1229 | U91,U113,leisure 1230 | U91,U113,work 1231 | U91,U123,facebook 1232 | U91,U124,facebook 1233 | U91,U124,leisure 1234 | U91,U126,leisure 1235 | U91,U126,lunch 1236 | U91,U138,leisure 1237 | U91,U138,work 1238 | U91,U142,facebook 1239 | U91,U17,leisure 1240 | U91,U29,facebook 1241 | U91,U32,facebook 1242 | U91,U4,facebook 1243 | U91,U53,coauthor 1244 | U91,U53,leisure 1245 | U91,U53,lunch 1246 | U91,U53,work 1247 | U91,U54,leisure 1248 | U91,U59,facebook 1249 | U91,U59,leisure 1250 | U91,U59,lunch 1251 | U91,U59,work 1252 | U91,U65,facebook 1253 | U91,U65,leisure 1254 | U91,U65,lunch 1255 | U91,U65,work 1256 | U91,U67,facebook 1257 | U91,U67,lunch 1258 | U91,U67,work 1259 | U91,U69,facebook 1260 | U91,U69,leisure 1261 | U91,U72,coauthor 1262 | U91,U72,leisure 1263 | U91,U72,lunch 1264 | U91,U72,work 1265 | U91,U79,facebook 1266 | U91,U90,leisure 1267 | U92,U134,lunch 1268 | U92,U13,work 1269 | U92,U141,lunch 1270 | U92,U48,lunch 1271 | U92,U4,lunch 1272 | U92,U4,work 1273 | U92,U68,lunch 1274 | U97,U106,lunch 1275 | U97,U110,coauthor 1276 | U97,U118,work 1277 | U97,U123,work 1278 | U97,U126,lunch 1279 | U97,U139,work 1280 | U97,U21,lunch 1281 | U97,U26,work 1282 | U97,U32,work 1283 | U97,U37,lunch 1284 | U97,U4,lunch 1285 | U97,U4,work 1286 | U97,U67,work 1287 | U97,U69,lunch 1288 | U97,U6,lunch 1289 | U97,U71,lunch 1290 | U97,U71,work 1291 | U99,U109,lunch 1292 | U99,U123,work 1293 | U99,U124,leisure 1294 | U99,U124,lunch 1295 | U99,U130,coauthor 1296 | U99,U130,work 1297 | U99,U134,lunch 1298 | U99,U134,work 1299 | U99,U18,leisure 1300 | U99,U18,lunch 1301 | U99,U47,coauthor 1302 | U99,U47,lunch 1303 | U99,U47,work 1304 | U99,U4,work 1305 | U99,U76,lunch 1306 | U99,U79,leisure 1307 | U99,U79,lunch 1308 | U99,U79,work 1309 | -------------------------------------------------------------------------------- /uunet/data/bankwiring.mpx: -------------------------------------------------------------------------------- 1 | #TYPE 2 | multiplex 3 | 4 | #LAYERS 5 | horseplay,UNDIRECTED 6 | arguments,UNDIRECTED 7 | friendship,UNDIRECTED 8 | antagonist,UNDIRECTED 9 | help,DIRECTED 10 | job_trading,DIRECTED 11 | 12 | #EDGE ATTRIBUTES 13 | job_trading,number,numeric 14 | 15 | #ACTORS 16 | I1 17 | I3 18 | W1 19 | W2 20 | W3 21 | W4 22 | W5 23 | W6 24 | W7 25 | W8 26 | W9 27 | S1 28 | S2 29 | S4 30 | 31 | #EDGES 32 | W1,W2,horseplay 33 | W1,W3,horseplay 34 | W1,W4,horseplay 35 | W1,W5,horseplay 36 | W1,S1,horseplay 37 | W2,W3,horseplay 38 | W2,W4,horseplay 39 | W2,S1,horseplay 40 | W3,W4,horseplay 41 | W3,W5,horseplay 42 | W3,S1,horseplay 43 | W4,W5,horseplay 44 | W4,S1,horseplay 45 | W5,W7,horseplay 46 | W5,S1,horseplay 47 | W6,W7,horseplay 48 | W6,W8,horseplay 49 | W6,W9,horseplay 50 | W7,W8,horseplay 51 | W7,W9,horseplay 52 | W7,S4,horseplay 53 | W8,W9,horseplay 54 | W8,S4,horseplay 55 | W9,S4,horseplay 56 | I1,W1,horseplay 57 | I1,W2,horseplay 58 | I1,W3,horseplay 59 | I1,W4,horseplay 60 | W4,W5,arguments 61 | W4,W6,arguments 62 | W4,W7,arguments 63 | W4,W9,arguments 64 | W5,W6,arguments 65 | W5,S1,arguments 66 | W6,W7,arguments 67 | W6,W8,arguments 68 | W6,W9,arguments 69 | W6,S1,arguments 70 | W6,S4,arguments 71 | W7,W8,arguments 72 | W7,W9,arguments 73 | W7,S4,arguments 74 | W8,W9,arguments 75 | W8,S1,arguments 76 | W8,S4,arguments 77 | W9,S1,arguments 78 | S1,S4,arguments 79 | W1,S1,friendship 80 | I1,W3,friendship 81 | W1,W3,friendship 82 | W1,W4,friendship 83 | W3,W4,friendship 84 | W3,S1,friendship 85 | W4,S1,friendship 86 | W7,W8,friendship 87 | W7,W9,friendship 88 | W7,S1,friendship 89 | W8,W9,friendship 90 | W8,S4,friendship 91 | W9,S4,friendship 92 | W1,W3,help 93 | W1,W9,help 94 | W1,S1,help 95 | W2,W3,help 96 | W2,W4,help 97 | W2,S1,help 98 | W3,W2,help 99 | W4,W1,help 100 | W4,W3,help 101 | W4,W6,help 102 | W5,W3,help 103 | W6,W3,help 104 | W8,W6,help 105 | W6,W7,help 106 | W6,W8,help 107 | W6,W9,help 108 | W7,S4,help 109 | W8,W7,help 110 | W8,W9,help 111 | W9,S4,help 112 | S1,W7,help 113 | S2,W6,help 114 | S4,W4,help 115 | S4,W8,help 116 | I1,I3,antagonist 117 | I1,W2,antagonist 118 | I3,W5,antagonist 119 | I3,W6,antagonist 120 | I3,W7,antagonist 121 | I3,W8,antagonist 122 | I3,W9,antagonist 123 | I3,S4,antagonist 124 | W2,W7,antagonist 125 | W2,W8,antagonist 126 | W2,W9,antagonist 127 | W4,W5,antagonist 128 | W5,W6,antagonist 129 | W5,W7,antagonist 130 | W5,W8,antagonist 131 | W5,W9,antagonist 132 | W5,S1,antagonist 133 | W5,S2,antagonist 134 | W6,W7,antagonist 135 | W1,S1,job_trading,2 136 | W2,S4,job_trading,4 137 | W2,S1,job_trading,12 138 | W6,S2,job_trading,2 139 | W5,S4,job_trading,7 140 | W8,S4,job_trading,20 141 | W7,S4,job_trading,2 142 | -------------------------------------------------------------------------------- /uunet/data/book.mpx: -------------------------------------------------------------------------------- 1 | Cici,Mat,LinkedIn 2 | Cici,Mark,LinkedIn 3 | Mark,Bin,LinkedIn 4 | Mat,Bin,LinkedIn 5 | Bin,Serena,LinkedIn 6 | Bin,Barby,LinkedIn 7 | Bin,Stine,LinkedIn 8 | Stine,Barby,LinkedIn 9 | Cici,Mat,Work 10 | Cici,Mark,Work 11 | Mat,Mark,Work 12 | Mat,Bin,Work 13 | Serena,Bin,Work 14 | Serena,Luca,Work 15 | Bin,Stine,Work 16 | Luca,Stine,Work 17 | Luca,Barby,Work 18 | Stine,Barby,Work 19 | Cici,Luca,Facebook 20 | Cici,Serena,Facebook 21 | Luca,Serena,Facebook 22 | Mark,Mat,Facebook 23 | Cici,Mat,Friend 24 | Cici,Mark,Friend 25 | Mat,Mark,Friend 26 | Mark,Serena,Friend 27 | Mat,Serena,Friend 28 | Bin,Luca,Friend 29 | Serena,Barby,Friend 30 | Luca,Barby,Friend 31 | -------------------------------------------------------------------------------- /uunet/data/florentine.mpx: -------------------------------------------------------------------------------- 1 | #TYPE 2 | multiplex 3 | 4 | #LAYERS 5 | marriage,UNDIRECTED 6 | business,UNDIRECTED 7 | 8 | #ACTOR ATTRIBUTES 9 | PRIORATES, NUMERIC 10 | TOTALTIES, NUMERIC 11 | WEALTH, NUMERIC 12 | 13 | #ACTORS 14 | Acciaiuoli,53,2,10 15 | Albizzi,65,3,36 16 | Barbadori,0,14,55 17 | Bischeri,12,9,44 18 | Castellani,22,18,20 19 | Ginori,0,9,32 20 | Guadagni,21,14, 8 21 | Lamberteschi,0,14,42 22 | Medici,53,54,103 23 | Pazzi,0,7,48 24 | Peruzzi,42,32,49 25 | Ridolfi,38,4,27 26 | Salviati,35,5,10 27 | Strozzi,74,29,146 28 | Tornabuoni,0,7,48 29 | 30 | #EDGES 31 | Ridolfi,Tornabuoni,marriage 32 | Ridolfi,Strozzi,marriage 33 | Peruzzi,Strozzi,marriage 34 | Pazzi,Salviati,marriage 35 | Medici,Tornabuoni,marriage 36 | Medici,Tornabuoni,business 37 | Medici,Salviati,business 38 | Medici,Salviati,marriage 39 | Medici,Ridolfi,marriage 40 | Medici,Pazzi,business 41 | Lamberteschi,Peruzzi,business 42 | Guadagni,Tornabuoni,marriage 43 | Guadagni,Lamberteschi,marriage 44 | Guadagni,Lamberteschi,business 45 | Ginori,Medici,business 46 | Castellani,Strozzi,marriage 47 | Castellani,Peruzzi,marriage 48 | Castellani,Peruzzi,business 49 | Castellani,Lamberteschi,business 50 | Bischeri,Strozzi,marriage 51 | Bischeri,Peruzzi,marriage 52 | Bischeri,Peruzzi,business 53 | Bischeri,Lamberteschi,business 54 | Bischeri,Guadagni,business 55 | Bischeri,Guadagni,marriage 56 | Barbadori,Peruzzi,business 57 | Barbadori,Medici,marriage 58 | Barbadori,Medici,business 59 | Barbadori,Ginori,business 60 | Barbadori,Castellani,business 61 | Barbadori,Castellani,marriage 62 | Albizzi,Medici,marriage 63 | Albizzi,Guadagni,marriage 64 | Albizzi,Ginori,marriage 65 | Acciaiuoli,Medici,marriage 66 | -------------------------------------------------------------------------------- /uunet/data/monastery.mpx: -------------------------------------------------------------------------------- 1 | #TYPE 2 | multiplex 3 | 4 | #LAYERS 5 | like1,DIRECTED 6 | like2,DIRECTED 7 | like3,DIRECTED 8 | dislike,DIRECTED 9 | esteem,DIRECTED 10 | desesteem,DIRECTED 11 | positive_influence,DIRECTED 12 | negative_influence,DIRECTED 13 | praise,DIRECTED 14 | blame,DIRECTED 15 | 16 | #EDGE ATTRIBUTES 17 | like1,rank,numeric 18 | like2,rank,numeric 19 | like3,rank,numeric 20 | dislike,rank,numeric 21 | esteem,rank,numeric 22 | desesteem,rank,numeric 23 | positive_influence,rank,numeric 24 | negative_influence,rank,numeric 25 | praise,rank,numeric 26 | blame,rank,numeric 27 | 28 | #ACTORS 29 | BONAVEN_5 30 | ROMUL_10 31 | AMBROSE_9 32 | PETER_4 33 | BERTH_6 34 | LOUIS_11 35 | BONI_15 36 | VICTOR_8 37 | AMAND_13 38 | WINF_12 39 | JOHN_1 40 | GREG_2 41 | HUGH_14 42 | MARK_7 43 | ALBERT_16 44 | BASIL_3 45 | ELIAS_17 46 | SIMP_18 47 | 48 | #EDGES 49 | ROMUL_10,AMBROSE_9,like1,2 50 | BONAVEN_5,VICTOR_8,like1,2 51 | ROMUL_10,PETER_4,like1,3 52 | ROMUL_10,ALBERT_16,like1,1 53 | AMBROSE_9,ROMUL_10,like1,2 54 | BONAVEN_5,ROMUL_10,like1,3 55 | BONAVEN_5,ALBERT_16,like1,1 56 | AMBROSE_9,BONAVEN_5,like1,3 57 | AMBROSE_9,ELIAS_17,like1,1 58 | BERTH_6,PETER_4,like1,3 59 | BERTH_6,LOUIS_11,like1,1 60 | BERTH_6,GREG_2,like1,2 61 | PETER_4,BERTH_6,like1,3 62 | PETER_4,HUGH_14,like1,2 63 | PETER_4,MARK_7,like1,1 64 | LOUIS_11,ROMUL_10,like1,1 65 | LOUIS_11,BERTH_6,like1,3 66 | LOUIS_11,JOHN_1,like1,2 67 | VICTOR_8,BONAVEN_5,like1,2 68 | VICTOR_8,WINF_12,like1,1 69 | WINF_12,BONAVEN_5,like1,2 70 | VICTOR_8,BASIL_3,like1,3 71 | WINF_12,ROMUL_10,like1,3 72 | JOHN_1,WINF_12,like1,3 73 | JOHN_1,BASIL_3,like1,1 74 | WINF_12,JOHN_1,like1,1 75 | JOHN_1,PETER_4,like1,2 76 | BASIL_3,VICTOR_8,like1,3 77 | GREG_2,ALBERT_16,like1,2 78 | GREG_2,BERTH_6,like1,3 79 | GREG_2,WINF_12,like1,1 80 | HUGH_14,ALBERT_16,like1,2 81 | HUGH_14,PETER_4,like1,3 82 | HUGH_14,WINF_12,like1,1 83 | BONI_15,BONAVEN_5,like1,2 84 | BONI_15,ROMUL_10,like1,3 85 | MARK_7,VICTOR_8,like1,1 86 | BONI_15,ALBERT_16,like1,1 87 | MARK_7,PETER_4,like1,2 88 | ALBERT_16,HUGH_14,like1,1 89 | ALBERT_16,BONI_15,like1,2 90 | MARK_7,SIMP_18,like1,3 91 | ALBERT_16,ROMUL_10,like1,3 92 | AMAND_13,BONAVEN_5,like1,2 93 | ALBERT_16,AMAND_13,like1,2 94 | AMAND_13,ROMUL_10,like1,3 95 | BASIL_3,BONAVEN_5,like1,2 96 | AMAND_13,ALBERT_16,like1,1 97 | BASIL_3,ROMUL_10,like1,1 98 | ELIAS_17,MARK_7,like1,2 99 | ELIAS_17,AMBROSE_9,like1,3 100 | SIMP_18,BONAVEN_5,like1,3 101 | ELIAS_17,SIMP_18,like1,1 102 | SIMP_18,ROMUL_10,like1,2 103 | SIMP_18,VICTOR_8,like1,1 104 | ROMUL_10,BONAVEN_5,like2,2 105 | BONAVEN_5,VICTOR_8,like2,1 106 | ROMUL_10,PETER_4,like2,1 107 | ROMUL_10,WINF_12,like2,3 108 | BONAVEN_5,AMAND_13,like2,1 109 | BONAVEN_5,ROMUL_10,like2,3 110 | AMBROSE_9,ELIAS_17,like2,1 111 | BONAVEN_5,BONI_15,like2,2 112 | AMBROSE_9,ROMUL_10,like2,3 113 | BERTH_6,LOUIS_11,like2,2 114 | AMBROSE_9,SIMP_18,like2,2 115 | BERTH_6,PETER_4,like2,3 116 | PETER_4,HUGH_14,like2,1 117 | BERTH_6,HUGH_14,like2,1 118 | PETER_4,ROMUL_10,like2,2 119 | PETER_4,BERTH_6,like2,3 120 | LOUIS_11,BERTH_6,like2,3 121 | LOUIS_11,ROMUL_10,like2,1 122 | VICTOR_8,BONAVEN_5,like2,2 123 | VICTOR_8,BASIL_3,like2,3 124 | LOUIS_11,JOHN_1,like2,2 125 | VICTOR_8,ROMUL_10,like2,1 126 | WINF_12,LOUIS_11,like2,1 127 | WINF_12,BERTH_6,like2,3 128 | JOHN_1,WINF_12,like2,3 129 | WINF_12,GREG_2,like2,2 130 | JOHN_1,PETER_4,like2,1 131 | GREG_2,PETER_4,like2,1 132 | JOHN_1,BONI_15,like2,2 133 | GREG_2,BERTH_6,like2,3 134 | HUGH_14,BASIL_3,like2,1 135 | GREG_2,MARK_7,like2,2 136 | HUGH_14,BERTH_6,like2,2 137 | HUGH_14,PETER_4,like2,3 138 | BONI_15,BONAVEN_5,like2,1 139 | BONI_15,ALBERT_16,like2,2 140 | BONI_15,ROMUL_10,like2,3 141 | MARK_7,VICTOR_8,like2,1 142 | MARK_7,PETER_4,like2,2 143 | ALBERT_16,BONAVEN_5,like2,1 144 | MARK_7,SIMP_18,like2,3 145 | ALBERT_16,ROMUL_10,like2,3 146 | AMAND_13,BONAVEN_5,like2,3 147 | AMAND_13,PETER_4,like2,1 148 | ALBERT_16,BONI_15,like2,1 149 | ALBERT_16,AMAND_13,like2,2 150 | AMAND_13,ROMUL_10,like2,2 151 | BASIL_3,VICTOR_8,like2,3 152 | BASIL_3,BONI_15,like2,1 153 | AMAND_13,ALBERT_16,like2,1 154 | BASIL_3,BONAVEN_5,like2,2 155 | ELIAS_17,AMBROSE_9,like2,2 156 | ELIAS_17,BONAVEN_5,like2,1 157 | SIMP_18,MARK_7,like2,2 158 | SIMP_18,ELIAS_17,like2,3 159 | ELIAS_17,SIMP_18,like2,3 160 | SIMP_18,BONAVEN_5,like2,1 161 | PETER_4,JOHN_1,like3,1 162 | BONI_15,BONAVEN_5,like3,2 163 | ROMUL_10,AMBROSE_9,like3,3 164 | BONAVEN_5,VICTOR_8,like3,1 165 | ROMUL_10,BONI_15,like3,1 166 | ROMUL_10,ALBERT_16,like3,2 167 | AMBROSE_9,ROMUL_10,like3,3 168 | BONAVEN_5,ROMUL_10,like3,3 169 | AMBROSE_9,MARK_7,like3,2 170 | BONAVEN_5,BONI_15,like3,2 171 | AMBROSE_9,ELIAS_17,like3,1 172 | AMBROSE_9,SIMP_18,like3,2 173 | BERTH_6,PETER_4,like3,3 174 | BERTH_6,LOUIS_11,like3,1 175 | BERTH_6,HUGH_14,like3,2 176 | PETER_4,BERTH_6,like3,3 177 | LOUIS_11,PETER_4,like3,1 178 | PETER_4,HUGH_14,like3,2 179 | LOUIS_11,BERTH_6,like3,3 180 | VICTOR_8,BONI_15,like3,1 181 | LOUIS_11,JOHN_1,like3,2 182 | VICTOR_8,BONAVEN_5,like3,3 183 | WINF_12,LOUIS_11,like3,2 184 | VICTOR_8,BASIL_3,like3,2 185 | WINF_12,BERTH_6,like3,3 186 | JOHN_1,BONI_15,like3,2 187 | WINF_12,JOHN_1,like3,1 188 | BASIL_3,AMAND_13,like3,1 189 | JOHN_1,PETER_4,like3,1 190 | JOHN_1,WINF_12,like3,3 191 | GREG_2,PETER_4,like3,1 192 | GREG_2,BERTH_6,like3,3 193 | HUGH_14,ALBERT_16,like3,1 194 | GREG_2,JOHN_1,like3,1 195 | GREG_2,MARK_7,like3,2 196 | HUGH_14,PETER_4,like3,2 197 | HUGH_14,WINF_12,like3,3 198 | MARK_7,PETER_4,like3,2 199 | BONI_15,ROMUL_10,like3,3 200 | BONI_15,VICTOR_8,like3,1 201 | MARK_7,SIMP_18,like3,3 202 | MARK_7,VICTOR_8,like3,1 203 | ALBERT_16,AMAND_13,like3,2 204 | ALBERT_16,ROMUL_10,like3,3 205 | ALBERT_16,BONI_15,like3,1 206 | AMAND_13,VICTOR_8,like3,1 207 | AMAND_13,BONAVEN_5,like3,3 208 | BASIL_3,VICTOR_8,like3,2 209 | AMAND_13,BONI_15,like3,2 210 | BASIL_3,BONAVEN_5,like3,3 211 | ELIAS_17,AMBROSE_9,like3,2 212 | ELIAS_17,SIMP_18,like3,3 213 | ELIAS_17,BONAVEN_5,like3,1 214 | SIMP_18,AMBROSE_9,like3,2 215 | SIMP_18,ELIAS_17,like3,3 216 | SIMP_18,BONAVEN_5,like3,1 217 | AMBROSE_9,BASIL_3,dislike,3 218 | AMBROSE_9,ELIAS_17,dislike,2 219 | AMBROSE_9,SIMP_18,dislike,1 220 | BERTH_6,GREG_2,dislike,1 221 | BERTH_6,ELIAS_17,dislike,2 222 | BERTH_6,MARK_7,dislike,2 223 | BERTH_6,BASIL_3,dislike,3 224 | PETER_4,JOHN_1,dislike,2 225 | LOUIS_11,GREG_2,dislike,3 226 | PETER_4,GREG_2,dislike,3 227 | PETER_4,HUGH_14,dislike,1 228 | LOUIS_11,JOHN_1,dislike,1 229 | VICTOR_8,HUGH_14,dislike,1 230 | LOUIS_11,BASIL_3,dislike,2 231 | VICTOR_8,GREG_2,dislike,3 232 | GREG_2,VICTOR_8,dislike,2 233 | GREG_2,AMAND_13,dislike,1 234 | VICTOR_8,BASIL_3,dislike,2 235 | JOHN_1,ROMUL_10,dislike,1 236 | JOHN_1,GREG_2,dislike,2 237 | JOHN_1,MARK_7,dislike,3 238 | GREG_2,PETER_4,dislike,3 239 | HUGH_14,ELIAS_17,dislike,1 240 | HUGH_14,PETER_4,dislike,3 241 | HUGH_14,VICTOR_8,dislike,2 242 | BONI_15,AMAND_13,dislike,3 243 | BONI_15,PETER_4,dislike,1 244 | MARK_7,PETER_4,dislike,3 245 | BONI_15,BASIL_3,dislike,2 246 | MARK_7,BERTH_6,dislike,2 247 | ALBERT_16,BASIL_3,dislike,1 248 | MARK_7,VICTOR_8,dislike,1 249 | ALBERT_16,PETER_4,dislike,3 250 | AMAND_13,WINF_12,dislike,1 251 | ALBERT_16,ELIAS_17,dislike,2 252 | AMAND_13,BERTH_6,dislike,2 253 | BASIL_3,GREG_2,dislike,2 254 | AMAND_13,GREG_2,dislike,3 255 | BASIL_3,BERTH_6,dislike,2 256 | BASIL_3,PETER_4,dislike,3 257 | ELIAS_17,VICTOR_8,dislike,2 258 | BASIL_3,ALBERT_16,dislike,1 259 | ELIAS_17,BERTH_6,dislike,3 260 | ELIAS_17,PETER_4,dislike,1 261 | SIMP_18,PETER_4,dislike,1 262 | SIMP_18,VICTOR_8,dislike,3 263 | SIMP_18,ROMUL_10,dislike,2 264 | AMBROSE_9,VICTOR_8,esteem,2 265 | BONAVEN_5,AMBROSE_9,esteem,1 266 | BONAVEN_5,PETER_4,esteem,3 267 | BONAVEN_5,LOUIS_11,esteem,2 268 | AMBROSE_9,PETER_4,esteem,3 269 | BERTH_6,PETER_4,esteem,3 270 | BERTH_6,LOUIS_11,esteem,2 271 | AMBROSE_9,JOHN_1,esteem,1 272 | PETER_4,BERTH_6,esteem,1 273 | PETER_4,ROMUL_10,esteem,2 274 | LOUIS_11,AMBROSE_9,esteem,3 275 | PETER_4,LOUIS_11,esteem,3 276 | LOUIS_11,BONAVEN_5,esteem,2 277 | VICTOR_8,BERTH_6,esteem,2 278 | VICTOR_8,BONAVEN_5,esteem,1 279 | WINF_12,GREG_2,esteem,2 280 | VICTOR_8,PETER_4,esteem,3 281 | WINF_12,JOHN_1,esteem,3 282 | JOHN_1,VICTOR_8,esteem,3 283 | WINF_12,HUGH_14,esteem,1 284 | JOHN_1,BONAVEN_5,esteem,1 285 | GREG_2,VICTOR_8,esteem,2 286 | JOHN_1,WINF_12,esteem,2 287 | GREG_2,BONAVEN_5,esteem,1 288 | HUGH_14,GREG_2,esteem,2 289 | GREG_2,JOHN_1,esteem,3 290 | HUGH_14,WINF_12,esteem,1 291 | HUGH_14,JOHN_1,esteem,3 292 | BONI_15,GREG_2,esteem,3 293 | HUGH_14,BONI_15,esteem,2 294 | BONI_15,JOHN_1,esteem,1 295 | MARK_7,GREG_2,esteem,3 296 | BONI_15,HUGH_14,esteem,2 297 | MARK_7,WINF_12,esteem,1 298 | ALBERT_16,GREG_2,esteem,3 299 | MARK_7,BONI_15,esteem,1 300 | MARK_7,ALBERT_16,esteem,2 301 | ALBERT_16,WINF_12,esteem,1 302 | AMAND_13,LOUIS_11,esteem,1 303 | ALBERT_16,BONI_15,esteem,2 304 | ALBERT_16,MARK_7,esteem,2 305 | AMAND_13,BONAVEN_5,esteem,3 306 | BASIL_3,AMAND_13,esteem,2 307 | AMAND_13,MARK_7,esteem,2 308 | BASIL_3,JOHN_1,esteem,3 309 | ELIAS_17,AMAND_13,esteem,1 310 | ELIAS_17,BASIL_3,esteem,2 311 | BASIL_3,ELIAS_17,esteem,1 312 | BASIL_3,SIMP_18,esteem,1 313 | ELIAS_17,GREG_2,esteem,1 314 | SIMP_18,BASIL_3,esteem,3 315 | ELIAS_17,SIMP_18,esteem,3 316 | SIMP_18,GREG_2,esteem,2 317 | SIMP_18,ELIAS_17,esteem,1 318 | BONI_15,PETER_4,desesteem,3 319 | BONI_15,LOUIS_11,desesteem,1 320 | BONI_15,BASIL_3,desesteem,2 321 | BONI_15,ELIAS_17,desesteem,1 322 | BONI_15,SIMP_18,desesteem,1 323 | MARK_7,BERTH_6,desesteem,3 324 | ALBERT_16,BASIL_3,desesteem,2 325 | MARK_7,PETER_4,desesteem,2 326 | MARK_7,VICTOR_8,desesteem,2 327 | MARK_7,BASIL_3,desesteem,2 328 | MARK_7,ELIAS_17,desesteem,1 329 | ALBERT_16,PETER_4,desesteem,3 330 | AMAND_13,GREG_2,desesteem,2 331 | AMAND_13,BASIL_3,desesteem,1 332 | ALBERT_16,ELIAS_17,desesteem,2 333 | ALBERT_16,SIMP_18,desesteem,1 334 | AMAND_13,BERTH_6,desesteem,3 335 | BASIL_3,BERTH_6,desesteem,2 336 | BASIL_3,PETER_4,desesteem,3 337 | ELIAS_17,VICTOR_8,desesteem,1 338 | BASIL_3,GREG_2,desesteem,1 339 | ELIAS_17,BERTH_6,desesteem,3 340 | ELIAS_17,PETER_4,desesteem,2 341 | SIMP_18,BERTH_6,desesteem,2 342 | SIMP_18,ROMUL_10,desesteem,1 343 | SIMP_18,PETER_4,desesteem,2 344 | SIMP_18,VICTOR_8,desesteem,3 345 | BERTH_6,BASIL_3,desesteem,2 346 | BONAVEN_5,BASIL_3,desesteem,1 347 | BONAVEN_5,ELIAS_17,desesteem,3 348 | BONAVEN_5,SIMP_18,desesteem,2 349 | AMBROSE_9,AMAND_13,desesteem,1 350 | BERTH_6,VICTOR_8,desesteem,1 351 | AMBROSE_9,ELIAS_17,desesteem,3 352 | AMBROSE_9,SIMP_18,desesteem,2 353 | BERTH_6,MARK_7,desesteem,3 354 | BERTH_6,ELIAS_17,desesteem,2 355 | PETER_4,JOHN_1,desesteem,2 356 | LOUIS_11,GREG_2,desesteem,3 357 | PETER_4,GREG_2,desesteem,3 358 | PETER_4,HUGH_14,desesteem,1 359 | LOUIS_11,JOHN_1,desesteem,1 360 | VICTOR_8,ELIAS_17,desesteem,2 361 | LOUIS_11,ALBERT_16,desesteem,1 362 | LOUIS_11,BASIL_3,desesteem,2 363 | VICTOR_8,HUGH_14,desesteem,1 364 | GREG_2,AMAND_13,desesteem,1 365 | VICTOR_8,SIMP_18,desesteem,3 366 | JOHN_1,GREG_2,desesteem,2 367 | JOHN_1,MARK_7,desesteem,3 368 | JOHN_1,BASIL_3,desesteem,1 369 | GREG_2,PETER_4,desesteem,3 370 | HUGH_14,LOUIS_11,desesteem,2 371 | GREG_2,BASIL_3,desesteem,2 372 | HUGH_14,PETER_4,desesteem,2 373 | HUGH_14,AMAND_13,desesteem,3 374 | HUGH_14,ELIAS_17,desesteem,1 375 | HUGH_14,SIMP_18,desesteem,1 376 | AMBROSE_9,JOHN_1,positive_influence,3 377 | BONAVEN_5,PETER_4,positive_influence,3 378 | BONAVEN_5,LOUIS_11,positive_influence,2 379 | BONAVEN_5,GREG_2,positive_influence,1 380 | AMBROSE_9,PETER_4,positive_influence,1 381 | BERTH_6,AMBROSE_9,positive_influence,2 382 | BERTH_6,PETER_4,positive_influence,3 383 | AMBROSE_9,GREG_2,positive_influence,2 384 | PETER_4,BERTH_6,positive_influence,1 385 | BERTH_6,GREG_2,positive_influence,1 386 | PETER_4,ROMUL_10,positive_influence,2 387 | LOUIS_11,AMBROSE_9,positive_influence,2 388 | PETER_4,LOUIS_11,positive_influence,3 389 | LOUIS_11,BONAVEN_5,positive_influence,3 390 | VICTOR_8,PETER_4,positive_influence,3 391 | LOUIS_11,PETER_4,positive_influence,1 392 | VICTOR_8,AMBROSE_9,positive_influence,1 393 | WINF_12,GREG_2,positive_influence,2 394 | VICTOR_8,LOUIS_11,positive_influence,2 395 | VICTOR_8,JOHN_1,positive_influence,2 396 | WINF_12,JOHN_1,positive_influence,3 397 | JOHN_1,GREG_2,positive_influence,3 398 | JOHN_1,MARK_7,positive_influence,1 399 | WINF_12,MARK_7,positive_influence,1 400 | JOHN_1,WINF_12,positive_influence,2 401 | GREG_2,MARK_7,positive_influence,1 402 | GREG_2,WINF_12,positive_influence,2 403 | GREG_2,JOHN_1,positive_influence,3 404 | HUGH_14,JOHN_1,positive_influence,3 405 | HUGH_14,WINF_12,positive_influence,1 406 | BONI_15,HUGH_14,positive_influence,2 407 | HUGH_14,GREG_2,positive_influence,2 408 | HUGH_14,BONI_15,positive_influence,2 409 | BONI_15,GREG_2,positive_influence,3 410 | BONI_15,MARK_7,positive_influence,1 411 | MARK_7,WINF_12,positive_influence,1 412 | MARK_7,GREG_2,positive_influence,3 413 | ALBERT_16,BONI_15,positive_influence,1 414 | ALBERT_16,MARK_7,positive_influence,2 415 | ALBERT_16,GREG_2,positive_influence,3 416 | MARK_7,ALBERT_16,positive_influence,2 417 | AMAND_13,BONAVEN_5,positive_influence,3 418 | AMAND_13,LOUIS_11,positive_influence,1 419 | BASIL_3,AMAND_13,positive_influence,2 420 | AMAND_13,MARK_7,positive_influence,2 421 | BASIL_3,JOHN_1,positive_influence,3 422 | ELIAS_17,BASIL_3,positive_influence,2 423 | BASIL_3,ELIAS_17,positive_influence,1 424 | ELIAS_17,GREG_2,positive_influence,1 425 | SIMP_18,BASIL_3,positive_influence,2 426 | ELIAS_17,SIMP_18,positive_influence,3 427 | SIMP_18,GREG_2,positive_influence,3 428 | SIMP_18,ELIAS_17,positive_influence,1 429 | BONAVEN_5,BASIL_3,negative_influence,1 430 | BONAVEN_5,ELIAS_17,negative_influence,3 431 | BONAVEN_5,SIMP_18,negative_influence,2 432 | AMBROSE_9,WINF_12,negative_influence,1 433 | BERTH_6,MARK_7,negative_influence,3 434 | AMBROSE_9,ELIAS_17,negative_influence,3 435 | AMBROSE_9,SIMP_18,negative_influence,2 436 | BERTH_6,ELIAS_17,negative_influence,2 437 | BERTH_6,SIMP_18,negative_influence,1 438 | PETER_4,JOHN_1,negative_influence,2 439 | LOUIS_11,ELIAS_17,negative_influence,1 440 | PETER_4,GREG_2,negative_influence,3 441 | PETER_4,HUGH_14,negative_influence,1 442 | LOUIS_11,MARK_7,negative_influence,3 443 | VICTOR_8,ALBERT_16,negative_influence,3 444 | LOUIS_11,SIMP_18,negative_influence,2 445 | VICTOR_8,WINF_12,negative_influence,1 446 | GREG_2,AMAND_13,negative_influence,2 447 | HUGH_14,PETER_4,negative_influence,2 448 | VICTOR_8,AMAND_13,negative_influence,2 449 | JOHN_1,ROMUL_10,negative_influence,2 450 | JOHN_1,ALBERT_16,negative_influence,1 451 | JOHN_1,SIMP_18,negative_influence,3 452 | GREG_2,PETER_4,negative_influence,3 453 | HUGH_14,AMAND_13,negative_influence,3 454 | SIMP_18,PETER_4,negative_influence,3 455 | BONI_15,AMAND_13,negative_influence,2 456 | HUGH_14,ELIAS_17,negative_influence,1 457 | HUGH_14,SIMP_18,negative_influence,1 458 | BONI_15,PETER_4,negative_influence,3 459 | MARK_7,PETER_4,negative_influence,2 460 | BONI_15,BASIL_3,negative_influence,1 461 | MARK_7,BERTH_6,negative_influence,3 462 | ALBERT_16,LOUIS_11,negative_influence,2 463 | MARK_7,VICTOR_8,negative_influence,2 464 | MARK_7,BASIL_3,negative_influence,2 465 | MARK_7,ELIAS_17,negative_influence,1 466 | ALBERT_16,PETER_4,negative_influence,3 467 | AMAND_13,WINF_12,negative_influence,1 468 | ALBERT_16,BASIL_3,negative_influence,1 469 | AMAND_13,BERTH_6,negative_influence,2 470 | BASIL_3,PETER_4,negative_influence,3 471 | AMAND_13,GREG_2,negative_influence,3 472 | BASIL_3,BERTH_6,negative_influence,2 473 | ELIAS_17,PETER_4,negative_influence,2 474 | ELIAS_17,VICTOR_8,negative_influence,1 475 | BASIL_3,GREG_2,negative_influence,1 476 | ELIAS_17,BERTH_6,negative_influence,3 477 | SIMP_18,LOUIS_11,negative_influence,2 478 | SIMP_18,BERTH_6,negative_influence,1 479 | PETER_4,BERTH_6,praise,1 480 | BERTH_6,AMBROSE_9,praise,1 481 | BERTH_6,PETER_4,praise,3 482 | BERTH_6,LOUIS_11,praise,2 483 | PETER_4,ROMUL_10,praise,2 484 | LOUIS_11,PETER_4,praise,3 485 | LOUIS_11,VICTOR_8,praise,2 486 | PETER_4,LOUIS_11,praise,3 487 | VICTOR_8,PETER_4,praise,3 488 | LOUIS_11,ALBERT_16,praise,1 489 | VICTOR_8,BERTH_6,praise,2 490 | GREG_2,JOHN_1,praise,3 491 | VICTOR_8,LOUIS_11,praise,1 492 | JOHN_1,WINF_12,praise,2 493 | JOHN_1,HUGH_14,praise,3 494 | JOHN_1,ELIAS_17,praise,1 495 | GREG_2,WINF_12,praise,2 496 | GREG_2,MARK_7,praise,1 497 | HUGH_14,JOHN_1,praise,3 498 | HUGH_14,GREG_2,praise,3 499 | BONI_15,GREG_2,praise,3 500 | HUGH_14,BONI_15,praise,2 501 | HUGH_14,ALBERT_16,praise,1 502 | BONI_15,JOHN_1,praise,1 503 | MARK_7,BONI_15,praise,1 504 | MARK_7,ALBERT_16,praise,2 505 | BONI_15,HUGH_14,praise,2 506 | MARK_7,GREG_2,praise,3 507 | ALBERT_16,BONI_15,praise,1 508 | ALBERT_16,GREG_2,praise,2 509 | ALBERT_16,MARK_7,praise,3 510 | AMAND_13,BONAVEN_5,praise,3 511 | BASIL_3,AMAND_13,praise,2 512 | AMAND_13,LOUIS_11,praise,2 513 | BASIL_3,JOHN_1,praise,3 514 | BASIL_3,ELIAS_17,praise,1 515 | SIMP_18,JOHN_1,praise,1 516 | SIMP_18,GREG_2,praise,1 517 | SIMP_18,ELIAS_17,praise,1 518 | BERTH_6,MARK_7,blame,3 519 | BERTH_6,AMAND_13,blame,1 520 | BERTH_6,ELIAS_17,blame,2 521 | BERTH_6,SIMP_18,blame,1 522 | PETER_4,MARK_7,blame,1 523 | PETER_4,GREG_2,blame,3 524 | LOUIS_11,ELIAS_17,blame,2 525 | PETER_4,HUGH_14,blame,2 526 | LOUIS_11,HUGH_14,blame,1 527 | LOUIS_11,SIMP_18,blame,3 528 | VICTOR_8,BASIL_3,blame,1 529 | WINF_12,ELIAS_17,blame,1 530 | VICTOR_8,ELIAS_17,blame,2 531 | VICTOR_8,SIMP_18,blame,3 532 | WINF_12,HUGH_14,blame,2 533 | JOHN_1,BASIL_3,blame,3 534 | WINF_12,SIMP_18,blame,3 535 | JOHN_1,LOUIS_11,blame,2 536 | HUGH_14,PETER_4,blame,3 537 | JOHN_1,SIMP_18,blame,1 538 | GREG_2,BASIL_3,blame,3 539 | HUGH_14,LOUIS_11,blame,2 540 | HUGH_14,BASIL_3,blame,1 541 | BONI_15,AMAND_13,blame,3 542 | BONI_15,PETER_4,blame,1 543 | MARK_7,PETER_4,blame,2 544 | MARK_7,BASIL_3,blame,3 545 | BONI_15,BASIL_3,blame,2 546 | BONI_15,SIMP_18,blame,1 547 | MARK_7,BERTH_6,blame,1 548 | ALBERT_16,AMAND_13,blame,1 549 | ALBERT_16,PETER_4,blame,3 550 | AMAND_13,ELIAS_17,blame,2 551 | ALBERT_16,BASIL_3,blame,2 552 | ALBERT_16,ELIAS_17,blame,2 553 | ALBERT_16,SIMP_18,blame,2 554 | AMAND_13,GREG_2,blame,1 555 | BASIL_3,GREG_2,blame,2 556 | AMAND_13,SIMP_18,blame,3 557 | BASIL_3,PETER_4,blame,3 558 | BASIL_3,HUGH_14,blame,1 559 | -------------------------------------------------------------------------------- /uunet/data/tailorshop.mpx: -------------------------------------------------------------------------------- 1 | #TYPE 2 | multiplex 3 | 4 | #LAYERS 5 | KAPFTS1,UNDIRECTED 6 | KAPFTS2,UNDIRECTED 7 | KAPFTI1,UNDIRECTED 8 | KAPFTI2,UNDIRECTED 9 | 10 | #ACTORS 11 | NKUMBULA 12 | KAMWEFU 13 | ABRAHAM 14 | CHIPATA 15 | SEAMS 16 | DONALD 17 | ZULU 18 | NKOLOYA 19 | NYIRENDA 20 | MATEO 21 | CHILWA 22 | CHIPALO 23 | LYASHI 24 | SIGN 25 | HASTINGS 26 | LWANGA 27 | KALUNDWE 28 | CHISOKONE 29 | ENOCH 30 | PAULOS 31 | MUKUBWA 32 | KALONGA 33 | ANGEL 34 | KALAMBA 35 | ZAKEYO 36 | BEN 37 | IBRAHIM 38 | MESHAK 39 | ADRIAN 40 | MPUNDU 41 | JOHN 42 | JOSEPH 43 | WILLIAM 44 | HENRY 45 | CHOBE 46 | MUBANGA 47 | CHRISTIAN 48 | CHILUFYA 49 | MABANGE 50 | 51 | #EDGES 52 | MPUNDU,WILLIAM,KAPFTS1 53 | PAULOS,MUKUBWA,KAPFTS1 54 | PAULOS,IBRAHIM,KAPFTS1 55 | PAULOS,KALUNDWE,KAPFTS1 56 | PAULOS,JOSEPH,KAPFTS1 57 | MUKUBWA,KALAMBA,KAPFTS1 58 | MUKUBWA,BEN,KAPFTS1 59 | MUKUBWA,IBRAHIM,KAPFTS1 60 | MUKUBWA,JOHN,KAPFTS1 61 | MUKUBWA,JOSEPH,KAPFTS1 62 | MUKUBWA,HENRY,KAPFTS1 63 | MUKUBWA,CHOBE,KAPFTS1 64 | MUKUBWA,MUBANGA,KAPFTS1 65 | SIGN,KALUNDWE,KAPFTS1 66 | KALAMBA,BEN,KAPFTS1 67 | KALAMBA,IBRAHIM,KAPFTS1 68 | KALAMBA,JOHN,KAPFTS1 69 | KALAMBA,HENRY,KAPFTS1 70 | ZAKEYO,BEN,KAPFTS1 71 | BEN,IBRAHIM,KAPFTS1 72 | BEN,KALUNDWE,KAPFTS1 73 | BEN,MPUNDU,KAPFTS1 74 | IBRAHIM,MPUNDU,KAPFTS1 75 | IBRAHIM,WILLIAM,KAPFTS1 76 | MPUNDU,CHOBE,KAPFTS1 77 | MPUNDU,CHRISTIAN,KAPFTS1 78 | KAMWEFU,ABRAHAM,KAPFTS1 79 | KAMWEFU,SEAMS,KAPFTS1 80 | KAMWEFU,CHILWA,KAPFTS1 81 | KAMWEFU,LYASHI,KAPFTS1 82 | NKUMBULA,ABRAHAM,KAPFTS1 83 | NKUMBULA,SEAMS,KAPFTS1 84 | NKUMBULA,LYASHI,KAPFTS1 85 | NKUMBULA,ZULU,KAPFTS1 86 | NKUMBULA,CHISOKONE,KAPFTS1 87 | ABRAHAM,SEAMS,KAPFTS1 88 | ABRAHAM,DONALD,KAPFTS1 89 | ABRAHAM,NKOLOYA,KAPFTS1 90 | ABRAHAM,MATEO,KAPFTS1 91 | ABRAHAM,CHILWA,KAPFTS1 92 | ABRAHAM,LYASHI,KAPFTS1 93 | ABRAHAM,ZULU,KAPFTS1 94 | ABRAHAM,HASTINGS,KAPFTS1 95 | ZULU,KALONGA,KAPFTS1 96 | ABRAHAM,NYIRENDA,KAPFTS1 97 | ABRAHAM,CHISOKONE,KAPFTS1 98 | ABRAHAM,MUKUBWA,KAPFTS1 99 | SEAMS,LYASHI,KAPFTS1 100 | SEAMS,ZULU,KAPFTS1 101 | SEAMS,HASTINGS,KAPFTS1 102 | SEAMS,LWANGA,KAPFTS1 103 | SEAMS,CHISOKONE,KAPFTS1 104 | SEAMS,MUKUBWA,KAPFTS1 105 | CHIPATA,NKOLOYA,KAPFTS1 106 | CHIPATA,CHILWA,KAPFTS1 107 | CHIPATA,LYASHI,KAPFTS1 108 | CHIPATA,ZULU,KAPFTS1 109 | CHIPATA,HASTINGS,KAPFTS1 110 | DONALD,LYASHI,KAPFTS1 111 | DONALD,ZULU,KAPFTS1 112 | DONALD,HASTINGS,KAPFTS1 113 | DONALD,CHISOKONE,KAPFTS1 114 | DONALD,MUKUBWA,KAPFTS1 115 | NKOLOYA,CHILWA,KAPFTS1 116 | NKOLOYA,LYASHI,KAPFTS1 117 | NKOLOYA,CHISOKONE,KAPFTS1 118 | NKOLOYA,HENRY,KAPFTS1 119 | MATEO,CHISOKONE,KAPFTS1 120 | MATEO,PAULOS,KAPFTS1 121 | CHILWA,LYASHI,KAPFTS1 122 | CHILWA,LWANGA,KAPFTS1 123 | CHILWA,CHISOKONE,KAPFTS1 124 | CHILWA,KALAMBA,KAPFTS1 125 | CHILWA,CHOBE,KAPFTS1 126 | CHIPALO,ZULU,KAPFTS1 127 | LYASHI,ZULU,KAPFTS1 128 | LYASHI,HASTINGS,KAPFTS1 129 | LYASHI,LWANGA,KAPFTS1 130 | LYASHI,CHISOKONE,KAPFTS1 131 | LYASHI,MUKUBWA,KAPFTS1 132 | LYASHI,MESHAK,KAPFTS1 133 | LYASHI,MUBANGA,KAPFTS1 134 | ZULU,HASTINGS,KAPFTS1 135 | ZULU,CHISOKONE,KAPFTS1 136 | ZULU,PAULOS,KAPFTS1 137 | ZULU,MUKUBWA,KAPFTS1 138 | ZULU,KALAMBA,KAPFTS1 139 | ZULU,WILLIAM,KAPFTS1 140 | HASTINGS,CHISOKONE,KAPFTS1 141 | HASTINGS,JOHN,KAPFTS1 142 | HASTINGS,HENRY,KAPFTS1 143 | HASTINGS,CHRISTIAN,KAPFTS1 144 | LWANGA,PAULOS,KAPFTS1 145 | LWANGA,MUKUBWA,KAPFTS1 146 | LWANGA,IBRAHIM,KAPFTS1 147 | LWANGA,MPUNDU,KAPFTS1 148 | LWANGA,WILLIAM,KAPFTS1 149 | NYIRENDA,CHISOKONE,KAPFTS1 150 | NYIRENDA,MUKUBWA,KAPFTS1 151 | NYIRENDA,BEN,KAPFTS1 152 | NYIRENDA,MPUNDU,KAPFTS1 153 | CHISOKONE,ENOCH,KAPFTS1 154 | CHISOKONE,MUKUBWA,KAPFTS1 155 | CHISOKONE,KALAMBA,KAPFTS1 156 | CHISOKONE,IBRAHIM,KAPFTS1 157 | CHISOKONE,MESHAK,KAPFTS1 158 | CHISOKONE,ADRIAN,KAPFTS1 159 | CHISOKONE,JOHN,KAPFTS1 160 | CHISOKONE,JOSEPH,KAPFTS1 161 | CHISOKONE,WILLIAM,KAPFTS1 162 | CHISOKONE,HENRY,KAPFTS1 163 | CHISOKONE,MUBANGA,KAPFTS1 164 | CHISOKONE,ANGEL,KAPFTS1 165 | CHISOKONE,CHILUFYA,KAPFTS1 166 | ENOCH,IBRAHIM,KAPFTS1 167 | IBRAHIM,HENRY,KAPFTS1 168 | IBRAHIM,MUBANGA,KAPFTS1 169 | MESHAK,JOHN,KAPFTS1 170 | MESHAK,CHOBE,KAPFTS1 171 | ADRIAN,HENRY,KAPFTS1 172 | KALUNDWE,MPUNDU,KAPFTS1 173 | KALUNDWE,MUBANGA,KAPFTS1 174 | MPUNDU,CHILUFYA,KAPFTS1 175 | JOHN,CHOBE,KAPFTS1 176 | JOHN,KALONGA,KAPFTS1 177 | JOHN,CHILUFYA,KAPFTS1 178 | MUBANGA,MABANGE,KAPFTS1 179 | JOHN,MABANGE,KAPFTS1 180 | JOSEPH,WILLIAM,KAPFTS1 181 | JOSEPH,HENRY,KAPFTS1 182 | JOSEPH,MUBANGA,KAPFTS1 183 | JOSEPH,KALONGA,KAPFTS1 184 | JOSEPH,ANGEL,KAPFTS1 185 | JOSEPH,CHILUFYA,KAPFTS1 186 | JOSEPH,MABANGE,KAPFTS1 187 | WILLIAM,CHOBE,KAPFTS1 188 | WILLIAM,MUBANGA,KAPFTS1 189 | WILLIAM,CHRISTIAN,KAPFTS1 190 | MUBANGA,KALONGA,KAPFTS1 191 | WILLIAM,KALONGA,KAPFTS1 192 | HENRY,MUBANGA,KAPFTS1 193 | HENRY,CHRISTIAN,KAPFTS1 194 | HENRY,KALONGA,KAPFTS1 195 | HENRY,ANGEL,KAPFTS1 196 | HENRY,CHILUFYA,KAPFTS1 197 | HENRY,MABANGE,KAPFTS1 198 | CHOBE,MUBANGA,KAPFTS1 199 | CHOBE,CHRISTIAN,KAPFTS1 200 | CHOBE,KALONGA,KAPFTS1 201 | CHOBE,MABANGE,KAPFTS1 202 | MUBANGA,CHRISTIAN,KAPFTS1 203 | MUBANGA,ANGEL,KAPFTS1 204 | MUBANGA,CHILUFYA,KAPFTS1 205 | CHRISTIAN,KALONGA,KAPFTS1 206 | CHRISTIAN,CHILUFYA,KAPFTS1 207 | KALONGA,ANGEL,KAPFTS1 208 | KALONGA,CHILUFYA,KAPFTS1 209 | ANGEL,CHILUFYA,KAPFTS1 210 | HASTINGS,ZAKEYO,KAPFTS2 211 | HASTINGS,BEN,KAPFTS2 212 | HASTINGS,IBRAHIM,KAPFTS2 213 | HASTINGS,MESHAK,KAPFTS2 214 | HASTINGS,ADRIAN,KAPFTS2 215 | HASTINGS,JOHN,KAPFTS2 216 | HASTINGS,JOSEPH,KAPFTS2 217 | HASTINGS,CHOBE,KAPFTS2 218 | LWANGA,ENOCH,KAPFTS2 219 | LWANGA,MUKUBWA,KAPFTS2 220 | LWANGA,IBRAHIM,KAPFTS2 221 | LWANGA,MESHAK,KAPFTS2 222 | LWANGA,MPUNDU,KAPFTS2 223 | LWANGA,JOSEPH,KAPFTS2 224 | LWANGA,KALONGA,KAPFTS2 225 | NYIRENDA,MUKUBWA,KAPFTS2 226 | NYIRENDA,KALAMBA,KAPFTS2 227 | NYIRENDA,ZAKEYO,KAPFTS2 228 | NYIRENDA,BEN,KAPFTS2 229 | NYIRENDA,MESHAK,KAPFTS2 230 | NYIRENDA,JOHN,KAPFTS2 231 | NYIRENDA,CHOBE,KAPFTS2 232 | NYIRENDA,KALONGA,KAPFTS2 233 | CHISOKONE,ENOCH,KAPFTS2 234 | CHISOKONE,MUKUBWA,KAPFTS2 235 | CHISOKONE,KALAMBA,KAPFTS2 236 | CHISOKONE,MESHAK,KAPFTS2 237 | CHISOKONE,JOHN,KAPFTS2 238 | CHISOKONE,IBRAHIM,KAPFTS2 239 | KAMWEFU,NKUMBULA,KAPFTS2 240 | KAMWEFU,ABRAHAM,KAPFTS2 241 | KAMWEFU,CHIPATA,KAPFTS2 242 | KAMWEFU,CHILWA,KAPFTS2 243 | KAMWEFU,LYASHI,KAPFTS2 244 | KAMWEFU,ZULU,KAPFTS2 245 | KAMWEFU,HASTINGS,KAPFTS2 246 | KAMWEFU,LWANGA,KAPFTS2 247 | KAMWEFU,CHISOKONE,KAPFTS2 248 | KAMWEFU,PAULOS,KAPFTS2 249 | KAMWEFU,MUKUBWA,KAPFTS2 250 | KAMWEFU,IBRAHIM,KAPFTS2 251 | NKUMBULA,ABRAHAM,KAPFTS2 252 | NKUMBULA,CHIPATA,KAPFTS2 253 | NKUMBULA,LYASHI,KAPFTS2 254 | NKUMBULA,ZULU,KAPFTS2 255 | NKUMBULA,HASTINGS,KAPFTS2 256 | NKUMBULA,LWANGA,KAPFTS2 257 | NKUMBULA,CHISOKONE,KAPFTS2 258 | NKUMBULA,MUKUBWA,KAPFTS2 259 | NKUMBULA,MESHAK,KAPFTS2 260 | NKUMBULA,MUBANGA,KAPFTS2 261 | NKUMBULA,KALONGA,KAPFTS2 262 | ABRAHAM,CHIPATA,KAPFTS2 263 | ABRAHAM,NKOLOYA,KAPFTS2 264 | ABRAHAM,CHILWA,KAPFTS2 265 | ABRAHAM,CHIPALO,KAPFTS2 266 | ABRAHAM,LYASHI,KAPFTS2 267 | ABRAHAM,ZULU,KAPFTS2 268 | ABRAHAM,HASTINGS,KAPFTS2 269 | ABRAHAM,LWANGA,KAPFTS2 270 | ABRAHAM,CHISOKONE,KAPFTS2 271 | ABRAHAM,MUKUBWA,KAPFTS2 272 | ABRAHAM,KALAMBA,KAPFTS2 273 | ABRAHAM,IBRAHIM,KAPFTS2 274 | ABRAHAM,MESHAK,KAPFTS2 275 | ABRAHAM,ADRIAN,KAPFTS2 276 | ABRAHAM,MUBANGA,KAPFTS2 277 | SEAMS,MATEO,KAPFTS2 278 | SEAMS,CHISOKONE,KAPFTS2 279 | SEAMS,MPUNDU,KAPFTS2 280 | CHIPATA,NKOLOYA,KAPFTS2 281 | CHIPATA,CHILWA,KAPFTS2 282 | CHIPATA,CHIPALO,KAPFTS2 283 | CHIPATA,LYASHI,KAPFTS2 284 | CHIPATA,ZULU,KAPFTS2 285 | CHIPATA,HASTINGS,KAPFTS2 286 | CHIPATA,ENOCH,KAPFTS2 287 | CHIPATA,IBRAHIM,KAPFTS2 288 | CHIPATA,MESHAK,KAPFTS2 289 | CHISOKONE,JOSEPH,KAPFTS2 290 | CHIPATA,JOSEPH,KAPFTS2 291 | CHIPATA,MUBANGA,KAPFTS2 292 | MESHAK,MABANGE,KAPFTS2 293 | DONALD,LYASHI,KAPFTS2 294 | DONALD,CHRISTIAN,KAPFTS2 295 | NKOLOYA,CHILWA,KAPFTS2 296 | NKOLOYA,CHIPALO,KAPFTS2 297 | NKOLOYA,LYASHI,KAPFTS2 298 | NKOLOYA,ZULU,KAPFTS2 299 | NKOLOYA,HASTINGS,KAPFTS2 300 | NKOLOYA,LWANGA,KAPFTS2 301 | NKOLOYA,CHISOKONE,KAPFTS2 302 | NKOLOYA,MUKUBWA,KAPFTS2 303 | NKOLOYA,MESHAK,KAPFTS2 304 | NKOLOYA,ADRIAN,KAPFTS2 305 | NKOLOYA,MPUNDU,KAPFTS2 306 | NKOLOYA,JOSEPH,KAPFTS2 307 | MATEO,CHISOKONE,KAPFTS2 308 | MATEO,ENOCH,KAPFTS2 309 | MATEO,PAULOS,KAPFTS2 310 | MATEO,MUKUBWA,KAPFTS2 311 | MATEO,IBRAHIM,KAPFTS2 312 | CHILWA,LYASHI,KAPFTS2 313 | CHILWA,ZULU,KAPFTS2 314 | CHILWA,CHISOKONE,KAPFTS2 315 | CHILWA,KALAMBA,KAPFTS2 316 | CHILWA,IBRAHIM,KAPFTS2 317 | CHIPALO,LYASHI,KAPFTS2 318 | CHIPALO,HASTINGS,KAPFTS2 319 | CHIPALO,BEN,KAPFTS2 320 | CHIPALO,MESHAK,KAPFTS2 321 | LYASHI,ZULU,KAPFTS2 322 | LYASHI,HASTINGS,KAPFTS2 323 | LYASHI,LWANGA,KAPFTS2 324 | LYASHI,PAULOS,KAPFTS2 325 | LYASHI,MUKUBWA,KAPFTS2 326 | LYASHI,KALAMBA,KAPFTS2 327 | LYASHI,BEN,KAPFTS2 328 | LYASHI,IBRAHIM,KAPFTS2 329 | LYASHI,ADRIAN,KAPFTS2 330 | LYASHI,JOSEPH,KAPFTS2 331 | CHISOKONE,WILLIAM,KAPFTS2 332 | LYASHI,WILLIAM,KAPFTS2 333 | ZULU,CHISOKONE,KAPFTS2 334 | ZULU,PAULOS,KAPFTS2 335 | ZULU,MUKUBWA,KAPFTS2 336 | ZULU,KALAMBA,KAPFTS2 337 | ZULU,IBRAHIM,KAPFTS2 338 | ZULU,MPUNDU,KAPFTS2 339 | ZULU,KALONGA,KAPFTS2 340 | HASTINGS,CHISOKONE,KAPFTS2 341 | HASTINGS,MUKUBWA,KAPFTS2 342 | HASTINGS,KALAMBA,KAPFTS2 343 | CHISOKONE,HENRY,KAPFTS2 344 | CHISOKONE,CHOBE,KAPFTS2 345 | CHISOKONE,CHRISTIAN,KAPFTS2 346 | CHISOKONE,KALONGA,KAPFTS2 347 | CHISOKONE,ANGEL,KAPFTS2 348 | ENOCH,PAULOS,KAPFTS2 349 | ENOCH,MUKUBWA,KAPFTS2 350 | ENOCH,IBRAHIM,KAPFTS2 351 | ENOCH,MPUNDU,KAPFTS2 352 | PAULOS,KALAMBA,KAPFTS2 353 | PAULOS,IBRAHIM,KAPFTS2 354 | PAULOS,MESHAK,KAPFTS2 355 | PAULOS,KALUNDWE,KAPFTS2 356 | MUKUBWA,KALAMBA,KAPFTS2 357 | MUKUBWA,ZAKEYO,KAPFTS2 358 | MUKUBWA,IBRAHIM,KAPFTS2 359 | MUKUBWA,MESHAK,KAPFTS2 360 | MUKUBWA,ADRIAN,KAPFTS2 361 | MUKUBWA,KALUNDWE,KAPFTS2 362 | MUKUBWA,MPUNDU,KAPFTS2 363 | MUKUBWA,JOHN,KAPFTS2 364 | MUKUBWA,JOSEPH,KAPFTS2 365 | MUKUBWA,HENRY,KAPFTS2 366 | MUKUBWA,CHOBE,KAPFTS2 367 | MUKUBWA,MUBANGA,KAPFTS2 368 | MUKUBWA,MABANGE,KAPFTS2 369 | SIGN,IBRAHIM,KAPFTS2 370 | SIGN,CHILUFYA,KAPFTS2 371 | KALAMBA,IBRAHIM,KAPFTS2 372 | KALAMBA,MESHAK,KAPFTS2 373 | KALAMBA,KALUNDWE,KAPFTS2 374 | KALAMBA,JOHN,KAPFTS2 375 | KALAMBA,JOSEPH,KAPFTS2 376 | KALAMBA,WILLIAM,KAPFTS2 377 | KALAMBA,HENRY,KAPFTS2 378 | ZAKEYO,BEN,KAPFTS2 379 | ZAKEYO,ADRIAN,KAPFTS2 380 | ZAKEYO,MPUNDU,KAPFTS2 381 | ZAKEYO,JOHN,KAPFTS2 382 | BEN,MPUNDU,KAPFTS2 383 | BEN,JOHN,KAPFTS2 384 | IBRAHIM,MESHAK,KAPFTS2 385 | IBRAHIM,JOSEPH,KAPFTS2 386 | IBRAHIM,HENRY,KAPFTS2 387 | IBRAHIM,MUBANGA,KAPFTS2 388 | IBRAHIM,ANGEL,KAPFTS2 389 | IBRAHIM,CHILUFYA,KAPFTS2 390 | MESHAK,ADRIAN,KAPFTS2 391 | MESHAK,JOSEPH,KAPFTS2 392 | MESHAK,HENRY,KAPFTS2 393 | MESHAK,MUBANGA,KAPFTS2 394 | ADRIAN,HENRY,KAPFTS2 395 | ADRIAN,CHOBE,KAPFTS2 396 | ADRIAN,MUBANGA,KAPFTS2 397 | KALUNDWE,MPUNDU,KAPFTS2 398 | MPUNDU,WILLIAM,KAPFTS2 399 | MPUNDU,CHRISTIAN,KAPFTS2 400 | JOHN,WILLIAM,KAPFTS2 401 | JOHN,HENRY,KAPFTS2 402 | JOHN,CHOBE,KAPFTS2 403 | JOHN,MUBANGA,KAPFTS2 404 | JOHN,CHILUFYA,KAPFTS2 405 | JOHN,MABANGE,KAPFTS2 406 | JOSEPH,WILLIAM,KAPFTS2 407 | JOSEPH,HENRY,KAPFTS2 408 | JOSEPH,MUBANGA,KAPFTS2 409 | JOSEPH,CHRISTIAN,KAPFTS2 410 | JOSEPH,ANGEL,KAPFTS2 411 | JOSEPH,CHILUFYA,KAPFTS2 412 | WILLIAM,CHOBE,KAPFTS2 413 | WILLIAM,MUBANGA,KAPFTS2 414 | WILLIAM,CHRISTIAN,KAPFTS2 415 | WILLIAM,KALONGA,KAPFTS2 416 | HENRY,MUBANGA,KAPFTS2 417 | HENRY,KALONGA,KAPFTS2 418 | HENRY,ANGEL,KAPFTS2 419 | HENRY,CHILUFYA,KAPFTS2 420 | CHOBE,MUBANGA,KAPFTS2 421 | CHOBE,KALONGA,KAPFTS2 422 | CHOBE,MABANGE,KAPFTS2 423 | MUBANGA,CHRISTIAN,KAPFTS2 424 | MUBANGA,KALONGA,KAPFTS2 425 | MUBANGA,ANGEL,KAPFTS2 426 | MUBANGA,CHILUFYA,KAPFTS2 427 | CHRISTIAN,KALONGA,KAPFTS2 428 | CHRISTIAN,CHILUFYA,KAPFTS2 429 | CHRISTIAN,MABANGE,KAPFTS2 430 | KALONGA,CHILUFYA,KAPFTS2 431 | KALONGA,MABANGE,KAPFTS2 432 | ANGEL,CHILUFYA,KAPFTS2 433 | CHISOKONE,LWANGA,KAPFTI1 434 | CHISOKONE,ENOCH,KAPFTI1 435 | CHISOKONE,IBRAHIM,KAPFTI1 436 | CHISOKONE,JOSEPH,KAPFTI1 437 | CHISOKONE,HENRY,KAPFTI1 438 | CHISOKONE,KALONGA,KAPFTI1 439 | CHISOKONE,ANGEL,KAPFTI1 440 | ENOCH,IBRAHIM,KAPFTI1 441 | MUKUBWA,ABRAHAM,KAPFTI1 442 | MUKUBWA,ZULU,KAPFTI1 443 | MUKUBWA,LWANGA,KAPFTI1 444 | MUKUBWA,NYIRENDA,KAPFTI1 445 | MUKUBWA,CHISOKONE,KAPFTI1 446 | MUKUBWA,BEN,KAPFTI1 447 | MUKUBWA,IBRAHIM,KAPFTI1 448 | MUKUBWA,MPUNDU,KAPFTI1 449 | MUKUBWA,WILLIAM,KAPFTI1 450 | MUKUBWA,CHOBE,KAPFTI1 451 | MUKUBWA,ANGEL,KAPFTI1 452 | SIGN,KALUNDWE,KAPFTI1 453 | KALAMBA,IBRAHIM,KAPFTI1 454 | KALAMBA,JOHN,KAPFTI1 455 | ZAKEYO,KALUNDWE,KAPFTI1 456 | ZAKEYO,CHRISTIAN,KAPFTI1 457 | IBRAHIM,BEN,KAPFTI1 458 | IBRAHIM,MPUNDU,KAPFTI1 459 | IBRAHIM,HENRY,KAPFTI1 460 | MESHAK,ABRAHAM,KAPFTI1 461 | MESHAK,MUBANGA,KAPFTI1 462 | JOHN,CHRISTIAN,KAPFTI1 463 | JOHN,KALONGA,KAPFTI1 464 | JOSEPH,HENRY,KAPFTI1 465 | JOSEPH,MUBANGA,KAPFTI1 466 | JOSEPH,ANGEL,KAPFTI1 467 | HENRY,MUBANGA,KAPFTI1 468 | HENRY,ANGEL,KAPFTI1 469 | HENRY,CHILUFYA,KAPFTI1 470 | HENRY,MABANGE,KAPFTI1 471 | CHOBE,MABANGE,KAPFTI1 472 | MUBANGA,KALUNDWE,KAPFTI1 473 | MUBANGA,CHRISTIAN,KAPFTI1 474 | NYIRENDA,MPUNDU,KAPFTI1 475 | CHISOKONE,CHILWA,KAPFTI1 476 | KAMWEFU,ABRAHAM,KAPFTI1 477 | NKUMBULA,LYASHI,KAPFTI1 478 | ABRAHAM,DONALD,KAPFTI1 479 | ABRAHAM,CHILWA,KAPFTI1 480 | ABRAHAM,LYASHI,KAPFTI1 481 | ABRAHAM,ZULU,KAPFTI1 482 | ABRAHAM,HASTINGS,KAPFTI1 483 | ABRAHAM,NYIRENDA,KAPFTI1 484 | ABRAHAM,CHISOKONE,KAPFTI1 485 | SEAMS,KAMWEFU,KAPFTI1 486 | CHIPATA,LYASHI,KAPFTI1 487 | NKOLOYA,DONALD,KAPFTI1 488 | NKOLOYA,LYASHI,KAPFTI1 489 | NKOLOYA,CHISOKONE,KAPFTI1 490 | NKOLOYA,JOHN,KAPFTI1 491 | CHILWA,LYASHI,KAPFTI1 492 | LYASHI,SEAMS,KAPFTI1 493 | LYASHI,ZULU,KAPFTI1 494 | LYASHI,CHISOKONE,KAPFTI1 495 | LYASHI,MUKUBWA,KAPFTI1 496 | ZULU,NKUMBULA,KAPFTI1 497 | ZULU,SEAMS,KAPFTI1 498 | ZULU,CHILWA,KAPFTI1 499 | ZULU,CHISOKONE,KAPFTI1 500 | ZULU,JOHN,KAPFTI1 501 | HASTINGS,CHILWA,KAPFTI1 502 | HASTINGS,CHISOKONE,KAPFTI1 503 | LWANGA,KAMWEFU,KAPFTI1 504 | LWANGA,SEAMS,KAPFTI1 505 | LWANGA,SIGN,KAPFTI1 506 | LWANGA,MPUNDU,KAPFTI1 507 | LWANGA,WILLIAM,KAPFTI1 508 | NYIRENDA,BEN,KAPFTI1 509 | KAMWEFU,NKUMBULA,KAPFTI2 510 | KAMWEFU,ABRAHAM,KAPFTI2 511 | KAMWEFU,CHIPATA,KAPFTI2 512 | KAMWEFU,LYASHI,KAPFTI2 513 | KAMWEFU,KALAMBA,KAPFTI2 514 | NKUMBULA,CHIPATA,KAPFTI2 515 | NKUMBULA,MESHAK,KAPFTI2 516 | NKUMBULA,MPUNDU,KAPFTI2 517 | NKUMBULA,MUBANGA,KAPFTI2 518 | ABRAHAM,CHIPATA,KAPFTI2 519 | ABRAHAM,NKOLOYA,KAPFTI2 520 | ABRAHAM,CHILWA,KAPFTI2 521 | ABRAHAM,LYASHI,KAPFTI2 522 | ABRAHAM,HASTINGS,KAPFTI2 523 | ABRAHAM,LWANGA,KAPFTI2 524 | ABRAHAM,CHISOKONE,KAPFTI2 525 | ABRAHAM,KALAMBA,KAPFTI2 526 | ABRAHAM,MPUNDU,KAPFTI2 527 | SEAMS,MATEO,KAPFTI2 528 | SEAMS,MPUNDU,KAPFTI2 529 | CHIPATA,NKOLOYA,KAPFTI2 530 | CHIPATA,LYASHI,KAPFTI2 531 | CHIPATA,ZULU,KAPFTI2 532 | CHIPATA,CHISOKONE,KAPFTI2 533 | CHIPATA,ENOCH,KAPFTI2 534 | CHIPATA,SIGN,KAPFTI2 535 | CHIPATA,JOHN,KAPFTI2 536 | DONALD,CHOBE,KAPFTI2 537 | NKOLOYA,CHIPALO,KAPFTI2 538 | NKOLOYA,LYASHI,KAPFTI2 539 | NKOLOYA,ZULU,KAPFTI2 540 | NKOLOYA,LWANGA,KAPFTI2 541 | NKOLOYA,MUBANGA,KAPFTI2 542 | MATEO,ENOCH,KAPFTI2 543 | MATEO,PAULOS,KAPFTI2 544 | MATEO,IBRAHIM,KAPFTI2 545 | CHILWA,LYASHI,KAPFTI2 546 | CHIPALO,LYASHI,KAPFTI2 547 | LYASHI,ZULU,KAPFTI2 548 | LYASHI,HASTINGS,KAPFTI2 549 | LYASHI,LWANGA,KAPFTI2 550 | LYASHI,MUKUBWA,KAPFTI2 551 | LYASHI,SIGN,KAPFTI2 552 | LYASHI,ZAKEYO,KAPFTI2 553 | LYASHI,IBRAHIM,KAPFTI2 554 | LYASHI,MPUNDU,KAPFTI2 555 | LYASHI,JOHN,KAPFTI2 556 | LYASHI,JOSEPH,KAPFTI2 557 | LYASHI,HENRY,KAPFTI2 558 | LYASHI,MUBANGA,KAPFTI2 559 | LYASHI,KALONGA,KAPFTI2 560 | LYASHI,ANGEL,KAPFTI2 561 | LYASHI,CHILUFYA,KAPFTI2 562 | ZULU,NKUMBULA,KAPFTI2 563 | ZULU,IBRAHIM,KAPFTI2 564 | HASTINGS,LWANGA,KAPFTI2 565 | HASTINGS,MUKUBWA,KAPFTI2 566 | HASTINGS,ANGEL,KAPFTI2 567 | LWANGA,IBRAHIM,KAPFTI2 568 | LWANGA,MESHAK,KAPFTI2 569 | NYIRENDA,BEN,KAPFTI2 570 | NYIRENDA,JOHN,KAPFTI2 571 | CHISOKONE,NKUMBULA,KAPFTI2 572 | CHISOKONE,CHILWA,KAPFTI2 573 | CHISOKONE,ENOCH,KAPFTI2 574 | CHISOKONE,KALAMBA,KAPFTI2 575 | CHISOKONE,IBRAHIM,KAPFTI2 576 | CHISOKONE,JOHN,KAPFTI2 577 | CHISOKONE,JOSEPH,KAPFTI2 578 | CHISOKONE,ANGEL,KAPFTI2 579 | ENOCH,PAULOS,KAPFTI2 580 | MUKUBWA,ABRAHAM,KAPFTI2 581 | MUKUBWA,NKOLOYA,KAPFTI2 582 | MUKUBWA,IBRAHIM,KAPFTI2 583 | MUKUBWA,MPUNDU,KAPFTI2 584 | MUKUBWA,JOHN,KAPFTI2 585 | SIGN,ANGEL,KAPFTI2 586 | KALAMBA,JOHN,KAPFTI2 587 | BEN,ZAKEYO,KAPFTI2 588 | IBRAHIM,JOSEPH,KAPFTI2 589 | IBRAHIM,HENRY,KAPFTI2 590 | IBRAHIM,MUBANGA,KAPFTI2 591 | MESHAK,MUKUBWA,KAPFTI2 592 | MESHAK,JOHN,KAPFTI2 593 | MESHAK,WILLIAM,KAPFTI2 594 | MESHAK,CHRISTIAN,KAPFTI2 595 | MESHAK,KALONGA,KAPFTI2 596 | MESHAK,ANGEL,KAPFTI2 597 | JOSEPH,HENRY,KAPFTI2 598 | JOSEPH,MUBANGA,KAPFTI2 599 | WILLIAM,KALONGA,KAPFTI2 600 | HENRY,MUBANGA,KAPFTI2 601 | HENRY,ANGEL,KAPFTI2 602 | CHOBE,MABANGE,KAPFTI2 603 | MUBANGA,CHRISTIAN,KAPFTI2 604 | -------------------------------------------------------------------------------- /uunet/multinet.py: -------------------------------------------------------------------------------- 1 | """Multinet: Multilayer social network analysis and mining 2 | 3 | This module defines a class to store multilayer networks and functions to pre-process, analyze 4 | and mine them. 5 | 6 | With multilayer social network we indicate a network where vertices (V) are organized into 7 | multiple layers (L) and each node corresponds to an actor (A), where the same actor can be 8 | mapped to nodes in different layers. Formally, a multilayer social network as implemented in 9 | this package is a graph G = (V, E) where V is a subset of A x L. 10 | 11 | Networks can be obtained from file (read) and written to file (write), some existing multilayer 12 | networks are also included (data), synthetic multilayer networks can be generated (grow) and 13 | layers can be added from networkx graphs (add_nx_layer). 14 | 15 | Updating and getting information about the basic objects of a multilayer network can be done 16 | using the functions add_obj, obj, delete_obj (where obj can be: layers, actors, vertices and 17 | edges). neighbors retrieves the neighbors of a node. Attribute values can also be attached to 18 | the basic objects in a multilayer network (actors, layers, vertices and edges) using the 19 | functions attributes, add_attributes, get_values, set_values. 20 | 21 | Each individual layer as well as combination of layers obtained using the data pre-processing 22 | (flattening) functions can be analyzed as a single-layer network using the networkx package 23 | (to_nx_dict). We can also visualize small networks using plot. 24 | 25 | Multilayer network analysis measures are available for single-actors (degree, neighborhood, 26 | xneighborhood, degree_deviation, relevance, xrelevance), based on geodesic distances (distance) 27 | and to compare different layers (layer_summary, layer_comparison). 28 | 29 | Communities can be extracted using various clustering algorithms: abacus, clique_percolation, 30 | glouvain, infomap. 31 | 32 | Most of the methods provided by this module are described in the book "Multilayer Social 33 | Networks" [1]. These methods have been proposed by many different authors: extensive references 34 | are available in the book, and in the documentation of each function we indicate the main 35 | reference we have followed for the implementation. For a few methods developed after the book 36 | was published we give specific references to the corresponding literature. 37 | Additional information (including references to more learning material) is available in [2]. 38 | 39 | References 40 | __________ 41 | .. [1] Dickison, Magnani, and Rossi, 2016. Multilayer Social Networks. 42 | Cambridge University Press. ISBN: 978-1107438750 43 | .. [2] http://multilayer.it.uu.se/ 44 | """ 45 | 46 | import networkx as nx 47 | import pkgutil 48 | import os 49 | import matplotlib.pyplot as plt 50 | import matplotlib.lines as mlines 51 | import itertools 52 | import functools 53 | 54 | try: 55 | from uunet._multinet import ( 56 | # creation 57 | empty, 58 | grow, evolution_pa, evolution_er, 59 | generate_communities, 60 | # io 61 | read, write, 62 | # info 63 | layers, actors, vertices, edges, edges_idx, 64 | num_layers, num_actors, num_vertices, num_edges, 65 | is_directed, 66 | # navigation 67 | neighbors, xneighbors, 68 | # manipulation 69 | add_layers, add_actors, add_vertices, add_edges, 70 | set_directed, 71 | delete_layers, delete_actors, delete_vertices, delete_edges, 72 | # attributes 73 | add_attributes, attributes, get_values, set_values, 74 | # transformation 75 | flatten, project, 76 | # measures 77 | degree, degree_deviation, neighborhood, xneighborhood, connective_redundancy, 78 | relevance, xrelevance, 79 | layer_summary, layer_comparison, 80 | distance, 81 | # clustering 82 | clique_percolation, glouvain, abacus, infomap, flat_ec, flat_nw, mdlp, 83 | modularity, nmi, omega_index, 84 | # visualization 85 | layout_multiforce, layout_circular, 86 | # networkx 87 | to_node_dict, to_edge_dict 88 | ) 89 | except ImportError as e: 90 | print('Failed importing!') 91 | print(e) 92 | 93 | 94 | def data(name): 95 | """Loads one of the predefined datasets provided with the library. 96 | 97 | Parameters 98 | ---------- 99 | name : str 100 | Can take the following values: 101 | - aucs: The AUCS multiplex network described in [1]. 102 | - bankwiring: The Bankwiring network described in [2]. 103 | - florentine: Padgett's Florentine Families multiplex network described in [3]. 104 | - monastery: The Monastery network described in [2]. 105 | - tailorshop: The Tailorshop network described in [4]. 106 | 107 | Returns 108 | ------- 109 | PyMLNetwork 110 | a multilayer network 111 | 112 | See Also 113 | ________ 114 | read : from file 115 | grow : synthetic networks 116 | 117 | References 118 | __________ 119 | .. [1] Rossi and Magnani (2015). "Towards effective visual analytics on multiplex networks". Chaos, Solitons and Fractals. Elsevier. 120 | .. [2] Breiger, R. and Boorman, S. and Arabic, P. (1975). An algorithm for clustering relational data with applications to social network analysis and comparison with multidimensional scaling. Journal of Mathematical Psychology, 12. 121 | .. [3] Padgett, John F., and McLean, Paul D. (2006). Organizational Invention and Elite Transformation: The Birth of Partnership Systems in Renaissance Florence. American Journal of Sociology, 111(5), 1463-1568. 122 | .. [4] Kapferer, Bruce (1972). Strategy and Transaction in an African Factory: African Workers and Indian Management in a Zambian Town. Manchester University Press. 123 | """ 124 | if name == "aucs": 125 | path = os.path.dirname(globals()["__file__"]) 126 | return read(path + "/data/aucs.mpx", name = "aucs") 127 | elif name == "florentine": 128 | path = os.path.dirname(globals()["__file__"]) 129 | return read(path + "/data/florentine.mpx", name = "florentine") 130 | elif name == "bankwiring": 131 | path = os.path.dirname(globals()["__file__"]) 132 | return read(path + "/data/bankwiring.mpx", name = "bankwiring") 133 | elif name == "monastery": 134 | path = os.path.dirname(globals()["__file__"]) 135 | return read(path + "/data/monastery.mpx", name = "monastery") 136 | elif name == "tailorshop": 137 | path = os.path.dirname(globals()["__file__"]) 138 | return read(path + "/data/tailorshop.mpx", name = "tailorshop") 139 | else: 140 | raise Exception("No predefined dataset named " + name) 141 | 142 | 143 | def to_nx_dict(n): 144 | """Converts the network into one networkx object per layer. 145 | 146 | Parameters 147 | ---------- 148 | n : PyMLNetwork 149 | A multilayer network. 150 | 151 | Returns 152 | ------- 153 | dict 154 | A dictionary where each key is a layer and each value is a networkx graph (or directed graph) 155 | coresponding to that layer. 156 | """ 157 | res = {} 158 | edges = to_edge_dict(n) 159 | nodes = to_node_dict(n) 160 | for layer in edges: 161 | if is_directed(n, [layer], [layer])["dir"][0]: 162 | res[layer] = nx.DiGraph(edges[layer]) 163 | else: 164 | res[layer] = nx.Graph(edges[layer]) 165 | nx.set_node_attributes(res[layer], nodes[layer]) 166 | return res 167 | 168 | 169 | def summary(n): 170 | """Produces basic layer-by-layer statistics. 171 | 172 | Parameters 173 | ---------- 174 | n : PyMLNetwork 175 | A multilayer network. 176 | 177 | Returns 178 | ------- 179 | dict 180 | A dictionary representing a table with the following keys/columns: 181 | - "layer": name of the layer 182 | - "n": order 183 | - "m": size 184 | - "dir": directed/undirected (bool) 185 | - "nc": number of (strongly connected) components 186 | - "slc": size of the largest (strongly connected) component 187 | - "dens": density 188 | - "cc" : clustering coefficient (triangle-based definition) 189 | - "apl": average path length in the largest component 190 | - "dia": diameter 191 | """ 192 | layers = to_nx_dict(n) 193 | res = { 194 | "layer": [], 195 | "n": [], 196 | "m": [], 197 | "dir": [], 198 | "nc": [], 199 | "slc": [], 200 | "dens": [], 201 | "cc" : [], 202 | "apl": [], 203 | "dia": [] } 204 | for l, net in layers.items(): 205 | res["layer"].append(l) 206 | res["n"].append(net.order()) 207 | res["m"].append(net.size()) 208 | dir = nx.is_directed(net) 209 | res["dir"].append(dir) 210 | if dir: 211 | components = [net.subgraph(c) for c in nx.strongly_connected_components(net)] 212 | largest_component = max(components, key=len) 213 | res["nc"].append(nx.number_strongly_connected_components(net)) 214 | res["slc"].append(len(largest_component)) 215 | res["apl"].append(nx.average_shortest_path_length(largest_component)) 216 | res["dia"].append(nx.diameter(largest_component)) 217 | else: 218 | components = [net.subgraph(c) for c in nx.connected_components(net)] 219 | largest_component = max(components, key=len) 220 | res["nc"].append(nx.number_connected_components(net)) 221 | res["slc"].append(len(largest_component)) 222 | res["apl"].append(nx.average_shortest_path_length(largest_component)) 223 | res["dia"].append(nx.diameter(largest_component)) 224 | res["dens"].append(nx.density(net)) 225 | res["cc"].append(nx.transitivity(net)) 226 | return res 227 | 228 | 229 | def add_nx_layer(n, g, name, node_attr = {"name":[], "type":[]}, edge_attr = {"name":[], "type":[]}): 230 | """Adds a new layer to a network starting from a networkx graph. 231 | 232 | Parameters 233 | ---------- 234 | n : PyMLNetwork 235 | A multilayer network. 236 | g : 237 | A networkx Graph or Digraph object. 238 | name : str 239 | Name of the new layer. 240 | node_attr : dict, optional 241 | Specifies which node attributes to copy to the layer. Must contain two lists: 242 | "name" (attribute names) and "type" (with values "string" or "numeric"). 243 | edge_attr : dict, optional 244 | Specifies which edge attributes to copy to the layer. Must contain two lists: 245 | "name" (attribute names) and "type" (with values "string" or "numeric"). 246 | 247 | See Also 248 | ________ 249 | to_nx_dict : to turn layers into networkx graphs 250 | """ 251 | add_layers(n, [name], [nx.is_directed(g)]) 252 | vertices = {"actor": g.nodes(), "layer": [name] * g.order() } 253 | add_vertices(n, vertices) 254 | # @todo test & add eges 255 | for attr, type in zip(node_attr["name"], node_attr["type"]): 256 | if type == "numeric": 257 | add_attributes(n, attributes=[attr], type="numeric", target="vertex", layer=name) 258 | values = [el[1] for el in g.nodes(data=attr, default=0)] 259 | set_values_ml(n, attr, vertices=vertices, values=vertex_attr(g)[[attr]]) 260 | elif type == "string": 261 | add_attributes(n, attributes=[attr], type="string", target="vertex", layer=name) 262 | values = [el[1] for el in g.nodes(data=attr, default="")] 263 | else: print("[Warning] wrong attribute type") 264 | edges = { 265 | "from_actor": [e[0] for e in g.edges()], 266 | "from_layer": [name] * g.size(), 267 | "to_actor": [e[1] for e in g.edges()], 268 | "to_layer": [name] * g.size() 269 | } 270 | add_edges(n, edges) 271 | 272 | 273 | 274 | def values2graphics(values, output = ["c"], shape_size=7): 275 | """A utility function to turn nominal values into graphical features to be used by the plot function. 276 | 277 | Parameters 278 | ---------- 279 | values : list 280 | A list of nominal values. 281 | output : list, optional 282 | A list of graphical features to be produced. Currently accepts "c" (colors) and "s" (shapes). 283 | shape_size : int, optional 284 | Size of the shapes associated to the values. 285 | 286 | Returns 287 | ------- 288 | dict 289 | A dictionary with the following items: 290 | - "colors": a list of the same length of the input (values), where values have been 291 | replaced by colors. 292 | - "shapes": a list of the same length of the input (values), where values have been 293 | replaced by strings indicating shapes. 294 | - "legend": a list with one element for each distinct value in the input (values), each 295 | corresponding to an entry for the legend of the plotting function. Can be directly 296 | passed to the "legend" argument of plot. 297 | 298 | See Also 299 | ________ 300 | plot : to plot multilayer networks 301 | """ 302 | res = dict() 303 | types = list(set(values)) 304 | num_types = len(types) 305 | if (num_types > 12): 306 | raise RuntimeError("only 12 distinct values supported") 307 | colors = ['black']*12 308 | if "c" in output: 309 | colors = plt.get_cmap("Paired").colors 310 | markers = ["s"]*12 311 | if "s" in output: 312 | markers = ["o","s","v","^","D","p","X","*","P",">","<","H"] 313 | res["legend"] = [] 314 | for i in range(num_types): 315 | h = mlines.Line2D([], [], color=colors[i], marker=markers[i], linestyle='None', markersize=shape_size, label=types[i]) 316 | res["legend"].append(h) 317 | res["colors"] = [colors[types.index(v)] for v in values] 318 | res["shapes"] = [markers[types.index(v)] for v in values] 319 | return res 320 | 321 | 322 | def plot(n, base_size=3, mai=[.15,.15,.15,.15], layout=None, com=None, com_border=.4, 323 | # 324 | grid=[], 325 | # 326 | vertex_shape=['o'], vertex_size=[7], vertex_color=["black"], vertex_alpha=[1], 327 | # 328 | edge_style=["-"], edge_width=[1], edge_color=["black"], edge_alpha=[.8], 329 | edge_arrow_size=[30], 330 | # 331 | vertex_labels=None, vertex_labels_family="serif", 332 | vertex_labels_size=12, vertex_labels_weight="normal", 333 | vertex_labels_color="black", 334 | vertex_labels_style="normal", vertex_labels_stretch="normal", 335 | vertex_labels_bbox={"visible": False}, 336 | vertex_labels_ha="center", vertex_labels_va="center", 337 | # 338 | legend=None, legend_loc="best", legend_ncol=1, 339 | show_layer_names=True, layer_names_bgcolor='white', layer_names_size=12, 340 | format="screen", file="mlfig"): 341 | """A (rudimentary) plotting function. 342 | 343 | This function uses matplotlib.pyplot drawing primitives. We repeat here some of 344 | the documentation; additional details can be found in pyplot's documentation. 345 | 346 | Parameters 347 | ---------- 348 | n : PyMLNetwork 349 | A multilayer network. 350 | base_size : double, optional 351 | Approximate width and height of the part of the plot corresponding to one layer. 352 | In general, layers contain multiple layers organized in a grid (rows and columns), and the 353 | width (resp., height) of the plot will be base_size*num_cols (resp., *num_rows) plus margins 354 | and padding. 355 | mai : list of double, optional 356 | A list with four elements indicating the margin (left, top, right, bottom) inside each 357 | layer plot. The margin is applied to the vertex layout, that is, other graphical objects 358 | such as vertex labels can appear on top of the margin area. Margins are typically intended 359 | to make space for these additional graphical objects. 360 | layout : dict 361 | A dictionary representing a table with the following keys/columns: 362 | - "actor": name of the actor. 363 | - "layer": name of the layer. 364 | - "x": x coordinate of the vertex relative to the layer's plot. 365 | - "y": y coordinate of the vertex relative to the layer's plot. 366 | - "z": order of a layer (0, 1, ...). 367 | com : dict 368 | The result of a community detection algorithm. When provided, areas behind each community 369 | are represented in the plot. 370 | com_border : float 371 | Indicates the border around the community areas. If 0, the area passes through the center 372 | of the vertices in the convex hull of the vertices in the community, on each layer. A 373 | positive value increases the area. 374 | grid: list of double, optional 375 | A list with two elements, indicating number of rows and number of columns. 376 | vertex_shape : list of char, optional 377 | Characters indicating the shape of the vertices. It can contain one element, determining 378 | the shape of all vertices, or as many elements as the number of vertices. 379 | Any value allowed for matplotlib.markers is also allowed here (vertices are plotted using 380 | markers). Examples are 'o' (circle), 's' (square), 'D', 'd' (diamonds), 'v', '^', '<', '>' 381 | (triangles). 382 | vertex_size : list of int, optional 383 | Values indicating the size of the vertices. It can contain one element, determining 384 | the size of all vertices, or as many elements as the number of vertices. 385 | vertex_color : list of str, optional 386 | Values indicating the color of the vertices. It can contain one element, determining 387 | the color of all vertices, or as many elements as the number of vertices. 388 | vertex_alpha : list of double, optional 389 | Values indicating the transparency of the vertices, from 0 (transparent) to 1 (opaque). 390 | It can contain one element, determining the transparency of all vertices, or as many 391 | elements as the number of vertices. 392 | edge_style : list of str, optional 393 | Values indicating the line style of the edges/arcs. 394 | It can contain one element, determining the style of all edges, or as many 395 | elements as the number of edges. Examples of valid styles are: '-', '--', '-.', ':', '', 396 | (offset, on-off-seq). 397 | edge_width : list of int, optional 398 | Values indicating the line width of the edges/arcs. 399 | It can contain one element, determining the width of all edges, or as many 400 | elements as the number of edges. 401 | edge_color : list of str, optional 402 | Values indicating the color of the edges/arcs. 403 | It can contain one element, determining the color of all edges, or as many 404 | elements as the number of edges. 405 | edge_alpha : list of double, optional 406 | Values indicating the transparency of the edges/arcs, from 0 (transparent) to 1 (opaque). 407 | It can contain one element, determining the transparency of all edges, or as many 408 | elements as the number of edges. 409 | edge_arrow_size : list of int, optional 410 | Only for directed edges (arcs), values indicating the size of the arrow of the arcs. 411 | It can contain one element, determining the arrow size of all arcs, or as many 412 | elements as the number of arcs. 413 | vertex_labels : list of str, optional 414 | Values indicating the labels of the vertices. It must contain as many elements as the 415 | number of vertices, or a single value which will be applied to all vertices (in this case 416 | typically being [""], not to print any labels). If this parameter is not specified, 417 | actor names are visualized. 418 | vertex_labels_family : str, optional 419 | One of 'serif', 'sans-serif', 'cursive', 'fantasy', 'monospace', or a supported fontname. 420 | vertex_labels_size : int, optional 421 | Font size. 422 | vertex_labels_weight : 423 | This can be a numeric value in range 0-1000, 'ultralight', 'light', 'normal', 'regular', 424 | 'book', 'medium', 'roman', 'semibold', 'demibold', 'demi', 'bold', 'heavy', 'extra bold', 425 | or 'black'. 426 | vertex_labels_color : str, optional 427 | A string representing a python color ('black', 'red', ...). 428 | vertex_labels_style : str, optional 429 | 'normal', 'italic' or 'oblique'. 430 | vertex_labels_stretch : str, optional 431 | This can be a numeric value in range 0-1000, 'ultra-condensed', 'extra-condensed', 432 | 'condensed', 'semi-condensed', 'normal', 'semi-expanded', 'expanded', 'extra-expanded', 433 | or 'ultra-expanded'. 434 | vertex_labels_bbox : dict, optional 435 | A dictionary with properties as in the documentation for patches.FancyBboxPatch. 436 | vertex_labels_ha : str, optional 437 | Can be 'center', 'right', or 'left'. 438 | vertex_labels_va : str, optional 439 | Can be 'center', 'top', 'bottom', 'baseline', or 'center_baseline'. 440 | legend : list of Artist, optional 441 | This parameter is equivalent to the handles parameter of pyplot.legend(). It can be easier 442 | to set it using the values2graphics function, that automatically produces the value for this 443 | parameter for nominal values. 444 | legend_loc : str, optional 445 | If a legend is provided (see legend parameter), this parameter controls its location. Can 446 | be 'upper right', 'upper left', 'lower left', 'lower right', 'right', 'center left', 447 | 'center right', 'lower center', 'upper center', 'center', or a 2-tuple giving the 448 | coordinates of the lower-left corner of the legend in axes coordinates (from 0 to 1). 449 | legend_ncol : int, optional 450 | Number of columns in the legend. 451 | show_layer_names : bool, optional 452 | If True, draws the name of the layer below each layer plot. 453 | layer_names_bgcolor : str, optional 454 | If show_layer_names is true, this parameter controls the background color 455 | of the layer names. 456 | layer_names_size : int, optional 457 | If show_layer_names is true, this parameter controls the size of the layer names. 458 | format : str, optional 459 | This values specifies whether the plot should be shown in a new window ("screen", default) 460 | or saved to a file, in which case it specifies the image format ("pdf", "png", ...). 461 | file : str, optional 462 | If the format parameter indicates that the plot should be saved to file, this parameter 463 | allows to choose a file name. 464 | 465 | See Also 466 | ________ 467 | values2graphics : to code nominal values into colors or shapes, also for the legend 468 | matplotlib.markers : for vertex shapes 469 | """ 470 | ###################################### 471 | # Some sub-functions used by plot(). # 472 | ###################################### 473 | # Functions to compute planar coordinates (plot shows the layers beside each other, not stacked) 474 | def x_coord(x, y, z): 475 | return x + z%num_cols*width 476 | def y_coord(x, y, z): 477 | return y + (num_rows - 1 - z//num_cols)*height 478 | # Functions to draw an area behind groups of vertices, used to visualize communities. 479 | # Groups vertices from the result of a community detection algorithms into communities. 480 | def to_community_list(com): 481 | res = {} 482 | for a,l,cid in zip(com["actor"],com["layer"],com["cid"]): 483 | if cid not in res.keys(): 484 | res[cid] = dict() 485 | if l not in res[cid].keys(): 486 | res[cid][l] = [] 487 | res[cid][l].append(a) 488 | return res 489 | # Produces a dictionary for quick retrieval of vertex coord., from the result of a layout algo. 490 | def index_layout(layout): 491 | res = {} 492 | for a,l,x,y,z in zip(layout["actor"], layout["layer"], layout["x"], layout["y"], layout["z"]): 493 | if a not in res.keys(): 494 | res[a] = dict() 495 | res[a][l] = [x,y,z] 496 | return res 497 | # The following set of functions compute a ConvexHull (I think). The main function to do so 498 | # is perimeter(). 499 | # (The ConvexHull function provided by scipy crashes on some systems.) 500 | def skyline(points, i, j): 501 | def comp(p1, p2, i, j): 502 | if i*p1[0]>i*p2[0]: 503 | if j*p1[1]>=j*p2[1]: 504 | return 1 505 | else: 506 | return 0 507 | if i*p1[0]j*p2[1]: 513 | return 1 514 | elif j*p1[1]i*p2[0]: 535 | return 1 536 | return -1 537 | def convex(points): 538 | res = [] 539 | p = 0 540 | while p < len(points): 541 | res.append(points[p]) 542 | max_slope=None 543 | idx=p+1 544 | for q in range(p+1,len(points)): 545 | slope = (points[q][1]-points[p][1])/(points[q][0]-points[p][0]) 546 | if max_slope is None: 547 | max_slope=slope 548 | elif slope>=max_slope: 549 | max_slope=slope 550 | idx = q 551 | p = idx 552 | return res 553 | def sky_ne(points): 554 | return skyline(points,1,1) 555 | def sky_se(points): 556 | return skyline(points,1,-1) 557 | def sky_nw(points): 558 | return skyline(points,-1,1) 559 | def sky_sw(points): 560 | return skyline(points,-1,-1) 561 | def c_nw(p1,p2): 562 | return scomp(p1,p2,1) 563 | def c_ne(p1,p2): 564 | return scomp(p1,p2,1) 565 | def c_sw(p1,p2): 566 | return scomp(p1,p2,-1) 567 | def c_se(p1,p2): 568 | return scomp(p1,p2,-1) 569 | def perimeter(points): 570 | per_nw = sorted(sky_nw(points), key=functools.cmp_to_key(c_nw)) 571 | per_ne = sorted(sky_ne(points), key=functools.cmp_to_key(c_ne)) 572 | per_se = sorted(sky_se(points), key=functools.cmp_to_key(c_se)) 573 | per_sw = sorted(sky_sw(points), key=functools.cmp_to_key(c_sw)) 574 | return convex(per_nw) + convex(per_ne) + convex(per_se) + convex(per_sw) 575 | # Given the results of to_community_list and index_layout, it draws polygons containing the 576 | # vertices inside communities. 577 | def draw_groups(com_list,coord): 578 | colors = plt.get_cmap("Set1").colors 579 | if (len(com_list) > 12): 580 | print("[Warning] some colors reused for different communities") 581 | for cid, l_dict in com_list.items(): 582 | for l, actors in l_dict.items(): 583 | point_set = set() 584 | for a in actors: 585 | xyz = coord[a][l] 586 | x = x_coord(xyz[0],xyz[1],xyz[2]) 587 | y = y_coord(xyz[0],xyz[1],xyz[2]) 588 | point_set.add((x-com_border*3/4,y-com_border*3/4)) 589 | point_set.add((x+com_border*3/4,y-com_border*3/4)) 590 | point_set.add((x+com_border*3/4,y+com_border*3/4)) 591 | point_set.add((x-com_border*3/4,y+com_border*3/4)) 592 | point_set.add((x-com_border,y)) 593 | point_set.add((x+com_border,y)) 594 | point_set.add((x,y+com_border)) 595 | point_set.add((x,y-com_border)) 596 | per = perimeter(point_set) 597 | x = [p[0] for p in per] 598 | y = [p[1] for p in per] 599 | plt.fill(x,y,color=colors[cid],alpha=.8) 600 | ###################################### 601 | # Main code of plot startig here. # 602 | ###################################### 603 | # checking argument: mai 604 | if len(mai) != 4: 605 | raise RuntimeError("argument mai must contain four values") 606 | if max(mai) > 1: 607 | print("[Warning] too high values for argument mai?") 608 | # computing layout if needed 609 | if layout is None: 610 | layout = layout_multiforce(n) 611 | # checking argument: vertex_shape, etc. 612 | if (len(vertex_shape) != 1) & (len(vertex_shape) != len(layout["actor"])): 613 | raise RuntimeError("argument vertex_shape must contain one element, or num_vertices elements.") 614 | if (len(vertex_size) != 1) & (len(vertex_size) != len(layout["actor"])): 615 | raise RuntimeError("argument vertex_size must contain one element, or num_vertices elements.") 616 | if (len(vertex_color) != 1) & (len(vertex_color) != len(layout["actor"])): 617 | raise RuntimeError("argument vertex_color must contain one element, or num_vertices elements.") 618 | if (len(vertex_alpha) != 1) & (len(vertex_alpha) != len(layout["actor"])): 619 | raise RuntimeError("argument vertex_alpha must contain one element, or num_vertices elements.") 620 | # checking argument: edge_style, etc. 621 | if (len(edge_width) != 1) & (len(edge_width) != num_edges(n)): 622 | raise RuntimeError("argument edge_width must contain one element, or num_edges elements.") 623 | if (len(edge_style) != 1) & (len(edge_style) != num_edges(n)): 624 | raise RuntimeError("argument edge_style must contain one element, or num_edges elements.") 625 | if (len(edge_color) != 1) & (len(edge_color) != num_edges(n)): 626 | raise RuntimeError("argument edge_color must contain one element, or num_edges elements.") 627 | if (len(edge_alpha) != 1) & (len(edge_alpha) != num_edges(n)): 628 | raise RuntimeError("argument edge_alpha must contain one element, or num_edges elements.") 629 | # option to select and reorder the layers 630 | # @todo only in the R version 631 | # grid, num columns, computing extreme coordinates... 632 | n_layers = num_layers(n) 633 | num_cols = n_layers 634 | num_rows = 1 635 | if len(grid) > 0: 636 | if len(grid) != 2: 637 | raise RuntimeError("argument grid must have two elements") 638 | if grid[0]*grid[1] < n_layers: 639 | raise RuntimeError("insufficient number of grid cells (< n_layers)") 640 | num_cols = grid[1] 641 | num_rows = grid[0] 642 | x_min = min(layout["x"]) 643 | y_min = min(layout["y"]) 644 | x_max = max(layout["x"]) 645 | y_max = max(layout["y"]) 646 | width = x_max-x_min + (mai[0]+mai[2])*(x_max-x_min) 647 | x_min = x_min - mai[0]*(x_max-x_min) 648 | height = y_max-y_min + (mai[1]+mai[3])*(y_max-y_min) 649 | y_min = y_min - mai[3]*(y_max-y_min) 650 | # create a figure 651 | f = plt.figure(figsize=(base_size*num_cols, base_size*num_rows)) 652 | # draw grid 653 | for i in range(num_cols+1): 654 | plt.plot([x_min+i*width, x_min+i*width], [y_min, y_min+height*num_rows], 'k-', lw=1) 655 | for i in range(num_rows+1): 656 | plt.plot([x_min, x_min+width*num_cols], [y_min+i*height, y_min+i*height], 'k-', lw=1) 657 | # draw communities 658 | if com is not None: 659 | draw_groups(to_community_list(com), index_layout(layout)) 660 | # draw edges 661 | e = edges_idx(n) 662 | for (fr, to, dir, style, size, color, alpha, arrow_w) in itertools.zip_longest(e["from"], e["to"], e["dir"], edge_style, edge_width, edge_color, edge_alpha, edge_arrow_size): 663 | fr_x = layout["x"][fr-1] 664 | fr_y = layout["y"][fr-1] 665 | fr_z = layout["z"][fr-1] 666 | to_x = layout["x"][to-1] 667 | to_y = layout["y"][to-1] 668 | to_z = layout["z"][to-1] 669 | marker = dict() 670 | if style is not None: 671 | st = style 672 | else: 673 | st = edge_style[0] 674 | if size is not None: 675 | wi = size 676 | else: 677 | wi = edge_width[0] 678 | if color is not None: 679 | co = color 680 | else: 681 | co = edge_color[0] 682 | if alpha is not None: 683 | al = alpha 684 | else: 685 | al = edge_alpha[0] 686 | if arrow_w is not None: 687 | arw = arrow_w 688 | else: 689 | arw = edge_arrow_size[0] 690 | x1 = x_coord(fr_x, fr_y, fr_z) 691 | y1 = y_coord(fr_x, fr_y, fr_z) 692 | x2 = x_coord(to_x, to_y, to_z) 693 | y2 = y_coord(to_x, to_y, to_z) 694 | if dir: 695 | plt.annotate('', 696 | xytext=(x1, y1), 697 | xy=(x2, y2), 698 | arrowprops=dict(arrowstyle="-|>", lw=wi, ls=st, color=co, alpha=al), 699 | size=arw 700 | ) 701 | else: 702 | plt.plot([x1, x2], [y1, y2], lw=wi, ls=st, color=co, alpha=al) 703 | # draw vertices 704 | for (x, y, z, shape, size, color, alpha) in itertools.zip_longest(layout["x"], layout["y"], layout["z"], vertex_shape, vertex_size, vertex_color, vertex_alpha): 705 | marker = dict() 706 | if shape is not None: 707 | marker["marker"] = shape 708 | else: 709 | marker["marker"] = vertex_shape[0] 710 | if size is not None: 711 | marker["markersize"] = size 712 | else: 713 | marker["markersize"] = vertex_size[0] 714 | if color is not None: 715 | marker["color"] = color 716 | else: 717 | marker["color"] = vertex_color[0] 718 | if alpha is not None: 719 | marker["alpha"] = alpha 720 | else: 721 | marker["alpha"] = vertex_alpha[0] 722 | plt.plot(x_coord(x,y,z), y_coord(x,y,z), **marker) 723 | # draw labels 724 | if vertex_labels is None: 725 | for (v, x, y, z) in zip(layout["actor"], layout["x"], layout["y"], layout["z"]): 726 | plt.text(x_coord(x,y,z), y_coord(x,y,z), v, family=vertex_labels_family, 727 | size=vertex_labels_size, weight=vertex_labels_weight, 728 | color=vertex_labels_color, 729 | style=vertex_labels_style, stretch=vertex_labels_stretch, 730 | bbox=vertex_labels_bbox, ha=vertex_labels_ha, va=vertex_labels_va) 731 | else: 732 | for (v, x, y, z) in zip(vertex_labels, layout["x"], layout["y"], layout["z"]): 733 | plt.text(x_coord(x,y,z), y_coord(x,y,z), v, family=vertex_labels_family, 734 | size=vertex_labels_size, weight=vertex_labels_weight, 735 | color=vertex_labels_color, 736 | style=vertex_labels_style, stretch=vertex_labels_stretch, 737 | bbox=vertex_labels_bbox, ha=vertex_labels_ha, va=vertex_labels_va) 738 | # draw layer names 739 | if show_layer_names: 740 | layer_names = layers(n) 741 | for i in range(n_layers): 742 | row = i // num_cols 743 | col = i % num_cols 744 | plt.text(x_min+col*width+width/2, y_min+(num_rows-row-1)*height, layer_names[i], 745 | ha="center", va="center", bbox={"visible":True, "color":layer_names_bgcolor}, 746 | size=layer_names_size) 747 | # legend 748 | if legend is not None: 749 | plt.legend(handles=legend, loc=legend_loc, ncol=legend_ncol) 750 | # show plot 751 | plt.axis(False) 752 | plt.tight_layout() 753 | if format == "screen": 754 | plt.show() 755 | else: 756 | plt.savefig(file, format=format) 757 | 758 | --------------------------------------------------------------------------------