From 09e1d02ae5a73d3bc209c4761060ddcd0b02eea5 Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Fri, 1 Jan 2021 16:26:12 +0100 Subject: [PATCH 01/24] Update GED fit distance experiments README. --- gklearn/experiments/thesis/ged/fit_distances/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gklearn/experiments/thesis/ged/fit_distances/README.md b/gklearn/experiments/thesis/ged/fit_distances/README.md index 367a92d..78fc992 100644 --- a/gklearn/experiments/thesis/ged/fit_distances/README.md +++ b/gklearn/experiments/thesis/ged/fit_distances/README.md @@ -4,8 +4,15 @@ ``` python3 -m pip install graphkit-learn python3 run_xp.py +``` + +Plot results in figure and LaTex tables: +``` +python3 ged_fit_distance_results_plot.py ``` # Run xp (deprecated). +``` export PYTHONPATH="/path/to/gedlibpy:/path/to/py-graph" python optim_costs.py dataset output_file +``` From 819b2563356b6f995d7619d5add323cea7287f8e Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Fri, 1 Jan 2021 18:39:42 +0100 Subject: [PATCH 02/24] Add GED fit distance experiments result figure. --- .../ged/fit_distances/ged_fit_distance_results.eps | 4459 ++++++++++++++++++++ .../fit_distances/ged_fit_distance_results_plot.py | 26 +- 2 files changed, 4480 insertions(+), 5 deletions(-) create mode 100644 gklearn/experiments/thesis/ged/fit_distances/ged_fit_distance_results.eps diff --git a/gklearn/experiments/thesis/ged/fit_distances/ged_fit_distance_results.eps b/gklearn/experiments/thesis/ged/fit_distances/ged_fit_distance_results.eps new file mode 100644 index 0000000..c54c4c2 --- /dev/null +++ b/gklearn/experiments/thesis/ged/fit_distances/ged_fit_distance_results.eps @@ -0,0 +1,4459 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Title: ged_fit_distance_results.eps +%%Creator: matplotlib version 3.2.1, http://matplotlib.org/ +%%CreationDate: Fri Jan 1 18:33:17 2021 +%%Orientation: portrait +%%BoundingBox: -38.395500000000034 231.6735 650.3955 560.3265 +%%EndComments +%%BeginProlog +/mpldict 8 dict def +mpldict begin +/m { moveto } bind def +/l { lineto } bind def +/r { rlineto } bind def +/c { curveto } bind def +/cl { closepath } bind def +/box { +m +1 index 0 r +0 exch r +neg 0 r +cl +} bind def +/clipbox { +box +clip +newpath +} bind def +%!PS-Adobe-3.0 Resource-Font +%%Title: DejaVu Sans +%%Copyright: Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. DejaVu changes are in public domain +%%Creator: Converted from TrueType to type 3 by PPR +25 dict begin +/_d{bind def}bind def +/_m{moveto}_d +/_l{lineto}_d +/_cl{closepath eofill}_d +/_c{curveto}_d +/_sc{7 -1 roll{setcachedevice}{pop pop pop pop pop pop}ifelse}_d +/_e{exec}_d +/FontName /DejaVuSans def +/PaintType 0 def +/FontMatrix[.001 0 0 .001 0 0]def +/FontBBox[-1021 -463 1793 1232]def +/FontType 3 def +/Encoding [ /space /comma /period /zero /one /two /three /four /five /six /eight /A /E /F /I /M /P /R /S /a /b /c /d /e /f /h /i /k /l /m /n /o /p /r /s /t /u /x /y ] def +/FontInfo 10 dict dup begin +/FamilyName (DejaVu Sans) def +/FullName (DejaVu Sans) def +/Notice (Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. DejaVu changes are in public domain ) def +/Weight (Book) def +/Version (Version 2.35) def +/ItalicAngle 0.0 def +/isFixedPitch false def +/UnderlinePosition -130 def +/UnderlineThickness 90 def +end readonly def +/CharStrings 40 dict dup begin +/.notdef 0 def +/space{318 0 0 0 0 0 _sc +}_d +/comma{318 0 77 -115 220 124 _sc +117 124 _m +220 124 _l +220 40 _l +140 -115 _l +77 -115 _l +117 40 _l +117 124 _l +_cl}_d +/period{318 0 107 0 210 124 _sc +107 124 _m +210 124 _l +210 0 _l +107 0 _l +107 124 _l +_cl}_d +/zero{636 0 66 -13 570 742 _sc +318 664 _m +267 664 229 639 203 589 _c +177 539 165 464 165 364 _c +165 264 177 189 203 139 _c +229 89 267 64 318 64 _c +369 64 407 89 433 139 _c +458 189 471 264 471 364 _c +471 464 458 539 433 589 _c +407 639 369 664 318 664 _c +318 742 _m +399 742 461 709 505 645 _c +548 580 570 486 570 364 _c +570 241 548 147 505 83 _c +461 19 399 -13 318 -13 _c +236 -13 173 19 130 83 _c +87 147 66 241 66 364 _c +66 486 87 580 130 645 _c +173 709 236 742 318 742 _c +_cl}_d +/one{636 0 110 0 544 729 _sc +124 83 _m +285 83 _l +285 639 _l +110 604 _l +110 694 _l +284 729 _l +383 729 _l +383 83 _l +544 83 _l +544 0 _l +124 0 _l +124 83 _l +_cl}_d +/two{{636 0 73 0 536 742 _sc +192 83 _m +536 83 _l +536 0 _l +73 0 _l +73 83 _l +110 121 161 173 226 239 _c +290 304 331 346 348 365 _c +380 400 402 430 414 455 _c +426 479 433 504 433 528 _c +433 566 419 598 392 622 _c +365 646 330 659 286 659 _c +255 659 222 653 188 643 _c +154 632 117 616 78 594 _c +78 694 _l +118 710 155 722 189 730 _c +223 738 255 742 284 742 _c +}_e{359 742 419 723 464 685 _c +509 647 532 597 532 534 _c +532 504 526 475 515 449 _c +504 422 484 390 454 354 _c +446 344 420 317 376 272 _c +332 227 271 164 192 83 _c +_cl}_e}_d +/three{{636 0 76 -13 556 742 _sc +406 393 _m +453 383 490 362 516 330 _c +542 298 556 258 556 212 _c +556 140 531 84 482 45 _c +432 6 362 -13 271 -13 _c +240 -13 208 -10 176 -4 _c +144 1 110 10 76 22 _c +76 117 _l +103 101 133 89 166 81 _c +198 73 232 69 268 69 _c +330 69 377 81 409 105 _c +441 129 458 165 458 212 _c +458 254 443 288 413 312 _c +383 336 341 349 287 349 _c +}_e{202 349 _l +202 430 _l +291 430 _l +339 430 376 439 402 459 _c +428 478 441 506 441 543 _c +441 580 427 609 401 629 _c +374 649 336 659 287 659 _c +260 659 231 656 200 650 _c +169 644 135 635 98 623 _c +98 711 _l +135 721 170 729 203 734 _c +235 739 266 742 296 742 _c +370 742 429 725 473 691 _c +517 657 539 611 539 553 _c +539 513 527 479 504 451 _c +481 423 448 403 406 393 _c +_cl}_e}_d +/four{636 0 49 0 580 729 _sc +378 643 _m +129 254 _l +378 254 _l +378 643 _l +352 729 _m +476 729 _l +476 254 _l +580 254 _l +580 172 _l +476 172 _l +476 0 _l +378 0 _l +378 172 _l +49 172 _l +49 267 _l +352 729 _l +_cl}_d +/five{{636 0 77 -13 549 729 _sc +108 729 _m +495 729 _l +495 646 _l +198 646 _l +198 467 _l +212 472 227 476 241 478 _c +255 480 270 482 284 482 _c +365 482 429 459 477 415 _c +525 370 549 310 549 234 _c +549 155 524 94 475 51 _c +426 8 357 -13 269 -13 _c +238 -13 207 -10 175 -6 _c +143 -1 111 6 77 17 _c +77 116 _l +106 100 136 88 168 80 _c +199 72 232 69 267 69 _c +}_e{323 69 368 83 401 113 _c +433 143 450 183 450 234 _c +450 284 433 324 401 354 _c +368 384 323 399 267 399 _c +241 399 214 396 188 390 _c +162 384 135 375 108 363 _c +108 729 _l +_cl}_e}_d +/six{{636 0 70 -13 573 742 _sc +330 404 _m +286 404 251 388 225 358 _c +199 328 186 286 186 234 _c +186 181 199 139 225 109 _c +251 79 286 64 330 64 _c +374 64 409 79 435 109 _c +461 139 474 181 474 234 _c +474 286 461 328 435 358 _c +409 388 374 404 330 404 _c +526 713 _m +526 623 _l +501 635 476 644 451 650 _c +425 656 400 659 376 659 _c +310 659 260 637 226 593 _c +}_e{192 549 172 482 168 394 _c +187 422 211 444 240 459 _c +269 474 301 482 336 482 _c +409 482 467 459 509 415 _c +551 371 573 310 573 234 _c +573 159 550 99 506 54 _c +462 9 403 -13 330 -13 _c +246 -13 181 19 137 83 _c +92 147 70 241 70 364 _c +70 479 97 571 152 639 _c +206 707 280 742 372 742 _c +396 742 421 739 447 735 _c +472 730 498 723 526 713 _c +_cl}_e}_d +/eight{{636 0 68 -13 568 742 _sc +318 346 _m +271 346 234 333 207 308 _c +180 283 167 249 167 205 _c +167 161 180 126 207 101 _c +234 76 271 64 318 64 _c +364 64 401 76 428 102 _c +455 127 469 161 469 205 _c +469 249 455 283 429 308 _c +402 333 365 346 318 346 _c +219 388 _m +177 398 144 418 120 447 _c +96 476 85 511 85 553 _c +85 611 105 657 147 691 _c +188 725 245 742 318 742 _c +}_e{390 742 447 725 489 691 _c +530 657 551 611 551 553 _c +551 511 539 476 515 447 _c +491 418 459 398 417 388 _c +464 377 501 355 528 323 _c +554 291 568 251 568 205 _c +568 134 546 80 503 43 _c +459 5 398 -13 318 -13 _c +237 -13 175 5 132 43 _c +89 80 68 134 68 205 _c +68 251 81 291 108 323 _c +134 355 171 377 219 388 _c +183 544 _m +183 506 194 476 218 455 _c +}_e{242 434 275 424 318 424 _c +360 424 393 434 417 455 _c +441 476 453 506 453 544 _c +453 582 441 611 417 632 _c +393 653 360 664 318 664 _c +275 664 242 653 218 632 _c +194 611 183 582 183 544 _c +_cl}_e}_d +/A{684 0 8 0 676 729 _sc +342 632 _m +208 269 _l +476 269 _l +342 632 _l +286 729 _m +398 729 _l +676 0 _l +573 0 _l +507 187 _l +178 187 _l +112 0 _l +8 0 _l +286 729 _l +_cl}_d +/E{632 0 98 0 568 729 _sc +98 729 _m +559 729 _l +559 646 _l +197 646 _l +197 430 _l +544 430 _l +544 347 _l +197 347 _l +197 83 _l +568 83 _l +568 0 _l +98 0 _l +98 729 _l +_cl}_d +/F{575 0 98 0 517 729 _sc +98 729 _m +517 729 _l +517 646 _l +197 646 _l +197 431 _l +486 431 _l +486 348 _l +197 348 _l +197 0 _l +98 0 _l +98 729 _l +_cl}_d +/I{295 0 98 0 197 729 _sc +98 729 _m +197 729 _l +197 0 _l +98 0 _l +98 729 _l +_cl}_d +/M{863 0 98 0 765 729 _sc +98 729 _m +245 729 _l +431 233 _l +618 729 _l +765 729 _l +765 0 _l +669 0 _l +669 640 _l +481 140 _l +382 140 _l +194 640 _l +194 0 _l +98 0 _l +98 729 _l +_cl}_d +/P{603 0 98 0 569 729 _sc +197 648 _m +197 374 _l +321 374 _l +367 374 402 385 427 409 _c +452 433 465 467 465 511 _c +465 555 452 588 427 612 _c +402 636 367 648 321 648 _c +197 648 _l +98 729 _m +321 729 _l +402 729 464 710 506 673 _c +548 636 569 582 569 511 _c +569 439 548 384 506 348 _c +464 311 402 293 321 293 _c +197 293 _l +197 0 _l +98 0 _l +98 729 _l +_cl}_d +/R{{695 0 98 0 666 729 _sc +444 342 _m +465 334 486 319 506 296 _c +526 272 546 240 566 199 _c +666 0 _l +560 0 _l +467 187 _l +443 235 419 268 397 284 _c +374 300 343 308 304 308 _c +197 308 _l +197 0 _l +98 0 _l +98 729 _l +321 729 _l +404 729 466 711 507 677 _c +548 642 569 589 569 519 _c +569 473 558 434 537 404 _c +515 374 484 353 444 342 _c +197 648 _m +197 389 _l +321 389 _l +}_e{368 389 404 400 428 422 _c +452 444 465 476 465 519 _c +465 561 452 593 428 615 _c +404 637 368 648 321 648 _c +197 648 _l +_cl}_e}_d +/S{{635 0 66 -13 579 742 _sc +535 705 _m +535 609 _l +497 627 462 640 429 649 _c +395 657 363 662 333 662 _c +279 662 237 651 208 631 _c +179 610 165 580 165 542 _c +165 510 174 485 194 469 _c +213 452 250 439 304 429 _c +364 417 _l +437 403 491 378 526 343 _c +561 307 579 260 579 201 _c +579 130 555 77 508 41 _c +460 5 391 -13 300 -13 _c +265 -13 228 -9 189 -2 _c +}_e{150 5 110 16 69 32 _c +69 134 _l +109 111 148 94 186 83 _c +224 71 262 66 300 66 _c +356 66 399 77 430 99 _c +460 121 476 152 476 194 _c +476 230 465 258 443 278 _c +421 298 385 313 335 323 _c +275 335 _l +201 349 148 372 115 404 _c +82 435 66 478 66 534 _c +66 598 88 649 134 686 _c +179 723 242 742 322 742 _c +356 742 390 739 426 733 _c +461 727 497 717 535 705 _c +}_e{_cl}_e}_d +/a{{613 0 60 -13 522 560 _sc +343 275 _m +270 275 220 266 192 250 _c +164 233 150 205 150 165 _c +150 133 160 107 181 89 _c +202 70 231 61 267 61 _c +317 61 357 78 387 114 _c +417 149 432 196 432 255 _c +432 275 _l +343 275 _l +522 312 _m +522 0 _l +432 0 _l +432 83 _l +411 49 385 25 355 10 _c +325 -5 287 -13 243 -13 _c +187 -13 142 2 109 33 _c +76 64 60 106 60 159 _c +}_e{60 220 80 266 122 298 _c +163 329 224 345 306 345 _c +432 345 _l +432 354 _l +432 395 418 427 391 450 _c +364 472 326 484 277 484 _c +245 484 215 480 185 472 _c +155 464 127 453 100 439 _c +100 522 _l +132 534 164 544 195 550 _c +226 556 256 560 286 560 _c +365 560 424 539 463 498 _c +502 457 522 395 522 312 _c +_cl}_e}_d +/b{{635 0 91 -13 580 760 _sc +487 273 _m +487 339 473 390 446 428 _c +418 466 381 485 334 485 _c +286 485 249 466 222 428 _c +194 390 181 339 181 273 _c +181 207 194 155 222 117 _c +249 79 286 61 334 61 _c +381 61 418 79 446 117 _c +473 155 487 207 487 273 _c +181 464 _m +199 496 223 520 252 536 _c +281 552 316 560 356 560 _c +422 560 476 533 518 481 _c +559 428 580 359 580 273 _c +}_e{580 187 559 117 518 65 _c +476 13 422 -13 356 -13 _c +316 -13 281 -5 252 10 _c +223 25 199 49 181 82 _c +181 0 _l +91 0 _l +91 760 _l +181 760 _l +181 464 _l +_cl}_e}_d +/c{{550 0 55 -13 488 560 _sc +488 526 _m +488 442 _l +462 456 437 466 411 473 _c +385 480 360 484 334 484 _c +276 484 230 465 198 428 _c +166 391 150 339 150 273 _c +150 206 166 154 198 117 _c +230 80 276 62 334 62 _c +360 62 385 65 411 72 _c +437 79 462 90 488 104 _c +488 21 _l +462 9 436 0 410 -5 _c +383 -10 354 -13 324 -13 _c +242 -13 176 12 128 64 _c +}_e{79 115 55 185 55 273 _c +55 362 79 432 128 483 _c +177 534 244 560 330 560 _c +358 560 385 557 411 551 _c +437 545 463 537 488 526 _c +_cl}_e}_d +/d{{635 0 55 -13 544 760 _sc +454 464 _m +454 760 _l +544 760 _l +544 0 _l +454 0 _l +454 82 _l +435 49 411 25 382 10 _c +353 -5 319 -13 279 -13 _c +213 -13 159 13 117 65 _c +75 117 55 187 55 273 _c +55 359 75 428 117 481 _c +159 533 213 560 279 560 _c +319 560 353 552 382 536 _c +411 520 435 496 454 464 _c +148 273 _m +148 207 161 155 188 117 _c +215 79 253 61 301 61 _c +}_e{348 61 385 79 413 117 _c +440 155 454 207 454 273 _c +454 339 440 390 413 428 _c +385 466 348 485 301 485 _c +253 485 215 466 188 428 _c +161 390 148 339 148 273 _c +_cl}_e}_d +/e{{615 0 55 -13 562 560 _sc +562 296 _m +562 252 _l +149 252 _l +153 190 171 142 205 110 _c +238 78 284 62 344 62 _c +378 62 412 66 444 74 _c +476 82 509 95 541 113 _c +541 28 _l +509 14 476 3 442 -3 _c +408 -9 373 -13 339 -13 _c +251 -13 182 12 131 62 _c +80 112 55 181 55 268 _c +55 357 79 428 127 481 _c +175 533 241 560 323 560 _c +397 560 455 536 498 489 _c +}_e{540 441 562 377 562 296 _c +472 322 _m +471 371 457 410 431 440 _c +404 469 368 484 324 484 _c +274 484 234 469 204 441 _c +174 413 156 373 152 322 _c +472 322 _l +_cl}_e}_d +/f{352 0 23 0 371 760 _sc +371 760 _m +371 685 _l +285 685 _l +253 685 230 678 218 665 _c +205 652 199 629 199 595 _c +199 547 _l +347 547 _l +347 477 _l +199 477 _l +199 0 _l +109 0 _l +109 477 _l +23 477 _l +23 547 _l +109 547 _l +109 585 _l +109 645 123 690 151 718 _c +179 746 224 760 286 760 _c +371 760 _l +_cl}_d +/h{634 0 91 0 549 760 _sc +549 330 _m +549 0 _l +459 0 _l +459 327 _l +459 379 448 417 428 443 _c +408 469 378 482 338 482 _c +289 482 251 466 223 435 _c +195 404 181 362 181 309 _c +181 0 _l +91 0 _l +91 760 _l +181 760 _l +181 462 _l +202 494 227 519 257 535 _c +286 551 320 560 358 560 _c +420 560 468 540 500 501 _c +532 462 549 405 549 330 _c +_cl}_d +/i{278 0 94 0 184 760 _sc +94 547 _m +184 547 _l +184 0 _l +94 0 _l +94 547 _l +94 760 _m +184 760 _l +184 646 _l +94 646 _l +94 760 _l +_cl}_d +/k{579 0 91 0 576 760 _sc +91 760 _m +181 760 _l +181 311 _l +449 547 _l +564 547 _l +274 291 _l +576 0 _l +459 0 _l +181 267 _l +181 0 _l +91 0 _l +91 760 _l +_cl}_d +/l{278 0 94 0 184 760 _sc +94 760 _m +184 760 _l +184 0 _l +94 0 _l +94 760 _l +_cl}_d +/m{{974 0 91 0 889 560 _sc +520 442 _m +542 482 569 511 600 531 _c +631 550 668 560 711 560 _c +767 560 811 540 842 500 _c +873 460 889 403 889 330 _c +889 0 _l +799 0 _l +799 327 _l +799 379 789 418 771 444 _c +752 469 724 482 686 482 _c +639 482 602 466 575 435 _c +548 404 535 362 535 309 _c +535 0 _l +445 0 _l +445 327 _l +445 379 435 418 417 444 _c +398 469 369 482 331 482 _c +}_e{285 482 248 466 221 435 _c +194 404 181 362 181 309 _c +181 0 _l +91 0 _l +91 547 _l +181 547 _l +181 462 _l +201 495 226 520 255 536 _c +283 552 317 560 357 560 _c +397 560 430 550 458 530 _c +486 510 506 480 520 442 _c +_cl}_e}_d +/n{634 0 91 0 549 560 _sc +549 330 _m +549 0 _l +459 0 _l +459 327 _l +459 379 448 417 428 443 _c +408 469 378 482 338 482 _c +289 482 251 466 223 435 _c +195 404 181 362 181 309 _c +181 0 _l +91 0 _l +91 547 _l +181 547 _l +181 462 _l +202 494 227 519 257 535 _c +286 551 320 560 358 560 _c +420 560 468 540 500 501 _c +532 462 549 405 549 330 _c +_cl}_d +/o{612 0 55 -13 557 560 _sc +306 484 _m +258 484 220 465 192 427 _c +164 389 150 338 150 273 _c +150 207 163 156 191 118 _c +219 80 257 62 306 62 _c +354 62 392 80 420 118 _c +448 156 462 207 462 273 _c +462 337 448 389 420 427 _c +392 465 354 484 306 484 _c +306 560 _m +384 560 445 534 490 484 _c +534 433 557 363 557 273 _c +557 183 534 113 490 63 _c +445 12 384 -13 306 -13 _c +227 -13 165 12 121 63 _c +77 113 55 183 55 273 _c +55 363 77 433 121 484 _c +165 534 227 560 306 560 _c +_cl}_d +/p{{635 0 91 -207 580 560 _sc +181 82 _m +181 -207 _l +91 -207 _l +91 547 _l +181 547 _l +181 464 _l +199 496 223 520 252 536 _c +281 552 316 560 356 560 _c +422 560 476 533 518 481 _c +559 428 580 359 580 273 _c +580 187 559 117 518 65 _c +476 13 422 -13 356 -13 _c +316 -13 281 -5 252 10 _c +223 25 199 49 181 82 _c +487 273 _m +487 339 473 390 446 428 _c +418 466 381 485 334 485 _c +}_e{286 485 249 466 222 428 _c +194 390 181 339 181 273 _c +181 207 194 155 222 117 _c +249 79 286 61 334 61 _c +381 61 418 79 446 117 _c +473 155 487 207 487 273 _c +_cl}_e}_d +/r{411 0 91 0 411 560 _sc +411 463 _m +401 469 390 473 378 476 _c +366 478 353 480 339 480 _c +288 480 249 463 222 430 _c +194 397 181 350 181 288 _c +181 0 _l +91 0 _l +91 547 _l +181 547 _l +181 462 _l +199 495 224 520 254 536 _c +284 552 321 560 365 560 _c +371 560 378 559 386 559 _c +393 558 401 557 411 555 _c +411 463 _l +_cl}_d +/s{{521 0 54 -13 472 560 _sc +443 531 _m +443 446 _l +417 458 391 468 364 475 _c +336 481 308 485 279 485 _c +234 485 200 478 178 464 _c +156 450 145 430 145 403 _c +145 382 153 366 169 354 _c +185 342 217 330 265 320 _c +296 313 _l +360 299 405 279 432 255 _c +458 230 472 195 472 151 _c +472 100 452 60 412 31 _c +372 1 316 -13 246 -13 _c +216 -13 186 -10 154 -5 _c +}_e{122 0 89 8 54 20 _c +54 113 _l +87 95 120 82 152 74 _c +184 65 216 61 248 61 _c +290 61 323 68 346 82 _c +368 96 380 117 380 144 _c +380 168 371 187 355 200 _c +339 213 303 226 247 238 _c +216 245 _l +160 257 119 275 95 299 _c +70 323 58 356 58 399 _c +58 450 76 490 112 518 _c +148 546 200 560 268 560 _c +301 560 332 557 362 552 _c +391 547 418 540 443 531 _c +}_e{_cl}_e}_d +/t{392 0 27 0 368 702 _sc +183 702 _m +183 547 _l +368 547 _l +368 477 _l +183 477 _l +183 180 _l +183 135 189 106 201 94 _c +213 81 238 75 276 75 _c +368 75 _l +368 0 _l +276 0 _l +206 0 158 13 132 39 _c +106 65 93 112 93 180 _c +93 477 _l +27 477 _l +27 547 _l +93 547 _l +93 702 _l +183 702 _l +_cl}_d +/u{634 0 85 -13 543 560 _sc +85 216 _m +85 547 _l +175 547 _l +175 219 _l +175 167 185 129 205 103 _c +225 77 255 64 296 64 _c +344 64 383 79 411 110 _c +439 141 453 183 453 237 _c +453 547 _l +543 547 _l +543 0 _l +453 0 _l +453 84 _l +431 50 405 26 377 10 _c +348 -5 315 -13 277 -13 _c +214 -13 166 6 134 45 _c +101 83 85 140 85 216 _c +311 560 _m +311 560 _l +_cl}_d +/x{592 0 29 0 559 547 _sc +549 547 _m +351 281 _l +559 0 _l +453 0 _l +294 215 _l +135 0 _l +29 0 _l +241 286 _l +47 547 _l +153 547 _l +298 352 _l +443 547 _l +549 547 _l +_cl}_d +/y{592 0 30 -207 562 547 _sc +322 -50 _m +296 -114 271 -157 247 -177 _c +223 -197 191 -207 151 -207 _c +79 -207 _l +79 -132 _l +132 -132 _l +156 -132 175 -126 189 -114 _c +203 -102 218 -75 235 -31 _c +251 9 _l +30 547 _l +125 547 _l +296 119 _l +467 547 _l +562 547 _l +322 -50 _l +_cl}_d +end readonly def + +/BuildGlyph + {exch begin + CharStrings exch + 2 copy known not{pop /.notdef}if + true 3 1 roll get exec + end}_d + +/BuildChar { + 1 index /Encoding get exch get + 1 index /BuildGlyph get exec +}_d + +FontName currentdict end definefont pop +end +%%EndProlog +mpldict begin +-38.396 231.673 translate +688.791 328.653 0 0 clipbox +gsave +0 0 m +688.791 0 l +688.791 328.653 l +0 328.653 l +cl +grestore +gsave +59.837875 42.52 m +673.637875 42.52 l +673.637875 306.328 l +59.837875 306.328 l +cl +grestore +1.000 setgray +/DejaVuSans findfont +10.000 scalefont +setfont +gsave +51.884750 27.926250 translate +0.000000 rotate +0.000000 0 m /zero glyphshow +6.362305 0 m /period glyphshow +9.541016 0 m /zero glyphshow +grestore +gsave +174.644750 27.926250 translate +0.000000 rotate +0.000000 0 m /zero glyphshow +6.362305 0 m /period glyphshow +9.541016 0 m /two glyphshow +grestore +gsave +297.404750 27.926250 translate +0.000000 rotate +0.000000 0 m /zero glyphshow +6.362305 0 m /period glyphshow +9.541016 0 m /four glyphshow +grestore +gsave +420.164750 27.926250 translate +0.000000 rotate +0.000000 0 m /zero glyphshow +6.362305 0 m /period glyphshow +9.541016 0 m /six glyphshow +grestore +gsave +542.924750 27.926250 translate +0.000000 rotate +0.000000 0 m /zero glyphshow +6.362305 0 m /period glyphshow +9.541016 0 m /eight glyphshow +grestore +gsave +665.684750 27.926250 translate +0.000000 rotate +0.000000 0 m /one glyphshow +6.362305 0 m /period glyphshow +9.541016 0 m /zero glyphshow +grestore +gsave +36.931625 38.723125 translate +0.000000 rotate +0.000000 0 m /zero glyphshow +6.362305 0 m /period glyphshow +9.541016 0 m /zero glyphshow +grestore +gsave +36.931625 91.484725 translate +0.000000 rotate +0.000000 0 m /zero glyphshow +6.362305 0 m /period glyphshow +9.541016 0 m /two glyphshow +grestore +gsave +36.931625 144.246325 translate +0.000000 rotate +0.000000 0 m /zero glyphshow +6.362305 0 m /period glyphshow +9.541016 0 m /four glyphshow +grestore +gsave +36.931625 197.007925 translate +0.000000 rotate +0.000000 0 m /zero glyphshow +6.362305 0 m /period glyphshow +9.541016 0 m /six glyphshow +grestore +gsave +36.931625 249.769525 translate +0.000000 rotate +0.000000 0 m /zero glyphshow +6.362305 0 m /period glyphshow +9.541016 0 m /eight glyphshow +grestore +gsave +36.931625 302.531125 translate +0.000000 rotate +0.000000 0 m /one glyphshow +6.362305 0 m /period glyphshow +9.541016 0 m /zero glyphshow +grestore +0.000 setgray +gsave +14.793750 160.306813 translate +90.000000 rotate +0.000000 0 m /R glyphshow +6.948242 0 m /M glyphshow +15.576172 0 m /S glyphshow +21.923828 0 m /E glyphshow +grestore +gsave +59.837875 42.52 m +59.837875 306.328 l +grestore +gsave +673.637875 42.52 m +673.637875 306.328 l +grestore +gsave +59.837875 42.52 m +673.637875 42.52 l +grestore +gsave +59.837875 306.328 m +673.637875 306.328 l +grestore +gsave +59.837875 191.62887 m +193.272658 191.62887 l +193.272658 306.328 l +59.837875 306.328 l +cl +grestore +0.200 setlinewidth +0 setlinejoin +0 setlinecap +[] 0 setdash +gsave +133.4 114.7 59.84 191.6 clipbox +65.903092 191.62887 m +80.95326 191.62887 l +80.95326 252.529533 l +65.903092 252.529533 l +cl +gsave +0.894 0.102 0.110 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 59.84 191.6 clipbox +141.153929 191.62887 m +156.204096 191.62887 l +156.204096 272.020396 l +141.153929 272.020396 l +cl +gsave +0.894 0.102 0.110 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 59.84 191.6 clipbox +81.404765 191.62887 m +96.454932 191.62887 l +96.454932 242.050476 l +81.404765 242.050476 l +cl +gsave +0.216 0.494 0.722 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 59.84 191.6 clipbox +156.655601 191.62887 m +171.705768 191.62887 l +171.705768 261.174247 l +156.655601 261.174247 l +cl +gsave +0.216 0.494 0.722 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 59.84 191.6 clipbox +96.906437 191.62887 m +111.956604 191.62887 l +111.956604 222.299087 l +96.906437 222.299087 l +cl +gsave +0.302 0.686 0.290 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 59.84 191.6 clipbox +172.157273 191.62887 m +187.20744 191.62887 l +187.20744 227.197041 l +172.157273 227.197041 l +cl +gsave +0.302 0.686 0.290 setrgbcolor +fill +grestore +stroke +grestore +gsave +77.289223 177.035120 translate +0.000000 rotate +0.000000 0 m /t glyphshow +3.920898 0 m /r glyphshow +8.032227 0 m /a glyphshow +14.160156 0 m /i glyphshow +16.938477 0 m /n glyphshow +grestore +gsave +154.571309 177.035120 translate +0.000000 rotate +0.000000 0 m /t glyphshow +3.920898 0 m /e glyphshow +10.073242 0 m /s glyphshow +15.283203 0 m /t glyphshow +grestore +0.800 setlinewidth +1 setlinejoin +[] 0 setdash +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +59.8379 191.629 o +grestore +gsave +46.478500 187.831995 translate +0.000000 rotate +0.000000 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +59.8379 217.489 o +grestore +gsave +46.478500 213.692519 translate +0.000000 rotate +0.000000 0 m /five glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +59.8379 243.35 o +grestore +gsave +40.119125 239.553044 translate +0.000000 rotate +0.000000 0 m /one glyphshow +6.362305 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +59.8379 269.21 o +grestore +gsave +40.119125 265.413569 translate +0.000000 rotate +0.000000 0 m /one glyphshow +6.362305 0 m /five glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +59.8379 295.071 o +grestore +gsave +40.119125 291.274094 translate +0.000000 rotate +0.000000 0 m /two glyphshow +6.362305 0 m /zero glyphshow +grestore +gsave +34.041000 232.017497 translate +90.000000 rotate +0.000000 0 m /A glyphshow +6.840820 0 m /l glyphshow +9.619141 0 m /k glyphshow +15.285156 0 m /a glyphshow +21.413086 0 m /n glyphshow +27.750977 0 m /e glyphshow +grestore +0.500 setlinewidth +gsave +133.4 114.7 59.84 191.6 clipbox +73.428176 239.158546 m +73.428176 265.90052 l +stroke +grestore +gsave +133.4 114.7 59.84 191.6 clipbox +148.679012 243.174656 m +148.679012 300.866137 l +stroke +grestore +gsave +133.4 114.7 59.84 191.6 clipbox +88.929848 238.192974 m +88.929848 245.907977 l +stroke +grestore +gsave +133.4 114.7 59.84 191.6 clipbox +164.180684 240.564191 m +164.180684 281.784302 l +stroke +grestore +gsave +133.4 114.7 59.84 191.6 clipbox +104.43152 220.296693 m +104.43152 224.30148 l +stroke +grestore +gsave +133.4 114.7 59.84 191.6 clipbox +179.682357 210.497379 m +179.682357 243.896704 l +stroke +grestore +gsave +133.4 114.7 59.84 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +73.4282 239.159 o +148.679 243.175 o +grestore +gsave +133.4 114.7 59.84 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +73.4282 265.901 o +148.679 300.866 o +grestore +gsave +133.4 114.7 59.84 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +88.9298 238.193 o +164.181 240.564 o +grestore +gsave +133.4 114.7 59.84 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +88.9298 245.908 o +164.181 281.784 o +grestore +gsave +133.4 114.7 59.84 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +104.432 220.297 o +179.682 210.497 o +grestore +gsave +133.4 114.7 59.84 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +104.432 224.301 o +179.682 243.897 o +grestore +0.800 setlinewidth +0 setlinejoin +2 setlinecap +[] 0 setdash +gsave +59.837875 191.62887 m +59.837875 306.328 l +stroke +grestore +gsave +193.272658 191.62887 m +193.272658 306.328 l +stroke +grestore +gsave +59.837875 191.62887 m +193.272658 191.62887 l +stroke +grestore +gsave +59.837875 306.328 m +193.272658 306.328 l +stroke +grestore +/DejaVuSans findfont +12.000 scalefont +setfont +gsave +68.031829 312.328000 translate +0.000000 rotate +0.000000 0 m /b glyphshow +7.617188 0 m /i glyphshow +10.951172 0 m /p glyphshow +18.568359 0 m /a glyphshow +25.921875 0 m /r glyphshow +30.855469 0 m /t glyphshow +35.560547 0 m /i glyphshow +38.894531 0 m /t glyphshow +43.599609 0 m /e glyphshow +50.982422 0 m /comma glyphshow +54.796875 0 m /space glyphshow +58.611328 0 m /E glyphshow +66.193359 0 m /u glyphshow +73.798828 0 m /c glyphshow +80.396484 0 m /l glyphshow +83.730469 0 m /i glyphshow +87.064453 0 m /d glyphshow +94.681641 0 m /e glyphshow +102.064453 0 m /a glyphshow +109.417969 0 m /n glyphshow +grestore +gsave +219.959614 191.62887 m +353.394397 191.62887 l +353.394397 306.328 l +219.959614 306.328 l +cl +grestore +0.200 setlinewidth +0 setlinecap +gsave +133.4 114.7 220 191.6 clipbox +226.024832 191.62887 m +241.074999 191.62887 l +241.074999 246.155207 l +226.024832 246.155207 l +cl +gsave +0.894 0.102 0.110 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 220 191.6 clipbox +301.275668 191.62887 m +316.325835 191.62887 l +316.325835 260.960428 l +301.275668 260.960428 l +cl +gsave +0.894 0.102 0.110 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 220 191.6 clipbox +241.526504 191.62887 m +256.576671 191.62887 l +256.576671 221.961446 l +241.526504 221.961446 l +cl +gsave +0.216 0.494 0.722 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 220 191.6 clipbox +316.77734 191.62887 m +331.827507 191.62887 l +331.827507 225.762742 l +316.77734 225.762742 l +cl +gsave +0.216 0.494 0.722 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 220 191.6 clipbox +257.028176 191.62887 m +272.078343 191.62887 l +272.078343 210.862439 l +257.028176 210.862439 l +cl +gsave +0.302 0.686 0.290 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 220 191.6 clipbox +332.279012 191.62887 m +347.329179 191.62887 l +347.329179 208.399727 l +332.279012 208.399727 l +cl +gsave +0.302 0.686 0.290 setrgbcolor +fill +grestore +stroke +grestore +/DejaVuSans findfont +10.000 scalefont +setfont +gsave +237.410962 177.035120 translate +0.000000 rotate +0.000000 0 m /t glyphshow +3.920898 0 m /r glyphshow +8.032227 0 m /a glyphshow +14.160156 0 m /i glyphshow +16.938477 0 m /n glyphshow +grestore +gsave +314.693048 177.035120 translate +0.000000 rotate +0.000000 0 m /t glyphshow +3.920898 0 m /e glyphshow +10.073242 0 m /s glyphshow +15.283203 0 m /t glyphshow +grestore +0.800 setlinewidth +1 setlinejoin +[] 0 setdash +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +219.96 191.629 o +grestore +gsave +206.600239 187.831995 translate +0.000000 rotate +0.000000 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +219.96 223.141 o +grestore +gsave +200.240864 219.344347 translate +0.000000 rotate +0.000000 0 m /one glyphshow +6.362305 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +219.96 254.654 o +grestore +gsave +200.240864 250.856699 translate +0.000000 rotate +0.000000 0 m /two glyphshow +6.362305 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +219.96 286.166 o +grestore +gsave +200.240864 282.369051 translate +0.000000 rotate +0.000000 0 m /three glyphshow +6.362305 0 m /zero glyphshow +grestore +0.500 setlinewidth +gsave +133.4 114.7 220 191.6 clipbox +233.549915 226.108467 m +233.549915 266.201948 l +stroke +grestore +gsave +133.4 114.7 220 191.6 clipbox +308.800751 221.05472 m +308.800751 300.866137 l +stroke +grestore +gsave +133.4 114.7 220 191.6 clipbox +249.051587 220.634914 m +249.051587 223.287979 l +stroke +grestore +gsave +133.4 114.7 220 191.6 clipbox +324.302423 220.359123 m +324.302423 231.16636 l +stroke +grestore +gsave +133.4 114.7 220 191.6 clipbox +264.55326 210.14662 m +264.55326 211.578258 l +stroke +grestore +gsave +133.4 114.7 220 191.6 clipbox +339.804096 205.528196 m +339.804096 211.271258 l +stroke +grestore +gsave +133.4 114.7 220 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +233.55 226.108 o +308.801 221.055 o +grestore +gsave +133.4 114.7 220 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +233.55 266.202 o +308.801 300.866 o +grestore +gsave +133.4 114.7 220 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +249.052 220.635 o +324.302 220.359 o +grestore +gsave +133.4 114.7 220 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +249.052 223.288 o +324.302 231.166 o +grestore +gsave +133.4 114.7 220 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +264.553 210.147 o +339.804 205.528 o +grestore +gsave +133.4 114.7 220 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +264.553 211.578 o +339.804 211.271 o +grestore +0.800 setlinewidth +0 setlinejoin +2 setlinecap +[] 0 setdash +gsave +219.959614 191.62887 m +219.959614 306.328 l +stroke +grestore +gsave +353.394397 191.62887 m +353.394397 306.328 l +stroke +grestore +gsave +219.959614 191.62887 m +353.394397 191.62887 l +stroke +grestore +gsave +219.959614 306.328 m +353.394397 306.328 l +stroke +grestore +/DejaVuSans findfont +12.000 scalefont +setfont +gsave +225.028568 312.328000 translate +0.000000 rotate +0.000000 0 m /b glyphshow +7.617188 0 m /i glyphshow +10.951172 0 m /p glyphshow +18.568359 0 m /a glyphshow +25.921875 0 m /r glyphshow +30.855469 0 m /t glyphshow +35.560547 0 m /i glyphshow +38.894531 0 m /t glyphshow +43.599609 0 m /e glyphshow +50.982422 0 m /comma glyphshow +54.796875 0 m /space glyphshow +58.611328 0 m /M glyphshow +68.964844 0 m /a glyphshow +76.318359 0 m /n glyphshow +83.923828 0 m /h glyphshow +91.529297 0 m /a glyphshow +98.882812 0 m /t glyphshow +103.587891 0 m /t glyphshow +108.292969 0 m /a glyphshow +115.646484 0 m /n glyphshow +grestore +gsave +380.081353 191.62887 m +513.516136 191.62887 l +513.516136 306.328 l +380.081353 306.328 l +cl +grestore +0.200 setlinewidth +0 setlinecap +gsave +133.4 114.7 380.1 191.6 clipbox +386.146571 191.62887 m +401.196738 191.62887 l +401.196738 273.947427 l +386.146571 273.947427 l +cl +gsave +0.894 0.102 0.110 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 380.1 191.6 clipbox +461.397407 191.62887 m +476.447574 191.62887 l +476.447574 279.041753 l +461.397407 279.041753 l +cl +gsave +0.894 0.102 0.110 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 380.1 191.6 clipbox +401.648243 191.62887 m +416.69841 191.62887 l +416.69841 260.448713 l +401.648243 260.448713 l +cl +gsave +0.216 0.494 0.722 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 380.1 191.6 clipbox +476.899079 191.62887 m +491.949246 191.62887 l +491.949246 267.15255 l +476.899079 267.15255 l +cl +gsave +0.216 0.494 0.722 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 380.1 191.6 clipbox +417.149915 191.62887 m +432.200082 191.62887 l +432.200082 244.957339 l +417.149915 244.957339 l +cl +gsave +0.302 0.686 0.290 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 380.1 191.6 clipbox +492.400751 191.62887 m +507.450918 191.62887 l +507.450918 237.614825 l +492.400751 237.614825 l +cl +gsave +0.302 0.686 0.290 setrgbcolor +fill +grestore +stroke +grestore +/DejaVuSans findfont +10.000 scalefont +setfont +gsave +397.532702 177.035120 translate +0.000000 rotate +0.000000 0 m /t glyphshow +3.920898 0 m /r glyphshow +8.032227 0 m /a glyphshow +14.160156 0 m /i glyphshow +16.938477 0 m /n glyphshow +grestore +gsave +474.814788 177.035120 translate +0.000000 rotate +0.000000 0 m /t glyphshow +3.920898 0 m /e glyphshow +10.073242 0 m /s glyphshow +15.283203 0 m /t glyphshow +grestore +0.800 setlinewidth +1 setlinejoin +[] 0 setdash +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +380.081 191.629 o +grestore +gsave +366.721978 187.831995 translate +0.000000 rotate +0.000000 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +380.081 237.331 o +grestore +gsave +366.721978 233.533771 translate +0.000000 rotate +0.000000 0 m /five glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +380.081 283.032 o +grestore +gsave +360.362603 279.235547 translate +0.000000 rotate +0.000000 0 m /one glyphshow +6.362305 0 m /zero glyphshow +grestore +0.500 setlinewidth +gsave +133.4 114.7 380.1 191.6 clipbox +393.671654 264.098863 m +393.671654 283.795991 l +stroke +grestore +gsave +133.4 114.7 380.1 191.6 clipbox +468.92249 257.217369 m +468.92249 300.866137 l +stroke +grestore +gsave +133.4 114.7 380.1 191.6 clipbox +409.173327 258.372832 m +409.173327 262.524595 l +stroke +grestore +gsave +133.4 114.7 380.1 191.6 clipbox +484.424163 256.670556 m +484.424163 277.634543 l +stroke +grestore +gsave +133.4 114.7 380.1 191.6 clipbox +424.674999 242.656833 m +424.674999 247.257844 l +stroke +grestore +gsave +133.4 114.7 380.1 191.6 clipbox +499.925835 229.109523 m +499.925835 246.120126 l +stroke +grestore +gsave +133.4 114.7 380.1 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +393.672 264.099 o +468.922 257.217 o +grestore +gsave +133.4 114.7 380.1 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +393.672 283.796 o +468.922 300.866 o +grestore +gsave +133.4 114.7 380.1 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +409.173 258.373 o +484.424 256.671 o +grestore +gsave +133.4 114.7 380.1 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +409.173 262.525 o +484.424 277.635 o +grestore +gsave +133.4 114.7 380.1 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +424.675 242.657 o +499.926 229.11 o +grestore +gsave +133.4 114.7 380.1 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +424.675 247.258 o +499.926 246.12 o +grestore +0.800 setlinewidth +0 setlinejoin +2 setlinecap +[] 0 setdash +gsave +380.081353 191.62887 m +380.081353 306.328 l +stroke +grestore +gsave +513.516136 191.62887 m +513.516136 306.328 l +stroke +grestore +gsave +380.081353 191.62887 m +513.516136 191.62887 l +stroke +grestore +gsave +380.081353 306.328 m +513.516136 306.328 l +stroke +grestore +/DejaVuSans findfont +12.000 scalefont +setfont +gsave +401.314370 312.328000 translate +0.000000 rotate +0.000000 0 m /I glyphshow +3.539062 0 m /P glyphshow +10.775391 0 m /F glyphshow +17.677734 0 m /P glyphshow +24.914062 0 m /comma glyphshow +28.728516 0 m /space glyphshow +32.542969 0 m /E glyphshow +40.125000 0 m /u glyphshow +47.730469 0 m /c glyphshow +54.328125 0 m /l glyphshow +57.662109 0 m /i glyphshow +60.996094 0 m /d glyphshow +68.613281 0 m /e glyphshow +75.996094 0 m /a glyphshow +83.349609 0 m /n glyphshow +grestore +gsave +540.203092 191.62887 m +673.637875 191.62887 l +673.637875 306.328 l +540.203092 306.328 l +cl +grestore +0.200 setlinewidth +0 setlinecap +gsave +133.4 114.7 540.2 191.6 clipbox +546.26831 191.62887 m +561.318477 191.62887 l +561.318477 261.100077 l +546.26831 261.100077 l +cl +gsave +0.894 0.102 0.110 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 540.2 191.6 clipbox +621.519146 191.62887 m +636.569313 191.62887 l +636.569313 269.39873 l +621.519146 269.39873 l +cl +gsave +0.894 0.102 0.110 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 540.2 191.6 clipbox +561.769982 191.62887 m +576.820149 191.62887 l +576.820149 231.641325 l +561.769982 231.641325 l +cl +gsave +0.216 0.494 0.722 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 540.2 191.6 clipbox +637.020818 191.62887 m +652.070985 191.62887 l +652.070985 230.708225 l +637.020818 230.708225 l +cl +gsave +0.216 0.494 0.722 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 540.2 191.6 clipbox +577.271654 191.62887 m +592.321821 191.62887 l +592.321821 218.952352 l +577.271654 218.952352 l +cl +gsave +0.302 0.686 0.290 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 540.2 191.6 clipbox +652.52249 191.62887 m +667.572658 191.62887 l +667.572658 220.975273 l +652.52249 220.975273 l +cl +gsave +0.302 0.686 0.290 setrgbcolor +fill +grestore +stroke +grestore +/DejaVuSans findfont +10.000 scalefont +setfont +gsave +557.654441 177.035120 translate +0.000000 rotate +0.000000 0 m /t glyphshow +3.920898 0 m /r glyphshow +8.032227 0 m /a glyphshow +14.160156 0 m /i glyphshow +16.938477 0 m /n glyphshow +grestore +gsave +634.936527 177.035120 translate +0.000000 rotate +0.000000 0 m /t glyphshow +3.920898 0 m /e glyphshow +10.073242 0 m /s glyphshow +15.283203 0 m /t glyphshow +grestore +0.800 setlinewidth +1 setlinejoin +[] 0 setdash +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +540.203 191.629 o +grestore +gsave +526.843717 187.831995 translate +0.000000 rotate +0.000000 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +540.203 216.211 o +grestore +gsave +526.843717 212.413902 translate +0.000000 rotate +0.000000 0 m /five glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +540.203 240.793 o +grestore +gsave +520.484342 236.995808 translate +0.000000 rotate +0.000000 0 m /one glyphshow +6.362305 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +540.203 265.375 o +grestore +gsave +520.484342 261.577715 translate +0.000000 rotate +0.000000 0 m /one glyphshow +6.362305 0 m /five glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +540.203 289.956 o +grestore +gsave +520.484342 286.159622 translate +0.000000 rotate +0.000000 0 m /two glyphshow +6.362305 0 m /zero glyphshow +grestore +0.500 setlinewidth +gsave +133.4 114.7 540.2 191.6 clipbox +553.793393 231.164141 m +553.793393 291.036012 l +stroke +grestore +gsave +133.4 114.7 540.2 191.6 clipbox +629.04423 237.931324 m +629.04423 300.866137 l +stroke +grestore +gsave +133.4 114.7 540.2 191.6 clipbox +569.295066 227.704853 m +569.295066 235.577797 l +stroke +grestore +gsave +133.4 114.7 540.2 191.6 clipbox +644.545902 224.422974 m +644.545902 236.993475 l +stroke +grestore +gsave +133.4 114.7 540.2 191.6 clipbox +584.796738 217.887329 m +584.796738 220.017376 l +stroke +grestore +gsave +133.4 114.7 540.2 191.6 clipbox +660.047574 216.54562 m +660.047574 225.404926 l +stroke +grestore +gsave +133.4 114.7 540.2 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +553.793 231.164 o +629.044 237.931 o +grestore +gsave +133.4 114.7 540.2 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +553.793 291.036 o +629.044 300.866 o +grestore +gsave +133.4 114.7 540.2 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +569.295 227.705 o +644.546 224.423 o +grestore +gsave +133.4 114.7 540.2 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +569.295 235.578 o +644.546 236.993 o +grestore +gsave +133.4 114.7 540.2 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +584.797 217.887 o +660.048 216.546 o +grestore +gsave +133.4 114.7 540.2 191.6 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +584.797 220.017 o +660.048 225.405 o +grestore +0.800 setlinewidth +0 setlinejoin +2 setlinecap +[] 0 setdash +gsave +540.203092 191.62887 m +540.203092 306.328 l +stroke +grestore +gsave +673.637875 191.62887 m +673.637875 306.328 l +stroke +grestore +gsave +540.203092 191.62887 m +673.637875 191.62887 l +stroke +grestore +gsave +540.203092 306.328 m +673.637875 306.328 l +stroke +grestore +/DejaVuSans findfont +12.000 scalefont +setfont +gsave +558.311109 312.328000 translate +0.000000 rotate +0.000000 0 m /I glyphshow +3.539062 0 m /P glyphshow +10.775391 0 m /F glyphshow +17.677734 0 m /P glyphshow +24.914062 0 m /comma glyphshow +28.728516 0 m /space glyphshow +32.542969 0 m /M glyphshow +42.896484 0 m /a glyphshow +50.250000 0 m /n glyphshow +57.855469 0 m /h glyphshow +65.460938 0 m /a glyphshow +72.814453 0 m /t glyphshow +77.519531 0 m /t glyphshow +82.224609 0 m /a glyphshow +89.578125 0 m /n glyphshow +grestore +gsave +59.837875 42.52 m +193.272658 42.52 l +193.272658 157.21913 l +59.837875 157.21913 l +cl +grestore +0.200 setlinewidth +0 setlinecap +gsave +133.4 114.7 59.84 42.52 clipbox +65.903092 42.52 m +80.95326 42.52 l +80.95326 119.792582 l +65.903092 119.792582 l +cl +gsave +0.894 0.102 0.110 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 59.84 42.52 clipbox +141.153929 42.52 m +156.204096 42.52 l +156.204096 137.156844 l +141.153929 137.156844 l +cl +gsave +0.894 0.102 0.110 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 59.84 42.52 clipbox +81.404765 42.52 m +96.454932 42.52 l +96.454932 121.798876 l +81.404765 121.798876 l +cl +gsave +0.216 0.494 0.722 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 59.84 42.52 clipbox +156.655601 42.52 m +171.705768 42.52 l +171.705768 142.139775 l +156.655601 142.139775 l +cl +gsave +0.216 0.494 0.722 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 59.84 42.52 clipbox +96.906437 42.52 m +111.956604 42.52 l +111.956604 74.13716 l +96.906437 74.13716 l +cl +gsave +0.302 0.686 0.290 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 59.84 42.52 clipbox +172.157273 42.52 m +187.20744 42.52 l +187.20744 94.000396 l +172.157273 94.000396 l +cl +gsave +0.302 0.686 0.290 setrgbcolor +fill +grestore +stroke +grestore +/DejaVuSans findfont +10.000 scalefont +setfont +gsave +77.289223 27.926250 translate +0.000000 rotate +0.000000 0 m /t glyphshow +3.920898 0 m /r glyphshow +8.032227 0 m /a glyphshow +14.160156 0 m /i glyphshow +16.938477 0 m /n glyphshow +grestore +gsave +154.571309 27.926250 translate +0.000000 rotate +0.000000 0 m /t glyphshow +3.920898 0 m /e glyphshow +10.073242 0 m /s glyphshow +15.283203 0 m /t glyphshow +grestore +0.800 setlinewidth +1 setlinejoin +[] 0 setdash +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +59.8379 42.52 o +grestore +gsave +46.478500 38.723125 translate +0.000000 rotate +0.000000 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +59.8379 72.2892 o +grestore +gsave +40.119125 68.492349 translate +0.000000 rotate +0.000000 0 m /one glyphshow +6.362305 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +59.8379 102.058 o +grestore +gsave +40.119125 98.261572 translate +0.000000 rotate +0.000000 0 m /two glyphshow +6.362305 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +59.8379 131.828 o +grestore +gsave +40.119125 128.030796 translate +0.000000 rotate +0.000000 0 m /three glyphshow +6.362305 0 m /zero glyphshow +grestore +gsave +34.041000 82.518003 translate +90.000000 rotate +0.000000 0 m /A glyphshow +6.715820 0 m /c glyphshow +12.213867 0 m /y glyphshow +18.131836 0 m /c glyphshow +23.629883 0 m /l glyphshow +26.408203 0 m /i glyphshow +29.186523 0 m /c glyphshow +grestore +0.500 setlinewidth +gsave +133.4 114.7 59.84 42.52 clipbox +73.428176 111.974862 m +73.428176 127.610303 l +stroke +grestore +gsave +133.4 114.7 59.84 42.52 clipbox +148.679012 122.556421 m +148.679012 151.757267 l +stroke +grestore +gsave +133.4 114.7 59.84 42.52 clipbox +88.929848 120.050855 m +88.929848 123.546898 l +stroke +grestore +gsave +133.4 114.7 59.84 42.52 clipbox +164.180684 135.534766 m +164.180684 148.744784 l +stroke +grestore +gsave +133.4 114.7 59.84 42.52 clipbox +104.43152 71.221861 m +104.43152 77.052459 l +stroke +grestore +gsave +133.4 114.7 59.84 42.52 clipbox +179.682357 86.511071 m +179.682357 101.48972 l +stroke +grestore +gsave +133.4 114.7 59.84 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +73.4282 111.975 o +148.679 122.556 o +grestore +gsave +133.4 114.7 59.84 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +73.4282 127.61 o +148.679 151.757 o +grestore +gsave +133.4 114.7 59.84 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +88.9298 120.051 o +164.181 135.535 o +grestore +gsave +133.4 114.7 59.84 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +88.9298 123.547 o +164.181 148.745 o +grestore +gsave +133.4 114.7 59.84 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +104.432 71.2219 o +179.682 86.5111 o +grestore +gsave +133.4 114.7 59.84 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +104.432 77.0525 o +179.682 101.49 o +grestore +0.800 setlinewidth +0 setlinejoin +2 setlinecap +[] 0 setdash +gsave +59.837875 42.52 m +59.837875 157.21913 l +stroke +grestore +gsave +193.272658 42.52 m +193.272658 157.21913 l +stroke +grestore +gsave +59.837875 42.52 m +193.272658 42.52 l +stroke +grestore +gsave +59.837875 157.21913 m +193.272658 157.21913 l +stroke +grestore +gsave +219.959614 42.52 m +353.394397 42.52 l +353.394397 157.21913 l +219.959614 157.21913 l +cl +grestore +0.200 setlinewidth +0 setlinecap +gsave +133.4 114.7 220 42.52 clipbox +226.024832 42.52 m +241.074999 42.52 l +241.074999 115.462705 l +226.024832 115.462705 l +cl +gsave +0.894 0.102 0.110 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 220 42.52 clipbox +301.275668 42.52 m +316.325835 42.52 l +316.325835 132.185301 l +301.275668 132.185301 l +cl +gsave +0.894 0.102 0.110 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 220 42.52 clipbox +241.526504 42.52 m +256.576671 42.52 l +256.576671 118.282832 l +241.526504 118.282832 l +cl +gsave +0.216 0.494 0.722 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 220 42.52 clipbox +316.77734 42.52 m +331.827507 42.52 l +331.827507 129.226592 l +316.77734 129.226592 l +cl +gsave +0.216 0.494 0.722 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 220 42.52 clipbox +257.028176 42.52 m +272.078343 42.52 l +272.078343 72.06464 l +257.028176 72.06464 l +cl +gsave +0.302 0.686 0.290 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 220 42.52 clipbox +332.279012 42.52 m +347.329179 42.52 l +347.329179 88.691969 l +332.279012 88.691969 l +cl +gsave +0.302 0.686 0.290 setrgbcolor +fill +grestore +stroke +grestore +gsave +237.410962 27.926250 translate +0.000000 rotate +0.000000 0 m /t glyphshow +3.920898 0 m /r glyphshow +8.032227 0 m /a glyphshow +14.160156 0 m /i glyphshow +16.938477 0 m /n glyphshow +grestore +gsave +314.693048 27.926250 translate +0.000000 rotate +0.000000 0 m /t glyphshow +3.920898 0 m /e glyphshow +10.073242 0 m /s glyphshow +15.283203 0 m /t glyphshow +grestore +0.800 setlinewidth +1 setlinejoin +[] 0 setdash +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +219.96 42.52 o +grestore +gsave +206.600239 38.723125 translate +0.000000 rotate +0.000000 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +219.96 70.2278 o +grestore +gsave +200.240864 66.430922 translate +0.000000 rotate +0.000000 0 m /one glyphshow +6.362305 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +219.96 97.9356 o +grestore +gsave +200.240864 94.138720 translate +0.000000 rotate +0.000000 0 m /two glyphshow +6.362305 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +219.96 125.643 o +grestore +gsave +200.240864 121.846517 translate +0.000000 rotate +0.000000 0 m /three glyphshow +6.362305 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +219.96 153.351 o +grestore +gsave +200.240864 149.554315 translate +0.000000 rotate +0.000000 0 m /four glyphshow +6.362305 0 m /zero glyphshow +grestore +0.500 setlinewidth +gsave +133.4 114.7 220 42.52 clipbox +233.549915 103.442124 m +233.549915 127.483286 l +stroke +grestore +gsave +133.4 114.7 220 42.52 clipbox +308.800751 112.613335 m +308.800751 151.757267 l +stroke +grestore +gsave +133.4 114.7 220 42.52 clipbox +249.051587 116.844583 m +249.051587 119.72108 l +stroke +grestore +gsave +133.4 114.7 220 42.52 clipbox +324.302423 120.31695 m +324.302423 138.136233 l +stroke +grestore +gsave +133.4 114.7 220 42.52 clipbox +264.55326 70.50228 m +264.55326 73.627 l +stroke +grestore +gsave +133.4 114.7 220 42.52 clipbox +339.804096 80.85671 m +339.804096 96.527227 l +stroke +grestore +gsave +133.4 114.7 220 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +233.55 103.442 o +308.801 112.613 o +grestore +gsave +133.4 114.7 220 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +233.55 127.483 o +308.801 151.757 o +grestore +gsave +133.4 114.7 220 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +249.052 116.845 o +324.302 120.317 o +grestore +gsave +133.4 114.7 220 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +249.052 119.721 o +324.302 138.136 o +grestore +gsave +133.4 114.7 220 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +264.553 70.5023 o +339.804 80.8567 o +grestore +gsave +133.4 114.7 220 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +264.553 73.627 o +339.804 96.5272 o +grestore +0.800 setlinewidth +0 setlinejoin +2 setlinecap +[] 0 setdash +gsave +219.959614 42.52 m +219.959614 157.21913 l +stroke +grestore +gsave +353.394397 42.52 m +353.394397 157.21913 l +stroke +grestore +gsave +219.959614 42.52 m +353.394397 42.52 l +stroke +grestore +gsave +219.959614 157.21913 m +353.394397 157.21913 l +stroke +grestore +gsave +380.081353 42.52 m +513.516136 42.52 l +513.516136 157.21913 l +380.081353 157.21913 l +cl +grestore +0.200 setlinewidth +0 setlinecap +gsave +133.4 114.7 380.1 42.52 clipbox +386.146571 42.52 m +401.196738 42.52 l +401.196738 110.380048 l +386.146571 110.380048 l +cl +gsave +0.894 0.102 0.110 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 380.1 42.52 clipbox +461.397407 42.52 m +476.447574 42.52 l +476.447574 127.516938 l +461.397407 127.516938 l +cl +gsave +0.894 0.102 0.110 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 380.1 42.52 clipbox +401.648243 42.52 m +416.69841 42.52 l +416.69841 113.427767 l +401.648243 113.427767 l +cl +gsave +0.216 0.494 0.722 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 380.1 42.52 clipbox +476.899079 42.52 m +491.949246 42.52 l +491.949246 121.966348 l +476.899079 121.966348 l +cl +gsave +0.216 0.494 0.722 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 380.1 42.52 clipbox +417.149915 42.52 m +432.200082 42.52 l +432.200082 75.48386 l +417.149915 75.48386 l +cl +gsave +0.302 0.686 0.290 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 380.1 42.52 clipbox +492.400751 42.52 m +507.450918 42.52 l +507.450918 88.023338 l +492.400751 88.023338 l +cl +gsave +0.302 0.686 0.290 setrgbcolor +fill +grestore +stroke +grestore +gsave +397.532702 27.926250 translate +0.000000 rotate +0.000000 0 m /t glyphshow +3.920898 0 m /r glyphshow +8.032227 0 m /a glyphshow +14.160156 0 m /i glyphshow +16.938477 0 m /n glyphshow +grestore +gsave +474.814788 27.926250 translate +0.000000 rotate +0.000000 0 m /t glyphshow +3.920898 0 m /e glyphshow +10.073242 0 m /s glyphshow +15.283203 0 m /t glyphshow +grestore +0.800 setlinewidth +1 setlinejoin +[] 0 setdash +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +380.081 42.52 o +grestore +gsave +366.721978 38.723125 translate +0.000000 rotate +0.000000 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +380.081 73.4552 o +grestore +gsave +360.362603 69.658359 translate +0.000000 rotate +0.000000 0 m /one glyphshow +6.362305 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +380.081 104.39 o +grestore +gsave +360.362603 100.593593 translate +0.000000 rotate +0.000000 0 m /two glyphshow +6.362305 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +380.081 135.326 o +grestore +gsave +360.362603 131.528827 translate +0.000000 rotate +0.000000 0 m /three glyphshow +6.362305 0 m /zero glyphshow +grestore +0.500 setlinewidth +gsave +133.4 114.7 380.1 42.52 clipbox +393.671654 97.902705 m +393.671654 122.857391 l +stroke +grestore +gsave +133.4 114.7 380.1 42.52 clipbox +468.92249 103.276609 m +468.92249 151.757267 l +stroke +grestore +gsave +133.4 114.7 380.1 42.52 clipbox +409.173327 111.515888 m +409.173327 115.339646 l +stroke +grestore +gsave +133.4 114.7 380.1 42.52 clipbox +484.424163 113.760328 m +484.424163 130.172368 l +stroke +grestore +gsave +133.4 114.7 380.1 42.52 clipbox +424.674999 72.189907 m +424.674999 78.777812 l +stroke +grestore +gsave +133.4 114.7 380.1 42.52 clipbox +499.925835 78.303162 m +499.925835 97.743515 l +stroke +grestore +gsave +133.4 114.7 380.1 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +393.672 97.9027 o +468.922 103.277 o +grestore +gsave +133.4 114.7 380.1 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +393.672 122.857 o +468.922 151.757 o +grestore +gsave +133.4 114.7 380.1 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +409.173 111.516 o +484.424 113.76 o +grestore +gsave +133.4 114.7 380.1 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +409.173 115.34 o +484.424 130.172 o +grestore +gsave +133.4 114.7 380.1 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +424.675 72.1899 o +499.926 78.3032 o +grestore +gsave +133.4 114.7 380.1 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +424.675 78.7778 o +499.926 97.7435 o +grestore +0.800 setlinewidth +0 setlinejoin +2 setlinecap +[] 0 setdash +gsave +380.081353 42.52 m +380.081353 157.21913 l +stroke +grestore +gsave +513.516136 42.52 m +513.516136 157.21913 l +stroke +grestore +gsave +380.081353 42.52 m +513.516136 42.52 l +stroke +grestore +gsave +380.081353 157.21913 m +513.516136 157.21913 l +stroke +grestore +gsave +540.203092 42.52 m +673.637875 42.52 l +673.637875 157.21913 l +540.203092 157.21913 l +cl +grestore +0.200 setlinewidth +0 setlinecap +gsave +133.4 114.7 540.2 42.52 clipbox +546.26831 42.52 m +561.318477 42.52 l +561.318477 106.995129 l +546.26831 106.995129 l +cl +gsave +0.894 0.102 0.110 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 540.2 42.52 clipbox +621.519146 42.52 m +636.569313 42.52 l +636.569313 126.689135 l +621.519146 126.689135 l +cl +gsave +0.894 0.102 0.110 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 540.2 42.52 clipbox +561.769982 42.52 m +576.820149 42.52 l +576.820149 126.549146 l +561.769982 126.549146 l +cl +gsave +0.216 0.494 0.722 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 540.2 42.52 clipbox +637.020818 42.52 m +652.070985 42.52 l +652.070985 138.957395 l +637.020818 138.957395 l +cl +gsave +0.216 0.494 0.722 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 540.2 42.52 clipbox +577.271654 42.52 m +592.321821 42.52 l +592.321821 82.255262 l +577.271654 82.255262 l +cl +gsave +0.302 0.686 0.290 setrgbcolor +fill +grestore +stroke +grestore +gsave +133.4 114.7 540.2 42.52 clipbox +652.52249 42.52 m +667.572658 42.52 l +667.572658 103.149604 l +652.52249 103.149604 l +cl +gsave +0.302 0.686 0.290 setrgbcolor +fill +grestore +stroke +grestore +gsave +557.654441 27.926250 translate +0.000000 rotate +0.000000 0 m /t glyphshow +3.920898 0 m /r glyphshow +8.032227 0 m /a glyphshow +14.160156 0 m /i glyphshow +16.938477 0 m /n glyphshow +grestore +gsave +634.936527 27.926250 translate +0.000000 rotate +0.000000 0 m /t glyphshow +3.920898 0 m /e glyphshow +10.073242 0 m /s glyphshow +15.283203 0 m /t glyphshow +grestore +0.800 setlinewidth +1 setlinejoin +[] 0 setdash +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +540.203 42.52 o +grestore +gsave +526.843717 38.723125 translate +0.000000 rotate +0.000000 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +540.203 78.8761 o +grestore +gsave +520.484342 75.079272 translate +0.000000 rotate +0.000000 0 m /one glyphshow +6.362305 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +540.203 115.232 o +grestore +gsave +520.484342 111.435420 translate +0.000000 rotate +0.000000 0 m /two glyphshow +6.362305 0 m /zero glyphshow +grestore +gsave +/o { +gsave +newpath +translate +0.8 setlinewidth +1 setlinejoin +0 setlinecap +0 0 m +-3.5 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +540.203 151.588 o +grestore +gsave +520.484342 147.791567 translate +0.000000 rotate +0.000000 0 m /three glyphshow +6.362305 0 m /zero glyphshow +grestore +0.500 setlinewidth +gsave +133.4 114.7 540.2 42.52 clipbox +553.793393 94.022874 m +553.793393 119.967384 l +stroke +grestore +gsave +133.4 114.7 540.2 42.52 clipbox +629.04423 105.480171 m +629.04423 147.898099 l +stroke +grestore +gsave +133.4 114.7 540.2 42.52 clipbox +569.295066 123.840912 m +569.295066 129.257379 l +stroke +grestore +gsave +133.4 114.7 540.2 42.52 clipbox +644.545902 126.157522 m +644.545902 151.757267 l +stroke +grestore +gsave +133.4 114.7 540.2 42.52 clipbox +584.796738 77.570435 m +584.796738 86.940089 l +stroke +grestore +gsave +133.4 114.7 540.2 42.52 clipbox +660.047574 91.80062 m +660.047574 114.498588 l +stroke +grestore +gsave +133.4 114.7 540.2 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +553.793 94.0229 o +629.044 105.48 o +grestore +gsave +133.4 114.7 540.2 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +553.793 119.967 o +629.044 147.898 o +grestore +gsave +133.4 114.7 540.2 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +569.295 123.841 o +644.546 126.158 o +grestore +gsave +133.4 114.7 540.2 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +569.295 129.257 o +644.546 151.757 o +grestore +gsave +133.4 114.7 540.2 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +584.797 77.5704 o +660.048 91.8006 o +grestore +gsave +133.4 114.7 540.2 42.52 clipbox +/o { +gsave +newpath +translate +0.5 setlinewidth +1 setlinejoin +0 setlinecap +3 -0 m +-3 0 l + +gsave +0.000 setgray +fill +grestore +stroke +grestore +} bind def +584.797 86.9401 o +660.048 114.499 o +grestore +0.800 setlinewidth +0 setlinejoin +2 setlinecap +[] 0 setdash +gsave +540.203092 42.52 m +540.203092 157.21913 l +stroke +grestore +gsave +673.637875 42.52 m +673.637875 157.21913 l +stroke +grestore +gsave +540.203092 42.52 m +673.637875 42.52 l +stroke +grestore +gsave +540.203092 157.21913 m +673.637875 157.21913 l +stroke +grestore +0.200 setlinewidth +0 setlinecap +gsave +233.434563 11.078125 m +253.434563 11.078125 l +253.434563 18.078125 l +233.434563 18.078125 l +cl +gsave +0.894 0.102 0.110 setrgbcolor +fill +grestore +stroke +grestore +gsave +261.434563 11.078125 translate +0.000000 rotate +0.000000 0 m /r glyphshow +4.111328 0 m /a glyphshow +10.239258 0 m /n glyphshow +16.577148 0 m /d glyphshow +22.924805 0 m /o glyphshow +29.042969 0 m /m glyphshow +grestore +gsave +320.231438 11.078125 m +340.231438 11.078125 l +340.231438 18.078125 l +320.231438 18.078125 l +cl +gsave +0.216 0.494 0.722 setrgbcolor +fill +grestore +stroke +grestore +gsave +348.231438 11.078125 translate +0.000000 rotate +0.000000 0 m /e glyphshow +6.027344 0 m /x glyphshow +11.945312 0 m /p glyphshow +18.292969 0 m /e glyphshow +24.445312 0 m /r glyphshow +28.556641 0 m /t glyphshow +grestore +gsave +400.715813 11.078125 m +420.715813 11.078125 l +420.715813 18.078125 l +400.715813 18.078125 l +cl +gsave +0.302 0.686 0.290 setrgbcolor +fill +grestore +stroke +grestore +gsave +428.715813 11.078125 translate +0.000000 rotate +0.000000 0 m /f glyphshow +3.520508 0 m /i glyphshow +6.298828 0 m /t glyphshow +10.219727 0 m /t glyphshow +14.140625 0 m /e glyphshow +20.292969 0 m /d glyphshow +grestore + +end +showpage diff --git a/gklearn/experiments/thesis/ged/fit_distances/ged_fit_distance_results_plot.py b/gklearn/experiments/thesis/ged/fit_distances/ged_fit_distance_results_plot.py index 6356794..e7e1c4c 100644 --- a/gklearn/experiments/thesis/ged/fit_distances/ged_fit_distance_results_plot.py +++ b/gklearn/experiments/thesis/ged/fit_distances/ged_fit_distance_results_plot.py @@ -10,6 +10,9 @@ import numpy as np import scipy.stats import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec +# import matplotlib as mpl +# mpl.rcParams['text.usetex'] = True +# mpl.rcParams['text.latex.preamble'] = [r'\usepackage{amsmath}'] #for \text command def rounder(x, decimals): @@ -54,7 +57,7 @@ def df_to_latex_table(df, replace_header=True, end_mid_line=7): i_end = ltx.find('\\\\\n\\midrule\n') replace = r"""\begin{tabular}{lll@{~~}c@{~~}c@{~~}c@{~~}c} \toprule -\multirow{2}[2]{*}{\textbf{Dataset}} & \multirow{2}[2]{*}{\textbf{Distance}} & \multirow{2}[2]{*}{\textbf{Method}} & \multicolumn{2}{c}{\textbf{BIPARTITE}} & \multicolumn{2}{c}{\textbf{IPFP}} \\ +\multirow{2}[2]{*}{\textbf{Dataset}} & \multirow{2}[2]{*}{\textbf{Distance}} & \multirow{2}[2]{*}{\textbf{Method}} & \multicolumn{2}{c}{\textbf{bipartite}} & \multicolumn{2}{c}{\textbf{IPFP}} \\ \cmidrule(lr){4-5}\cmidrule(lr){6-7} & & & \textbf{Train errors} & \textbf{Test errors} & \textbf{Train errors} & \textbf{Test errors} \\ \midrule @@ -95,6 +98,9 @@ def beautify_df(df): for idx, index in enumerate(min_indices): df.loc[(ds, gk, index), min_labels[idx]] = '\\textbf{' + df.loc[(ds, gk, index), min_labels[idx]] + '}' + # Rename indices. + df.index.set_levels([r'Euclidean', r'Manhattan'], level=1, inplace=True) + return df @@ -118,6 +124,11 @@ def params_to_latex_table(results): df.loc[idx_r, idx_c] = '-' # df = beautify_df(df) + # Rename indices. +# df.index.set_levels([r'\texttt{bipartite}', r'\texttt{IPFP}'], level=1, inplace=True) + df.index.set_levels([r'bipartite', r'IPFP'], level=1, inplace=True) + df.index.set_levels([r'Euclidean', r'Manhattan'], level=2, inplace=True) + ltx = df_to_latex_table(df, replace_header=False, end_mid_line=9) return ltx @@ -208,14 +219,11 @@ def print_table_results(results_by_xp): tab.append(["Method", "App","Test"]) #setups = ["random","expert","fitted"] - for i,setup in enumerate(results_by_xp.keys()): current_line = [setup] p = results_by_xp[setup] current_line.append(f"{p['mean'][0]:.2f} +- {p['interval'][0]:.2f}") - current_line.append(f"{p['mean'][1]:.2f} +- {p['interval'][1]:.2f}") - tab.append(current_line) print(tabulate(tab, headers="firstrow")) @@ -342,6 +350,13 @@ def set_figure(nb_rows): return fig +def get_title(edit_cost, distance): + ed = 'bipartite' if edit_cost == 'BIPARTITE' else 'IPFP' +# ed = r'\texttt{' + ed + r'}' + dis = distance[0].upper() + distance[1:] + return ed + ', ' + dis + + if __name__ == '__main__': from sklearn.model_selection import ParameterGrid import pickle @@ -370,7 +385,8 @@ if __name__ == '__main__': for col, contents in enumerate(row_grid_list): ax = fig.add_subplot(gs[row, col]) y_label = (ds_name[:-10] if ds_name.endswith('_unlabeled') else ds_name) if col == 0 else '' - title = contents['edit_cost'] + ', ' + contents['distance'] if row == 0 else '' + + title = get_title(contents['edit_cost'], contents['distance']) if row == 0 else '' p, c = plot_a_task(ax, ds_name, contents['edit_cost'], contents['distance'], title, y_label) results[(ds_name, contents['distance'], contents['edit_cost'])] = p params[(ds_name, contents['distance'], contents['edit_cost'])] = c From 920ebda3f90a839f974113cd2a755381b0ce0aba Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Sun, 3 Jan 2021 15:08:03 +0100 Subject: [PATCH 03/24] Hide deprecation warning in graph_file.py. --- gklearn/utils/graph_files.py | 126 +++++++++++++++++++++---------------------- 1 file changed, 63 insertions(+), 63 deletions(-) diff --git a/gklearn/utils/graph_files.py b/gklearn/utils/graph_files.py index 57d0052..bcb983e 100644 --- a/gklearn/utils/graph_files.py +++ b/gklearn/utils/graph_files.py @@ -1,8 +1,8 @@ """ Utilities function to manage graph files """ -import warnings -warnings.simplefilter('always', DeprecationWarning) -warnings.warn('The functions in the module "gklearn.utils.graph_files" will be deprecated and removed since version 0.4.0. Use the corresponding functions in the module "gklearn.dataset" instead.', DeprecationWarning) +# import warnings +# warnings.simplefilter('always', DeprecationWarning) +# warnings.warn('The functions in the module "gklearn.utils.graph_files" will be deprecated and removed since version 0.4.0. Use the corresponding functions in the module "gklearn.dataset" instead.', DeprecationWarning) from os.path import dirname, splitext @@ -26,17 +26,17 @@ def load_dataset(filename, filename_targets=None, gformat=None, **kwargs): y : List Targets corresponding to graphs. - + Notes ----- This function supports following graph dataset formats: 'ds': load data from .ds file. See comments of function loadFromDS for a example. - 'cxl': load data from Graph eXchange Language file (.cxl file). See + 'cxl': load data from Graph eXchange Language file (.cxl file). See `here `__ for detail. - 'sdf': load data from structured data file (.sdf file). See + 'sdf': load data from structured data file (.sdf file). See `here `__ for details. @@ -77,20 +77,20 @@ def save_dataset(Gn, y, gformat='gxl', group=None, filename='gfile', **kwargs): import warnings warnings.simplefilter('always', DeprecationWarning) warnings.warn('The function "gklearn.utils.save_dataset" will be deprecated and removed since version 0.4.0. Use the class "gklearn.dataset.DataSaver" instead.', DeprecationWarning) - + import os dirname_ds = os.path.dirname(filename) if dirname_ds != '': dirname_ds += '/' os.makedirs(dirname_ds, exist_ok=True) - + if 'graph_dir' in kwargs: graph_dir = kwargs['graph_dir'] + '/' os.makedirs(graph_dir, exist_ok=True) del kwargs['graph_dir'] else: - graph_dir = dirname_ds - + graph_dir = dirname_ds + if group == 'xml' and gformat == 'gxl': with open(filename + '.xml', 'w') as fgroup: fgroup.write("") @@ -122,7 +122,7 @@ def load_ct(filename): # @todo: this function is only tested on CTFile V2000; he 1 3 1 1 <- each line describes an edge : to, from, bond type, bond stereo 2 3 1 1 - + Check `CTFile Formats file `__ for detailed format discription. """ @@ -144,7 +144,7 @@ def load_ct(filename): # @todo: this function is only tested on CTFile V2000; he if count_line_tags[i] != '': # if not obsoleted g.graph[count_line_tags[i]] = tmp[i].strip() i += 1 - + # read the atom block. atom_tags = ['x', 'y', 'z', 'atom_symbol', 'mass_difference', 'charge', 'atom_stereo_parity', 'hydrogen_count_plus_1', 'stereo_care_box', 'valence', 'h0_designator', '', '', 'atom_atom_mapping_number', 'inversion_retention_flag', 'exact_change_flag'] for i in range(0, nb_atoms): @@ -156,7 +156,7 @@ def load_ct(filename): # @todo: this function is only tested on CTFile V2000; he if atom_tags[j] != '': g.nodes[i][atom_tags[j]] = tmp[j].strip() j += 1 - + # read the bond block. bond_tags = ['first_atom_number', 'second_atom_number', 'bond_type', 'bond_stereo', '', 'bond_topology', 'reacting_center_status'] for i in range(0, nb_bonds): @@ -169,7 +169,7 @@ def load_ct(filename): # @todo: this function is only tested on CTFile V2000; he if bond_tags[j] != '': g.edges[(n1, n2)][bond_tags[j]] = tmp[j].strip() j += 1 - + # get label names. label_names = {'node_labels': [], 'edge_labels': [], 'node_attrs': [], 'edge_attrs': []} atom_symbolic = [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, None, None, 1, 1, 1] @@ -188,7 +188,7 @@ def load_ct(filename): # @todo: this function is only tested on CTFile V2000; he else: label_names['edge_attrs'].append(key) break - + return g, label_names @@ -215,19 +215,19 @@ def load_gxl(filename): # @todo: directed graphs. for attr in edge.iter('attr'): labels[attr.attrib['name']] = attr[0].text g.add_edge(dic[edge.attrib['from']], dic[edge.attrib['to']], **labels) - + # get label names. label_names = {'node_labels': [], 'edge_labels': [], 'node_attrs': [], 'edge_attrs': []} for node in root.iter('node'): for attr in node.iter('attr'): - if attr[0].tag == 'int': # @todo: this maybe wrong, and slow. + if attr[0].tag == 'int': # @todo: this maybe wrong, and slow. label_names['node_labels'].append(attr.attrib['name']) else: label_names['node_attrs'].append(attr.attrib['name']) break for edge in root.iter('edge'): for attr in edge.iter('attr'): - if attr[0].tag == 'int': # @todo: this maybe wrong, and slow. + if attr[0].tag == 'int': # @todo: this maybe wrong, and slow. label_names['edge_labels'].append(attr.attrib['name']) else: label_names['edge_attrs'].append(attr.attrib['name']) @@ -249,20 +249,20 @@ def save_gxl(graph, filename, method='default', node_labels=[], edge_labels=[], gxl_file.write("\n") for v, attrs in graph.nodes(data=True): gxl_file.write("") - for l_name in node_labels: - gxl_file.write("" + + for l_name in node_labels: + gxl_file.write("" + str(attrs[l_name]) + "") - for a_name in node_attrs: - gxl_file.write("" + + for a_name in node_attrs: + gxl_file.write("" + str(attrs[a_name]) + "") gxl_file.write("\n") for v1, v2, attrs in graph.edges(data=True): gxl_file.write("") - for l_name in edge_labels: - gxl_file.write("" + + for l_name in edge_labels: + gxl_file.write("" + str(attrs[l_name]) + "") - for a_name in edge_attrs: - gxl_file.write("" + + for a_name in edge_attrs: + gxl_file.write("" + str(attrs[a_name]) + "") gxl_file.write("\n") gxl_file.write("\n") @@ -276,7 +276,7 @@ def save_gxl(graph, filename, method='default', node_labels=[], edge_labels=[], attr['edgeids'] = 'true' attr['edgemode'] = 'undirected' graph_node = ET.SubElement(root_node, 'graph', attrib=attr) - + for v in graph: current_node = ET.SubElement(graph_node, 'node', attrib={'id': str(v)}) for attr in graph.nodes[v].keys(): @@ -285,7 +285,7 @@ def save_gxl(graph, filename, method='default', node_labels=[], edge_labels=[], cur_value = ET.SubElement(cur_attr, graph.nodes[v][attr].__class__.__name__) cur_value.text = graph.nodes[v][attr] - + for v1 in graph: for v2 in graph[v1]: if (v1 < v2): # Non oriented graphs @@ -302,7 +302,7 @@ def save_gxl(graph, filename, method='default', node_labels=[], edge_labels=[], cur_value = ET.SubElement( cur_attr, graph[v1][v2][attr].__class__.__name__) cur_value.text = str(graph[v1][v2][attr]) - + tree = ET.ElementTree(root_node) tree.write(filename) elif method == 'gedlib': @@ -458,11 +458,11 @@ def load_mat(filename, order): # @todo: need to be updated (auto order) or depre g.add_edge(col, row) data.append(g) # print(g.edges(data=True)) - + label_names = {'node_labels': ['label_1'], 'edge_labels': [], 'node_attrs': [], 'edge_attrs': []} if order[1] == 0: label_names['edge_labels'].append('label_1') - + return data, y, label_names @@ -477,12 +477,12 @@ def load_tud(filename): import networkx as nx from os import listdir from os.path import dirname, basename - - + + def get_infos_from_readme(frm): # @todo: add README (cuniform), maybe node/edge label maps. """Get information from DS_label_readme.txt file. """ - + def get_label_names_from_line(line): """Get names of labels/attributes from a line. """ @@ -490,8 +490,8 @@ def load_tud(filename): names = str_names.split(',') names = [attr.strip() for attr in names] return names - - + + def get_class_label_map(label_map_strings): label_map = {} for string in label_map_strings: @@ -500,7 +500,7 @@ def load_tud(filename): return label_map - label_names = {'node_labels': [], 'node_attrs': [], + label_names = {'node_labels': [], 'node_attrs': [], 'edge_labels': [], 'edge_attrs': []} class_label_map = None class_label_map_strings = [] @@ -528,16 +528,16 @@ def load_tud(filename): line = content_rm[i].strip() class_label_map = get_class_label_map(class_label_map_strings) i += 1 - + return label_names, class_label_map - + # get dataset name. dirname_dataset = dirname(filename) filename = basename(filename) fn_split = filename.split('_A') ds_name = fn_split[0].strip() - + # load data file names for name in listdir(dirname_dataset): if ds_name + '_A' in name: @@ -561,20 +561,20 @@ def load_tud(filename): # this is supposed to be the node attrs, make sure to put this as the last 'elif' elif ds_name + '_attributes' in name: fna = dirname_dataset + '/' + name - + # get labels and attributes names. if 'frm' in locals(): label_names, class_label_map = get_infos_from_readme(frm) else: - label_names = {'node_labels': [], 'node_attrs': [], + label_names = {'node_labels': [], 'node_attrs': [], 'edge_labels': [], 'edge_attrs': []} class_label_map = None - + with open(fgi) as gi: content_gi = gi.read().splitlines() # graph indicator with open(fam) as am: content_am = am.read().splitlines() # adjacency matrix - + # load targets. if 'fgl' in locals(): with open(fgl) as gl: @@ -609,7 +609,7 @@ def load_tud(filename): else: for i, line in enumerate(content_gi): data[int(line) - 1].add_node(i) - + # add edges for line in content_am: tmp = line.split(',') @@ -670,7 +670,7 @@ def load_tud(filename): data[g].edges[n[0], n[1]][a_name] = attrs[i] return data, targets, label_names - + def load_from_ds(filename, filename_targets): """Load data from .ds file. @@ -681,9 +681,9 @@ def load_from_ds(filename, filename_targets): '.gxl': see dunction load_gxl for detail. - Note these graph formats are checked automatically by the extensions of + Note these graph formats are checked automatically by the extensions of graph files. - """ + """ dirname_dataset = dirname(filename) data = [] y = [] @@ -695,7 +695,7 @@ def load_from_ds(filename, filename_targets): load_file_fun = load_ct elif extension == 'gxl' or extension == 'sdf': # @todo: .sdf not tested yet. load_file_fun = load_gxl - + if filename_targets is None or filename_targets == '': for i in range(0, len(content)): tmp = content[i].split(' ') @@ -711,7 +711,7 @@ def load_from_ds(filename, filename_targets): g, l_names = load_file_fun(dirname_dataset + '/' + tmp.replace('#', '', 1)) data.append(g) _append_label_names(label_names, l_names) - + with open(filename_targets) as fnt: content_y = fnt.read().splitlines() # assume entries in filename and filename_targets have the same order. @@ -719,13 +719,13 @@ def load_from_ds(filename, filename_targets): tmp = item.split(' ') # assume the 3rd entry in a line is y (for Alkane dataset) y.append(float(tmp[2])) - + return data, y, label_names # def load_from_cxl(filename): # import xml.etree.ElementTree as ET -# +# # dirname_dataset = dirname(filename) # tree = ET.parse(filename) # root = tree.getroot() @@ -736,11 +736,11 @@ def load_from_ds(filename, filename_targets): # mol_class = graph.attrib['class'] # data.append(load_gxl(dirname_dataset + '/' + mol_filename)) # y.append(mol_class) - - + + def load_from_xml(filename, dir_dataset=None): import xml.etree.ElementTree as ET - + if dir_dataset is not None: dir_dataset = dir_dataset else: @@ -757,16 +757,16 @@ def load_from_xml(filename, dir_dataset=None): data.append(g) _append_label_names(label_names, l_names) y.append(mol_class) - + return data, y, label_names def _append_label_names(label_names, new_names): for key, val in label_names.items(): label_names[key] += [name for name in new_names[key] if name not in val] - - -if __name__ == '__main__': + + +if __name__ == '__main__': # ### Load dataset from .ds file. # # .ct files. # ds = {'name': 'Alkane', 'dataset': '../../datasets/Alkane/dataset.ds', @@ -782,7 +782,7 @@ if __name__ == '__main__': # print(Gn[1].nodes(data=True)) # print(Gn[1].edges(data=True)) # print(targets[1]) - + # # .gxl file. # ds_file = '../../datasets/monoterpenoides/dataset_10+.ds' # node/edge symb # Gn, y, label_names = load_dataset(ds_file) @@ -803,7 +803,7 @@ if __name__ == '__main__': # ### Convert graph from one format to another. # # .gxl file. # import networkx as nx -# ds = {'name': 'monoterpenoides', +# ds = {'name': 'monoterpenoides', # 'dataset': '../../datasets/monoterpenoides/dataset_10+.ds'} # node/edge symb # Gn, y = loadDataset(ds['dataset']) # y = [int(i) for i in y] @@ -826,13 +826,13 @@ if __name__ == '__main__': # filename = '/media/ljia/DATA/research-repo/codes/others/gedlib/tests_linlin/generated_datsets/monoterpenoides/gxl/monoterpenoides' # xparams = {'method': 'gedlib'} # saveDataset(Gn, y, gformat='gxl', group='xml', filename=filename, xparams=xparams) - + # save dataset. # ds = {'name': 'MUTAG', 'dataset': '../../datasets/MUTAG/MUTAG.mat', # 'extra_params': {'am_sp_al_nl_el': [0, 0, 3, 1, 2]}} # node/edge symb # Gn, y = loadDataset(ds['dataset'], extra_params=ds['extra_params']) # saveDataset(Gn, y, group='xml', filename='temp/temp') - + # test - new way to add labels and attributes. # dataset = '../../datasets/SYNTHETICnew/SYNTHETICnew_A.txt' # filename = '../../datasets/Fingerprint/Fingerprint_A.txt' From 95598397a13bbf8f68691666ced81058cb6a8a34 Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Sun, 3 Jan 2021 15:12:57 +0100 Subject: [PATCH 04/24] Add pairwise_ged function. --- gklearn/ged/util/__init__.py | 2 +- gklearn/ged/util/util.py | 125 ++++++++++++++++++++++++++++--------------- 2 files changed, 82 insertions(+), 45 deletions(-) diff --git a/gklearn/ged/util/__init__.py b/gklearn/ged/util/__init__.py index f885b18..fe85783 100644 --- a/gklearn/ged/util/__init__.py +++ b/gklearn/ged/util/__init__.py @@ -1,3 +1,3 @@ from gklearn.ged.util.lsape_solver import LSAPESolver -from gklearn.ged.util.util import compute_geds, ged_options_to_string +from gklearn.ged.util.util import pairwise_ged, compute_geds, get_nb_edit_operations, ged_options_to_string from gklearn.ged.util.util import compute_geds_cml, label_costs_to_matrix diff --git a/gklearn/ged/util/util.py b/gklearn/ged/util/util.py index 7453b65..80141e3 100644 --- a/gklearn/ged/util/util.py +++ b/gklearn/ged/util/util.py @@ -23,7 +23,7 @@ def compute_ged(g1, g2, options): ged_env.set_edit_cost(options['edit_cost'], edit_cost_constant=options['edit_cost_constants']) ged_env.add_nx_graph(g1, '') ged_env.add_nx_graph(g2, '') - listID = ged_env.get_all_graph_ids() + listID = ged_env.get_all_graph_ids() ged_env.init(init_type=options['init_option']) ged_env.set_method(options['method'], ged_options_to_string(options)) ged_env.init_method() @@ -33,9 +33,46 @@ def compute_ged(g1, g2, options): ged_env.run_method(g, h) pi_forward = ged_env.get_forward_map(g, h) pi_backward = ged_env.get_backward_map(g, h) - upper = ged_env.get_upper_bound(g, h) + upper = ged_env.get_upper_bound(g, h) dis = upper - + + # make the map label correct (label remove map as np.inf) + nodes1 = [n for n in g1.nodes()] + nodes2 = [n for n in g2.nodes()] + nb1 = nx.number_of_nodes(g1) + nb2 = nx.number_of_nodes(g2) + pi_forward = [nodes2[pi] if pi < nb2 else np.inf for pi in pi_forward] + pi_backward = [nodes1[pi] if pi < nb1 else np.inf for pi in pi_backward] +# print(pi_forward) + + return dis, pi_forward, pi_backward + + +def pairwise_ged(g1, g2, options={}, sort=True, repeats=1, parallel=False, verbose=True): + from gklearn.gedlib import librariesImport, gedlibpy + + ged_env = gedlibpy.GEDEnv() + ged_env.set_edit_cost(options['edit_cost'], edit_cost_constant=options['edit_cost_constants']) + ged_env.add_nx_graph(g1, '') + ged_env.add_nx_graph(g2, '') + listID = ged_env.get_all_graph_ids() + ged_env.init(init_option=(options['init_option'] if 'init_option' in options else 'EAGER_WITHOUT_SHUFFLED_COPIES')) + ged_env.set_method(options['method'], ged_options_to_string(options)) + ged_env.init_method() + + g = listID[0] + h = listID[1] + dis_min = np.inf + for i in range(0, repeats): + ged_env.run_method(g, h) + upper = ged_env.get_upper_bound(g, h) + dis = upper + if dis < dis_min: + dis_min = dis + pi_forward = ged_env.get_forward_map(g, h) + pi_backward = ged_env.get_backward_map(g, h) +# lower = ged_env.get_lower_bound(g, h) + # make the map label correct (label remove map as np.inf) nodes1 = [n for n in g1.nodes()] nodes2 = [n for n in g2.nodes()] @@ -56,7 +93,7 @@ def compute_geds_cml(graphs, options={}, sort=True, parallel=False, verbose=True for g in graphs: ged_env.add_nx_graph(g, '') listID = ged_env.get_all_graph_ids() - + node_labels = ged_env.get_all_node_labels() edge_labels = ged_env.get_all_edge_labels() node_label_costs = label_costs_to_matrix(options['node_label_costs'], len(node_labels)) if 'node_label_costs' in options else None @@ -73,7 +110,7 @@ def compute_geds_cml(graphs, options={}, sort=True, parallel=False, verbose=True if node_label_costs is None and edge_label_costs is None: neo_options = {'edit_cost': options['edit_cost'], 'is_cml': False, - 'node_labels': options['node_labels'], 'edge_labels': options['edge_labels'], + 'node_labels': options['node_labels'], 'edge_labels': options['edge_labels'], 'node_attrs': options['node_attrs'], 'edge_attrs': options['edge_attrs']} else: neo_options = {'edit_cost': options['edit_cost'], @@ -114,7 +151,7 @@ def compute_geds_cml(graphs, options={}, sort=True, parallel=False, verbose=True # print(i, j, idx_itr, dis) pool.close() pool.join() - + else: ged_vec = [] n_edit_operations = [] @@ -146,7 +183,7 @@ def compute_geds(graphs, options={}, sort=True, repeats=1, parallel=False, verbo ged_env.set_edit_cost(options['edit_cost'], edit_cost_constant=options['edit_cost_constants']) for g in graphs: ged_env.add_nx_graph(g, '') - listID = ged_env.get_all_graph_ids() + listID = ged_env.get_all_graph_ids() ged_env.init() if parallel: options['threads'] = 1 @@ -155,7 +192,7 @@ def compute_geds(graphs, options={}, sort=True, repeats=1, parallel=False, verbo # compute ged. neo_options = {'edit_cost': options['edit_cost'], - 'node_labels': options['node_labels'], 'edge_labels': options['edge_labels'], + 'node_labels': options['node_labels'], 'edge_labels': options['edge_labels'], 'node_attrs': options['node_attrs'], 'edge_attrs': options['edge_attrs']} ged_mat = np.zeros((len(graphs), len(graphs))) if parallel: @@ -191,7 +228,7 @@ def compute_geds(graphs, options={}, sort=True, repeats=1, parallel=False, verbo # print(i, j, idx_itr, dis) pool.close() pool.join() - + else: ged_vec = [] n_edit_operations = [] @@ -232,14 +269,14 @@ def _compute_ged_parallel(env, gid1, gid2, g1, g2, options, sort, repeats): def _compute_ged(env, gid1, gid2, g1, g2, repeats): - dis_min = np.inf + dis_min = np.inf # @todo: maybe compare distance and then do others (faster). for i in range(0, repeats): env.run_method(gid1, gid2) pi_forward = env.get_forward_map(gid1, gid2) pi_backward = env.get_backward_map(gid1, gid2) - upper = env.get_upper_bound(gid1, gid2) + upper = env.get_upper_bound(gid1, gid2) dis = upper - + # make the map label correct (label remove map as np.inf) nodes1 = [n for n in g1.nodes()] nodes2 = [n for n in g2.nodes()] @@ -247,7 +284,7 @@ def _compute_ged(env, gid1, gid2, g1, g2, repeats): nb2 = nx.number_of_nodes(g2) pi_forward = [nodes2[pi] if pi < nb2 else np.inf for pi in pi_forward] pi_backward = [nodes1[pi] if pi < nb1 else np.inf for pi in pi_backward] - + if dis < dis_min: dis_min = dis pi_forward_min = pi_forward @@ -268,7 +305,7 @@ def label_costs_to_matrix(costs, nb_labels): Returns ------- - cost_matrix : numpy.array. + cost_matrix : numpy.array. The reformed label cost matrix of size (nb_labels, nb_labels). Each row/column of cost_matrix corresponds to a label, and the first label is the dummy label. This is the same setting as in GEDData. """ # Initialize label cost matrix. @@ -282,13 +319,13 @@ def label_costs_to_matrix(costs, nb_labels): for row in range(1, nb_labels + 1): cost_matrix[row, 0] = costs[i] i += 1 - # Costs of substitutions. + # Costs of substitutions. for row in range(1, nb_labels + 1): for col in range(row + 1, nb_labels + 1): cost_matrix[row, col] = costs[i] cost_matrix[col, row] = costs[i] i += 1 - + return cost_matrix @@ -299,7 +336,7 @@ def get_nb_edit_operations(g1, g2, forward_map, backward_map, edit_cost=None, is edge_labels = kwargs.get('edge_labels', []) return get_nb_edit_operations_symbolic_cml(g1, g2, forward_map, backward_map, node_labels=node_labels, edge_labels=edge_labels) - else: + else: raise Exception('Edit cost "', edit_cost, '" is not supported.') else: if edit_cost == 'LETTER' or edit_cost == 'LETTER2': @@ -307,21 +344,21 @@ def get_nb_edit_operations(g1, g2, forward_map, backward_map, edit_cost=None, is elif edit_cost == 'NON_SYMBOLIC': node_attrs = kwargs.get('node_attrs', []) edge_attrs = kwargs.get('edge_attrs', []) - return get_nb_edit_operations_nonsymbolic(g1, g2, forward_map, backward_map, + return get_nb_edit_operations_nonsymbolic(g1, g2, forward_map, backward_map, node_attrs=node_attrs, edge_attrs=edge_attrs) elif edit_cost == 'CONSTANT': node_labels = kwargs.get('node_labels', []) edge_labels = kwargs.get('edge_labels', []) - return get_nb_edit_operations_symbolic(g1, g2, forward_map, backward_map, + return get_nb_edit_operations_symbolic(g1, g2, forward_map, backward_map, node_labels=node_labels, edge_labels=edge_labels) - else: - return get_nb_edit_operations_symbolic(g1, g2, forward_map, backward_map) - - -def get_nb_edit_operations_symbolic_cml(g1, g2, forward_map, backward_map, + else: + return get_nb_edit_operations_symbolic(g1, g2, forward_map, backward_map) + + +def get_nb_edit_operations_symbolic_cml(g1, g2, forward_map, backward_map, node_labels=[], edge_labels=[]): """Compute times that edit operations are used in an edit path for symbolic-labeled graphs, where the costs are different for each pair of nodes. - + Returns ------- list @@ -330,7 +367,7 @@ def get_nb_edit_operations_symbolic_cml(g1, g2, forward_map, backward_map, # Initialize. nb_ops_node = np.zeros((1 + len(node_labels), 1 + len(node_labels))) nb_ops_edge = np.zeros((1 + len(edge_labels), 1 + len(edge_labels))) - + # For nodes. nodes1 = [n for n in g1.nodes()] for i, map_i in enumerate(forward_map): @@ -350,7 +387,7 @@ def get_nb_edit_operations_symbolic_cml(g1, g2, forward_map, backward_map, label = tuple(g2.nodes[nodes2[i]].items()) idx_label = node_labels.index(label) # @todo: faster nb_ops_node[0, idx_label + 1] += 1 - + # For edges. edges1 = [e for e in g1.edges()] edges2_marked = [] @@ -371,7 +408,7 @@ def get_nb_edit_operations_symbolic_cml(g1, g2, forward_map, backward_map, label2 = tuple(g2.edges[(nf2, nt2)].items()) if label1 != label2: idx_label2 = edge_labels.index(label2) # @todo: faster - nb_ops_edge[idx_label1 + 1, idx_label2 + 1] += 1 + nb_ops_edge[idx_label1 + 1, idx_label2 + 1] += 1 # Switch nf2 and nt2, for directed graphs. elif (nt2, nf2) in g2.edges(): edges2_marked.append((nt2, nf2)) @@ -389,7 +426,7 @@ def get_nb_edit_operations_symbolic_cml(g1, g2, forward_map, backward_map, label = tuple(g2.edges[(nt, nf)].items()) idx_label = edge_labels.index(label) # @todo: faster nb_ops_edge[0, idx_label + 1] += 1 - + # Reform the numbers of edit oeprations into a vector. nb_eo_vector = [] # node insertion. @@ -412,9 +449,9 @@ def get_nb_edit_operations_symbolic_cml(g1, g2, forward_map, backward_map, for i in range(1, len(nb_ops_edge)): for j in range(i + 1, len(nb_ops_edge)): nb_eo_vector.append(nb_ops_edge[i, j]) - + return nb_eo_vector - + def get_nb_edit_operations_symbolic(g1, g2, forward_map, backward_map, node_labels=[], edge_labels=[]): @@ -426,7 +463,7 @@ def get_nb_edit_operations_symbolic(g1, g2, forward_map, backward_map, n_ei = 0 n_er = 0 n_es = 0 - + nodes1 = [n for n in g1.nodes()] for i, map_i in enumerate(forward_map): if map_i == np.inf: @@ -441,9 +478,9 @@ def get_nb_edit_operations_symbolic(g1, g2, forward_map, backward_map, for map_i in backward_map: if map_i == np.inf: n_vi += 1 - + # idx_nodes1 = range(0, len(node1)) - + edges1 = [e for e in g1.edges()] nb_edges2_cnted = 0 for n1, n2 in edges1: @@ -475,7 +512,7 @@ def get_nb_edit_operations_symbolic(g1, g2, forward_map, backward_map, else: n_er += 1 n_ei = nx.number_of_edges(g2) - nb_edges2_cnted - + return n_vi, n_vr, n_vs, n_ei, n_er, n_es @@ -488,7 +525,7 @@ def get_nb_edit_operations_letter(g1, g2, forward_map, backward_map): sod_vs = 0 n_ei = 0 n_er = 0 - + nodes1 = [n for n in g1.nodes()] for i, map_i in enumerate(forward_map): if map_i == np.inf: @@ -501,9 +538,9 @@ def get_nb_edit_operations_letter(g1, g2, forward_map, backward_map): for map_i in backward_map: if map_i == np.inf: n_vi += 1 - + # idx_nodes1 = range(0, len(node1)) - + edges1 = [e for e in g1.edges()] nb_edges2_cnted = 0 for n1, n2 in edges1: @@ -520,7 +557,7 @@ def get_nb_edit_operations_letter(g1, g2, forward_map, backward_map): else: n_er += 1 n_ei = nx.number_of_edges(g2) - nb_edges2_cnted - + return n_vi, n_vr, n_vs, sod_vs, n_ei, n_er @@ -536,7 +573,7 @@ def get_nb_edit_operations_nonsymbolic(g1, g2, forward_map, backward_map, n_er = 0 n_es = 0 sod_es = 0 - + nodes1 = [n for n in g1.nodes()] for i, map_i in enumerate(forward_map): if map_i == np.inf: @@ -551,9 +588,9 @@ def get_nb_edit_operations_nonsymbolic(g1, g2, forward_map, backward_map, for map_i in backward_map: if map_i == np.inf: n_vi += 1 - + # idx_nodes1 = range(0, len(node1)) - + edges1 = [e for e in g1.edges()] for n1, n2 in edges1: idx1 = nodes1.index(n1) @@ -582,7 +619,7 @@ def get_nb_edit_operations_nonsymbolic(g1, g2, forward_map, backward_map, else: n_er += 1 n_ei = nx.number_of_edges(g2) - n_es - + return n_vi, n_vr, sod_vs, n_ei, n_er, sod_es @@ -615,7 +652,7 @@ def ged_options_to_string(options): opt_str += '--log ' + str(val) + ' ' elif key == 'randomness': opt_str += '--randomness ' + str(val) + ' ' - + # if not isinstance(val, list): # opt_str += '--' + key.replace('_', '-') + ' ' # if val == False: From 6326e22abc50241ad35528cf2aa75ae21000c3a5 Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Sun, 3 Jan 2021 15:15:44 +0100 Subject: [PATCH 05/24] Put deprecation warning of gklearn.utils.Dataset inside the __init__(). --- gklearn/utils/dataset.py | 340 ++++++++++++------------- gklearn/utils/graphdataset.py | 570 +++++++++++++++++++++--------------------- gklearn/utils/kernels.py | 8 +- 3 files changed, 459 insertions(+), 459 deletions(-) diff --git a/gklearn/utils/dataset.py b/gklearn/utils/dataset.py index 8e225d6..3d6fa2c 100644 --- a/gklearn/utils/dataset.py +++ b/gklearn/utils/dataset.py @@ -12,13 +12,13 @@ import os class Dataset(object): - - import warnings - warnings.simplefilter('always', DeprecationWarning) - warnings.warn('This class has been moved to "gklearn.dataset" module. The class "gklearn.utils.dataset.Dataset" has not been maintained since Nov 12th, 2020 (version 0.2.1) and will be removed since version 0.4.0.', DeprecationWarning) - - + + def __init__(self, filename=None, filename_targets=None, **kwargs): + import warnings + warnings.simplefilter('always', DeprecationWarning) + warnings.warn('This class has been moved to "gklearn.dataset" module. The class "gklearn.utils.dataset.Dataset" has not been maintained since Nov 12th, 2020 (version 0.2.1) and will be removed since version 0.4.0.', DeprecationWarning) + if filename is None: self._graphs = None self._targets = None @@ -28,7 +28,7 @@ class Dataset(object): self._edge_attrs = None else: self.load_dataset(filename, filename_targets=filename_targets, **kwargs) - + self._substructures = None self._node_label_dim = None self._edge_label_dim = None @@ -53,8 +53,8 @@ class Dataset(object): self._node_attr_dim = None self._edge_attr_dim = None self._class_number = None - - + + def load_dataset(self, filename, filename_targets=None, **kwargs): self._graphs, self._targets, label_names = load_dataset(filename, filename_targets=filename_targets, **kwargs) self._node_labels = label_names['node_labels'] @@ -62,15 +62,15 @@ class Dataset(object): self._edge_labels = label_names['edge_labels'] self._edge_attrs = label_names['edge_attrs'] self.clean_labels() - - + + def load_graphs(self, graphs, targets=None): # this has to be followed by set_labels(). self._graphs = graphs self._targets = targets # self.set_labels_attrs() # @todo - - + + def load_predefined_dataset(self, ds_name): current_path = os.path.dirname(os.path.realpath(__file__)) + '/' if ds_name == 'Acyclic': @@ -130,7 +130,7 @@ class Dataset(object): self._graphs, self._targets, label_names = load_dataset(ds_file) elif ds_name == 'NCI109': ds_file = current_path + '../../datasets/NCI109/NCI109_A.txt' - self._graphs, self._targets, label_names = load_dataset(ds_file) + self._graphs, self._targets, label_names = load_dataset(ds_file) elif ds_name == 'PAH': ds_file = current_path + '../../datasets/PAH/dataset.ds' self._graphs, self._targets, label_names = load_dataset(ds_file) @@ -143,13 +143,13 @@ class Dataset(object): pass else: raise Exception('The dataset name "', ds_name, '" is not pre-defined.') - + self._node_labels = label_names['node_labels'] self._node_attrs = label_names['node_attrs'] self._edge_labels = label_names['edge_labels'] self._edge_attrs = label_names['edge_attrs'] self.clean_labels() - + def set_labels(self, node_labels=[], node_attrs=[], edge_labels=[], edge_attrs=[]): self._node_labels = node_labels @@ -157,7 +157,7 @@ class Dataset(object): self._edge_labels = edge_labels self._edge_attrs = edge_attrs - + def set_labels_attrs(self, node_labels=None, node_attrs=None, edge_labels=None, edge_attrs=None): # @todo: remove labels which have only one possible values. if node_labels is None: @@ -183,86 +183,86 @@ class Dataset(object): # if 'attributes' in e[2]: # return len(e[2]['attributes']) # return 0 - - + + def get_dataset_infos(self, keys=None, params=None): """Computes and returns the structure and property information of the graph dataset. - + Parameters ---------- keys : list, optional A list of strings which indicate which informations will be returned. The possible choices includes: - - 'substructures': sub-structures graphs contains, including 'linear', 'non + + 'substructures': sub-structures graphs contains, including 'linear', 'non linear' and 'cyclic'. - + 'node_label_dim': whether vertices have symbolic labels. - + 'edge_label_dim': whether egdes have symbolic labels. - + 'directed': whether graphs in dataset are directed. - + 'dataset_size': number of graphs in dataset. - + 'total_node_num': total number of vertices of all graphs in dataset. - + 'ave_node_num': average number of vertices of graphs in dataset. - + 'min_node_num': minimum number of vertices of graphs in dataset. - + 'max_node_num': maximum number of vertices of graphs in dataset. - + 'total_edge_num': total number of edges of all graphs in dataset. - + 'ave_edge_num': average number of edges of graphs in dataset. - + 'min_edge_num': minimum number of edges of graphs in dataset. - + 'max_edge_num': maximum number of edges of graphs in dataset. - + 'ave_node_degree': average vertex degree of graphs in dataset. - + 'min_node_degree': minimum vertex degree of graphs in dataset. - + 'max_node_degree': maximum vertex degree of graphs in dataset. - - 'ave_fill_factor': average fill factor (number_of_edges / + + 'ave_fill_factor': average fill factor (number_of_edges / (number_of_nodes ** 2)) of graphs in dataset. - + 'min_fill_factor': minimum fill factor of graphs in dataset. - + 'max_fill_factor': maximum fill factor of graphs in dataset. - + 'node_label_nums': list of numbers of symbolic vertex labels of graphs in dataset. - + 'edge_label_nums': list number of symbolic edge labels of graphs in dataset. - - 'node_attr_dim': number of dimensions of non-symbolic vertex labels. + + 'node_attr_dim': number of dimensions of non-symbolic vertex labels. Extracted from the 'attributes' attribute of graph nodes. - - 'edge_attr_dim': number of dimensions of non-symbolic edge labels. + + 'edge_attr_dim': number of dimensions of non-symbolic edge labels. Extracted from the 'attributes' attribute of graph edges. - + 'class_number': number of classes. Only available for classification problems. - + 'all_degree_entropy': the entropy of degree distribution of each graph. - + 'ave_degree_entropy': the average entropy of degree distribution of all graphs. - + All informations above will be returned if `keys` is not given. - + params: dict of dict, optional - A dictinary which contains extra parameters for each possible + A dictinary which contains extra parameters for each possible element in ``keys``. - + Return ------ dict Information of the graph dataset keyed by `keys`. """ infos = {} - + if keys == None: keys = [ 'substructures', @@ -292,13 +292,13 @@ class Dataset(object): 'all_degree_entropy', 'ave_degree_entropy' ] - + # dataset size if 'dataset_size' in keys: if self._dataset_size is None: self._dataset_size = self._get_dataset_size() infos['dataset_size'] = self._dataset_size - + # graph node number if any(i in keys for i in ['total_node_num', 'ave_node_num', 'min_node_num', 'max_node_num']): all_node_nums = self._get_all_node_nums() @@ -307,22 +307,22 @@ class Dataset(object): if self._total_node_num is None: self._total_node_num = self._get_total_node_num(all_node_nums) infos['total_node_num'] = self._total_node_num - + if 'ave_node_num' in keys: if self._ave_node_num is None: self._ave_node_num = self._get_ave_node_num(all_node_nums) infos['ave_node_num'] = self._ave_node_num - + if 'min_node_num' in keys: if self._min_node_num is None: self._min_node_num = self._get_min_node_num(all_node_nums) infos['min_node_num'] = self._min_node_num - + if 'max_node_num' in keys: if self._max_node_num is None: self._max_node_num = self._get_max_node_num(all_node_nums) infos['max_node_num'] = self._max_node_num - + # graph edge number if any(i in keys for i in ['total_edge_num', 'ave_edge_num', 'min_edge_num', 'max_edge_num']): all_edge_nums = self._get_all_edge_nums() @@ -331,12 +331,12 @@ class Dataset(object): if self._total_edge_num is None: self._total_edge_num = self._get_total_edge_num(all_edge_nums) infos['total_edge_num'] = self._total_edge_num - + if 'ave_edge_num' in keys: if self._ave_edge_num is None: self._ave_edge_num = self._get_ave_edge_num(all_edge_nums) infos['ave_edge_num'] = self._ave_edge_num - + if 'max_edge_num' in keys: if self._max_edge_num is None: self._max_edge_num = self._get_max_edge_num(all_edge_nums) @@ -346,120 +346,120 @@ class Dataset(object): if self._min_edge_num is None: self._min_edge_num = self._get_min_edge_num(all_edge_nums) infos['min_edge_num'] = self._min_edge_num - + # label number if 'node_label_dim' in keys: if self._node_label_dim is None: self._node_label_dim = self._get_node_label_dim() - infos['node_label_dim'] = self._node_label_dim - + infos['node_label_dim'] = self._node_label_dim + if 'node_label_nums' in keys: if self._node_label_nums is None: self._node_label_nums = {} for node_label in self._node_labels: self._node_label_nums[node_label] = self._get_node_label_num(node_label) infos['node_label_nums'] = self._node_label_nums - + if 'edge_label_dim' in keys: if self._edge_label_dim is None: self._edge_label_dim = self._get_edge_label_dim() - infos['edge_label_dim'] = self._edge_label_dim - + infos['edge_label_dim'] = self._edge_label_dim + if 'edge_label_nums' in keys: if self._edge_label_nums is None: self._edge_label_nums = {} for edge_label in self._edge_labels: self._edge_label_nums[edge_label] = self._get_edge_label_num(edge_label) infos['edge_label_nums'] = self._edge_label_nums - + if 'directed' in keys or 'substructures' in keys: if self._directed is None: self._directed = self._is_directed() infos['directed'] = self._directed - + # node degree if any(i in keys for i in ['ave_node_degree', 'max_node_degree', 'min_node_degree']): all_node_degrees = self._get_all_node_degrees() - + if 'ave_node_degree' in keys: if self._ave_node_degree is None: self._ave_node_degree = self._get_ave_node_degree(all_node_degrees) infos['ave_node_degree'] = self._ave_node_degree - + if 'max_node_degree' in keys: if self._max_node_degree is None: self._max_node_degree = self._get_max_node_degree(all_node_degrees) infos['max_node_degree'] = self._max_node_degree - + if 'min_node_degree' in keys: if self._min_node_degree is None: self._min_node_degree = self._get_min_node_degree(all_node_degrees) infos['min_node_degree'] = self._min_node_degree - + # fill factor if any(i in keys for i in ['ave_fill_factor', 'max_fill_factor', 'min_fill_factor']): all_fill_factors = self._get_all_fill_factors() - + if 'ave_fill_factor' in keys: if self._ave_fill_factor is None: self._ave_fill_factor = self._get_ave_fill_factor(all_fill_factors) infos['ave_fill_factor'] = self._ave_fill_factor - + if 'max_fill_factor' in keys: if self._max_fill_factor is None: self._max_fill_factor = self._get_max_fill_factor(all_fill_factors) infos['max_fill_factor'] = self._max_fill_factor - + if 'min_fill_factor' in keys: if self._min_fill_factor is None: self._min_fill_factor = self._get_min_fill_factor(all_fill_factors) infos['min_fill_factor'] = self._min_fill_factor - + if 'substructures' in keys: if self._substructures is None: self._substructures = self._get_substructures() infos['substructures'] = self._substructures - + if 'class_number' in keys: if self._class_number is None: self._class_number = self._get_class_number() infos['class_number'] = self._class_number - + if 'node_attr_dim' in keys: if self._node_attr_dim is None: self._node_attr_dim = self._get_node_attr_dim() infos['node_attr_dim'] = self._node_attr_dim - + if 'edge_attr_dim' in keys: if self._edge_attr_dim is None: self._edge_attr_dim = self._get_edge_attr_dim() infos['edge_attr_dim'] = self._edge_attr_dim - + # entropy of degree distribution. - + if 'all_degree_entropy' in keys: if params is not None and ('all_degree_entropy' in params) and ('base' in params['all_degree_entropy']): base = params['all_degree_entropy']['base'] else: base = None infos['all_degree_entropy'] = self._compute_all_degree_entropy(base=base) - + if 'ave_degree_entropy' in keys: if params is not None and ('ave_degree_entropy' in params) and ('base' in params['ave_degree_entropy']): base = params['ave_degree_entropy']['base'] else: base = None infos['ave_degree_entropy'] = np.mean(self._compute_all_degree_entropy(base=base)) - + return infos - - + + def print_graph_infos(self, infos): from collections import OrderedDict keys = list(infos.keys()) print(OrderedDict(sorted(infos.items(), key=lambda i: keys.index(i[0])))) - - + + def remove_labels(self, node_labels=[], edge_labels=[], node_attrs=[], edge_attrs=[]): node_labels = [item for item in node_labels if item in self._node_labels] edge_labels = [item for item in edge_labels if item in self._edge_labels] @@ -485,8 +485,8 @@ class Dataset(object): self._node_attrs = [na for na in self._node_attrs if na not in node_attrs] if len(edge_attrs) > 0: self._edge_attrs = [ea for ea in self._edge_attrs if ea not in edge_attrs] - - + + def clean_labels(self): labels = [] for name in self._node_labels: @@ -543,8 +543,8 @@ class Dataset(object): for ed in G.edges(): del G.edges[ed][name] self._edge_attrs = labels - - + + def cut_graphs(self, range_): self._graphs = [self._graphs[i] for i in range_] if self._targets is not None: @@ -561,8 +561,8 @@ class Dataset(object): self._graphs = [p[1] for p in trimed_pairs] self._targets = [self._targets[i] for i in idx] self.clean_labels() - - + + def copy(self): dataset = Dataset() graphs = [g.copy() for g in self._graphs] if self._graphs is not None else None @@ -575,8 +575,8 @@ class Dataset(object): dataset.set_labels(node_labels=node_labels, node_attrs=node_attrs, edge_labels=edge_labels, edge_attrs=edge_attrs) # @todo: clean_labels and add other class members? return dataset - - + + def get_all_node_labels(self): node_labels = [] for g in self._graphs: @@ -585,8 +585,8 @@ class Dataset(object): if nl not in node_labels: node_labels.append(nl) return node_labels - - + + def get_all_edge_labels(self): edge_labels = [] for g in self._graphs: @@ -595,94 +595,94 @@ class Dataset(object): if el not in edge_labels: edge_labels.append(el) return edge_labels - - + + def _get_dataset_size(self): return len(self._graphs) - - + + def _get_all_node_nums(self): return [nx.number_of_nodes(G) for G in self._graphs] - - + + def _get_total_node_nums(self, all_node_nums): return np.sum(all_node_nums) - - + + def _get_ave_node_num(self, all_node_nums): return np.mean(all_node_nums) - - + + def _get_min_node_num(self, all_node_nums): return np.amin(all_node_nums) - - + + def _get_max_node_num(self, all_node_nums): return np.amax(all_node_nums) - - + + def _get_all_edge_nums(self): return [nx.number_of_edges(G) for G in self._graphs] - - + + def _get_total_edge_nums(self, all_edge_nums): return np.sum(all_edge_nums) - - + + def _get_ave_edge_num(self, all_edge_nums): return np.mean(all_edge_nums) - - + + def _get_min_edge_num(self, all_edge_nums): return np.amin(all_edge_nums) - - + + def _get_max_edge_num(self, all_edge_nums): return np.amax(all_edge_nums) - - + + def _get_node_label_dim(self): return len(self._node_labels) - - + + def _get_node_label_num(self, node_label): nl = set() for G in self._graphs: nl = nl | set(nx.get_node_attributes(G, node_label).values()) return len(nl) - - + + def _get_edge_label_dim(self): return len(self._edge_labels) - - + + def _get_edge_label_num(self, edge_label): el = set() for G in self._graphs: el = el | set(nx.get_edge_attributes(G, edge_label).values()) return len(el) - - + + def _is_directed(self): return nx.is_directed(self._graphs[0]) - - + + def _get_all_node_degrees(self): return [np.mean(list(dict(G.degree()).values())) for G in self._graphs] - - + + def _get_ave_node_degree(self, all_node_degrees): return np.mean(all_node_degrees) - - + + def _get_max_node_degree(self, all_node_degrees): return np.amax(all_node_degrees) - - + + def _get_min_node_degree(self, all_node_degrees): return np.amin(all_node_degrees) - - + + def _get_all_fill_factors(self): """Get fill factor, the number of non-zero entries in the adjacency matrix. @@ -692,20 +692,20 @@ class Dataset(object): List of fill factors for all graphs. """ return [nx.number_of_edges(G) / (nx.number_of_nodes(G) ** 2) for G in self._graphs] - + def _get_ave_fill_factor(self, all_fill_factors): return np.mean(all_fill_factors) - - + + def _get_max_fill_factor(self, all_fill_factors): return np.amax(all_fill_factors) - - + + def _get_min_fill_factor(self, all_fill_factors): return np.amin(all_fill_factors) - - + + def _get_substructures(self): subs = set() for G in self._graphs: @@ -737,22 +737,22 @@ class Dataset(object): # if any(len(i) > 2 for i in cyc): # subs.add('cyclic') # break - + return subs - - + + def _get_class_num(self): return len(set(self._targets)) - - + + def _get_node_attr_dim(self): return len(self._node_attrs) - - + + def _get_edge_attr_dim(self): return len(self._edge_attrs) - + def _compute_all_degree_entropy(self, base=None): """Compute the entropy of degree distribution of each graph. @@ -767,15 +767,15 @@ class Dataset(object): The calculated entropy. """ from gklearn.utils.stats import entropy - + degree_entropy = [] for g in self._graphs: degrees = list(dict(g.degree()).values()) en = entropy(degrees, base=base) degree_entropy.append(en) return degree_entropy - - + + @property def graphs(self): return self._graphs @@ -784,8 +784,8 @@ class Dataset(object): @property def targets(self): return self._targets - - + + @property def node_labels(self): return self._node_labels @@ -794,25 +794,25 @@ class Dataset(object): @property def edge_labels(self): return self._edge_labels - - + + @property def node_attrs(self): return self._node_attrs - - + + @property def edge_attrs(self): return self._edge_attrs - - + + def split_dataset_by_target(dataset): import warnings warnings.simplefilter('always', DeprecationWarning) warnings.warn('This function has been moved to "gklearn.dataset" module. The function "gklearn.utils.dataset.split_dataset_by_target" has not been maintained since Nov 12th, 2020 (version 0.2.1) and will be removed since version 0.4.0.', DeprecationWarning) - + from gklearn.preimage.utils import get_same_item_indices - + graphs = dataset.graphs targets = dataset.targets datasets = [] diff --git a/gklearn/utils/graphdataset.py b/gklearn/utils/graphdataset.py index 4c64fd0..4dd7881 100644 --- a/gklearn/utils/graphdataset.py +++ b/gklearn/utils/graphdataset.py @@ -5,345 +5,345 @@ This file is for old version of graphkit-learn. def get_dataset_attributes(Gn, - target=None, - attr_names=[], - node_label=None, - edge_label=None): - """Returns the structure and property information of the graph dataset Gn. - - Parameters - ---------- - Gn : List of NetworkX graph - List of graphs whose information will be returned. - - target : list - The list of classification targets corresponding to Gn. Only works for - classification problems. - - attr_names : list - List of strings which indicate which informations will be returned. The - possible choices includes: - - 'substructures': sub-structures Gn contains, including 'linear', 'non + target=None, + attr_names=[], + node_label=None, + edge_label=None): + """Returns the structure and property information of the graph dataset Gn. + + Parameters + ---------- + Gn : List of NetworkX graph + List of graphs whose information will be returned. + + target : list + The list of classification targets corresponding to Gn. Only works for + classification problems. + + attr_names : list + List of strings which indicate which informations will be returned. The + possible choices includes: + + 'substructures': sub-structures Gn contains, including 'linear', 'non linear' and 'cyclic'. - 'node_labeled': whether vertices have symbolic labels. + 'node_labeled': whether vertices have symbolic labels. - 'edge_labeled': whether egdes have symbolic labels. + 'edge_labeled': whether egdes have symbolic labels. - 'is_directed': whether graphs in Gn are directed. + 'is_directed': whether graphs in Gn are directed. - 'dataset_size': number of graphs in Gn. + 'dataset_size': number of graphs in Gn. - 'ave_node_num': average number of vertices of graphs in Gn. + 'ave_node_num': average number of vertices of graphs in Gn. - 'min_node_num': minimum number of vertices of graphs in Gn. + 'min_node_num': minimum number of vertices of graphs in Gn. - 'max_node_num': maximum number of vertices of graphs in Gn. + 'max_node_num': maximum number of vertices of graphs in Gn. - 'ave_edge_num': average number of edges of graphs in Gn. + 'ave_edge_num': average number of edges of graphs in Gn. - 'min_edge_num': minimum number of edges of graphs in Gn. + 'min_edge_num': minimum number of edges of graphs in Gn. - 'max_edge_num': maximum number of edges of graphs in Gn. + 'max_edge_num': maximum number of edges of graphs in Gn. - 'ave_node_degree': average vertex degree of graphs in Gn. + 'ave_node_degree': average vertex degree of graphs in Gn. - 'min_node_degree': minimum vertex degree of graphs in Gn. + 'min_node_degree': minimum vertex degree of graphs in Gn. - 'max_node_degree': maximum vertex degree of graphs in Gn. + 'max_node_degree': maximum vertex degree of graphs in Gn. - 'ave_fill_factor': average fill factor (number_of_edges / + 'ave_fill_factor': average fill factor (number_of_edges / (number_of_nodes ** 2)) of graphs in Gn. - 'min_fill_factor': minimum fill factor of graphs in Gn. + 'min_fill_factor': minimum fill factor of graphs in Gn. - 'max_fill_factor': maximum fill factor of graphs in Gn. + 'max_fill_factor': maximum fill factor of graphs in Gn. - 'node_label_num': number of symbolic vertex labels. + 'node_label_num': number of symbolic vertex labels. - 'edge_label_num': number of symbolic edge labels. + 'edge_label_num': number of symbolic edge labels. - 'node_attr_dim': number of dimensions of non-symbolic vertex labels. + 'node_attr_dim': number of dimensions of non-symbolic vertex labels. Extracted from the 'attributes' attribute of graph nodes. - 'edge_attr_dim': number of dimensions of non-symbolic edge labels. + 'edge_attr_dim': number of dimensions of non-symbolic edge labels. Extracted from the 'attributes' attribute of graph edges. - 'class_number': number of classes. Only available for classification problems. + 'class_number': number of classes. Only available for classification problems. - node_label : string - Node attribute used as label. The default node label is atom. Mandatory - when 'node_labeled' or 'node_label_num' is required. + node_label : string + Node attribute used as label. The default node label is atom. Mandatory + when 'node_labeled' or 'node_label_num' is required. - edge_label : string - Edge attribute used as label. The default edge label is bond_type. - Mandatory when 'edge_labeled' or 'edge_label_num' is required. - - Return - ------ - attrs : dict - Value for each property. - """ - import networkx as nx - import numpy as np - - attrs = {} - - def get_dataset_size(Gn): - return len(Gn) - - def get_all_node_num(Gn): - return [nx.number_of_nodes(G) for G in Gn] - - def get_ave_node_num(all_node_num): - return np.mean(all_node_num) - - def get_min_node_num(all_node_num): - return np.amin(all_node_num) - - def get_max_node_num(all_node_num): - return np.amax(all_node_num) - - def get_all_edge_num(Gn): - return [nx.number_of_edges(G) for G in Gn] - - def get_ave_edge_num(all_edge_num): - return np.mean(all_edge_num) - - def get_min_edge_num(all_edge_num): - return np.amin(all_edge_num) - - def get_max_edge_num(all_edge_num): - return np.amax(all_edge_num) - - def is_node_labeled(Gn): - return False if node_label is None else True - - def get_node_label_num(Gn): - nl = set() - for G in Gn: - nl = nl | set(nx.get_node_attributes(G, node_label).values()) - return len(nl) - - def is_edge_labeled(Gn): - return False if edge_label is None else True - - def get_edge_label_num(Gn): - el = set() - for G in Gn: - el = el | set(nx.get_edge_attributes(G, edge_label).values()) - return len(el) - - def is_directed(Gn): - return nx.is_directed(Gn[0]) - - def get_ave_node_degree(Gn): - return np.mean([np.mean(list(dict(G.degree()).values())) for G in Gn]) - - def get_max_node_degree(Gn): - return np.amax([np.mean(list(dict(G.degree()).values())) for G in Gn]) - - def get_min_node_degree(Gn): - return np.amin([np.mean(list(dict(G.degree()).values())) for G in Gn]) - - # get fill factor, the number of non-zero entries in the adjacency matrix. - def get_ave_fill_factor(Gn): - return np.mean([nx.number_of_edges(G) / (nx.number_of_nodes(G) - * nx.number_of_nodes(G)) for G in Gn]) - - def get_max_fill_factor(Gn): - return np.amax([nx.number_of_edges(G) / (nx.number_of_nodes(G) - * nx.number_of_nodes(G)) for G in Gn]) - - def get_min_fill_factor(Gn): - return np.amin([nx.number_of_edges(G) / (nx.number_of_nodes(G) - * nx.number_of_nodes(G)) for G in Gn]) - - def get_substructures(Gn): - subs = set() - for G in Gn: - degrees = list(dict(G.degree()).values()) - if any(i == 2 for i in degrees): - subs.add('linear') - if np.amax(degrees) >= 3: - subs.add('non linear') - if 'linear' in subs and 'non linear' in subs: - break - - if is_directed(Gn): - for G in Gn: - if len(list(nx.find_cycle(G))) > 0: - subs.add('cyclic') - break - # else: - # # @todo: this method does not work for big graph with large amount of edges like D&D, try a better way. - # upper = np.amin([nx.number_of_edges(G) for G in Gn]) * 2 + 10 - # for G in Gn: - # if (nx.number_of_edges(G) < upper): - # cyc = list(nx.simple_cycles(G.to_directed())) - # if any(len(i) > 2 for i in cyc): - # subs.add('cyclic') - # break - # if 'cyclic' not in subs: - # for G in Gn: - # cyc = list(nx.simple_cycles(G.to_directed())) - # if any(len(i) > 2 for i in cyc): - # subs.add('cyclic') - # break - - return subs - - def get_class_num(target): - return len(set(target)) - - def get_node_attr_dim(Gn): - for G in Gn: - for n in G.nodes(data=True): - if 'attributes' in n[1]: - return len(n[1]['attributes']) - return 0 - - def get_edge_attr_dim(Gn): - for G in Gn: - if nx.number_of_edges(G) > 0: - for e in G.edges(data=True): - if 'attributes' in e[2]: - return len(e[2]['attributes']) - return 0 - - if attr_names == []: - attr_names = [ - 'substructures', - 'node_labeled', - 'edge_labeled', - 'is_directed', - 'dataset_size', - 'ave_node_num', - 'min_node_num', - 'max_node_num', - 'ave_edge_num', - 'min_edge_num', - 'max_edge_num', - 'ave_node_degree', - 'min_node_degree', - 'max_node_degree', - 'ave_fill_factor', - 'min_fill_factor', - 'max_fill_factor', - 'node_label_num', - 'edge_label_num', - 'node_attr_dim', - 'edge_attr_dim', - 'class_number', - ] - - # dataset size - if 'dataset_size' in attr_names: - - attrs.update({'dataset_size': get_dataset_size(Gn)}) - - # graph node number - if any(i in attr_names - for i in ['ave_node_num', 'min_node_num', 'max_node_num']): - - all_node_num = get_all_node_num(Gn) - - if 'ave_node_num' in attr_names: - - attrs.update({'ave_node_num': get_ave_node_num(all_node_num)}) - - if 'min_node_num' in attr_names: - - attrs.update({'min_node_num': get_min_node_num(all_node_num)}) - - if 'max_node_num' in attr_names: - - attrs.update({'max_node_num': get_max_node_num(all_node_num)}) - - # graph edge number - if any(i in attr_names for i in - ['ave_edge_num', 'min_edge_num', 'max_edge_num']): - - all_edge_num = get_all_edge_num(Gn) + edge_label : string + Edge attribute used as label. The default edge label is bond_type. + Mandatory when 'edge_labeled' or 'edge_label_num' is required. - if 'ave_edge_num' in attr_names: + Return + ------ + attrs : dict + Value for each property. + """ + import networkx as nx + import numpy as np + + attrs = {} + + def get_dataset_size(Gn): + return len(Gn) + + def get_all_node_num(Gn): + return [nx.number_of_nodes(G) for G in Gn] + + def get_ave_node_num(all_node_num): + return np.mean(all_node_num) + + def get_min_node_num(all_node_num): + return np.amin(all_node_num) + + def get_max_node_num(all_node_num): + return np.amax(all_node_num) + + def get_all_edge_num(Gn): + return [nx.number_of_edges(G) for G in Gn] + + def get_ave_edge_num(all_edge_num): + return np.mean(all_edge_num) + + def get_min_edge_num(all_edge_num): + return np.amin(all_edge_num) + + def get_max_edge_num(all_edge_num): + return np.amax(all_edge_num) + + def is_node_labeled(Gn): + return False if node_label is None else True + + def get_node_label_num(Gn): + nl = set() + for G in Gn: + nl = nl | set(nx.get_node_attributes(G, node_label).values()) + return len(nl) + + def is_edge_labeled(Gn): + return False if edge_label is None else True + + def get_edge_label_num(Gn): + el = set() + for G in Gn: + el = el | set(nx.get_edge_attributes(G, edge_label).values()) + return len(el) + + def is_directed(Gn): + return nx.is_directed(Gn[0]) + + def get_ave_node_degree(Gn): + return np.mean([np.mean(list(dict(G.degree()).values())) for G in Gn]) + + def get_max_node_degree(Gn): + return np.amax([np.mean(list(dict(G.degree()).values())) for G in Gn]) + + def get_min_node_degree(Gn): + return np.amin([np.mean(list(dict(G.degree()).values())) for G in Gn]) + + # get fill factor, the number of non-zero entries in the adjacency matrix. + def get_ave_fill_factor(Gn): + return np.mean([nx.number_of_edges(G) / (nx.number_of_nodes(G) + * nx.number_of_nodes(G)) for G in Gn]) + + def get_max_fill_factor(Gn): + return np.amax([nx.number_of_edges(G) / (nx.number_of_nodes(G) + * nx.number_of_nodes(G)) for G in Gn]) + + def get_min_fill_factor(Gn): + return np.amin([nx.number_of_edges(G) / (nx.number_of_nodes(G) + * nx.number_of_nodes(G)) for G in Gn]) + + def get_substructures(Gn): + subs = set() + for G in Gn: + degrees = list(dict(G.degree()).values()) + if any(i == 2 for i in degrees): + subs.add('linear') + if np.amax(degrees) >= 3: + subs.add('non linear') + if 'linear' in subs and 'non linear' in subs: + break + + if is_directed(Gn): + for G in Gn: + if len(list(nx.find_cycle(G))) > 0: + subs.add('cyclic') + break +# else: +# # @todo: this method does not work for big graph with large amount of edges like D&D, try a better way. +# upper = np.amin([nx.number_of_edges(G) for G in Gn]) * 2 + 10 +# for G in Gn: +# if (nx.number_of_edges(G) < upper): +# cyc = list(nx.simple_cycles(G.to_directed())) +# if any(len(i) > 2 for i in cyc): +# subs.add('cyclic') +# break +# if 'cyclic' not in subs: +# for G in Gn: +# cyc = list(nx.simple_cycles(G.to_directed())) +# if any(len(i) > 2 for i in cyc): +# subs.add('cyclic') +# break + + return subs + + def get_class_num(target): + return len(set(target)) + + def get_node_attr_dim(Gn): + for G in Gn: + for n in G.nodes(data=True): + if 'attributes' in n[1]: + return len(n[1]['attributes']) + return 0 + + def get_edge_attr_dim(Gn): + for G in Gn: + if nx.number_of_edges(G) > 0: + for e in G.edges(data=True): + if 'attributes' in e[2]: + return len(e[2]['attributes']) + return 0 + + if attr_names == []: + attr_names = [ + 'substructures', + 'node_labeled', + 'edge_labeled', + 'is_directed', + 'dataset_size', + 'ave_node_num', + 'min_node_num', + 'max_node_num', + 'ave_edge_num', + 'min_edge_num', + 'max_edge_num', + 'ave_node_degree', + 'min_node_degree', + 'max_node_degree', + 'ave_fill_factor', + 'min_fill_factor', + 'max_fill_factor', + 'node_label_num', + 'edge_label_num', + 'node_attr_dim', + 'edge_attr_dim', + 'class_number', + ] + + # dataset size + if 'dataset_size' in attr_names: - attrs.update({'ave_edge_num': get_ave_edge_num(all_edge_num)}) + attrs.update({'dataset_size': get_dataset_size(Gn)}) - if 'max_edge_num' in attr_names: + # graph node number + if any(i in attr_names + for i in ['ave_node_num', 'min_node_num', 'max_node_num']): - attrs.update({'max_edge_num': get_max_edge_num(all_edge_num)}) + all_node_num = get_all_node_num(Gn) + + if 'ave_node_num' in attr_names: - if 'min_edge_num' in attr_names: + attrs.update({'ave_node_num': get_ave_node_num(all_node_num)}) + + if 'min_node_num' in attr_names: - attrs.update({'min_edge_num': get_min_edge_num(all_edge_num)}) + attrs.update({'min_node_num': get_min_node_num(all_node_num)}) + + if 'max_node_num' in attr_names: - # label number - if any(i in attr_names for i in ['node_labeled', 'node_label_num']): - is_nl = is_node_labeled(Gn) - node_label_num = get_node_label_num(Gn) + attrs.update({'max_node_num': get_max_node_num(all_node_num)}) + + # graph edge number + if any(i in attr_names for i in + ['ave_edge_num', 'min_edge_num', 'max_edge_num']): - if 'node_labeled' in attr_names: - # graphs are considered node unlabeled if all nodes have the same label. - attrs.update({'node_labeled': is_nl if node_label_num > 1 else False}) + all_edge_num = get_all_edge_num(Gn) - if 'node_label_num' in attr_names: - attrs.update({'node_label_num': node_label_num}) + if 'ave_edge_num' in attr_names: - if any(i in attr_names for i in ['edge_labeled', 'edge_label_num']): - is_el = is_edge_labeled(Gn) - edge_label_num = get_edge_label_num(Gn) + attrs.update({'ave_edge_num': get_ave_edge_num(all_edge_num)}) - if 'edge_labeled' in attr_names: - # graphs are considered edge unlabeled if all edges have the same label. - attrs.update({'edge_labeled': is_el if edge_label_num > 1 else False}) + if 'max_edge_num' in attr_names: - if 'edge_label_num' in attr_names: - attrs.update({'edge_label_num': edge_label_num}) + attrs.update({'max_edge_num': get_max_edge_num(all_edge_num)}) - if 'is_directed' in attr_names: - attrs.update({'is_directed': is_directed(Gn)}) + if 'min_edge_num' in attr_names: - if 'ave_node_degree' in attr_names: - attrs.update({'ave_node_degree': get_ave_node_degree(Gn)}) + attrs.update({'min_edge_num': get_min_edge_num(all_edge_num)}) - if 'max_node_degree' in attr_names: - attrs.update({'max_node_degree': get_max_node_degree(Gn)}) + # label number + if any(i in attr_names for i in ['node_labeled', 'node_label_num']): + is_nl = is_node_labeled(Gn) + node_label_num = get_node_label_num(Gn) - if 'min_node_degree' in attr_names: - attrs.update({'min_node_degree': get_min_node_degree(Gn)}) - - if 'ave_fill_factor' in attr_names: - attrs.update({'ave_fill_factor': get_ave_fill_factor(Gn)}) + if 'node_labeled' in attr_names: + # graphs are considered node unlabeled if all nodes have the same label. + attrs.update({'node_labeled': is_nl if node_label_num > 1 else False}) - if 'max_fill_factor' in attr_names: - attrs.update({'max_fill_factor': get_max_fill_factor(Gn)}) + if 'node_label_num' in attr_names: + attrs.update({'node_label_num': node_label_num}) - if 'min_fill_factor' in attr_names: - attrs.update({'min_fill_factor': get_min_fill_factor(Gn)}) + if any(i in attr_names for i in ['edge_labeled', 'edge_label_num']): + is_el = is_edge_labeled(Gn) + edge_label_num = get_edge_label_num(Gn) - if 'substructures' in attr_names: - attrs.update({'substructures': get_substructures(Gn)}) + if 'edge_labeled' in attr_names: + # graphs are considered edge unlabeled if all edges have the same label. + attrs.update({'edge_labeled': is_el if edge_label_num > 1 else False}) - if 'class_number' in attr_names: - attrs.update({'class_number': get_class_num(target)}) + if 'edge_label_num' in attr_names: + attrs.update({'edge_label_num': edge_label_num}) - if 'node_attr_dim' in attr_names: - attrs['node_attr_dim'] = get_node_attr_dim(Gn) + if 'is_directed' in attr_names: + attrs.update({'is_directed': is_directed(Gn)}) - if 'edge_attr_dim' in attr_names: - attrs['edge_attr_dim'] = get_edge_attr_dim(Gn) + if 'ave_node_degree' in attr_names: + attrs.update({'ave_node_degree': get_ave_node_degree(Gn)}) - from collections import OrderedDict - return OrderedDict( - sorted(attrs.items(), key=lambda i: attr_names.index(i[0]))) + if 'max_node_degree' in attr_names: + attrs.update({'max_node_degree': get_max_node_degree(Gn)}) + + if 'min_node_degree' in attr_names: + attrs.update({'min_node_degree': get_min_node_degree(Gn)}) + + if 'ave_fill_factor' in attr_names: + attrs.update({'ave_fill_factor': get_ave_fill_factor(Gn)}) + + if 'max_fill_factor' in attr_names: + attrs.update({'max_fill_factor': get_max_fill_factor(Gn)}) + + if 'min_fill_factor' in attr_names: + attrs.update({'min_fill_factor': get_min_fill_factor(Gn)}) + + if 'substructures' in attr_names: + attrs.update({'substructures': get_substructures(Gn)}) + + if 'class_number' in attr_names: + attrs.update({'class_number': get_class_num(target)}) + + if 'node_attr_dim' in attr_names: + attrs['node_attr_dim'] = get_node_attr_dim(Gn) + + if 'edge_attr_dim' in attr_names: + attrs['edge_attr_dim'] = get_edge_attr_dim(Gn) + + from collections import OrderedDict + return OrderedDict( + sorted(attrs.items(), key=lambda i: attr_names.index(i[0]))) def load_predefined_dataset(ds_name): import os from gklearn.utils.graphfiles import loadDataset - + current_path = os.path.dirname(os.path.realpath(__file__)) + '/' if ds_name == 'Acyclic': ds_file = current_path + '../../datasets/Acyclic/dataset_bps.ds' @@ -415,5 +415,5 @@ def load_predefined_dataset(ds_name): pass else: raise Exception('The dataset name "', ds_name, '" is not pre-defined.') - + return graphs, targets \ No newline at end of file diff --git a/gklearn/utils/kernels.py b/gklearn/utils/kernels.py index 49ce04b..5bd7e4d 100644 --- a/gklearn/utils/kernels.py +++ b/gklearn/utils/kernels.py @@ -18,8 +18,8 @@ def deltakernel(x, y): References ---------- - [1] H. Kashima, K. Tsuda, and A. Inokuchi. Marginalized kernels between - labeled graphs. In Proceedings of the 20th International Conference on + [1] H. Kashima, K. Tsuda, and A. Inokuchi. Marginalized kernels between + labeled graphs. In Proceedings of the 20th International Conference on Machine Learning, Washington, DC, United States, 2003. """ return x == y #(1 if condition else 0) @@ -68,7 +68,7 @@ def polynomialkernel(x, y, d=1, c=0): x, y : array d : integer, default 1 - + c : float, default 0 Returns @@ -89,7 +89,7 @@ def linearkernel(x, y): x, y : array d : integer, default 1 - + c : float, default 0 Returns From 349d7a76caf583580aeabb6f37b365701d0cdc3e Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Sun, 3 Jan 2021 15:17:26 +0100 Subject: [PATCH 06/24] Use get_iters function instead of tqdm in StructuralSP. --- gklearn/kernels/graph_kernel.py | 2 +- gklearn/kernels/structural_sp.py | 42 ++++++++++++++-------------------------- 2 files changed, 16 insertions(+), 28 deletions(-) diff --git a/gklearn/kernels/graph_kernel.py b/gklearn/kernels/graph_kernel.py index e9a4032..2692713 100644 --- a/gklearn/kernels/graph_kernel.py +++ b/gklearn/kernels/graph_kernel.py @@ -37,7 +37,7 @@ class GraphKernel(object): elif len(graphs[0]) == 0: raise Exception('The graph list given is empty. No computation was performed.') else: - self._graphs = [g.copy() for g in graphs[0]] + self._graphs = [g.copy() for g in graphs[0]] # @todo: might be very slow. self._gram_matrix = self._compute_gram_matrix() self._gram_matrix_unnorm = np.copy(self._gram_matrix) if self._normalize: diff --git a/gklearn/kernels/structural_sp.py b/gklearn/kernels/structural_sp.py index 5662d18..35ed9d1 100644 --- a/gklearn/kernels/structural_sp.py +++ b/gklearn/kernels/structural_sp.py @@ -14,7 +14,7 @@ import sys from itertools import product # from functools import partial from multiprocessing import Pool -from tqdm import tqdm +from gklearn.utils import get_iters # import networkx as nx import numpy as np from gklearn.utils.parallel import parallel_gm, parallel_me @@ -41,10 +41,7 @@ class StructuralSP(GraphKernel): def _compute_gm_series(self): # get shortest paths of each graph in the graphs. splist = [] - if self._verbose >= 2: - iterator = tqdm(self._graphs, desc='getting sp graphs', file=sys.stdout) - else: - iterator = self._graphs + iterator = get_iters(self._graphs, desc='getting sp graphs', file=sys.stdout, verbose=(self._verbose >= 2)) if self._compute_method == 'trie': for g in iterator: splist.append(self._get_sps_as_trie(g)) @@ -57,10 +54,9 @@ class StructuralSP(GraphKernel): from itertools import combinations_with_replacement itr = combinations_with_replacement(range(0, len(self._graphs)), 2) - if self._verbose >= 2: - iterator = tqdm(itr, desc='Computing kernels', file=sys.stdout) - else: - iterator = itr + len_itr = int(len(self._graphs) * (len(self._graphs) + 1) / 2) + iterator = get_iters(itr, desc='Computing kernels', file=sys.stdout, + length=len_itr, verbose=(self._verbose >= 2)) if self._compute_method == 'trie': for i, j in iterator: kernel = self._ssp_do_trie(self._graphs[i], self._graphs[j], splist[i], splist[j]) @@ -91,11 +87,9 @@ class StructuralSP(GraphKernel): get_sps_fun = self._wrapper_get_sps_trie else: get_sps_fun = self._wrapper_get_sps_naive - if self.verbose >= 2: - iterator = tqdm(pool.imap_unordered(get_sps_fun, itr, chunksize), - desc='getting shortest paths', file=sys.stdout) - else: - iterator = pool.imap_unordered(get_sps_fun, itr, chunksize) + iterator = get_iters(pool.imap_unordered(get_sps_fun, itr, chunksize), + desc='getting shortest paths', file=sys.stdout, + length=len(self._graphs), verbose=(self._verbose >= 2)) for i, sp in iterator: splist[i] = sp pool.close() @@ -122,10 +116,8 @@ class StructuralSP(GraphKernel): # get shortest paths of g1 and each graph in g_list. sp1 = get_shortest_paths(g1, self._edge_weight, self._ds_infos['directed']) splist = [] - if self._verbose >= 2: - iterator = tqdm(g_list, desc='getting sp graphs', file=sys.stdout) - else: - iterator = g_list + iterator = get_iters(g_list, desc='getting sp graphs', file=sys.stdout, + verbose=(self._verbose >= 2)) if self._compute_method == 'trie': for g in iterator: splist.append(self._get_sps_as_trie(g)) @@ -135,10 +127,8 @@ class StructuralSP(GraphKernel): # compute kernel list. kernel_list = [None] * len(g_list) - if self._verbose >= 2: - iterator = tqdm(range(len(g_list)), desc='Computing kernels', file=sys.stdout) - else: - iterator = range(len(g_list)) + iterator = get_iters(range(len(g_list)), desc='Computing kernels', + file=sys.stdout, length=len(g_list), verbose=(self._verbose >= 2)) if self._compute_method == 'trie': for i in iterator: kernel = self._ssp_do_trie(g1, g_list[i], sp1, splist[i]) @@ -166,11 +156,9 @@ class StructuralSP(GraphKernel): get_sps_fun = self._wrapper_get_sps_trie else: get_sps_fun = self._wrapper_get_sps_naive - if self.verbose >= 2: - iterator = tqdm(pool.imap_unordered(get_sps_fun, itr, chunksize), - desc='getting shortest paths', file=sys.stdout) - else: - iterator = pool.imap_unordered(get_sps_fun, itr, chunksize) + iterator = get_iters(pool.imap_unordered(get_sps_fun, itr, chunksize), + desc='getting shortest paths', file=sys.stdout, + length=len(g_list), verbose=(self._verbose >= 2)) for i, sp in iterator: splist[i] = sp pool.close() From e93ab877b3bedc13d800497ebbd801e26ab968c2 Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Sun, 3 Jan 2021 20:41:59 +0100 Subject: [PATCH 07/24] [update] Dataset class: Remove null graphs after loading the dataset. --- gklearn/dataset/dataset.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gklearn/dataset/dataset.py b/gklearn/dataset/dataset.py index faca89b..75684c2 100644 --- a/gklearn/dataset/dataset.py +++ b/gklearn/dataset/dataset.py @@ -14,7 +14,7 @@ from gklearn.dataset import DATASET_META, DataFetcher, DataLoader class Dataset(object): - def __init__(self, inputs=None, root='datasets', filename_targets=None, targets=None, mode='networkx', clean_labels=True, reload=False, verbose=False, **kwargs): + def __init__(self, inputs=None, root='datasets', filename_targets=None, targets=None, mode='networkx', remove_null_graphs=True, clean_labels=True, reload=False, verbose=False, **kwargs): self._substructures = None self._node_label_dim = None self._edge_label_dim = None @@ -82,6 +82,8 @@ class Dataset(object): else: raise TypeError('The "inputs" argument cannot be recognized. "Inputs" can be a list of graphs, a predefined dataset name, or a file name of a dataset.') + if remove_null_graphs: + self.trim_dataset(edge_required=False) def load_dataset(self, filename, filename_targets=None, clean_labels=True, **kwargs): @@ -537,7 +539,7 @@ class Dataset(object): def trim_dataset(self, edge_required=False): - if edge_required: + if edge_required: # @todo: there is a possibility that some node labels will be removed. trimed_pairs = [(idx, g) for idx, g in enumerate(self._graphs) if (nx.number_of_nodes(g) != 0 and nx.number_of_edges(g) != 0)] else: trimed_pairs = [(idx, g) for idx, g in enumerate(self._graphs) if nx.number_of_nodes(g) != 0] From 62145db2072f0602bb1fe3df3c7364d043242ad1 Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Sun, 3 Jan 2021 20:44:01 +0100 Subject: [PATCH 08/24] [exp] fcsp: add program for slurm and the exps for space complexity. --- .../thesis/graph_kernels/fcsp/compare_fcsp.py | 101 +++-- .../graph_kernels/fcsp/compare_fcsp_space.py | 98 +++++ .../graph_kernels/fcsp/run_jobs_compare_fcsp.py | 121 +++++- .../fcsp/run_jobs_compare_fcsp_space.py | 225 +++++++++++ .../thesis/graph_kernels/fcsp/shortest_path.py | 253 ++++++++++++ .../thesis/graph_kernels/fcsp/structural_sp.py | 439 +++++++++++++++++++++ 6 files changed, 1190 insertions(+), 47 deletions(-) create mode 100644 gklearn/experiments/thesis/graph_kernels/fcsp/compare_fcsp_space.py create mode 100644 gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py create mode 100644 gklearn/experiments/thesis/graph_kernels/fcsp/shortest_path.py create mode 100644 gklearn/experiments/thesis/graph_kernels/fcsp/structural_sp.py diff --git a/gklearn/experiments/thesis/graph_kernels/fcsp/compare_fcsp.py b/gklearn/experiments/thesis/graph_kernels/fcsp/compare_fcsp.py index 76e41b7..9a91b27 100644 --- a/gklearn/experiments/thesis/graph_kernels/fcsp/compare_fcsp.py +++ b/gklearn/experiments/thesis/graph_kernels/fcsp/compare_fcsp.py @@ -10,6 +10,7 @@ This script compares the results with and without FCSP. from gklearn.dataset import Dataset from gklearn.utils import get_graph_kernel_by_name from gklearn.utils.kernels import deltakernel, gaussiankernel, kernelproduct +from gklearn.experiments import DATASET_ROOT import functools import os import pickle @@ -17,50 +18,77 @@ import sys import logging -def run_all(fcsp): - save_dir = 'outputs/' + ('fscp' if fcsp == True else 'naive') + '/' - os.makedirs(save_dir, exist_ok=True) +# def run_all(fcsp): + +# from sklearn.model_selection import ParameterGrid + +# Dataset_List = ['Alkane_unlabeled', 'Alkane', 'Acyclic', 'MAO_lite', 'MAO', +# 'PAH_unlabeled', 'PAH', 'MUTAG', 'Monoterpens', +# 'Letter-high', 'Letter-med', 'Letter-low', +# 'ENZYMES', 'AIDS', 'NCI1', 'NCI109', 'DD', +# 'BZR', 'COX2', 'DHFR', 'PTC_FM', 'PTC_FR', 'PTC_MM', 'PTC_MR', +# 'Cuneiform', 'KKI', 'OHSU', 'Peking_1', 'SYNTHETICnew', +# 'Synthie', 'SYNTHETIC', 'Fingerprint', 'IMDB-BINARY', +# 'IMDB-MULTI', 'COIL-DEL', 'PROTEINS', 'PROTEINS_full', +# 'Mutagenicity', 'REDDIT-BINARY'] + +# Kernel_List = ['ShortestPath', 'StructuralSP'] + +# task_grid = ParameterGrid({'kernel': Kernel_List[:], 'dataset': Dataset_List[:]}) + +# for task in list(task_grid): - from sklearn.model_selection import ParameterGrid +# save_file_suffix = '.' + task['kernel'] + '.' + task['dataset'] +# file_name = os.path.join(save_dir, 'run_time' + save_file_suffix + '.pkl') +# if not os.path.isfile(file_name): +# print() +# print((task['kernel'], task['dataset'])) - Dataset_List = ['Alkane_unlabeled', 'Alkane', 'Acyclic', 'MAO_lite', 'MAO', - 'PAH_unlabeled', 'PAH', 'MUTAG', 'Letter-high', 'Letter-med', 'Letter-low', - 'ENZYMES', 'AIDS', 'NCI1', 'NCI109', 'DD', - 'BZR', 'COX2', 'DHFR', 'PTC_FM', 'PTC_FR', 'PTC_MM', 'PTC_MR', - 'Cuneiform', 'KKI', 'OHSU', 'Peking_1', 'SYNTHETICnew', - 'Synthie', 'SYNTHETIC', 'Fingerprint', 'IMDB-BINARY', - 'IMDB-MULTI', 'COIL-DEL', 'PROTEINS', 'PROTEINS_full', - 'Mutagenicity', 'REDDIT-BINARY'] +# try: +# gram_matrix, run_time = compute(task['kernel'], task['dataset'], fcsp) - Kernel_List = ['ShortestPath', 'StructuralSP'] +# except Exception as exp: +# print('An exception occured when running this experiment:') +# LOG_FILENAME = save_dir + 'error.txt' +# logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG) +# logging.exception('\n--------------' + save_file_suffix + '------------------') +# print(repr(exp)) +# else: +# save_file_suffix = '.' + task['kernel'] + task['dataset'] - work_grid = ParameterGrid({'kernel': Kernel_List[:], 'dataset': Dataset_List[:]}) +# with open(file_name, 'wb') as f: +# pickle.dump(run_time, f) - for work in list(work_grid): - save_file_suffix = '.' + work['kernel'] + '.' + work['dataset'] - file_name = os.path.join(save_dir, 'run_time' + save_file_suffix + '.pkl') - if not os.path.isfile(file_name): - print() - print((work['kernel'], work['dataset'])) - try: - gram_matrix, run_time = run_work(work['kernel'], work['dataset'], fcsp) - except Exception as exp: - print('An exception occured when running this experiment:') - LOG_FILENAME = save_dir + 'error.txt' - logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG) - logging.exception(save_file_suffix) - print(repr(exp)) +def run_task(kernel_name, ds_name, fcsp): + save_file_suffix = '.' + kernel_name + '.' + ds_name + '.' + str(fcsp) + file_name = os.path.join(save_dir, 'run_time' + save_file_suffix + '.pkl') - save_file_suffix = '.' + work['kernel'] + work['dataset'] + if not os.path.isfile(file_name): + print() + print((kernel_name, ds_name, str(fcsp))) + try: + gram_matrix, run_time = compute(kernel_name, ds_name, fcsp) + + except Exception as exp: + print('An exception occured when running this experiment:') + LOG_FILENAME = os.path.join(save_dir, 'error' + save_file_suffix + '.txt') + logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG) + logging.exception('\n--------------' + save_file_suffix + '------------------') + print(repr(exp)) + + else: with open(file_name, 'wb') as f: pickle.dump(run_time, f) -def run_work(kernel_name, ds_name, fcsp): - dataset = Dataset(ds_name, verbose=True) +def compute(kernel_name, ds_name, fcsp): + dataset = Dataset(ds_name, root=DATASET_ROOT, verbose=True) + if kernel_name == 'ShortestPath': + dataset.trim_dataset(edge_required=True) + mixkernel = functools.partial(kernelproduct, deltakernel, gaussiankernel) node_kernels = {'symb': deltakernel, 'nsymb': gaussiankernel, 'mix': mixkernel} @@ -87,8 +115,15 @@ def run_work(kernel_name, ds_name, fcsp): if __name__ == '__main__': if len(sys.argv) > 1: - fcsp = True if sys.argv[1] == 'True' else False + kernel_name = sys.argv[1] + ds_name = sys.argv[2] + fcsp = True if sys.argv[3] == 'True' else False else: + kernel_name = 'ShortestPath' + ds_name = 'Acyclic' fcsp = True - run_all(fcsp) + save_dir = 'outputs/' + os.makedirs(save_dir, exist_ok=True) + + run_task(kernel_name, ds_name, fcsp) \ No newline at end of file diff --git a/gklearn/experiments/thesis/graph_kernels/fcsp/compare_fcsp_space.py b/gklearn/experiments/thesis/graph_kernels/fcsp/compare_fcsp_space.py new file mode 100644 index 0000000..3beacfd --- /dev/null +++ b/gklearn/experiments/thesis/graph_kernels/fcsp/compare_fcsp_space.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Wed Dec 2 17:41:54 2020 + +@author: ljia + +This script compares the results with and without FCSP. +""" +from gklearn.dataset import Dataset +from shortest_path import SPSpace +from structural_sp import SSPSpace +from gklearn.utils.kernels import deltakernel, gaussiankernel, kernelproduct +from gklearn.experiments import DATASET_ROOT +import functools +import os +import pickle +import sys +import logging + + +def run_task(kernel_name, ds_name, fcsp): + save_file_suffix = '.' + kernel_name + '.' + ds_name + '.' + str(fcsp) + file_name = os.path.join(save_dir, 'space' + save_file_suffix + '.pkl') + + # Return if the task is already completed. + if os.path.isfile(file_name): + with open(file_name, 'rb') as f: + data = pickle.load(f) + if data['completed']: + return + + print() + print((kernel_name, ds_name, str(fcsp))) + + try: + gram_matrix, run_time = compute(kernel_name, ds_name, fcsp, file_name) + + except Exception as exp: + print('An exception occured when running this experiment:') + LOG_FILENAME = os.path.join(save_dir, 'error.space' + save_file_suffix + '.txt') + logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG) + logging.exception('\n--------------' + save_file_suffix + '------------------') + print(repr(exp)) + +# else: +# with open(file_name, 'wb') as f: +# pickle.dump(run_time, f) + + +def compute(kernel_name, ds_name, fcsp, file_name): + dataset = Dataset(ds_name, root=DATASET_ROOT, verbose=True) + if kernel_name == 'ShortestPath': + dataset.trim_dataset(edge_required=True) +# dataset.cut_graphs(range(0, 10)) + kernel_class = SPSpace + else: +# dataset.cut_graphs(range(0, 10)) + kernel_class = SSPSpace + + mixkernel = functools.partial(kernelproduct, deltakernel, gaussiankernel) + node_kernels = {'symb': deltakernel, 'nsymb': gaussiankernel, 'mix': mixkernel} + edge_kernels = {'symb': deltakernel, 'nsymb': gaussiankernel, 'mix': mixkernel} + + graph_kernel = kernel_class(name=kernel_name, + node_labels=dataset.node_labels, + edge_labels=dataset.edge_labels, + node_attrs=dataset.node_attrs, + edge_attrs=dataset.edge_attrs, + ds_infos=dataset.get_dataset_infos(keys=['directed']), + fcsp=fcsp, + compute_method='naive', + node_kernels=node_kernels, + edge_kernels=edge_kernels, + file_name=file_name + ) + gram_matrix, run_time = graph_kernel.compute(dataset.graphs, + parallel=None, + normalize=False, + verbose=2 + ) + return gram_matrix, run_time + + +if __name__ == '__main__': + if len(sys.argv) > 1: + kernel_name = sys.argv[1] + ds_name = sys.argv[2] + fcsp = True if sys.argv[3] == 'True' else False + else: + kernel_name = 'StructuralSP' + ds_name = 'Fingerprint' + fcsp = True + + save_dir = 'outputs/' + os.makedirs(save_dir, exist_ok=True) + + run_task(kernel_name, ds_name, fcsp) \ No newline at end of file diff --git a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py index 53ae39c..b241c22 100644 --- a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py +++ b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py @@ -10,27 +10,60 @@ import os import re -def get_job_script(param): +OUT_TIME_LIST = [('ShortestPath', 'ENZYMES', 'False'), + ('StructuralSP', 'ENZYMES', 'True'), + ('StructuralSP', 'ENZYMES', 'False'), + ('StructuralSP', 'AIDS', 'False'), + ('ShortestPath', 'NCI1', 'False'), + ('StructuralSP', 'NCI1', 'True'), + ('StructuralSP', 'NCI1', 'False'), + ('ShortestPath', 'NCI109', 'False'), + ('StructuralSP', 'NCI109', 'True'), + ('StructuralSP', 'NCI109', 'False'), + ('ShortestPath', 'DD', 'True'), + ('ShortestPath', 'DD', 'False'), + ('StructuralSP', 'BZR', 'False'), + ('ShortestPath', 'COX2', 'False'), + ('StructuralSP', 'COX2', 'False'), + ('ShortestPath', 'DHFR', 'False'), + ] + +OUT_MEM_LIST = [('StructuralSP', 'PROTEINS', 'True'), + ('StructuralSP', 'PROTEINS', 'False'), + ('StructuralSP', 'PROTEINS_full', 'True'), + ('StructuralSP', 'PROTEINS_full', 'False'), + ('ShortestPath', 'REDDIT-BINARY', 'True'), + ] + +MISS_LABEL_LIST = [('StructuralSP', 'GREC', 'True'), + ('StructuralSP', 'GREC', 'False'), + ('StructuralSP', 'Web', 'True'), + ('StructuralSP', 'Web', 'False'), + ] + + +def get_job_script(kernel, dataset, fcsp): script = r""" #!/bin/bash #SBATCH --exclusive -#SBATCH --job-name="fcsp.""" + param + r"""" -#SBATCH --partition=long +#SBATCH --job-name="fcsp.""" + kernel + r"." + dataset + r"." + fcsp + r"""" +#SBATCH --partition=tlong #SBATCH --mail-type=ALL #SBATCH --mail-user=jajupmochi@gmail.com -#SBATCH --output="outputs/output_fcsp.""" + param + r""".txt" -#SBATCH --error="errors/error_fcsp.""" + param + r""".txt" +#SBATCH --output="outputs/output_fcsp.""" + kernel + r"." + dataset + r"." + fcsp + r""".txt" +#SBATCH --error="errors/error_fcsp.""" + kernel + r"." + dataset + r"." + fcsp + r""".txt" # #SBATCH --ntasks=1 #SBATCH --nodes=1 #SBATCH --cpus-per-task=1 -#SBATCH --time=100:00:00 -#SBATCH --mem-per-cpu=4000 +#SBATCH --time=300:00:00 +##SBATCH --mem-per-cpu=4000 +#SBATCH --mem=40000 srun hostname srun cd /home/2019015/ljia02/graphkit-learn/gklearn/experiments/thesis/graph_kernels/fcsp -srun python3 compare_fcsp.py """ + param +srun python3 compare_fcsp.py """ + kernel + r" " + dataset + r" " + fcsp script = script.strip() script = re.sub('\n\t+', '\n', script) script = re.sub('\n +', '\n', script) @@ -38,15 +71,75 @@ srun python3 compare_fcsp.py """ + param return script +def check_task_status(save_dir, *params): + str_task_id = '.' + '.'.join(params) + + # Check if the task is in out of memeory or out of space lists or missing labels. + if params in OUT_MEM_LIST or params in OUT_TIME_LIST or params in MISS_LABEL_LIST: + return True + + # Check if the task is running or in queue of slurm. + command = 'squeue --user ljia02 --name "fcsp' + str_task_id + '" --format "%.2t" --noheader' + stream = os.popen(command) + output = stream.readlines() + if len(output) > 0: + return True + + # Check if the results are already computed. + file_name = os.path.join(save_dir, 'run_time' + str_task_id + '.pkl') + if os.path.isfile(file_name): + return True + + return False + + if __name__ == '__main__': + save_dir = 'outputs/' + os.makedirs(save_dir, exist_ok=True) os.makedirs('outputs/', exist_ok=True) os.makedirs('errors/', exist_ok=True) - param_list = ['True', 'False'] - for param in param_list[:]: - job_script = get_job_script(param) - command = 'sbatch < 0: + return True + + # Check if the task is already computed. + file_name = os.path.join(save_dir, 'space' + str_task_id + '.pkl') + if os.path.isfile(file_name): + with open(file_name, 'rb') as f: + data = pickle.load(f) + if data['completed']: + return True + + return False + + +if __name__ == '__main__': + save_dir = 'outputs/' + os.makedirs(save_dir, exist_ok=True) + os.makedirs('outputs/', exist_ok=True) + os.makedirs('errors/', exist_ok=True) + + from sklearn.model_selection import ParameterGrid + + Dataset_List = ['Alkane_unlabeled', 'Alkane', 'Acyclic', 'MAO_lite', 'MAO', + 'PAH_unlabeled', 'PAH', 'MUTAG', 'Monoterpens', + 'Letter-high', 'Letter-med', 'Letter-low', + 'ENZYMES', 'AIDS', 'NCI1', 'NCI109', 'DD', + # new: not so large. + 'PTC_FM', 'PTC_FR', 'PTC_MM', 'PTC_MR', 'Chiral', 'Vitamin_D', + 'ACE', 'Steroid', 'KKI', 'Fingerprint', 'IMDB-BINARY', + 'IMDB-MULTI', 'Peking_1', 'Cuneiform', 'OHSU', 'BZR', 'COX2', + 'DHFR', 'SYNTHETICnew', 'Synthie', 'SYNTHETIC', + # new: large. + 'TWITTER-Real-Graph-Partial', 'GREC', 'Web', 'MCF-7', + 'MCF-7H', 'MOLT-4', 'MOLT-4H', 'NCI-H23', 'NCI-H23H', + 'OVCAR-8', 'OVCAR-8H', 'P388', 'P388H', 'PC-3', 'PC-3H', + 'SF-295', 'SF-295H', 'SN12C', 'SN12CH', 'SW-620', 'SW-620H', + 'TRIANGLES', 'UACC257', 'UACC257H', 'Yeast', 'YeastH', + 'COLORS-3', 'DBLP_v1', 'REDDIT-MULTI-12K', + 'REDDIT-MULTI-12K', 'REDDIT-MULTI-12K', + 'REDDIT-MULTI-12K', 'MSRC_9', 'MSRC_21', 'MSRC_21C', + 'COLLAB', 'COIL-DEL', + 'COIL-RAG', 'PROTEINS', 'PROTEINS_full', 'Mutagenicity', + 'REDDIT-BINARY', 'FRANKENSTEIN', 'REDDIT-MULTI-5K', + 'REDDIT-MULTI-12K'] + + Kernel_List = ['ShortestPath', 'StructuralSP'] + + fcsp_list = ['True', 'False'] + + task_grid = ParameterGrid({'kernel': Kernel_List[:], + 'dataset': Dataset_List[:], + 'fcsp': fcsp_list[:]}) + + from tqdm import tqdm + + for task in tqdm(list(task_grid), desc='submitting tasks/jobs'): + + if False == check_task_status(save_dir, task['kernel'], task['dataset'], task['fcsp']): + job_script = get_job_script(task['kernel'], task['dataset'], task['fcsp']) + command = 'sbatch < 0: + results['vk_dict_mem'] = np.mean(results['vk_dict_mem']) + save_results(file_name, results) + + +class SPSpace(ShortestPath): + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self._file_name = kwargs.get('file_name') + +# @profile + def _compute_gm_series(self): + self._all_graphs_have_edges(self._graphs) + # get shortest path graph of each graph. + iterator = get_iters(self._graphs, desc='getting sp graphs', file=sys.stdout, verbose=(self._verbose >= 2)) + self._graphs = [getSPGraph(g, edge_weight=self._edge_weight) for g in iterator] + + + results = load_results(self._file_name, self._fcsp) + + # compute Gram matrix. + gram_matrix = np.zeros((len(self._graphs), len(self._graphs))) + + from itertools import combinations_with_replacement + itr = combinations_with_replacement(range(0, len(self._graphs)), 2) + len_itr = int(len(self._graphs) * (len(self._graphs) + 1) / 2) + iterator = get_iters(itr, desc='Computing kernels', + length=len_itr, file=sys.stdout,verbose=(self._verbose >= 2)) + + time0 = time.time() + for i, j in iterator: + if i > results['i'] or (i == results['i'] and j > results['j']): + data = self._sp_do_space(self._graphs[i], self._graphs[j]) + if self._fcsp: + results['nb_comparison'].append(data[0]) + if data[1] != {}: + results['vk_dict_mem'].append(estimate_vk_memory(data[1], + nx.number_of_nodes(self._graphs[i]), + nx.number_of_nodes(self._graphs[j]))) + else: + results['nb_comparison'].append(data) + results['i'] = i + results['j'] = j + + time1 = time.time() + if time1 - time0 > 600: + save_results(self._file_name, results) + time0 = time1 + + compute_stats(self._file_name, results) + + return gram_matrix + + + def _sp_do_space(self, g1, g2): + + if self._fcsp: # @todo: it may be put outside the _sp_do(). + return self._sp_do_fcsp(g1, g2) + else: + return self._sp_do_naive(g1, g2) + + + def _sp_do_fcsp(self, g1, g2): + + nb_comparison = 0 + + # compute shortest path matrices first, method borrowed from FCSP. + vk_dict = {} # shortest path matrices dict + if len(self._node_labels) > 0: # @todo: it may be put outside the _sp_do(). + # node symb and non-synb labeled + if len(self._node_attrs) > 0: + kn = self._node_kernels['mix'] + for n1, n2 in product( + g1.nodes(data=True), g2.nodes(data=True)): + n1_labels = [n1[1][nl] for nl in self._node_labels] + n2_labels = [n2[1][nl] for nl in self._node_labels] + n1_attrs = [n1[1][na] for na in self._node_attrs] + n2_attrs = [n2[1][na] for na in self._node_attrs] + vk_dict[(n1[0], n2[0])] = kn(n1_labels, n2_labels, n1_attrs, n2_attrs) + nb_comparison += 1 + # node symb labeled + else: + kn = self._node_kernels['symb'] + for n1 in g1.nodes(data=True): + for n2 in g2.nodes(data=True): + n1_labels = [n1[1][nl] for nl in self._node_labels] + n2_labels = [n2[1][nl] for nl in self._node_labels] + vk_dict[(n1[0], n2[0])] = kn(n1_labels, n2_labels) + nb_comparison += 1 + else: + # node non-synb labeled + if len(self._node_attrs) > 0: + kn = self._node_kernels['nsymb'] + for n1 in g1.nodes(data=True): + for n2 in g2.nodes(data=True): + n1_attrs = [n1[1][na] for na in self._node_attrs] + n2_attrs = [n2[1][na] for na in self._node_attrs] + vk_dict[(n1[0], n2[0])] = kn(n1_attrs, n2_attrs) + nb_comparison += 1 + # node unlabeled + else: + for e1, e2 in product( + g1.edges(data=True), g2.edges(data=True)): + pass +# if e1[2]['cost'] == e2[2]['cost']: +# kernel += 1 +# nb_comparison += 1 + + return nb_comparison, vk_dict + +# # compute graph kernels +# if self._ds_infos['directed']: +# for e1, e2 in product(g1.edges(data=True), g2.edges(data=True)): +# if e1[2]['cost'] == e2[2]['cost']: +# nk11, nk22 = vk_dict[(e1[0], e2[0])], vk_dict[(e1[1], e2[1])] +# kn1 = nk11 * nk22 +# kernel += kn1 +# else: +# for e1, e2 in product(g1.edges(data=True), g2.edges(data=True)): +# if e1[2]['cost'] == e2[2]['cost']: +# # each edge walk is counted twice, starting from both its extreme nodes. +# nk11, nk12, nk21, nk22 = vk_dict[(e1[0], e2[0])], vk_dict[( +# e1[0], e2[1])], vk_dict[(e1[1], e2[0])], vk_dict[(e1[1], e2[1])] +# kn1 = nk11 * nk22 +# kn2 = nk12 * nk21 +# kernel += kn1 + kn2 + + + def _sp_do_naive(self, g1, g2): + + nb_comparison = 0 + + # Define the function to compute kernels between vertices in each condition. + if len(self._node_labels) > 0: + # node symb and non-synb labeled + if len(self._node_attrs) > 0: + def compute_vk(n1, n2): + kn = self._node_kernels['mix'] + n1_labels = [g1.nodes[n1][nl] for nl in self._node_labels] + n2_labels = [g2.nodes[n2][nl] for nl in self._node_labels] + n1_attrs = [g1.nodes[n1][na] for na in self._node_attrs] + n2_attrs = [g2.nodes[n2][na] for na in self._node_attrs] + return kn(n1_labels, n2_labels, n1_attrs, n2_attrs) + # node symb labeled + else: + def compute_vk(n1, n2): + kn = self._node_kernels['symb'] + n1_labels = [g1.nodes[n1][nl] for nl in self._node_labels] + n2_labels = [g2.nodes[n2][nl] for nl in self._node_labels] + return kn(n1_labels, n2_labels) + else: + # node non-synb labeled + if len(self._node_attrs) > 0: + def compute_vk(n1, n2): + kn = self._node_kernels['nsymb'] + n1_attrs = [g1.nodes[n1][na] for na in self._node_attrs] + n2_attrs = [g2.nodes[n2][na] for na in self._node_attrs] + return kn(n1_attrs, n2_attrs) + # node unlabeled + else: +# for e1, e2 in product(g1.edges(data=True), g2.edges(data=True)): +# if e1[2]['cost'] == e2[2]['cost']: +# kernel += 1 + return 0 + + # compute graph kernels + if self._ds_infos['directed']: + for e1, e2 in product(g1.edges(data=True), g2.edges(data=True)): + if e1[2]['cost'] == e2[2]['cost']: +# nk11, nk22 = compute_vk(e1[0], e2[0]), compute_vk(e1[1], e2[1]) +# kn1 = nk11 * nk22 +# kernel += kn1 + nb_comparison += 2 + else: + for e1, e2 in product(g1.edges(data=True), g2.edges(data=True)): + if e1[2]['cost'] == e2[2]['cost']: + # each edge walk is counted twice, starting from both its extreme nodes. +# nk11, nk12, nk21, nk22 = compute_vk(e1[0], e2[0]), compute_vk( +# e1[0], e2[1]), compute_vk(e1[1], e2[0]), compute_vk(e1[1], e2[1]) +# kn1 = nk11 * nk22 +# kn2 = nk12 * nk21 +# kernel += kn1 + kn2 + nb_comparison += 4 + + return nb_comparison \ No newline at end of file diff --git a/gklearn/experiments/thesis/graph_kernels/fcsp/structural_sp.py b/gklearn/experiments/thesis/graph_kernels/fcsp/structural_sp.py new file mode 100644 index 0000000..7f5b721 --- /dev/null +++ b/gklearn/experiments/thesis/graph_kernels/fcsp/structural_sp.py @@ -0,0 +1,439 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Mon Mar 30 11:59:57 2020 + +@author: ljia + +@references: + + [1] Suard F, Rakotomamonjy A, Bensrhair A. Kernel on Bag of Paths For + Measuring Similarity of Shapes. InESANN 2007 Apr 25 (pp. 355-360). +""" +import sys +from itertools import product +from gklearn.utils import get_iters +import numpy as np +import time +import os, errno +import pickle +from pympler import asizeof +import networkx as nx +from gklearn.utils.utils import get_shortest_paths +from gklearn.kernels import StructuralSP + + +def load_splist(file_name): + if os.path.isfile(file_name): + with open(file_name, 'rb') as f: + return pickle.load(f) + else: + results_path = {'splist': [], 'i': -1, 'completed': False} + return results_path + + +def load_results(file_name, fcsp): + if os.path.isfile(file_name): + with open(file_name, 'rb') as f: + return pickle.load(f) + else: + results = {'nb_v_comparison': [], 'nb_e_comparison': [], 'i': -1, 'j': -1, 'completed': False} + if fcsp: + results['vk_dict_mem'] = [] + results['ek_dict_mem'] = [] + return results + + +def save_results(file_name, results): + with open(file_name, 'wb') as f: + pickle.dump(results, f) + + +def estimate_vk_memory(obj, nb_nodes1, nb_nodes2): +# asizeof.asized(obj, detail=1).format() +# return asizeof.asizeof(obj) + key, val = next(iter(obj.items())) +# key = dict.iterkeys().next() +# key_mem = asizeof.asizeof(key) + dict_flat = sys.getsizeof(obj) + key_mem = 64 + + if isinstance(val, float): + val_mem = 24 + mem = (key_mem + val_mem) * len(obj) + dict_flat + 28 * (nb_nodes1 + nb_nodes2) + else: # value is True or False + mem = (key_mem) * len(obj) + dict_flat + 52 + 28 * (nb_nodes1 + nb_nodes2) + +# print(mem, asizeof.asizeof(obj), '\n', asizeof.asized(obj, detail=3).format(), '\n') + return mem + + +def estimate_ek_memory(obj, nb_nodes1, nb_nodes2): +# asizeof.asized(obj, detail=1).format() +# return asizeof.asizeof(obj) + key, val = next(iter(obj.items())) +# key = dict.iterkeys().next() +# key_mem = asizeof.asizeof(key) + dict_flat = sys.getsizeof(obj) + key_mem = 192 + + if isinstance(val, float): + val_mem = 24 + mem = (key_mem + val_mem) * len(obj) + dict_flat + 28 * (nb_nodes1 + nb_nodes2) + else: # value is True or False + mem = (key_mem) * len(obj) + dict_flat + 52 + 28 * (nb_nodes1 + nb_nodes2) + +# print(mem, asizeof.asizeof(obj), '\n', asizeof.asized(obj, detail=3).format(), '\n') + return mem + + +def compute_stats(file_name, results, splist): + del results['i'] + del results['j'] + results['nb_v_comparison'] = np.mean(results['nb_v_comparison']) +# if len(results['nb_e_comparison']) > 0: + results['nb_e_comparison'] = np.mean(results['nb_e_comparison']) + results['completed'] = True + if 'vk_dict_mem' in results and len(results['vk_dict_mem']) > 0: + results['vk_dict_mem'] = np.mean(results['vk_dict_mem']) + if 'ek_dict_mem' in results and len(results['ek_dict_mem']) > 0: + results['ek_dict_mem'] = np.mean(results['ek_dict_mem']) + results['nb_sp_ave'] = np.mean([len(ps) for ps in splist]) + results['sp_len_ave'] = np.mean([np.mean([len(p) for p in ps]) for ps in splist]) + results['sp_mem_all'] = asizeof.asizeof(splist) + save_results(file_name, results) + + +class SSPSpace(StructuralSP): + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self._file_name = kwargs.get('file_name') + +# @profile + def _compute_gm_series(self): + # get shortest paths of each graph in the graphs. + fn_paths = os.path.splitext(self._file_name)[0] + '.paths.pkl' + results_path = load_splist(fn_paths) + + if not results_path['completed']: + + iterator = get_iters(self._graphs, desc='getting sp graphs', file=sys.stdout, verbose=(self._verbose >= 2)) + if self._compute_method == 'trie': + for g in iterator: + splist.append(self._get_sps_as_trie(g)) + else: + time0 = time.time() + for i, g in enumerate(iterator): + if i > results_path['i']: + results_path['splist'].append(get_shortest_paths(g, self._edge_weight, self._ds_infos['directed'])) + results_path['i'] = i + + time1 = time.time() + if time1 - time0 > 600: + save_results(fn_paths, results_path) + time0 = time1 + + del results_path['i'] + results_path['completed'] = True + save_results(fn_paths, results_path) + + ######### + splist = results_path['splist'] + results = load_results(self._file_name, self._fcsp) + + # compute Gram matrix. + gram_matrix = np.zeros((len(self._graphs), len(self._graphs))) + + from itertools import combinations_with_replacement + itr = combinations_with_replacement(range(0, len(self._graphs)), 2) + len_itr = int(len(self._graphs) * (len(self._graphs) + 1) / 2) + iterator = get_iters(itr, desc='Computing kernels', file=sys.stdout, + length=len_itr, verbose=(self._verbose >= 2)) + if self._compute_method == 'trie': + for i, j in iterator: + kernel = self._ssp_do_trie(self._graphs[i], self._graphs[j], splist[i], splist[j]) + gram_matrix[i][j] = kernel + gram_matrix[j][i] = kernel + else: + time0 = time.time() + for i, j in iterator: + if i > results['i'] or (i == results['i'] and j > results['j']): + data = self._ssp_do_naive_space(self._graphs[i], self._graphs[j], splist[i], splist[j]) + results['nb_v_comparison'].append(data[0]) + results['nb_e_comparison'].append(data[1]) + if self._fcsp: + if data[2] != {}: + results['vk_dict_mem'].append(estimate_vk_memory(data[2], + nx.number_of_nodes(self._graphs[i]), + nx.number_of_nodes(self._graphs[j]))) + if data[3] != {}: + results['ek_dict_mem'].append(estimate_ek_memory(data[3], + nx.number_of_nodes(self._graphs[i]), + nx.number_of_nodes(self._graphs[j]))) + results['i'] = i + results['j'] = j + + time1 = time.time() + if time1 - time0 > 600: + save_results(self._file_name, results) + time0 = time1 + + compute_stats(self._file_name, results, splist) + # @todo: may not remove the path file if the program stops exactly here. + try: + os.remove(fn_paths) + except OSError as e: + if e.errno != errno.ENOENT: + raise + + return gram_matrix + + + def _ssp_do_naive_space(self, g1, g2, spl1, spl2): + if self._fcsp: # @todo: it may be put outside the _sp_do(). + return self._sp_do_naive_fcsp(g1, g2, spl1, spl2) + else: + return self._sp_do_naive_naive(g1, g2, spl1, spl2) + + + def _sp_do_naive_fcsp(self, g1, g2, spl1, spl2): + + # First, compute shortest path matrices, method borrowed from FCSP. + vk_dict, nb_v_comparison = self._get_all_node_kernels(g1, g2) + # Then, compute kernels between all pairs of edges, which is an idea of + # extension of FCSP. It suits sparse graphs, which is the most case we + # went though. For dense graphs, this would be slow. + ek_dict, nb_e_comparison = self._get_all_edge_kernels(g1, g2) + + return nb_v_comparison, nb_e_comparison, vk_dict, ek_dict + + + def _sp_do_naive_naive(self, g1, g2, spl1, spl2): + + nb_v_comparison = 0 + nb_e_comparison = 0 + + # Define the function to compute kernels between vertices in each condition. + if len(self._node_labels) > 0: + # node symb and non-synb labeled + if len(self._node_attrs) > 0: + def compute_vk(n1, n2): + kn = self._node_kernels['mix'] + n1_labels = [g1.nodes[n1][nl] for nl in self._node_labels] + n2_labels = [g2.nodes[n2][nl] for nl in self._node_labels] + n1_attrs = [g1.nodes[n1][na] for na in self._node_attrs] + n2_attrs = [g2.nodes[n2][na] for na in self._node_attrs] + return kn(n1_labels, n2_labels, n1_attrs, n2_attrs) + # node symb labeled + else: + def compute_vk(n1, n2): + kn = self._node_kernels['symb'] + n1_labels = [g1.nodes[n1][nl] for nl in self._node_labels] + n2_labels = [g2.nodes[n2][nl] for nl in self._node_labels] + return kn(n1_labels, n2_labels) + else: + # node non-synb labeled + if len(self._node_attrs) > 0: + def compute_vk(n1, n2): + kn = self._node_kernels['nsymb'] + n1_attrs = [g1.nodes[n1][na] for na in self._node_attrs] + n2_attrs = [g2.nodes[n2][na] for na in self._node_attrs] + return kn(n1_attrs, n2_attrs) +# # node unlabeled +# else: +# for e1, e2 in product(g1.edges(data=True), g2.edges(data=True)): +# if e1[2]['cost'] == e2[2]['cost']: +# kernel += 1 +# return kernel + + # Define the function to compute kernels between edges in each condition. + if len(self._edge_labels) > 0: + # edge symb and non-synb labeled + if len(self._edge_attrs) > 0: + def compute_ek(e1, e2): + ke = self._edge_kernels['mix'] + e1_labels = [g1.edges[e1][el] for el in self._edge_labels] + e2_labels = [g2.edges[e2][el] for el in self._edge_labels] + e1_attrs = [g1.edges[e1][ea] for ea in self._edge_attrs] + e2_attrs = [g2.edges[e2][ea] for ea in self._edge_attrs] + return ke(e1_labels, e2_labels, e1_attrs, e2_attrs) + # edge symb labeled + else: + def compute_ek(e1, e2): + ke = self._edge_kernels['symb'] + e1_labels = [g1.edges[e1][el] for el in self._edge_labels] + e2_labels = [g2.edges[e2][el] for el in self._edge_labels] + return ke(e1_labels, e2_labels) + else: + # edge non-synb labeled + if len(self._edge_attrs) > 0: + def compute_ek(e1, e2): + ke = self._edge_kernels['nsymb'] + e1_attrs = [g1.edges[e1][ea] for ea in self._edge_attrs] + e2_attrs = [g2.edges[e2][ea] for ea in self._edge_attrs] + return ke(e1_attrs, e2_attrs) + + + # compute graph kernels + if len(self._node_labels) > 0 or len(self._node_attrs) > 0: + if len(self._edge_labels) > 0 or len(self._edge_attrs) > 0: + for p1, p2 in product(spl1, spl2): + if len(p1) == len(p2): +# nb_v_comparison = len(p1) +# nb_e_comparison = len(p1) - 1 + kpath = compute_vk(p1[0], p2[0]) + nb_v_comparison += 1 + if kpath: + for idx in range(1, len(p1)): + kpath *= compute_vk(p1[idx], p2[idx]) * \ + compute_ek((p1[idx-1], p1[idx]), + (p2[idx-1], p2[idx])) + nb_v_comparison += 1 + nb_e_comparison += 1 + if not kpath: + break +# kernel += kpath # add up kernels of all paths + else: + for p1, p2 in product(spl1, spl2): + if len(p1) == len(p2): + kpath = compute_vk(p1[0], p2[0]) + nb_v_comparison += 1 + if kpath: + for idx in range(1, len(p1)): + kpath *= compute_vk(p1[idx], p2[idx]) + nb_v_comparison += 1 + if not kpath: + break +# kernel += kpath # add up kernels of all paths + else: + if len(self._edge_labels) > 0 or len(self._edge_attrs) > 0: + for p1, p2 in product(spl1, spl2): + if len(p1) == len(p2): + if len(p1) == 0: + pass + else: + kpath = 1 + for idx in range(0, len(p1) - 1): + kpath *= compute_ek((p1[idx], p1[idx+1]), + (p2[idx], p2[idx+1])) + nb_e_comparison += 1 + if not kpath: + break + else: + pass +# for p1, p2 in product(spl1, spl2): +# if len(p1) == len(p2): +# kernel += 1 +# try: +# kernel = kernel / (len(spl1) * len(spl2)) # Compute mean average +# except ZeroDivisionError: +# print(spl1, spl2) +# print(g1.nodes(data=True)) +# print(g1.edges(data=True)) +# raise Exception + + return nb_v_comparison, nb_e_comparison + + + def _get_all_node_kernels(self, g1, g2): + nb_comparison = 0 + + vk_dict = {} # shortest path matrices dict + if len(self._node_labels) > 0: + # node symb and non-synb labeled + if len(self._node_attrs) > 0: + kn = self._node_kernels['mix'] + for n1 in g1.nodes(data=True): + for n2 in g2.nodes(data=True): + n1_labels = [n1[1][nl] for nl in self._node_labels] + n2_labels = [n2[1][nl] for nl in self._node_labels] + n1_attrs = [n1[1][na] for na in self._node_attrs] + n2_attrs = [n2[1][na] for na in self._node_attrs] + vk_dict[(n1[0], n2[0])] = kn(n1_labels, n2_labels, n1_attrs, n2_attrs) + nb_comparison += 1 + # node symb labeled + else: + kn = self._node_kernels['symb'] + for n1 in g1.nodes(data=True): + for n2 in g2.nodes(data=True): + n1_labels = [n1[1][nl] for nl in self._node_labels] + n2_labels = [n2[1][nl] for nl in self._node_labels] + vk_dict[(n1[0], n2[0])] = kn(n1_labels, n2_labels) + nb_comparison += 1 + else: + # node non-synb labeled + if len(self._node_attrs) > 0: + kn = self._node_kernels['nsymb'] + for n1 in g1.nodes(data=True): + for n2 in g2.nodes(data=True): + n1_attrs = [n1[1][na] for na in self._node_attrs] + n2_attrs = [n2[1][na] for na in self._node_attrs] + vk_dict[(n1[0], n2[0])] = kn(n1_attrs, n2_attrs) + nb_comparison += 1 + # node unlabeled + else: + pass # @todo: add edge weights. + # for e1 in g1.edges(data=True): + # for e2 in g2.edges(data=True): + # if e1[2]['cost'] == e2[2]['cost']: + # kernel += 1 + # return kernel + + return vk_dict, nb_comparison + + + def _get_all_edge_kernels(self, g1, g2): + nb_comparison = 0 + + # compute kernels between all pairs of edges, which is an idea of + # extension of FCSP. It suits sparse graphs, which is the most case we + # went though. For dense graphs, this would be slow. + ek_dict = {} # dict of edge kernels + if len(self._edge_labels) > 0: + # edge symb and non-synb labeled + if len(self._edge_attrs) > 0: + ke = self._edge_kernels['mix'] + for e1, e2 in product(g1.edges(data=True), g2.edges(data=True)): + e1_labels = [e1[2][el] for el in self._edge_labels] + e2_labels = [e2[2][el] for el in self._edge_labels] + e1_attrs = [e1[2][ea] for ea in self._edge_attrs] + e2_attrs = [e2[2][ea] for ea in self._edge_attrs] + ek_temp = ke(e1_labels, e2_labels, e1_attrs, e2_attrs) + ek_dict[((e1[0], e1[1]), (e2[0], e2[1]))] = ek_temp + ek_dict[((e1[1], e1[0]), (e2[0], e2[1]))] = ek_temp + ek_dict[((e1[0], e1[1]), (e2[1], e2[0]))] = ek_temp + ek_dict[((e1[1], e1[0]), (e2[1], e2[0]))] = ek_temp + nb_comparison += 1 + # edge symb labeled + else: + ke = self._edge_kernels['symb'] + for e1 in g1.edges(data=True): + for e2 in g2.edges(data=True): + e1_labels = [e1[2][el] for el in self._edge_labels] + e2_labels = [e2[2][el] for el in self._edge_labels] + ek_temp = ke(e1_labels, e2_labels) + ek_dict[((e1[0], e1[1]), (e2[0], e2[1]))] = ek_temp + ek_dict[((e1[1], e1[0]), (e2[0], e2[1]))] = ek_temp + ek_dict[((e1[0], e1[1]), (e2[1], e2[0]))] = ek_temp + ek_dict[((e1[1], e1[0]), (e2[1], e2[0]))] = ek_temp + nb_comparison += 1 + else: + # edge non-synb labeled + if len(self._edge_attrs) > 0: + ke = self._edge_kernels['nsymb'] + for e1 in g1.edges(data=True): + for e2 in g2.edges(data=True): + e1_attrs = [e1[2][ea] for ea in self._edge_attrs] + e2_attrs = [e2[2][ea] for ea in self._edge_attrs] + ek_temp = ke(e1_attrs, e2_attrs) + ek_dict[((e1[0], e1[1]), (e2[0], e2[1]))] = ek_temp + ek_dict[((e1[1], e1[0]), (e2[0], e2[1]))] = ek_temp + ek_dict[((e1[0], e1[1]), (e2[1], e2[0]))] = ek_temp + ek_dict[((e1[1], e1[0]), (e2[1], e2[0]))] = ek_temp + nb_comparison += 1 + # edge unlabeled + else: + pass + + return ek_dict, nb_comparison \ No newline at end of file From d61db07d587c41e1782bda682e50d5aad37c1c98 Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Sun, 3 Jan 2021 20:47:05 +0100 Subject: [PATCH 09/24] [Update] Change an excepetion output msg in DataLoader. --- gklearn/dataset/file_managers.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gklearn/dataset/file_managers.py b/gklearn/dataset/file_managers.py index 9a804f5..df00d4c 100644 --- a/gklearn/dataset/file_managers.py +++ b/gklearn/dataset/file_managers.py @@ -332,7 +332,8 @@ class DataLoader(): content_targets = ga.read().splitlines() # targets (regression) targets = [int(i) for i in content_targets] else: - raise Exception('Can not find targets file. Please make sure there is a "', ds_name, '_graph_labels.txt" or "', ds_name, '_graph_attributes.txt"', 'file in your dataset folder.') + exp_msg = 'Can not find targets file. Please make sure there is a "', ds_name, '_graph_labels.txt" or "', ds_name, '_graph_attributes.txt"', 'file in your dataset folder.' + raise Exception(exp_msg) if class_label_map is not None: targets = [class_label_map[t] for t in targets] From 0b7f281d3878fa36d7631bd4e56b16f1cd04be9a Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Sun, 3 Jan 2021 20:48:27 +0100 Subject: [PATCH 10/24] [Add] __init__.py for exps. --- gklearn/experiments/__init__.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 gklearn/experiments/__init__.py diff --git a/gklearn/experiments/__init__.py b/gklearn/experiments/__init__.py new file mode 100644 index 0000000..7564765 --- /dev/null +++ b/gklearn/experiments/__init__.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Tue Dec 15 18:22:34 2020 + +@author: ljia +""" + +import os +EXP_ROOT = os.path.dirname(os.path.realpath(__file__)) + '/' +DATASET_ROOT = os.path.dirname(os.path.realpath(__file__)) + '/datasets/' \ No newline at end of file From 743d610827d709c8b264d81e5caf520000779de8 Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Tue, 5 Jan 2021 15:13:00 +0100 Subject: [PATCH 11/24] [Update] Use get_iters istof tqdm when computing GEDs. --- gklearn/ged/util/util.py | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/gklearn/ged/util/util.py b/gklearn/ged/util/util.py index 80141e3..52aa126 100644 --- a/gklearn/ged/util/util.py +++ b/gklearn/ged/util/util.py @@ -11,9 +11,10 @@ import multiprocessing from multiprocessing import Pool from functools import partial import sys -from tqdm import tqdm +# from tqdm import tqdm import networkx as nx from gklearn.ged.env import GEDEnv +from gklearn.utils import get_iters def compute_ged(g1, g2, options): @@ -135,11 +136,7 @@ def compute_geds_cml(graphs, options={}, sort=True, parallel=False, verbose=True G_listID = listID_toshare do_partial = partial(_wrapper_compute_ged_parallel, neo_options, sort) pool = Pool(processes=n_jobs, initializer=init_worker, initargs=(graphs, ged_env, listID)) - if verbose: - iterator = tqdm(pool.imap_unordered(do_partial, itr, chunksize), - desc='computing GEDs', file=sys.stdout) - else: - iterator = pool.imap_unordered(do_partial, itr, chunksize) + iterator = get_iters(pool.imap_unordered(do_partial, itr, chunksize), desc='computing GEDs', file=sys.stdout, length=len(graphs), verbose=verbose) # iterator = pool.imap_unordered(do_partial, itr, chunksize) for i, j, dis, n_eo_tmp in iterator: idx_itr = int(len(graphs) * i + j - (i + 1) * (i + 2) / 2) @@ -155,10 +152,7 @@ def compute_geds_cml(graphs, options={}, sort=True, parallel=False, verbose=True else: ged_vec = [] n_edit_operations = [] - if verbose: - iterator = tqdm(range(len(graphs)), desc='computing GEDs', file=sys.stdout) - else: - iterator = range(len(graphs)) + iterator = get_iters(range(len(graphs)), desc='computing GEDs', file=sys.stdout, length=len(graphs), verbose=verbose) for i in iterator: # for i in range(len(graphs)): for j in range(i + 1, len(graphs)): @@ -175,7 +169,7 @@ def compute_geds_cml(graphs, options={}, sort=True, parallel=False, verbose=True return ged_vec, ged_mat, n_edit_operations -def compute_geds(graphs, options={}, sort=True, repeats=1, parallel=False, verbose=True): +def compute_geds(graphs, options={}, sort=True, repeats=1, parallel=False, n_jobs=None, verbose=True): from gklearn.gedlib import librariesImport, gedlibpy # initialize ged env. @@ -200,7 +194,8 @@ def compute_geds(graphs, options={}, sort=True, repeats=1, parallel=False, verbo ged_vec = [0 for i in range(len_itr)] n_edit_operations = [0 for i in range(len_itr)] itr = combinations(range(0, len(graphs)), 2) - n_jobs = multiprocessing.cpu_count() + if n_jobs is None: + n_jobs = multiprocessing.cpu_count() if len_itr < 100 * n_jobs: chunksize = int(len_itr / n_jobs) + 1 else: @@ -212,11 +207,7 @@ def compute_geds(graphs, options={}, sort=True, repeats=1, parallel=False, verbo G_listID = listID_toshare do_partial = partial(_wrapper_compute_ged_parallel, neo_options, sort, repeats) pool = Pool(processes=n_jobs, initializer=init_worker, initargs=(graphs, ged_env, listID)) - if verbose: - iterator = tqdm(pool.imap_unordered(do_partial, itr, chunksize), - desc='computing GEDs', file=sys.stdout) - else: - iterator = pool.imap_unordered(do_partial, itr, chunksize) + iterator = get_iters(pool.imap_unordered(do_partial, itr, chunksize), desc='computing GEDs', file=sys.stdout, length=len(graphs), verbose=verbose) # iterator = pool.imap_unordered(do_partial, itr, chunksize) for i, j, dis, n_eo_tmp in iterator: idx_itr = int(len(graphs) * i + j - (i + 1) * (i + 2) / 2) @@ -232,10 +223,7 @@ def compute_geds(graphs, options={}, sort=True, repeats=1, parallel=False, verbo else: ged_vec = [] n_edit_operations = [] - if verbose: - iterator = tqdm(range(len(graphs)), desc='computing GEDs', file=sys.stdout) - else: - iterator = range(len(graphs)) + iterator = get_iters(range(len(graphs)), desc='computing GEDs', file=sys.stdout, length=len(graphs), verbose=verbose) for i in iterator: # for i in range(len(graphs)): for j in range(i + 1, len(graphs)): From 85c17b06c1cc82d63178ce92ab2ab123e9c1e341 Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Tue, 5 Jan 2021 15:19:25 +0100 Subject: [PATCH 12/24] [Exp] GED stability: add marker file, use edge labels in datasets, test Acyclic and Alkane. --- ... edit_costs.real_data.nums_sols.ratios.IPFP.py} | 79 ++++--- gklearn/experiments/ged/stability/group_results.py | 105 ++++++--- ..._edit_costs.real_data.nums_sols.ratios.IPFP.py} | 16 +- gklearn/experiments/ged/stability/utils.py | 249 ++++++++++++++++++++- 4 files changed, 368 insertions(+), 81 deletions(-) rename gklearn/experiments/ged/stability/{edit_costs.nums_sols.ratios.IPFP.py => edit_costs.real_data.nums_sols.ratios.IPFP.py} (72%) rename gklearn/experiments/ged/stability/{run_job_edit_costs.nums_sols.ratios.IPFP.py => run_job_edit_costs.real_data.nums_sols.ratios.IPFP.py} (62%) diff --git a/gklearn/experiments/ged/stability/edit_costs.nums_sols.ratios.IPFP.py b/gklearn/experiments/ged/stability/edit_costs.real_data.nums_sols.ratios.IPFP.py similarity index 72% rename from gklearn/experiments/ged/stability/edit_costs.nums_sols.ratios.IPFP.py rename to gklearn/experiments/ged/stability/edit_costs.real_data.nums_sols.ratios.IPFP.py index 710213a..33c6973 100644 --- a/gklearn/experiments/ged/stability/edit_costs.nums_sols.ratios.IPFP.py +++ b/gklearn/experiments/ged/stability/edit_costs.real_data.nums_sols.ratios.IPFP.py @@ -4,7 +4,7 @@ Created on Wed Oct 20 11:48:02 2020 @author: ljia -""" +""" # This script tests the influence of the ratios between node costs and edge costs on the stability of the GED computation, where the base edit costs are [1, 1, 1, 1, 1, 1]. import os @@ -13,15 +13,15 @@ import pickle import logging from gklearn.ged.util import compute_geds import time -from utils import get_dataset +from utils import get_dataset, set_edit_cost_consts import sys -from group_results import group_trials +from group_results import group_trials, check_group_existence, update_group_marker def xp_compute_ged_matrix(dataset, ds_name, num_solutions, ratio, trial): save_file_suffix = '.' + ds_name + '.num_sols_' + str(num_solutions) + '.ratio_' + "{:.2f}".format(ratio) + '.trial_' + str(trial) - + # Return if the file exists. if os.path.isfile(save_dir + 'ged_matrix' + save_file_suffix + '.pkl'): return None, None @@ -41,8 +41,11 @@ def xp_compute_ged_matrix(dataset, ds_name, num_solutions, ratio, trial): 'threads': multiprocessing.cpu_count(), 'init_option': 'EAGER_WITHOUT_SHUFFLED_COPIES' } - - edit_cost_constants = [i * ratio for i in [1, 1, 1]] + [1, 1, 1] + + edit_cost_constants = set_edit_cost_consts(ratio, + node_labeled=len(dataset.node_labels), + edge_labeled=len(dataset.edge_labels), + mode='uniform') # edit_cost_constants = [item * 0.01 for item in edit_cost_constants] # pickle.dump(edit_cost_constants, open(save_dir + "edit_costs" + save_file_suffix + ".pkl", "wb")) @@ -53,7 +56,7 @@ def xp_compute_ged_matrix(dataset, ds_name, num_solutions, ratio, trial): options['node_attrs'] = dataset.node_attrs options['edge_attrs'] = dataset.edge_attrs parallel = True # if num_solutions == 1 else False - + """**5. Compute GED matrix.**""" ged_mat = 'error' runtime = 0 @@ -67,9 +70,9 @@ def xp_compute_ged_matrix(dataset, ds_name, num_solutions, ratio, trial): logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG) logging.exception(save_file_suffix) print(repr(exp)) - + """**6. Get results.**""" - + with open(save_dir + 'ged_matrix' + save_file_suffix + '.pkl', 'wb') as f: pickle.dump(ged_mat, f) with open(save_dir + 'runtime' + save_file_suffix + '.pkl', 'wb') as f: @@ -77,66 +80,76 @@ def xp_compute_ged_matrix(dataset, ds_name, num_solutions, ratio, trial): return ged_mat, runtime - + def save_trials_as_group(dataset, ds_name, num_solutions, ratio): # Return if the group file exists. name_middle = '.' + ds_name + '.num_sols_' + str(num_solutions) + '.ratio_' + "{:.2f}".format(ratio) + '.' name_group = save_dir + 'groups/ged_mats' + name_middle + 'npy' - if os.path.isfile(name_group): + if check_group_existence(name_group): return - + ged_mats = [] runtimes = [] - for trial in range(1, 101): + num_trials = 100 + for trial in range(1, num_trials + 1): print() print('Trial:', trial) ged_mat, runtime = xp_compute_ged_matrix(dataset, ds_name, num_solutions, ratio, trial) ged_mats.append(ged_mat) runtimes.append(runtime) - + # Group trials and Remove single files. + # @todo: if the program stops between the following lines, then there may be errors. name_prefix = 'ged_matrix' + name_middle - group_trials(save_dir, name_prefix, True, True, False) + group_trials(save_dir, name_prefix, True, True, False, num_trials=num_trials) name_prefix = 'runtime' + name_middle - group_trials(save_dir, name_prefix, True, True, False) + group_trials(save_dir, name_prefix, True, True, False, num_trials=num_trials) + update_group_marker(name_group) def results_for_a_dataset(ds_name): """**1. Get dataset.**""" dataset = get_dataset(ds_name) - - for num_solutions in num_solutions_list: + + for ratio in ratio_list: print() - print('# of solutions:', num_solutions) - for ratio in ratio_list: + print('Ratio:', ratio) + for num_solutions in num_solutions_list: print() - print('Ratio:', ratio) + print('# of solutions:', num_solutions) save_trials_as_group(dataset, ds_name, num_solutions, ratio) - - -def get_param_lists(ds_name): + + +def get_param_lists(ds_name, test=False): + if test: + num_solutions_list = [1, 10, 20, 30, 40, 50] + ratio_list = [10] + return num_solutions_list, ratio_list + if ds_name == 'AIDS_symb': num_solutions_list = [1, 20, 40, 60, 80, 100] ratio_list = [0.1, 0.3, 0.5, 0.7, 0.9, 1, 3, 5, 7, 9] else: - num_solutions_list = [1, 20, 40, 60, 80, 100] - ratio_list = [0.1, 0.3, 0.5, 0.7, 0.9, 1, 3, 5, 7, 9] - + num_solutions_list = [1, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100] # [1, 20, 40, 60, 80, 100] + ratio_list = [0.1, 0.3, 0.5, 0.7, 0.9, 1, 3, 5, 7, 9, 10][::-1] + return num_solutions_list, ratio_list - + if __name__ == '__main__': if len(sys.argv) > 1: ds_name_list = sys.argv[1:] else: - ds_name_list = ['MAO', 'Monoterpenoides', 'MUTAG', 'AIDS_symb'] - - save_dir = 'outputs/edit_costs.num_sols.ratios.IPFP/' + ds_name_list = ['Acyclic', 'Alkane_unlabeled', 'MAO_lite', 'Monoterpenoides', 'MUTAG'] +# ds_name_list = ['Acyclic'] # 'Alkane_unlabeled'] +# ds_name_list = ['Acyclic', 'MAO', 'Monoterpenoides', 'MUTAG', 'AIDS_symb'] + + save_dir = 'outputs/edit_costs.real_data.num_sols.ratios.IPFP/' os.makedirs(save_dir, exist_ok=True) os.makedirs(save_dir + 'groups/', exist_ok=True) - + for ds_name in ds_name_list: print() print('Dataset:', ds_name) - num_solutions_list, ratio_list = get_param_lists(ds_name) + num_solutions_list, ratio_list = get_param_lists(ds_name, test=False) results_for_a_dataset(ds_name) diff --git a/gklearn/experiments/ged/stability/group_results.py b/gklearn/experiments/ged/stability/group_results.py index e1f999e..564625d 100644 --- a/gklearn/experiments/ged/stability/group_results.py +++ b/gklearn/experiments/ged/stability/group_results.py @@ -5,7 +5,7 @@ Created on Thu Oct 29 17:26:43 2020 @author: ljia -This script groups results together into a single file for the sake of faster +This script groups results together into a single file for the sake of faster searching and loading. """ import os @@ -16,9 +16,55 @@ from tqdm import tqdm import sys +def check_group_existence(file_name): + path, name = os.path.split(file_name) + marker_fn = os.path.join(path, 'group_names_finished.pkl') + if os.path.isfile(marker_fn): + with open(marker_fn, 'rb') as f: + fns = pickle.load(f) + if name in fns: + return True + + if os.path.isfile(file_name): + return True + + return False + + +def update_group_marker(file_name): + path, name = os.path.split(file_name) + marker_fn = os.path.join(path, 'group_names_finished.pkl') + if os.path.isfile(marker_fn): + with open(marker_fn, 'rb') as f: + fns = pickle.loads(f) + if name in fns: + return + else: + fns.add(name) + else: + fns = set({name}) + with open(marker_fn, 'wb') as f: + pickle.dump(fns, f) + + +def create_group_marker_file(dir_folder, overwrite=True): + if not overwrite: + return + + fns = set() + for file in sorted(os.listdir(dir_folder)): + if os.path.isfile(os.path.join(dir_folder, file)): + if file.endswith('.npy'): + fns.add(file) + + marker_fn = os.path.join(dir_folder, 'group_names_finished.pkl') + with open(marker_fn, 'wb') as f: + pickle.dump(fns, f) + + # This function is used by other scripts. Modify it carefully. -def group_trials(dir_folder, name_prefix, override, clear, backup): - +def group_trials(dir_folder, name_prefix, overwrite, clear, backup, num_trials=100): + # Get group name. label_name = name_prefix.split('.')[0] if label_name == 'ged_matrix': @@ -33,10 +79,10 @@ def group_trials(dir_folder, name_prefix, override, clear, backup): else: name_group = dir_folder + 'groups/' + group_label + name_suffix + 'pkl' - if not override and os.path.isfile(name_group): + if not overwrite and os.path.isfile(name_group): # Check if all trial files exist. trials_complete = True - for trial in range(1, 101): + for trial in range(1, num_trials + 1): file_name = dir_folder + name_prefix + 'trial_' + str(trial) + '.pkl' if not os.path.isfile(file_name): trials_complete = False @@ -44,7 +90,7 @@ def group_trials(dir_folder, name_prefix, override, clear, backup): else: # Get data. data_group = [] - for trial in range(1, 101): + for trial in range(1, num_trials + 1): file_name = dir_folder + name_prefix + 'trial_' + str(trial) + '.pkl' if os.path.isfile(file_name): with open(file_name, 'rb') as f: @@ -64,7 +110,7 @@ def group_trials(dir_folder, name_prefix, override, clear, backup): else: # Not all trials are completed. return - + # Write groups. if label_name == 'ged_matrix': data_group = np.array(data_group) @@ -73,31 +119,31 @@ def group_trials(dir_folder, name_prefix, override, clear, backup): else: with open(name_group, 'wb') as f: pickle.dump(data_group, f) - + trials_complete = True if trials_complete: # Backup. if backup: - for trial in range(1, 101): + for trial in range(1, num_trials + 1): src = dir_folder + name_prefix + 'trial_' + str(trial) + '.pkl' dst = dir_folder + 'backups/' + name_prefix + 'trial_' + str(trial) + '.pkl' copyfile(src, dst) - + # Clear. if clear: - for trial in range(1, 101): + for trial in range(1, num_trials + 1): src = dir_folder + name_prefix + 'trial_' + str(trial) + '.pkl' os.remove(src) -def group_all_in_folder(dir_folder, override=False, clear=True, backup=True): - +def group_all_in_folder(dir_folder, overwrite=False, clear=True, backup=True): + # Create folders. os.makedirs(dir_folder + 'groups/', exist_ok=True) if backup: os.makedirs(dir_folder + 'backups', exist_ok=True) - + # Iterate all files. cur_file_prefix = '' for file in tqdm(sorted(os.listdir(dir_folder)), desc='Grouping', file=sys.stdout): @@ -106,20 +152,23 @@ def group_all_in_folder(dir_folder, override=False, clear=True, backup=True): # print(name) # print(name_prefix) if name_prefix != cur_file_prefix: - group_trials(dir_folder, name_prefix, override, clear, backup) + group_trials(dir_folder, name_prefix, overwrite, clear, backup) cur_file_prefix = name_prefix - - + + if __name__ == '__main__': - dir_folder = 'outputs/CRIANN/edit_costs.num_sols.ratios.IPFP/' - group_all_in_folder(dir_folder) - - dir_folder = 'outputs/CRIANN/edit_costs.repeats.ratios.IPFP/' - group_all_in_folder(dir_folder) - - dir_folder = 'outputs/CRIANN/edit_costs.max_num_sols.ratios.bipartite/' - group_all_in_folder(dir_folder) - - dir_folder = 'outputs/CRIANN/edit_costs.repeats.ratios.bipartite/' - group_all_in_folder(dir_folder) \ No newline at end of file + # dir_folder = 'outputs/CRIANN/edit_costs.num_sols.ratios.IPFP/' + # group_all_in_folder(dir_folder) + + # dir_folder = 'outputs/CRIANN/edit_costs.repeats.ratios.IPFP/' + # group_all_in_folder(dir_folder) + + # dir_folder = 'outputs/CRIANN/edit_costs.max_num_sols.ratios.bipartite/' + # group_all_in_folder(dir_folder) + + # dir_folder = 'outputs/CRIANN/edit_costs.repeats.ratios.bipartite/' + # group_all_in_folder(dir_folder) + + dir_folder = 'outputs/edit_costs.real_data.num_sols.ratios.IPFP/groups/' + create_group_marker_file(dir_folder) \ No newline at end of file diff --git a/gklearn/experiments/ged/stability/run_job_edit_costs.nums_sols.ratios.IPFP.py b/gklearn/experiments/ged/stability/run_job_edit_costs.real_data.nums_sols.ratios.IPFP.py similarity index 62% rename from gklearn/experiments/ged/stability/run_job_edit_costs.nums_sols.ratios.IPFP.py rename to gklearn/experiments/ged/stability/run_job_edit_costs.real_data.nums_sols.ratios.IPFP.py index 6939a06..7ab72b2 100644 --- a/gklearn/experiments/ged/stability/run_job_edit_costs.nums_sols.ratios.IPFP.py +++ b/gklearn/experiments/ged/stability/run_job_edit_costs.real_data.nums_sols.ratios.IPFP.py @@ -15,30 +15,30 @@ def get_job_script(arg): #SBATCH --exclusive #SBATCH --job-name="st.""" + arg + r""".IPFP" -#SBATCH --partition=tlong +#SBATCH --partition=court #SBATCH --mail-type=ALL #SBATCH --mail-user=jajupmochi@gmail.com -#SBATCH --output="outputs/output_edit_costs.nums_sols.ratios.IPFP.""" + arg + """.txt" -#SBATCH --error="errors/error_edit_costs.nums_sols.ratios.IPFP.""" + arg + """.txt" +#SBATCH --output="outputs/output_edit_costs.real_data.nums_sols.ratios.IPFP.""" + arg + """.txt" +#SBATCH --error="errors/error_edit_costs.real_data.nums_sols.ratios.IPFP.""" + arg + """.txt" # #SBATCH --ntasks=1 #SBATCH --nodes=1 #SBATCH --cpus-per-task=1 -#SBATCH --time=300:00:00 +#SBATCH --time=48:00:00 #SBATCH --mem-per-cpu=4000 srun hostname srun cd /home/2019015/ljia02/graphkit-learn/gklearn/experiments/ged/stability -srun python3 edit_costs.nums_sols.ratios.IPFP.py """ + arg +srun python3 edit_costs.real_data.nums_sols.ratios.IPFP.py """ + arg script = script.strip() script = re.sub('\n\t+', '\n', script) script = re.sub('\n +', '\n', script) - + return script if __name__ == '__main__': - ds_list = ['MAO', 'Monoterpenoides', 'MUTAG', 'AIDS_symb'] - for ds_name in [ds_list[i] for i in [0, 3]]: + ds_list = ['Acyclic', 'Alkane_unlabeled', 'MAO_lite', 'Monoterpenoides', 'MUTAG'] + for ds_name in [ds_list[i] for i in [0, 1, 2, 3, 4]]: job_script = get_job_script(ds_name) command = 'sbatch < Date: Tue, 5 Jan 2021 16:30:40 +0100 Subject: [PATCH 13/24] [Exp] Fix typo bug in gklearn/experiments/ged/stability/group_results.py. --- gklearn/experiments/ged/stability/group_results.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gklearn/experiments/ged/stability/group_results.py b/gklearn/experiments/ged/stability/group_results.py index 564625d..bdbe89f 100644 --- a/gklearn/experiments/ged/stability/group_results.py +++ b/gklearn/experiments/ged/stability/group_results.py @@ -36,7 +36,7 @@ def update_group_marker(file_name): marker_fn = os.path.join(path, 'group_names_finished.pkl') if os.path.isfile(marker_fn): with open(marker_fn, 'rb') as f: - fns = pickle.loads(f) + fns = pickle.load(f) if name in fns: return else: @@ -170,5 +170,5 @@ if __name__ == '__main__': # dir_folder = 'outputs/CRIANN/edit_costs.repeats.ratios.bipartite/' # group_all_in_folder(dir_folder) - dir_folder = 'outputs/edit_costs.real_data.num_sols.ratios.IPFP/groups/' + dir_folder = 'outputs/CRIANN/edit_costs.real_data.num_sols.ratios.IPFP/groups/' create_group_marker_file(dir_folder) \ No newline at end of file From c3c3921b2016d242aa91f4c1d9e5b5d386115ece Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Tue, 5 Jan 2021 16:49:47 +0100 Subject: [PATCH 14/24] [Exp] Remove #SBATCH --exclusive in the fcsp exps. --- .../experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py | 4 ++-- .../thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py index b241c22..164740f 100644 --- a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py +++ b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py @@ -46,7 +46,7 @@ def get_job_script(kernel, dataset, fcsp): script = r""" #!/bin/bash -#SBATCH --exclusive +##SBATCH --exclusive #SBATCH --job-name="fcsp.""" + kernel + r"." + dataset + r"." + fcsp + r"""" #SBATCH --partition=tlong #SBATCH --mail-type=ALL @@ -142,4 +142,4 @@ if __name__ == '__main__': # print(command) os.system(command) # os.popen(command) - # output = stream.readlines() \ No newline at end of file + # output = stream.readlines() diff --git a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py index cd1a94c..e6669c5 100644 --- a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py +++ b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py @@ -123,7 +123,7 @@ def get_job_script(kernel, dataset, fcsp): script = r""" #!/bin/bash -#SBATCH --exclusive +##SBATCH --exclusive #SBATCH --job-name="fcsp.space.""" + kernel + r"." + dataset + r"." + fcsp + r"""" #SBATCH --partition=""" + (r"court" if kernel == 'ShortestPath' else r"court") + r""" #SBATCH --mail-type=ALL @@ -222,4 +222,4 @@ if __name__ == '__main__': # print(command) os.system(command) # os.popen(command) - # output = stream.readlines() \ No newline at end of file + # output = stream.readlines() From 367c8e400a2368e0375d34d4b73a283ced15bf9d Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Tue, 5 Jan 2021 20:28:15 +0100 Subject: [PATCH 15/24] [Exp] Update exceptions in fcsp exps. --- .../graph_kernels/fcsp/run_jobs_compare_fcsp.py | 22 +++++++++---- .../fcsp/run_jobs_compare_fcsp_space.py | 38 +++++++++++++++++++--- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py index 164740f..2c05455 100644 --- a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py +++ b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py @@ -10,7 +10,7 @@ import os import re -OUT_TIME_LIST = [('ShortestPath', 'ENZYMES', 'False'), +OUT_TIME_LIST = set({('ShortestPath', 'ENZYMES', 'False'), ('StructuralSP', 'ENZYMES', 'True'), ('StructuralSP', 'ENZYMES', 'False'), ('StructuralSP', 'AIDS', 'False'), @@ -26,20 +26,28 @@ OUT_TIME_LIST = [('ShortestPath', 'ENZYMES', 'False'), ('ShortestPath', 'COX2', 'False'), ('StructuralSP', 'COX2', 'False'), ('ShortestPath', 'DHFR', 'False'), - ] - -OUT_MEM_LIST = [('StructuralSP', 'PROTEINS', 'True'), + ('StructuralSP', 'DHFR', 'False'), + ('StructuralSP', 'OHSU', 'True'), + ('StructuralSP', 'OHSU', 'False'), + ('ShortestPath', 'SYNTHETICnew', 'False'), + ('StructuralSP', 'SYNTHETICnew', 'True'), + ('StructuralSP', 'SYNTHETICnew', 'False'), + ('ShortestPath', 'Synthie', 'False'), + ('StructuralSP', 'Synthie', 'True'), + }) + +OUT_MEM_LIST = set({('StructuralSP', 'PROTEINS', 'True'), ('StructuralSP', 'PROTEINS', 'False'), ('StructuralSP', 'PROTEINS_full', 'True'), ('StructuralSP', 'PROTEINS_full', 'False'), ('ShortestPath', 'REDDIT-BINARY', 'True'), - ] + }) -MISS_LABEL_LIST = [('StructuralSP', 'GREC', 'True'), +MISS_LABEL_LIST = set({('StructuralSP', 'GREC', 'True'), ('StructuralSP', 'GREC', 'False'), ('StructuralSP', 'Web', 'True'), ('StructuralSP', 'Web', 'False'), - ] + }) def get_job_script(kernel, dataset, fcsp): diff --git a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py index e6669c5..233c4a2 100644 --- a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py +++ b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py @@ -14,10 +14,14 @@ import pickle OUT_TIME_LIST = [] -OUT_MEM_LIST = [('ShortestPath', 'REDDIT-BINARY', 'True'), +OUT_MEM_LIST = set({('ShortestPath', 'REDDIT-BINARY', 'True'), ('ShortestPath', 'REDDIT-BINARY', 'False'), ('ShortestPath', 'DD', 'True'), ('ShortestPath', 'DD', 'False'), + ('ShortestPath', 'COLORS-3', 'True'), + ('ShortestPath', 'COLORS-3', 'False'), + ('StructuralSP', 'COLORS-3', 'True'), + ('StructuralSP', 'COLORS-3', 'False'), ('ShortestPath', 'MCF-7', 'True'), ('ShortestPath', 'MCF-7', 'False'), ('StructuralSP', 'MCF-7', 'True'), @@ -35,7 +39,13 @@ OUT_MEM_LIST = [('ShortestPath', 'REDDIT-BINARY', 'True'), ('StructuralSP', 'MOLT-4H', 'True'), ('StructuralSP', 'MOLT-4H', 'False'), ('ShortestPath', 'P388', 'True'), + ('ShortestPath', 'P388', 'False'), + ('StructuralSP', 'P388', 'True'), + ('StructuralSP', 'P388', 'False'), ('ShortestPath', 'P388H', 'True'), + ('ShortestPath', 'P388H', 'False'), + ('StructuralSP', 'P388H', 'True'), + ('StructuralSP', 'P388H', 'False'), ('ShortestPath', 'NCI-H23', 'True'), ('ShortestPath', 'NCI-H23', 'False'), ('StructuralSP', 'NCI-H23', 'True'), @@ -48,7 +58,9 @@ OUT_MEM_LIST = [('ShortestPath', 'REDDIT-BINARY', 'True'), ('ShortestPath', 'OVCAR-8', 'False'), ('StructuralSP', 'OVCAR-8', 'True'), ('StructuralSP', 'OVCAR-8', 'False'), + ('ShortestPath', 'OVCAR-8H', 'True'), ('ShortestPath', 'OVCAR-8H', 'False'), + ('StructuralSP', 'OVCAR-8H', 'True'), ('StructuralSP', 'OVCAR-8H', 'False'), ('ShortestPath', 'SN12C', 'True'), ('ShortestPath', 'SN12C', 'False'), @@ -60,21 +72,30 @@ OUT_MEM_LIST = [('ShortestPath', 'REDDIT-BINARY', 'True'), ('ShortestPath', 'SF-295', 'False'), ('StructuralSP', 'SF-295', 'True'), ('StructuralSP', 'SF-295', 'False'), + ('ShortestPath', 'SF-295H', 'True'), ('ShortestPath', 'SF-295H', 'False'), + ('StructuralSP', 'SF-295H', 'True'), ('StructuralSP', 'SF-295H', 'False'), ('ShortestPath', 'SW-620', 'True'), ('ShortestPath', 'SW-620', 'False'), ('StructuralSP', 'SW-620', 'True'), ('StructuralSP', 'SW-620', 'False'), + ('ShortestPath', 'SW-620H', 'True'), ('ShortestPath', 'SW-620H', 'False'), + ('StructuralSP', 'SW-620H', 'True'), ('StructuralSP', 'SW-620H', 'False'), + ('ShortestPath', 'TRIANGLES', 'True'), ('ShortestPath', 'TRIANGLES', 'False'), + ('StructuralSP', 'TRIANGLES', 'True'), ('StructuralSP', 'TRIANGLES', 'False'), ('ShortestPath', 'Yeast', 'True'), ('ShortestPath', 'Yeast', 'False'), ('StructuralSP', 'Yeast', 'True'), ('StructuralSP', 'Yeast', 'False'), ('ShortestPath', 'YeastH', 'True'), + ('ShortestPath', 'YeastH', 'False'), + ('StructuralSP', 'YeastH', 'True'), + ('StructuralSP', 'YeastH', 'False'), ('ShortestPath', 'FRANKENSTEIN', 'True'), ('ShortestPath', 'FRANKENSTEIN', 'False'), ('StructuralSP', 'FRANKENSTEIN', 'True'), @@ -97,22 +118,31 @@ OUT_MEM_LIST = [('ShortestPath', 'REDDIT-BINARY', 'True'), ('ShortestPath', 'PC-3H', 'False'), ('StructuralSP', 'PC-3H', 'True'), ('StructuralSP', 'PC-3H', 'False'), + ('ShortestPath', 'DBLP_v1', 'True'), ('ShortestPath', 'DBLP_v1', 'False'), ('StructuralSP', 'DBLP_v1', 'True'), + ('ShortestPath', 'COLLAB', 'True'), + ('ShortestPath', 'COLLAB', 'False'), + ('StructuralSP', 'COLLAB', 'True'), + ('StructuralSP', 'COLLAB', 'False'), ('ShortestPath', 'REDDIT-BINARY', 'False'), + ('StructuralSP', 'REDDIT-MULTI-5K', 'True'), + ('StructuralSP', 'REDDIT-MULTI-5K', 'False'), + ('ShortestPath', 'REDDIT-MULTI-12K', 'True'), ('ShortestPath', 'REDDIT-MULTI-12K', 'False'), + ('StructuralSP', 'REDDIT-MULTI-12K', 'True'), ('StructuralSP', 'REDDIT-MULTI-12K', 'False'), ('ShortestPath', 'TWITTER-Real-Graph-Partial', 'True'), ('ShortestPath', 'TWITTER-Real-Graph-Partial', 'False'), ('StructuralSP', 'TWITTER-Real-Graph-Partial', 'True'), ('StructuralSP', 'TWITTER-Real-Graph-Partial', 'False'), - ] + }) -MISS_LABEL_LIST = [('StructuralSP', 'GREC', 'True'), +MISS_LABEL_LIST = set({('StructuralSP', 'GREC', 'True'), ('StructuralSP', 'GREC', 'False'), ('StructuralSP', 'Web', 'True'), ('StructuralSP', 'Web', 'False'), - ] + }) def get_job_script(kernel, dataset, fcsp): From f282e933226e32de912cdc8af193d17505f15bdf Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Tue, 5 Jan 2021 20:34:46 +0100 Subject: [PATCH 16/24] [Exp] Update exceptions in fcsp exps. --- gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py | 1 + 1 file changed, 1 insertion(+) diff --git a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py index 2c05455..e67966a 100644 --- a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py +++ b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py @@ -34,6 +34,7 @@ OUT_TIME_LIST = set({('ShortestPath', 'ENZYMES', 'False'), ('StructuralSP', 'SYNTHETICnew', 'False'), ('ShortestPath', 'Synthie', 'False'), ('StructuralSP', 'Synthie', 'True'), + ('StructuralSP', 'Synthie', 'False'), }) OUT_MEM_LIST = set({('StructuralSP', 'PROTEINS', 'True'), From e5b977734ced4460fb2198f52f53ad5ee3ebd7a6 Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Tue, 5 Jan 2021 21:11:03 +0100 Subject: [PATCH 17/24] [Fix bugs] length in get_iters in compute_geds(). --- gklearn/ged/util/util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gklearn/ged/util/util.py b/gklearn/ged/util/util.py index 52aa126..a5a5ac5 100644 --- a/gklearn/ged/util/util.py +++ b/gklearn/ged/util/util.py @@ -136,7 +136,7 @@ def compute_geds_cml(graphs, options={}, sort=True, parallel=False, verbose=True G_listID = listID_toshare do_partial = partial(_wrapper_compute_ged_parallel, neo_options, sort) pool = Pool(processes=n_jobs, initializer=init_worker, initargs=(graphs, ged_env, listID)) - iterator = get_iters(pool.imap_unordered(do_partial, itr, chunksize), desc='computing GEDs', file=sys.stdout, length=len(graphs), verbose=verbose) + iterator = get_iters(pool.imap_unordered(do_partial, itr, chunksize), desc='computing GEDs', file=sys.stdout, length=len_itr, verbose=verbose) # iterator = pool.imap_unordered(do_partial, itr, chunksize) for i, j, dis, n_eo_tmp in iterator: idx_itr = int(len(graphs) * i + j - (i + 1) * (i + 2) / 2) @@ -207,7 +207,7 @@ def compute_geds(graphs, options={}, sort=True, repeats=1, parallel=False, n_job G_listID = listID_toshare do_partial = partial(_wrapper_compute_ged_parallel, neo_options, sort, repeats) pool = Pool(processes=n_jobs, initializer=init_worker, initargs=(graphs, ged_env, listID)) - iterator = get_iters(pool.imap_unordered(do_partial, itr, chunksize), desc='computing GEDs', file=sys.stdout, length=len(graphs), verbose=verbose) + iterator = get_iters(pool.imap_unordered(do_partial, itr, chunksize), desc='computing GEDs', file=sys.stdout, length=len_itr, verbose=verbose) # iterator = pool.imap_unordered(do_partial, itr, chunksize) for i, j, dis, n_eo_tmp in iterator: idx_itr = int(len(graphs) * i + j - (i + 1) * (i + 2) / 2) From 8c6168b8f851613d65a7bdbb593508d474daa719 Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Fri, 8 Jan 2021 10:04:02 +0100 Subject: [PATCH 18/24] [Exp] Update special tasks. --- .../thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py | 1 + .../thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py index e67966a..e033790 100644 --- a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py +++ b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py @@ -29,6 +29,7 @@ OUT_TIME_LIST = set({('ShortestPath', 'ENZYMES', 'False'), ('StructuralSP', 'DHFR', 'False'), ('StructuralSP', 'OHSU', 'True'), ('StructuralSP', 'OHSU', 'False'), + ('StructuralSP', 'SYNTHETIC', 'True'), ('ShortestPath', 'SYNTHETICnew', 'False'), ('StructuralSP', 'SYNTHETICnew', 'True'), ('StructuralSP', 'SYNTHETICnew', 'False'), diff --git a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py index 233c4a2..c82d6c9 100644 --- a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py +++ b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py @@ -18,10 +18,17 @@ OUT_MEM_LIST = set({('ShortestPath', 'REDDIT-BINARY', 'True'), ('ShortestPath', 'REDDIT-BINARY', 'False'), ('ShortestPath', 'DD', 'True'), ('ShortestPath', 'DD', 'False'), + ('StructuralSP', 'DD', 'True'), + ('StructuralSP', 'DD', 'False'), ('ShortestPath', 'COLORS-3', 'True'), ('ShortestPath', 'COLORS-3', 'False'), ('StructuralSP', 'COLORS-3', 'True'), ('StructuralSP', 'COLORS-3', 'False'), + ('StructuralSP', 'PROTEINS', 'True'), + ('StructuralSP', 'PROTEINS', 'False'), + ('StructuralSP', 'PROTEINS_full', 'True'), + ('StructuralSP', 'PROTEINS_full', 'False'), + ('StructuralSP', 'MSRC_21', 'False'), ('ShortestPath', 'MCF-7', 'True'), ('ShortestPath', 'MCF-7', 'False'), ('StructuralSP', 'MCF-7', 'True'), @@ -126,6 +133,10 @@ OUT_MEM_LIST = set({('ShortestPath', 'REDDIT-BINARY', 'True'), ('StructuralSP', 'COLLAB', 'True'), ('StructuralSP', 'COLLAB', 'False'), ('ShortestPath', 'REDDIT-BINARY', 'False'), + ('StructuralSP', 'REDDIT-BINARY', 'True'), + ('StructuralSP', 'REDDIT-BINARY', 'False'), + ('ShortestPath', 'REDDIT-MULTI-5K', 'True'), + ('ShortestPath', 'REDDIT-MULTI-5K', 'False'), ('StructuralSP', 'REDDIT-MULTI-5K', 'True'), ('StructuralSP', 'REDDIT-MULTI-5K', 'False'), ('ShortestPath', 'REDDIT-MULTI-12K', 'True'), From a638bfa45a92f7a748bf69157b223dafe95c6613 Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Tue, 12 Jan 2021 15:24:13 +0100 Subject: [PATCH 19/24] [Exp] FCSP: 1. Use no more than 10 tlong tasks. 2. use ljia instead of explicit name. 3. My first SCI journal paper is accepted! --- .../graph_kernels/fcsp/run_jobs_compare_fcsp.py | 19 ++++++++++++++++++- .../graph_kernels/fcsp/run_jobs_compare_fcsp_space.py | 2 +- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py index e033790..61b61cc 100644 --- a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py +++ b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py @@ -29,13 +29,22 @@ OUT_TIME_LIST = set({('ShortestPath', 'ENZYMES', 'False'), ('StructuralSP', 'DHFR', 'False'), ('StructuralSP', 'OHSU', 'True'), ('StructuralSP', 'OHSU', 'False'), + ('StructuralSP', 'SYNTHETIC', 'False'), ('StructuralSP', 'SYNTHETIC', 'True'), + ('StructuralSP', 'SYNTHETIC', 'False'), ('ShortestPath', 'SYNTHETICnew', 'False'), ('StructuralSP', 'SYNTHETICnew', 'True'), ('StructuralSP', 'SYNTHETICnew', 'False'), ('ShortestPath', 'Synthie', 'False'), ('StructuralSP', 'Synthie', 'True'), ('StructuralSP', 'Synthie', 'False'), + ('ShortestPath', 'COIL-DEL', 'False'), + ('StructuralSP', 'COIL-DEL', 'True'), + ('StructuralSP', 'COIL-DEL', 'False'), + ('ShortestPath', 'PROTEINS', 'False'), + ('ShortestPath', 'PROTEINS_full', 'False'), + ('StructuralSP', 'Mutagenicity', 'True'), + ('StructuralSP', 'Mutagenicity', 'False'), }) OUT_MEM_LIST = set({('StructuralSP', 'PROTEINS', 'True'), @@ -89,12 +98,20 @@ def check_task_status(save_dir, *params): return True # Check if the task is running or in queue of slurm. - command = 'squeue --user ljia02 --name "fcsp' + str_task_id + '" --format "%.2t" --noheader' + command = 'squeue --user $USER --name "fcsp' + str_task_id + '" --format "%.2t" --noheader' stream = os.popen(command) output = stream.readlines() if len(output) > 0: return True + # Check if there are more than 10 tlong tasks running. + command = 'squeue --user $USER --partition tlong --noheader' + stream = os.popen(command) + output = stream.readlines() + if len(output) > 10: + return True + + # Check if the results are already computed. file_name = os.path.join(save_dir, 'run_time' + str_task_id + '.pkl') if os.path.isfile(file_name): diff --git a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py index c82d6c9..e21a6e6 100644 --- a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py +++ b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py @@ -197,7 +197,7 @@ def check_task_status(save_dir, *params): return True # Check if the task is running or in queue of slurm. - command = 'squeue --user ljia02 --name "fcsp.space' + str_task_id + '" --format "%.2t" --noheader' + command = 'squeue --user $USER --name "fcsp.space' + str_task_id + '" --format "%.2t" --noheader' stream = os.popen(command) output = stream.readlines() if len(output) > 0: From 59a36aa0a06903a39736e0edee8da572f9d632fd Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Tue, 12 Jan 2021 20:41:04 +0100 Subject: [PATCH 20/24] [Exp] Update exceptions in fcsp exps. --- .../thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py index 61b61cc..9fb73a0 100644 --- a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py +++ b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py @@ -47,12 +47,14 @@ OUT_TIME_LIST = set({('ShortestPath', 'ENZYMES', 'False'), ('StructuralSP', 'Mutagenicity', 'False'), }) -OUT_MEM_LIST = set({('StructuralSP', 'PROTEINS', 'True'), - ('StructuralSP', 'PROTEINS', 'False'), - ('StructuralSP', 'PROTEINS_full', 'True'), - ('StructuralSP', 'PROTEINS_full', 'False'), - ('ShortestPath', 'REDDIT-BINARY', 'True'), - }) +OUT_MEM_LIST = set({('StructuralSP', 'DD', 'True'), + ('StructuralSP', 'DD', 'False'), + ('StructuralSP', 'PROTEINS', 'True'), + ('StructuralSP', 'PROTEINS', 'False'), + ('StructuralSP', 'PROTEINS_full', 'True'), + ('StructuralSP', 'PROTEINS_full', 'False'), + ('ShortestPath', 'REDDIT-BINARY', 'True'), + }) MISS_LABEL_LIST = set({('StructuralSP', 'GREC', 'True'), ('StructuralSP', 'GREC', 'False'), @@ -108,7 +110,7 @@ def check_task_status(save_dir, *params): command = 'squeue --user $USER --partition tlong --noheader' stream = os.popen(command) output = stream.readlines() - if len(output) > 10: + if len(output) >= 10: return True From 4bfde8d881f98afe63f89096dfe5efdfd09861c5 Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Fri, 15 Jan 2021 11:46:14 +0100 Subject: [PATCH 21/24] [Exp] Update exceptions in fcsp exps. --- gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py index 9fb73a0..98a25d4 100644 --- a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py +++ b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py @@ -45,6 +45,8 @@ OUT_TIME_LIST = set({('ShortestPath', 'ENZYMES', 'False'), ('ShortestPath', 'PROTEINS_full', 'False'), ('StructuralSP', 'Mutagenicity', 'True'), ('StructuralSP', 'Mutagenicity', 'False'), + ('StructuralSP', 'REDDIT-BINARY', 'True'), + ('StructuralSP', 'REDDIT-BINARY', 'False'), }) OUT_MEM_LIST = set({('StructuralSP', 'DD', 'True'), From 6332e5684de7674233385d91bef2e2163809803c Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Fri, 15 Jan 2021 11:58:11 +0100 Subject: [PATCH 22/24] [Exp] Update exceptions in fcsp exps. --- gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py index 98a25d4..7a98686 100644 --- a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py +++ b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp.py @@ -56,6 +56,9 @@ OUT_MEM_LIST = set({('StructuralSP', 'DD', 'True'), ('StructuralSP', 'PROTEINS_full', 'True'), ('StructuralSP', 'PROTEINS_full', 'False'), ('ShortestPath', 'REDDIT-BINARY', 'True'), + ('ShortestPath', 'TWITTER-Real-Graph-Partial', 'True'), + ('ShortestPath', 'TWITTER-Real-Graph-Partial', 'False'), + ('StructuralSP', 'TWITTER-Real-Graph-Partial', 'True'), }) MISS_LABEL_LIST = set({('StructuralSP', 'GREC', 'True'), From bfe64a1f6698698c2eab45956b36529f84cb9707 Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Sun, 17 Jan 2021 12:18:54 +0100 Subject: [PATCH 23/24] [Exp] Update exceptions in fcsp exps. --- .../thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py index e21a6e6..37cbb2e 100644 --- a/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py +++ b/gklearn/experiments/thesis/graph_kernels/fcsp/run_jobs_compare_fcsp_space.py @@ -16,10 +16,12 @@ OUT_TIME_LIST = [] OUT_MEM_LIST = set({('ShortestPath', 'REDDIT-BINARY', 'True'), ('ShortestPath', 'REDDIT-BINARY', 'False'), + ('StructuralSP', 'ENZYMES', 'False'), ('ShortestPath', 'DD', 'True'), ('ShortestPath', 'DD', 'False'), ('StructuralSP', 'DD', 'True'), ('StructuralSP', 'DD', 'False'), + ('StructuralSP', 'COIL-DEL', 'True'), ('ShortestPath', 'COLORS-3', 'True'), ('ShortestPath', 'COLORS-3', 'False'), ('StructuralSP', 'COLORS-3', 'True'), From b72fb5db21c971affec29885131cdc890402d4d1 Mon Sep 17 00:00:00 2001 From: jajupmochi Date: Mon, 18 Jan 2021 10:33:38 +0100 Subject: [PATCH 24/24] [Doc] Update citation. --- README.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 91215c8..0380c68 100644 --- a/README.md +++ b/README.md @@ -139,7 +139,20 @@ Fork the library and open a pull request! Make your own contribute to the commun ## Citation -Still waiting... +If you have used `graphkit-learn` in your publication, please cite the the following paper: +``` +@article{JIA2021, + title = "graphkit-learn: A Python Library for Graph Kernels Based on Linear Patterns", + journal = "Pattern Recognition Letters", + year = "2021", + issn = "0167-8655", + doi = "https://doi.org/10.1016/j.patrec.2021.01.003", + url = "http://www.sciencedirect.com/science/article/pii/S0167865521000131", + author = "Linlin Jia and Benoit Gaüzère and Paul Honeine", + keywords = "Graph Kernels, Linear Patterns, Python Implementation", + abstract = "This paper presents graphkit-learn, the first Python library for efficient computation of graph kernels based on linear patterns, able to address various types of graphs. Graph kernels based on linear patterns are thoroughly implemented, each with specific computing methods, as well as two well-known graph kernels based on non-linear patterns for comparative analysis. Since computational complexity is an Achilles’ heel of graph kernels, we provide several strategies to address this critical issue, including parallelization, the trie data structure, and the FCSP method that we extend to other kernels and edge comparison. All proposed strategies save orders of magnitudes of computing time and memory usage. Moreover, all the graph kernels can be simply computed with a single Python statement, thus are appealing to researchers and practitioners. For the convenience of use, an advanced model selection procedure is provided for both regression and classification problems. Experiments on synthesized datasets and 11 real-world benchmark datasets show the relevance of the proposed library." +} +``` ## Acknowledgments