From fc4bae09317ba9231780c81bfa3ba94dd539e108 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 3 Jul 2023 13:24:35 +0200 Subject: [PATCH 01/34] Use Ripser in RipsPersistence --- CMakeLists.txt | 1 + .../tore3D_1307_distance_matrix.csv | 4 +- src/CMakeLists.txt | 1 + src/Ripser/include/gudhi/ripser.h | 1419 +++++++++++++++++ src/Ripser/utilities/CMakeLists.txt | 3 + src/Ripser/utilities/ripser.cc | 391 +++++ src/common/include/gudhi/uint128.h | 147 ++ src/python/CMakeLists.txt | 1 + src/python/gudhi/_ripser.cc | 200 +++ src/python/gudhi/sklearn/rips_persistence.py | 136 +- .../test/test_sklearn_rips_persistence.py | 12 + 11 files changed, 2276 insertions(+), 39 deletions(-) create mode 100644 src/Ripser/include/gudhi/ripser.h create mode 100644 src/Ripser/utilities/CMakeLists.txt create mode 100644 src/Ripser/utilities/ripser.cc create mode 100644 src/common/include/gudhi/uint128.h create mode 100644 src/python/gudhi/_ripser.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index ccd0635dd5..9e3abd84c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,7 @@ add_gudhi_module(Hasse_complex) add_gudhi_module(Persistence_representations) add_gudhi_module(Persistent_cohomology) add_gudhi_module(Rips_complex) +add_gudhi_module(Ripser) add_gudhi_module(Simplex_tree) add_gudhi_module(Skeleton_blocker) add_gudhi_module(Spatial_searching) diff --git a/data/distance_matrix/tore3D_1307_distance_matrix.csv b/data/distance_matrix/tore3D_1307_distance_matrix.csv index afab863435..8df9e05ae8 100644 --- a/data/distance_matrix/tore3D_1307_distance_matrix.csv +++ b/data/distance_matrix/tore3D_1307_distance_matrix.csv @@ -1,4 +1,4 @@ -0. + 0.485593 0.738424 0.885478 0.188641 0.420709 0.67781 @@ -1304,4 +1304,4 @@ 1.8113 1.83101 1.40725 1.85421 1.59879 0.734918 1.35786 1.48372 1.35527 0.738936 1.87299 1.62667 1.15888 1.06351 1.01194 1.43559 1.64675 1.775 0.974258 1.48989 1.41247 0.854514 1.2493 0.271864 0.811688 1.23359 0.960687 1.67431 0.727966 0.737152 0.79253 0.683712 0.639196 0.667212 0.682323 1.14862 1.22595 1.26012 1.27812 1.37573 1.33697 1.25392 1.19951 1.39057 1.33256 1.97046 1.95145 1.80436 1.8655 1.82531 1.85551 1.88924 1.99138 2.02134 1.99613 1.96933 1.40568 1.67377 1.58185 1.7263 1.60619 1.42651 1.49596 1.49267 1.42953 1.72673 1.81775 1.93221 1.85297 1.80766 1.85765 1.96055 1.93289 2.00576 1.96405 1.86285 1.8234 1.96457 1.93582 2.02526 2.00864 2.00286 2.01824 2.02595 2.02237 2.00903 2.01265 1.7845 1.81151 1.9112 1.97035 1.98978 1.96702 1.86384 1.95143 2.01551 2.00217 2.01875 2.00244 1.98826 2.01706 1.66968 1.70363 1.68626 1.47424 1.46825 1.5299 1.63291 1.58239 1.51358 1.42563 1.4352 1.45417 1.45202 1.68629 1.75018 1.85174 1.83792 1.91947 1.9758 1.94166 1.89838 1.70397 1.74889 1.84373 1.9068 1.95718 1.96579 1.84538 1.90322 1.58901 1.52726 1.72796 1.67983 1.75682 1.76784 1.57751 1.6655 1.93873 1.87171 1.94515 1.96446 1.99388 1.99073 2.00265 2.00664 1.97896 1.96138 1.97654 1.97877 1.96627 1.95171 1.89771 1.95369 1.42061 1.43024 1.46063 1.61039 1.71344 1.55997 1.85248 1.91893 1.92685 1.86898 1.78178 1.77835 1.89548 1.84493 1.89157 1.8296 1.9435 1.93811 1.68545 1.57623 1.74553 1.75844 1.59212 1.86675 1.91556 1.90257 1.91678 1.87993 1.91166 1.90129 1.93324 1.92074 1.94322 1.9691 1.98546 1.93603 1.95789 1.72598 1.76881 1.89665 1.90364 1.86919 1.8385 1.86261 1.84555 1.80667 1.72776 1.71629 1.76025 1.98268 1.92722 1.93867 1.9793 1.89189 1.88906 1.78215 1.85157 1.36816 1.44855 1.43386 1.64106 1.54476 1.87489 1.86016 1.75828 1.67845 1.7556 1.82112 1.80523 1.70747 1.532 1.45531 1.65536 1.62925 1.77515 1.76142 1.54888 1.74794 1.75403 1.44406 1.52462 1.36109 1.36598 1.31429 1.25768 1.33653 1.34458 1.42112 1.61191 1.58118 1.54378 1.61754 1.32259 1.26893 1.39248 1.3482 1.35749 1.41012 1.43227 1.62882 1.5242 1.5245 1.6006 1.83633 1.70594 1.63731 1.59898 1.77485 1.71038 1.0668 1.05746 1.16435 1.10789 1.15585 1.09257 0.969334 1.01022 0.991799 0.943252 0.887349 0.964135 1.79384 1.76752 1.77415 1.80313 1.64305 1.44631 1.45004 1.25433 1.25515 1.35517 1.76848 1.76948 1.68333 1.71417 1.81893 1.71534 1.79983 1.35689 1.09527 1.1546 1.43486 1.34593 1.27261 1.71953 1.64948 1.67351 1.59911 1.51536 1.57753 1.62504 1.6471 1.67441 1.45793 1.54317 1.47098 1.66935 1.64055 1.50134 1.70298 1.73519 1.72391 1.659 1.70996 1.58477 1.56706 1.37889 1.39795 1.27385 1.18131 1.2227 1.27722 1.5255 1.57151 1.6708 1.6555 1.60871 1.57448 1.53082 1.62625 1.6071 1.57204 1.51411 1.55341 0.873697 1.06431 0.997937 0.971373 0.960128 1.0965 1.02087 1.52002 1.50205 1.54809 1.09773 1.0766 1.24163 1.09525 1.24611 1.18575 1.03101 0.93392 0.912656 0.976079 1.0423 1.07896 1.41822 1.29191 1.3674 1.42345 1.49788 1.38438 1.3147 1.41888 1.44542 1.16303 1.12012 1.16752 1.18438 1.51145 1.57805 1.60372 1.57632 1.50968 1.5669 1.23548 1.23372 1.22455 1.12944 1.05352 1.0912 1.17433 1.36255 1.2636 1.38944 1.33043 1.51052 1.47754 1.4605 1.37448 1.35176 1.32133 1.17785 1.22136 1.21835 1.17859 1.16144 1.47635 1.41482 1.49736 1.52457 1.36895 1.31967 1.2967 1.35086 1.04093 0.916437 0.929274 0.79795 0.859095 0.695163 1.14828 1.05845 0.949859 1.1118 1.13279 1.26424 1.26561 1.19127 1.132 1.09552 1.20813 1.177 0.930393 0.91014 0.989762 0.980488 1.43423 1.4442 1.29022 1.37393 1.43576 1.40385 1.30426 1.37744 1.21372 1.22102 1.14048 1.03928 1.19242 1.30868 1.33738 1.2659 1.12811 1.02895 1.11244 1.1618 1.1638 1.10346 1.15013 1.06763 1.01931 1.04773 1.133 1.18901 1.00868 0.984821 1.07414 1.08318 1.2976 1.21636 1.15483 1.15539 1.08717 1.00725 1.07828 1.01964 1.04081 0.913429 0.979598 0.988745 0.938433 0.892117 0.963176 0.85066 0.83968 0.796097 0.890168 0.934945 0.889839 0.788952 0.715328 0.748381 0.80791 0.86644 0.809344 0.850741 0.663995 0.742685 1.2793 1.21112 1.30508 1.24767 1.21934 1.22921 1.29952 1.34351 0.808688 0.740942 0.92246 0.897505 0.650656 0.642831 0.569524 0.465291 0.604859 0.48917 0.40529 0.612826 0.588742 1.07992 1.01122 0.872725 0.776768 0.913865 0.931939 0.863055 0.888094 0.861099 0.811209 0.799629 0.850497 0.72409 0.68026 0.552046 0.455959 0.579881 0.601431 0.867201 0.837127 0.692761 0.798585 1.20295 1.18306 1.11343 1.16146 0.476312 0.574951 0.703217 0.76394 0.597126 0.621667 0.764241 0.765179 0.688236 0.624801 0.678343 0.712825 1.06596 0.986578 1.09304 1.11838 0.796594 0.773031 0.667449 0.74529 0.66354 0.715221 0.423705 0.502116 0.396115 0.482944 0.625745 0.523279 0.771323 0.816987 0.738525 0.683228 0.785948 1.02157 1.03283 0.97919 0.126503 0.211205 0.291484 0.272291 0.290479 0.396017 0.326337 0.37907 0.36418 0.121886 0.2308 0.300104 0.314049 0.30922 0.121067 0.235705 0.609519 0.632652 0.590344 0.564364 0.496134 0.423377 0.453326 0.557537 0.659466 0.70029 0.719593 0.685578 0.642449 0.648685 0.627906 0.597771 0.614412 0.84144 0.783122 0.749231 0.613206 0.606897 0.598438 0.564964 0.602098 0.587168 0.427922 0.380698 0.52745 0.497667 0.503691 0.537161 0.516879 0.442823 0.384398 0.431576 0.680797 0.636572 0.511195 0.417376 0.53458 0.130915 0.240805 0.389947 0.45873 0.336373 0.311546 0.703108 0.671967 0.754937 0.763575 0.69352 0.589324 0.570873 0.510442 0.437927 0.441057 0.527846 0.605883 0.656054 0.596806 0.578645 0.311169 0.133036 0.626541 0.430062 0.472189 0.563565 0.49529 0.568428 0.536673 0.566394 0.594521 0.623209 0.654513 0.609384 0.610891 0.227386 0.11966 0.118102 0.226183 0.277791 0.283032 0.723218 0.728508 0.661142 0.62411 0.641573 0.676011 0.527855 0.438778 0.427401 0.5025 0.586256 0.601419 0.843361 0.893317 0.868497 0.779933 0.706338 0.753861 1.00819 1.03844 0.954903 1.66379 1.59253 1.5083 1.49317 1.57343 1.6681 1.53212 1.5951 1.55187 1.46302 1.41187 1.44564 1.45099 1.4179 1.43501 1.50856 1.56921 1.53176 1.57713 1.5509 1.64333 1.71746 1.68028 1.47928 1.55795 1.55689 1.47512 0.662094 0.742351 0.760192 0.681638 1.18916 1.22139 1.29108 0.843934 0.832544 0.896884 0.915947 0.802527 0.83659 0.825165 0.609357 0.604068 0.550072 0.544923 0.919838 0.914328 0.861435 0.913015 0.882821 0.792672 0.771442 0.847163 1.53605 1.60794 1.64368 1.57263 1.7035 1.61916 1.62335 1.70878 1.39883 1.41615 1.38875 1.74505 1.72135 1.78414 1.45472 1.44102 1.49336 1.30846 1.32934 1.35699 1.37155 1.35146 1.04037 1.06041 0.99604 1.38613 1.3326 1.38906 1.43806 1.83752 1.83194 1.8553 1.86498 1.73835 1.78416 1.73976 1.41622 1.39727 1.3805 1.40672 0.937361 0.837279 0.794736 0.853857 0.934672 1.36452 1.4044 1.49135 1.51055 1.43757 1.48617 1.44294 1.38089 1.41762 1.32601 1.36839 1.44329 1.39769 1.55685 1.62659 1.63069 1.56643 1.70919 1.62524 1.68616 0.394551 0.387226 0.296244 0.310481 0.705857 0.658655 0.703345 0.746256 1.27347 1.27913 1.22296 1.1966 1.24175 1.37872 1.42792 1.37406 1.289 1.29399 0.984593 1.03172 1.69945 1.613 1.68874 1.45192 1.42745 1.42022 1.84972 1.80964 1.81454 1.87124 1.78626 1.83223 1.12101 1.14246 1.21939 1.193 1.39589 1.34172 1.46308 1.21451 1.26527 1.22129 1.16622 0.238796 0.305216 0.35907 0.305265 0.495571 0.435718 0.489897 0.543145 0.837877 0.805183 0.850178 0.885425 0.575302 0.552404 0.469227 0.499093 1.0018 0.972536 1.0347 1.05513 0.534851 0.530583 0.567363 0.586379 0.578315 0.883779 0.938304 0.965812 0.914616 0.873708 0.9183 0.557698 1.01313 0.522482 0.846213 0.488525 0.302506 1.21519 1.17006 1.3516 1.23849 0.702858 0.343768 1.59976 1.38259 1.43091 1.43892 0.867951 1.39702 1.8504 1.38613 1.33755 1.75607 1.66274 1.5882 0.838831 0.578259 0.844001 0.875418 0.709374 1.51594 1.62831 1.476 1.49588 1.58597 0.961611 0.80177 0.510185 0.680305 0.189329 0.638388 0.582976 0.509809 0.573873 0.210348 0.620164 0.512624 0.676809 0.640611 0.393932 0.227141 0.41504 0.583688 0.467249 0.461949 0.554513 0.592052 0.593682 0.774987 0.774444 0.777393 0.569256 0.613528 0.677729 0.506252 0.525899 0.209868 0.20758 0.35218 0.43679 0.462101 0.346819 0.348812 0.200512 0.201095 0.966618 0.712409 0.747531 0.846645 0.579578 0.474287 0.401887 0.658253 0.729157 1.04843 0.656196 0.722866 0.682722 0.528892 1.14933 0.766365 0.520436 0.650643 0.810672 0.831851 0.840755 1.00022 0.512294 0.396505 0.487879 0.556706 0.831526 1.28064 1.24413 0.649285 0.758711 0.723748 0.844258 0.778549 0.92804 0.911689 0.968153 0.994372 1.08416 1.22427 0.989852 0.925608 1.10676 1.09703 1.04067 1.22705 1.12678 1.37002 1.29923 1.36018 0.919901 0.958454 0.851302 1.15144 1.21746 1.10454 1.04888 0.844568 0.694397 0.767827 0.86556 0.980617 1.08262 1.31725 1.46937 1.09044 1.11985 1.26921 1.40823 1.42798 1.28868 1.15187 1.15685 1.5536 1.51233 1.10716 1.37959 1.46217 1.31709 1.30689 0.986266 1.13962 1.30143 0.999937 1.46598 1.03615 1.05236 0.938564 0.900284 1.47898 1.57527 1.63715 1.56484 1.53493 1.19577 1.28398 1.48085 1.65486 1.69909 1.59229 1.48292 1.57024 1.5572 1.6255 1.69598 1.33858 1.15377 1.13921 1.29261 1.2931 1.74361 1.73675 1.26317 1.35356 1.54501 1.74707 1.80651 0.915041 0.922697 1.06789 1.16358 1.11405 1.00361 1.69392 1.76369 1.61341 1.53719 1.33235 1.29067 1.32992 1.49801 1.65659 1.51305 1.43062 1.29705 1.44477 1.29123 1.8146 1.66462 1.52032 1.65892 1.54019 1.7309 1.78485 1.53059 1.37613 1.37891 1.83538 1.93643 1.68674 1.76378 1.82047 1.8784 1.81127 1.66094 1.9693 1.92927 1.92276 1.88183 1.88465 1.84905 1.51395 1.65576 1.89773 1.83057 1.85675 1.67984 1.52724 1.39222 1.93219 1.9389 1.96286 1.99783 1.91415 1.97858 1.67713 1.62578 1.91097 1.83746 1.63779 1.95608 1.90004 1.77654 1.64913 1.41657 1.51088 1.5599 1.60043 1.99721 2.0142 1.92637 1.88933 1.98024 2.02369 2.00853 1.9033 1.98674 1.98617 1.89529 1.76604 1.77442 1.43972 1.4305 1.64259 1.69519 1.57292 1.46244 1.41279 1.39296 2.01166 1.94185 1.78671 1.75622 1.90229 2.0042 1.30602 1.39861 1.32163 1.21035 1.16667 0.629723 0.731106 0.792859 0.732444 1.28782 1.92318 1.49696 1.89986 2.01196 2.0223 1.74832 1.45826 1.97937 1.81801 1.947 1.647 1.76425 1.98477 1.97858 1.49632 1.79124 1.93008 1.97107 1.78628 1.93483 1.95442 1.8012 1.99941 1.89196 1.47112 1.46997 1.60294 1.83798 1.75768 1.8013 1.3839 1.6879 1.37723 1.46375 1.04013 1.83361 1.88389 1.46488 1.73401 1.86193 1.4093 1.2111 1.7433 1.67131 1.61855 1.69166 1.74829 1.56965 1.36641 1.43024 1.6412 1.60272 1.13546 1.45595 1.2152 1.61296 1.03545 1.44008 1.2017 1.27208 1.52851 1.39262 1.46009 0.93886 1.44622 1.21179 1.22769 1.08537 1.14407 1.03808 0.851871 1.06503 0.96875 0.833911 1.35211 1.41836 1.22869 1.23445 0.893315 0.980055 0.686534 0.585535 0.949308 0.894314 0.629484 0.921146 1.20268 0.650772 0.750682 1.16368 1.31811 1.13942 0.820043 0.581968 0.895501 0.359771 0.665476 0.651668 0.889529 0.628317 0.476551 0.593194 0.326165 0.616672 0.584721 0.347747 1.06882 0.748825 0.559261 0.401563 0.604459 0.570964 0.341348 0.818873 0.697751 0.519713 1.89976 1.92976 1.61101 1.97065 1.84013 0.585472 1.02538 1.74986 1.02428 1.00864 1.74242 1.74854 1.47774 1.38265 1.33031 1.37387 1.81119 1.53898 0.663134 1.75274 1.32086 0.566972 1.40414 0.49327 1.06903 1.50145 1.19234 1.79895 0.427452 0.447907 0.490767 0.386815 0.349789 0.344431 0.372258 1.43033 1.50653 1.56281 1.56863 1.66472 1.62173 1.52247 1.45446 1.65399 1.60459 1.9136 1.88231 1.74451 1.794 1.74042 1.73967 1.79181 1.91282 1.9491 1.89131 1.87567 1.28006 1.62927 1.52955 1.64067 1.53192 1.35271 1.45772 1.47867 1.39523 1.71658 1.80559 1.88417 1.80446 1.77105 1.83228 1.92312 1.9068 1.98958 1.94939 1.86319 1.83898 1.9749 1.93437 1.96846 1.9574 1.96384 1.98913 1.99435 1.97647 1.90977 1.93084 1.72726 1.73498 1.82562 1.89546 1.94379 1.93521 1.8144 1.89398 2.01066 2.01051 2.01219 2.0075 1.96757 1.99725 1.64951 1.66962 1.62765 1.40822 1.42284 1.49334 1.58895 1.57039 1.4958 1.41332 1.43548 1.47286 1.44836 1.52041 1.59905 1.67564 1.68123 1.7927 1.85458 1.78863 1.7544 1.57145 1.63265 1.81128 1.88052 1.94765 1.96917 1.84283 1.89071 1.59374 1.5492 1.74671 1.68447 1.73631 1.76299 1.5699 1.64128 1.96316 1.89973 1.99404 1.99982 2.02657 2.03396 2.02084 2.0263 2.03484 2.02034 2.00661 2.02117 2.03029 2.03006 1.95532 2.00884 1.44603 1.4941 1.5006 1.62267 1.72357 1.59278 1.86392 1.93375 1.95595 1.91141 1.81986 1.7992 1.9496 1.88935 1.96095 1.90881 2.02676 2.00984 1.72238 1.61689 1.81567 1.80916 1.43101 1.94174 2.00203 2.00682 2.01477 2.00609 2.02172 1.72144 1.76551 1.74086 1.77433 1.82264 1.85363 1.78284 1.80164 1.52368 1.55045 1.70179 1.71093 1.66884 1.62372 1.65228 1.62291 1.56787 1.49323 1.45483 1.51395 1.87231 1.82343 1.80081 1.85236 1.71386 1.72473 1.59391 1.66179 1.24183 1.51694 1.52362 1.71799 1.60652 1.74288 1.74592 1.65295 1.56358 1.58448 1.6613 1.66272 1.57335 1.39835 1.31497 1.4916 1.4853 1.8558 1.86182 1.68288 1.90048 1.89009 1.27983 1.35248 1.16943 1.19204 1.14586 1.07344 1.19054 1.19582 1.60647 1.81001 1.40464 1.33065 1.41987 1.15531 1.08315 1.55114 1.52279 1.49976 1.51783 1.55971 1.72462 1.62569 1.64361 1.72718 1.96312 1.81521 1.77463 1.75046 1.91326 1.84496 0.756405 0.754721 0.844978 0.799579 0.852077 0.792356 0.689739 0.723022 0.705148 0.670649 0.62237 0.683976 1.95464 1.92143 1.94997 1.96384 1.37781 1.17582 1.19759 1.04831 1.00593 1.11503 1.94433 1.95226 1.87995 1.89678 1.6089 1.52938 1.60855 1.45742 1.28581 1.32617 1.56321 1.46672 1.40823 1.45107 1.36517 1.39217 1.31991 1.23366 1.27783 1.33695 1.44752 1.45367 1.25766 1.35258 1.25222 1.40934 1.36598 1.24795 1.90763 1.93145 1.90813 1.86796 1.90756 1.79067 1.75457 1.15254 1.15487 1.05488 0.951015 1.02226 1.07438 1.78251 1.82044 1.88888 1.87632 1.84145 1.82128 1.78172 1.85365 1.84504 1.79768 1.75347 1.76425 1.11898 1.26733 1.21648 1.2098 1.20882 1.32049 1.2499 1.73983 1.75037 1.78251 1.35274 1.34568 1.48312 1.29417 1.4564 1.41164 1.27404 1.18252 1.15252 1.20017 1.25862 1.30644 1.66804 1.55355 1.63046 1.70595 1.76519 1.66033 1.60115 1.70417 1.72119 0.946521 0.890032 0.927185 0.963718 1.24217 1.29937 1.30916 1.27289 1.2119 1.27535 1.51732 1.48814 1.46366 1.36528 1.30282 1.35346 1.43581 1.08518 0.994765 1.09715 1.02855 1.20686 1.18347 1.1466 1.0603 1.02164 0.998503 0.851113 0.901407 0.921543 0.899154 0.854026 1.15703 1.08719 1.18751 1.21219 1.66355 1.61673 1.60297 1.64888 1.37442 1.24641 1.25272 1.11145 1.17401 0.993017 1.43531 1.33418 1.22901 1.43297 1.43266 1.57708 1.57268 1.50056 1.45793 1.42724 1.52877 1.49952 1.23545 1.1734 1.26133 1.26474 1.15959 1.15487 1.00704 1.08057 1.12059 1.07793 0.996749 1.071 0.929315 0.9256 0.846718 0.757281 0.948462 1.0588 1.07252 0.995482 0.854151 0.75486 0.857745 0.896512 1.48772 1.43443 1.46701 1.3844 1.32558 1.3432 1.42807 1.49526 0.750264 0.698615 0.801338 0.829396 0.962377 0.882478 0.815843 0.819338 0.762241 0.674601 0.746523 1.34417 1.37288 1.24667 1.31563 1.32621 1.27422 1.23113 1.30215 1.1847 1.17636 1.10568 1.20283 1.25681 1.21668 1.11827 1.04357 1.06502 1.13228 1.1251 1.06766 1.12248 0.944634 1.01238 0.941713 0.871932 0.971484 0.916614 0.896463 0.913364 0.981336 1.01631 0.492834 0.415509 0.593734 0.578687 0.968102 0.966598 0.882431 0.785052 0.906137 0.786625 0.702988 0.906156 0.880837 0.741953 0.675398 0.54136 0.44693 0.585741 0.59868 1.20057 1.22422 1.18852 1.13046 1.12511 1.18136 1.02837 0.978844 0.84232 0.742937 0.864328 0.892447 0.596583 0.574617 0.42249 0.527373 0.870338 0.846219 0.791284 0.835812 0.798432 0.898876 1.0332 1.09755 0.916463 0.947185 1.07983 1.07861 0.986908 0.911964 0.969386 1.01487 0.730831 0.658742 0.766762 0.784179 1.12945 1.09878 0.988422 1.07609 0.973469 1.02862 0.740115 0.811251 0.663768 0.770546 0.88984 0.74808 0.53223 0.49758 0.413304 0.401242 0.48617 0.716332 0.716269 0.66304 0.378291 0.426847 0.549959 0.448938 0.404577 0.585684 0.519325 0.303656 0.123078 0.437357 0.527613 0.608858 0.627273 0.593238 0.453747 0.563523 0.313843 0.311934 0.262998 0.258096 0.205533 0.109298 0.119418 0.226016 0.936666 1.00032 1.02289 0.975581 0.9024 0.919348 0.903643 0.872793 0.874827 0.593511 0.57138 0.597714 0.839721 0.811968 0.753321 0.767503 0.829072 0.718385 0.570167 0.471562 0.594751 0.626645 0.73919 0.798959 0.789079 0.715111 0.637813 0.656496 0.464339 0.394907 0.245398 0.134382 0.315482 0.403578 0.491496 0.612007 0.654785 0.440084 0.505489 0.584998 0.421342 0.506934 0.530626 0.492162 0.496829 0.535255 0.528074 0.458478 0.39342 0.42726 0.586811 0.599234 0.667859 0.621129 0.125434 0.296582 0.471014 0.500414 0.600203 0.551609 0.484497 0.611954 0.64387 0.713888 0.717654 0.657736 0.624754 0.634343 0.672646 0.302234 0.289002 0.223569 0.115406 0.127413 0.242525 0.595509 0.569054 0.534066 0.56121 0.604826 0.609968 0.378872 0.29279 0.222576 0.259429 0.357068 0.409877 1.11695 1.17826 1.16421 1.07905 0.999101 1.03134 1.31766 1.33901 1.24647 1.83887 1.77612 1.68576 1.65499 1.72549 1.82814 1.41985 1.46476 1.40651 1.31551 1.27563 1.33033 1.37211 1.32428 1.32541 1.39357 1.46428 1.44677 1.48052 1.47345 1.57108 1.63165 1.58015 1.55633 1.63568 1.6519 1.57021 0.949919 1.02962 1.03947 0.96345 1.35655 1.39481 1.45312 0.550942 0.559435 0.612787 0.614794 0.6056 0.615993 0.602859 0.901921 0.879346 0.811607 0.826357 0.636692 0.640365 0.583055 1.21763 1.17872 1.08659 1.07157 1.15427 1.28998 1.35595 1.40561 1.34168 1.77017 1.68489 1.67125 1.75809 1.30316 1.31085 1.28033 1.48678 1.46657 1.53947 1.72774 1.70776 1.76142 1.41644 1.42312 1.43071 1.44829 1.45031 0.723714 0.753728 0.696957 1.63666 1.57472 1.62139 1.67859 1.98934 1.9841 1.9939 2.00304 1.50949 1.56136 1.4975 1.45146 1.43462 1.43733 1.46153 0.666788 0.563562 0.514905 0.578304 0.667117 1.52618 1.58507 1.66777 1.66694 1.58435 1.315 1.28521 1.21195 1.23605 1.11656 1.14652 1.23257 1.1992 1.3262 1.39431 1.38255 1.32038 1.87201 1.80365 1.8625 0.710437 0.70826 0.622863 0.631167 0.561919 0.524092 0.525357 0.562161 1.40093 1.42168 1.38303 1.3541 1.37932 1.61245 1.64604 1.57449 1.49621 1.52197 1.3079 1.35827 1.82523 1.71883 1.79832 1.40542 1.38091 1.35788 1.97823 1.9373 1.92693 1.97235 1.89224 1.945 1.32175 1.35262 1.41986 1.38254 1.6148 1.55166 1.67248 1.39028 1.44576 1.41669 1.35727 0.285157 0.342956 0.293416 0.224778 0.338607 0.333127 0.415699 0.416083 0.612896 0.590918 0.60905 0.634768 0.868003 0.851834 0.775783 0.799003 0.746745 0.710876 0.782773 0.811097 0.752243 0.70099 0.735328 0.79719 0.811916 0.634516 0.665414 0.677781 0.638161 0.622599 0.649066 0.758977 0.760111 0.822159 0.612584 0.373601 0.283994 1.40085 1.37005 1.56899 1.38317 0.542007 0.66555 1.36018 1.17226 1.26134 1.60281 0.595102 1.44299 1.99583 1.62775 1.42762 1.50805 1.72 1.3465 1.1394 0.857072 0.616846 0.58641 0.993357 1.60223 1.54211 1.37895 1.36552 1.75429 1.26185 1.08855 0.316263 0.581165 0.19967 0.636431 0.669517 0.564404 0.491533 0.196831 0.627311 0.471639 0.45119 0.55519 0.549196 0.388766 0.23404 0.397092 0.720979 0.542088 0.666232 0.771291 0.777359 0.593581 0.591085 0.559983 0.823001 0.858332 0.962947 0.178561 0.213594 0.515162 0.535007 0.209786 0.174983 0.356915 0.499957 0.572928 0.463258 0.369152 0.666897 0.40318 0.480283 0.592262 0.825462 0.726339 0.700272 0.951583 1.05311 0.720672 0.945463 1.02684 1.01067 0.849326 0.818267 0.50429 0.803434 0.945275 1.13392 1.16477 0.511371 0.665732 0.80533 0.705093 0.799179 0.877294 0.505089 0.954394 0.907533 0.936592 1.02919 1.04729 1.16305 1.11142 1.26696 1.24914 1.29822 0.670114 0.747587 0.886176 0.721367 0.658375 1.41373 1.4225 0.775288 0.96983 0.843286 1.05191 1.0037 1.08074 1.19503 1.25385 1.15562 1.47857 1.53358 1.41591 1.33816 1.1297 0.98756 1.07385 1.18785 1.31213 1.41 1.62122 1.14955 0.798081 0.802813 0.939656 1.08525 1.1235 1.00211 1.40197 1.43004 1.25074 1.22815 0.871748 1.66644 1.73828 1.56493 1.58057 1.21905 1.34901 1.52774 1.25763 1.70096 1.27325 1.26882 1.16995 1.14654 1.70397 1.81363 1.86715 1.80902 1.79315 0.980084 1.04945 1.68007 1.84729 1.90788 1.32968 1.24647 1.35749 1.26499 1.3324 1.42561 1.48111 1.33194 1.32417 1.47562 1.40938 1.53476 1.92722 1.03609 1.09381 1.27993 1.91647 1.97319 0.649024 0.647993 0.776775 0.851091 0.798371 0.710234 1.8426 1.88617 1.7264 1.67456 1.4543 1.45187 1.14107 1.30601 1.84406 1.70793 1.60196 1.13093 1.26311 1.1051 1.95808 1.80583 1.63389 1.7466 1.38547 1.57795 1.66055 1.61309 1.45308 1.25329 1.6596 1.81507 1.43634 1.50948 1.59293 1.67144 1.60804 1.44159 1.82705 1.76215 1.74159 1.99478 2.00765 1.94493 1.35627 1.71245 1.98327 1.89238 1.88311 1.70976 1.58421 1.44452 2.00205 1.98187 2.03214 2.02873 1.95331 2.02441 1.67145 1.64719 1.91187 1.82066 1.52298 1.81853 1.73685 1.60549 1.50148 1.43049 1.51269 1.50309 1.57241 1.98916 2.02082 1.88522 1.82203 1.8873 1.98123 1.97555 1.91603 1.98363 1.95911 1.8581 1.74233 1.77707 1.4132 1.37615 1.54754 1.62991 1.54323 1.33795 1.33388 1.28405 1.92316 1.8321 1.68686 1.68422 1.843 1.93983 1.56276 1.67533 1.61806 1.50402 1.43475 0.318625 0.417016 0.505004 0.451636 1.56732 1.84056 1.4344 1.88641 1.94936 2.00427 1.70104 1.43322 1.93273 1.68303 1.92663 1.6397 1.72596 2.00654 2.03088 1.50915 1.79831 1.99088 1.98788 1.81869 2.02862 1.79588 1.57079 1.88342 1.70328 1.38003 1.51326 1.47853 1.74234 1.87648 1.85995 1.22808 1.50441 1.23017 1.60936 0.745087 1.97653 1.73506 1.23415 1.90213 1.66767 1.49578 1.36404 1.83403 1.39593 1.43949 1.44992 1.93624 1.73842 1.15728 1.53987 1.85358 1.824 1.37634 1.71942 1.01323 1.32754 1.24348 1.15631 1.42168 0.960762 1.21836 1.68314 1.71425 1.25327 1.14325 0.936667 1.54218 0.841101 0.812869 1.37439 1.18183 1.34791 1.2321 1.0925 1.0188 1.15925 0.922342 1.53114 0.592153 1.29513 0.993443 0.875952 0.616202 1.22721 0.924001 0.647294 0.875602 0.977511 1.06027 0.903469 1.51169 0.800863 1.15651 0.886894 0.580977 0.683731 0.335251 0.92988 0.639245 0.874124 0.666531 0.330129 0.572623 0.465032 0.315736 0.631683 0.751818 1.06444 0.573822 0.393734 0.701527 0.847469 0.362623 0.567206 0.604514 0.690462 0.339427 2.42085 2.4499 2.09679 2.49161 2.30944 0.398883 1.09951 2.19391 1.07661 1.44905 2.17696 2.26402 1.82802 1.71608 1.65548 1.86769 2.31644 1.85537 0.897208 2.20131 1.79876 0.897271 1.91374 0.822265 1.52322 1.92892 1.6637 2.31338 0.762653 0.781448 0.810082 0.728869 0.692905 0.65486 0.708024 1.84621 1.92616 1.95576 1.9787 2.08173 2.04153 1.95613 1.90055 2.09754 2.0376 2.39868 2.36031 2.22551 2.26907 2.20719 2.18548 2.25118 2.38665 2.42806 2.3488 2.33945 1.73843 2.12268 2.02179 2.11271 2.0129 1.8396 1.95863 1.98763 1.8996 2.21879 2.3073 2.37266 2.29144 2.26315 2.32948 2.41722 2.40505 2.49388 2.45286 2.36954 2.34907 2.48662 2.44166 2.45582 2.44661 2.45857 2.48882 2.49366 2.46954 2.37232 2.40468 2.21378 2.21142 2.29686 2.37327 2.43663 2.43395 2.30455 2.38092 2.51948 2.52298 2.52093 2.51973 2.47098 2.50132 2.14883 2.16317 2.11011 1.89532 1.91992 1.99062 2.07951 2.07437 2.00052 1.92488 1.95023 1.98915 1.96022 1.92171 2.01456 2.06777 2.09225 2.23135 2.29948 2.2062 2.17829 2.00395 2.07781 2.30862 2.38074 2.45457 2.4803 2.35055 2.39587 2.10224 2.0631 2.25695 2.19142 2.23803 2.2697 2.07803 2.14256 2.47784 2.41358 2.51389 2.51779 2.54513 2.55472 2.53663 2.54226 2.5572 2.54232 2.5247 2.54168 2.5535 2.55406 2.47621 2.53074 1.96583 2.01608 2.0206 2.13493 2.23433 2.10945 2.37557 2.44718 2.47283 2.42965 2.33626 2.31241 2.46871 2.40579 2.48172 2.42857 2.55051 2.53241 2.23617 2.13231 2.33335 2.32519 1.8394 2.46342 2.52547 2.52988 2.53792 2.5267 2.54467 2.11175 2.16943 2.13448 2.17859 2.24759 2.29131 2.20334 2.21855 1.89541 1.90085 2.07662 2.09002 2.04012 1.97718 2.00753 1.96402 1.88555 1.82163 1.73796 1.82249 2.32745 2.28311 2.23479 2.29493 2.1103 2.13514 1.9808 2.04593 1.70134 2.03715 2.04313 2.23522 2.12419 2.18184 2.19835 2.11227 2.01782 1.98976 2.0766 2.09355 2.01254 1.84382 1.75922 1.90638 1.91857 2.37587 2.38142 2.19557 2.41289 2.40583 1.69326 1.75185 1.55743 1.60208 1.56961 1.48863 1.63676 1.63635 2.10154 2.30337 1.80949 1.69513 1.80019 1.58508 1.49887 2.05711 2.0228 2.01173 2.03675 2.07437 2.24139 2.14228 2.15777 2.24027 2.48184 2.3319 2.28625 2.25817 2.42828 2.35865 0.628148 0.672942 0.807961 0.769041 0.916378 0.823412 0.834948 0.785506 0.629618 0.524458 0.666409 0.693211 2.46671 2.43334 2.45688 2.47583 1.65691 1.45384 1.50892 1.44366 1.34039 1.45394 2.45141 2.45709 2.37651 2.39969 1.96165 1.90853 1.98276 1.97826 1.78422 1.83252 2.07636 1.98389 1.9241 1.71792 1.59361 1.63251 1.57219 1.4842 1.47849 1.56642 1.81021 1.78785 1.62553 1.72903 1.59189 1.68161 1.61005 1.52584 2.40158 2.43003 2.41011 2.35733 2.40418 2.27808 2.24951 1.48488 1.45465 1.41146 1.30175 1.42022 1.45734 2.23646 2.2832 2.37511 2.36004 2.31615 2.28602 2.24163 2.33302 2.31714 2.27579 2.22073 2.24968 1.5828 1.75819 1.69875 1.67236 1.65926 1.79166 1.71971 2.21742 2.20891 2.25275 1.79873 1.77613 1.94163 1.78746 1.93804 1.88285 1.7337 1.64056 1.6208 1.67975 1.7416 1.77877 2.12095 1.99007 2.0695 2.13256 2.20959 2.08843 2.01299 2.12677 2.15429 1.33432 1.25951 1.28676 1.34798 1.48767 1.52951 1.51168 1.45711 1.39149 1.47731 1.92872 1.92971 1.9196 1.82446 1.74894 1.78354 1.86828 1.35486 1.29211 1.32967 1.23919 1.40098 1.4062 1.30976 1.22795 1.11663 1.13449 0.976811 1.05717 1.15799 1.18496 1.06503 1.29382 1.18485 1.33625 1.36605 2.07205 2.01709 1.99256 2.05306 1.67288 1.50653 1.54111 1.37607 1.46814 1.31886 1.83419 1.74531 1.63255 1.77115 1.81081 1.95286 1.95496 1.87048 1.79188 1.74451 1.8862 1.84752 1.61005 1.61523 1.68958 1.67539 1.38921 1.34766 1.20465 1.25377 1.24047 1.16168 1.10644 1.20289 1.11636 1.06575 0.971171 0.928664 1.26544 1.34882 1.32487 1.23314 1.0819 0.984495 1.15957 1.15561 1.83639 1.7596 1.82951 1.74133 1.70034 1.73727 1.82547 1.87865 1.07064 1.00486 1.11877 1.1795 1.02266 0.958791 0.821315 0.874752 0.90723 0.764858 0.844179 1.67972 1.68923 1.54158 1.60911 1.601 1.5293 1.47891 1.57406 1.46274 1.42815 1.46948 1.55979 1.59246 1.53315 1.4104 1.32642 1.40816 1.4499 1.56789 1.51875 1.5427 1.37316 1.45517 0.961522 0.859776 0.992026 0.903773 0.892224 0.952101 1.04578 1.06933 0.763599 0.666302 0.737845 0.801072 1.30966 1.27198 1.25106 1.13876 1.30579 1.17703 1.07682 1.25384 1.2608 0.722126 0.699549 0.646352 0.601173 0.524282 0.617731 1.4237 1.4534 1.42353 1.36364 1.30899 1.39534 1.29346 1.27392 1.17251 1.08414 1.13451 1.18999 0.782609 0.708623 0.714718 0.786426 0.822143 0.793198 0.681415 0.766574 1.10403 1.18384 1.28346 1.32966 1.11817 1.19102 1.25363 1.28034 1.22111 1.14975 1.14222 1.21673 0.649797 0.537568 0.636974 0.691589 1.3242 1.26801 1.16107 1.27422 1.10492 1.16266 1.00681 1.0132 0.822079 0.920105 0.937478 0.769093 0.125517 0.445846 0.500331 0.301496 0.337182 0.53178 0.536444 0.469929 0.757387 0.780372 0.889111 0.769575 0.7161 0.827248 0.810389 0.616894 0.572715 0.815022 0.899045 0.988793 0.912122 0.82217 0.807378 0.904815 0.378175 0.466745 0.601391 0.631371 0.601945 0.55833 0.509163 0.525009 1.0124 1.11438 1.1637 1.11656 0.977977 1.03485 1.07875 1.08292 1.0131 0.596665 0.125757 0.320407 0.88238 0.80473 0.700344 0.741578 0.829495 0.689357 0.764093 0.7076 0.655075 0.739381 0.941097 1.02495 1.05829 1.02233 0.939454 0.899611 0.119091 0.226388 0.371523 0.448588 0.29239 0.711634 0.724041 0.717246 0.682676 0.535245 0.651771 0.409574 0.667887 0.664429 0.606692 0.572535 0.548691 0.562907 0.623703 0.64894 0.617521 0.583604 0.532394 0.450896 0.597162 0.595339 0.480692 0.619081 0.125671 0.473789 0.557772 0.328009 0.352669 0.42427 0.531819 0.626568 0.609887 0.504587 0.420592 0.414891 0.50621 0.671836 0.684226 0.619618 0.556637 0.581017 0.624618 0.244717 0.124104 0.125432 0.24305 0.314468 0.317892 0.591064 0.601254 0.595208 0.610875 0.626046 0.595641 1.5482 1.58951 1.55726 1.46825 1.40717 1.4629 1.66309 1.7068 1.62583 2.34256 2.27478 2.18504 2.15977 2.23403 2.33642 1.87435 1.9019 1.83211 1.74458 1.71965 1.7885 1.85692 1.80255 1.79308 1.85382 1.92862 1.92461 1.9439 1.94994 2.04717 2.09822 2.03792 2.07673 2.15485 2.17024 2.08946 1.34343 1.41655 1.44979 1.37881 1.86306 1.89674 1.95815 0.306262 0.236141 0.312723 0.368711 0.300691 0.362474 0.230918 1.00462 0.947753 0.875501 0.931107 0.963231 0.979866 0.91828 1.5613 1.54301 1.45044 1.40694 1.47715 1.60712 1.6602 1.73105 1.68041 2.28893 2.20354 2.18874 2.27552 1.78058 1.7791 1.74977 1.76919 1.75139 1.84522 2.16551 2.15062 2.20549 1.93842 1.94635 1.95482 1.97184 1.9723 0.918867 0.984319 0.966593 2.09089 2.03408 2.08927 2.14215 2.50475 2.49939 2.51238 2.52181 1.83391 1.89615 1.8026 1.97183 1.95639 1.96068 1.98341 0.939336 0.848575 0.834229 0.902683 0.973756 2.02986 2.08039 2.1656 2.1721 2.09248 1.72995 1.71543 1.63603 1.64488 1.50102 1.51102 1.60599 1.59083 1.64468 1.71052 1.67301 1.61278 2.37967 2.30378 2.36542 1.09859 1.07934 0.989402 1.01351 0.45701 0.510953 0.522539 0.477575 1.91973 1.93567 1.8923 1.86542 1.89618 2.07597 2.12152 2.05954 1.97688 1.98795 1.61387 1.66848 2.34124 2.23619 2.31604 1.90499 1.88133 1.85168 2.49788 2.45582 2.44705 2.49374 2.41089 2.46466 1.81095 1.8338 1.90582 1.87631 2.09161 2.0333 2.15615 1.89252 1.94427 1.908 1.85275 0.531152 0.493263 0.419397 0.463708 0.290096 0.346309 0.303473 0.231337 0.430251 0.471513 0.52903 0.494761 1.28486 1.26132 1.17665 1.20371 1.09137 1.05846 1.1399 1.17137 0.896742 0.7977 0.776821 0.863551 0.932482 0.359976 0.446967 0.447118 0.341776 0.295 0.375365 0.853748 1.11393 1.23131 0.479127 0.292731 0.472145 1.89788 1.85773 2.04329 1.89787 0.491107 1.04377 1.66422 1.55072 1.6813 2.10516 0.897373 1.96514 2.51297 2.08885 1.95122 1.80599 2.23809 1.66832 1.48481 0.941533 0.303228 0.304571 1.39557 2.12157 2.01034 1.85233 1.80778 2.2582 1.62253 1.50081 0.603648 0.211077 0.620443 0.408331 0.5166 0.437369 0.227503 0.540241 0.513615 0.596979 0.622485 0.494174 0.598681 0.608157 0.3829 0.20234 0.979522 0.690338 0.690223 0.719009 0.785011 0.21221 0.398819 0.537536 0.998148 0.951074 1.07107 0.569488 0.446569 0.812727 0.909783 0.598587 0.587288 0.601848 0.76635 0.865524 0.82675 0.729842 0.425188 0.398255 0.217283 0.222495 0.852563 0.814462 0.914905 1.04494 1.21687 0.582439 1.15036 1.19767 1.22501 1.09924 0.731753 0.722463 1.10765 1.21167 1.33971 1.36551 0.550215 0.621463 1.16878 1.09723 1.18784 1.20662 0.70053 0.977453 0.890308 1.36026 1.46254 1.3619 1.5019 1.37512 1.51649 1.52122 1.61267 0.83442 0.787328 0.917788 1.06123 0.992426 1.79133 1.76253 1.05194 1.24769 1.02483 1.14296 1.15914 1.29432 1.62033 1.64669 1.53129 1.81621 1.89737 1.77125 1.72739 1.5204 1.34929 1.37386 1.4507 1.59542 1.73064 2.01405 1.27085 1.06669 0.982728 1.04379 1.2145 1.31989 1.25747 1.84656 1.84803 1.42719 1.44032 1.24391 2.08364 2.17311 2.01524 2.00566 1.69052 1.83348 1.99846 1.70259 2.16686 1.73374 1.749 1.64426 1.60507 2.17912 2.28423 2.34529 2.27426 2.24748 1.35725 1.37497 2.16745 2.34337 2.39953 1.59268 1.55611 1.70334 1.48839 1.5452 1.68363 1.99229 1.83519 1.82327 1.97057 1.92998 1.88645 2.4282 1.40364 1.39962 1.5633 2.42391 2.48416 0.592115 0.74738 0.877537 0.860233 0.720028 0.556952 2.35319 2.40296 2.24162 2.18511 1.97249 1.95861 1.549 1.69838 2.34318 2.19997 2.10306 1.56194 1.65631 1.51014 2.47444 2.3185 2.15032 2.2654 1.81298 2.00085 2.10611 2.13103 1.97588 1.71041 2.05911 2.26218 1.7407 1.80217 1.92414 2.03327 1.97706 1.79335 2.2568 2.16923 2.13247 2.5163 2.529 2.46668 1.77178 2.22868 2.50535 2.41084 2.39822 2.22461 2.10364 1.96761 2.52499 2.50161 2.55558 2.54735 2.47047 2.54498 2.17837 2.1587 2.42138 2.32376 1.9712 2.24985 2.14337 2.00146 1.92149 1.94829 2.02303 1.9902 2.07038 2.49721 2.53352 2.37952 2.30346 2.35427 2.4754 2.47432 2.42682 2.49192 2.45846 2.35088 2.23961 2.28321 1.92044 1.8723 2.0157 2.11344 2.04462 1.79389 1.82009 1.75417 2.39202 2.28412 2.14374 2.15866 2.32524 2.42213 2.00926 2.10676 2.02304 1.90673 1.86695 0.669275 0.726899 0.838679 0.767602 1.99062 2.31006 1.92515 2.3888 2.43412 2.50878 2.18835 1.93855 2.42316 2.11317 2.42959 2.14366 2.22096 2.52206 2.55291 2.0243 2.30834 2.51194 2.50282 2.3321 2.55263 2.20959 1.90315 2.33382 2.08788 1.85307 2.03188 1.92809 2.20734 2.3946 2.37917 1.6563 1.89837 1.67384 2.11908 0.729667 2.49315 2.15985 1.5789 2.41026 2.04079 2.01736 1.87634 2.35221 1.65274 1.82751 1.7533 2.4382 2.24041 1.51924 2.05688 2.34149 2.30453 1.83562 2.16355 1.41538 1.54798 1.73289 1.40618 1.89379 1.14583 1.38829 2.0989 2.16851 1.57345 1.29898 1.15901 1.91429 1.18295 0.911735 1.67227 1.48115 1.76071 1.66181 1.54467 1.07505 1.42472 1.01091 1.92385 0.883755 1.65025 1.3693 1.28361 0.692144 1.46512 1.24326 0.873691 0.839257 1.25063 1.29336 1.23065 2.00274 0.756375 1.37981 1.03491 0.417383 1.01604 0.569144 1.07799 0.427723 0.909686 0.839438 0.309316 0.746737 0.557928 0.65004 0.981991 0.60237 1.21484 0.593454 0.409931 0.599778 1.09035 0.658104 0.649401 0.354569 0.649851 0.712571 0.524131 -2.40859 2.42069 1.99303 2.45586 2.16306 0.466146 1.40423 2.02177 1.37759 1.29686 2.32016 2.22623 1.59334 1.47611 1.41387 1.95853 2.23253 2.07792 1.14877 2.03789 1.9058 1.10339 1.8427 0.676623 1.38191 1.75157 1.53567 2.26161 0.956311 0.966318 1.01918 0.909112 0.856988 0.857398 0.900106 1.67252 1.75152 1.7529 1.79088 1.89184 1.85869 1.79385 1.75354 1.93707 1.86946 2.49051 2.46053 2.31417 2.36798 2.31475 2.31693 2.37013 2.49597 2.53526 2.47881 2.45904 1.87341 2.20969 2.11226 2.2306 2.11977 1.93475 2.03631 2.04817 1.96867 2.26966 2.36125 2.45637 2.37304 2.33487 2.39411 2.49409 2.47243 2.55713 2.51288 2.41525 2.38257 2.52804 2.49078 2.55158 2.53629 2.53868 2.56266 2.57115 2.55841 2.50065 2.52058 2.31186 2.32399 2.4169 2.48524 2.52681 2.5138 2.39764 2.48009 2.57525 2.56793 2.57967 2.57047 2.54208 2.57071 2.20628 2.23106 2.19544 1.98421 1.9949 2.05896 2.15363 2.12532 2.05571 1.979 1.99809 2.01907 2.00641 2.08417 2.16842 2.24508 2.25381 2.37373 2.44083 2.37051 2.33289 2.14266 2.20605 2.38898 2.45671 2.51762 2.53333 2.40858 2.46147 2.14113 2.0896 2.28657 2.23092 2.30878 2.32897 2.13647 2.21471 2.50776 2.43884 2.52585 2.54065 2.57189 2.57443 2.57683 2.57969 2.56663 2.54772 2.55659 2.56349 2.55781 2.54686 2.48776 2.54314 1.9958 2.02021 2.04234 2.17967 2.28199 2.13847 2.42305 2.49192 2.50644 2.45335 2.36339 2.35256 2.47501 2.41813 2.47642 2.41425 2.53744 2.52716 2.25183 2.1448 2.32456 2.33129 1.99522 2.46151 2.51322 2.50295 2.51245 2.47894 2.51096 2.29513 2.34527 2.32223 2.35741 2.40919 2.44255 2.3725 2.38875 2.09904 2.11709 2.27275 2.28665 2.24331 2.19081 2.21423 2.18192 2.11514 2.04941 1.98537 2.0589 2.46512 2.41657 2.39298 2.44442 2.29761 2.31266 2.17496 2.24182 1.83326 2.02998 2.01973 2.2204 2.12095 2.33578 2.33914 2.24512 2.15591 2.17084 2.25039 2.25441 2.16538 1.99095 1.9078 2.07963 2.07652 2.37014 2.36009 2.14839 2.34855 2.35541 1.84708 1.91335 1.7272 1.76054 1.72434 1.6534 1.7805 1.77951 2.01338 2.20135 1.98987 1.90169 1.99757 1.74498 1.6683 1.99087 1.94407 1.95811 2.00919 2.03228 2.21199 2.10861 2.11019 2.18658 2.43135 2.2925 2.22415 2.18448 2.36715 2.2994 0.921016 0.943901 1.09546 1.03911 1.17128 1.07429 1.04511 1.0134 0.876638 0.767961 0.863664 0.916852 2.39376 2.35994 2.3672 2.39864 1.90683 1.7022 1.74251 1.62829 1.56003 1.67271 2.36538 2.36328 2.27406 2.30938 2.16464 2.08718 2.16942 1.9485 1.69115 1.75296 2.02227 1.93796 1.86885 1.96905 1.85376 1.89308 1.83237 1.74451 1.75432 1.83346 1.99633 1.99173 1.80452 1.9043 1.78479 1.9187 1.85908 1.74748 2.2902 2.3243 2.31181 2.23751 2.29515 2.15917 2.14591 1.67918 1.66245 1.59607 1.4898 1.59297 1.63189 2.07354 2.12954 2.25118 2.23118 2.17587 2.13621 2.08986 2.20208 2.17537 2.14874 2.08169 2.13715 1.44875 1.65314 1.583 1.53536 1.51111 1.66272 1.58971 2.08589 2.05227 2.10906 1.65424 1.61819 1.80663 1.69011 1.83085 1.76312 1.60197 1.5061 1.49281 1.56286 1.63139 1.65948 1.9617 1.81894 1.89735 1.94828 2.03783 1.90435 1.81724 1.93696 1.97262 1.51643 1.44627 1.49163 1.53784 1.72372 1.77838 1.77939 1.7342 1.65573 1.7386 1.73664 1.76618 1.77155 1.68214 1.59522 1.61425 1.69817 1.60519 1.52902 1.59464 1.51047 1.67987 1.67601 1.59695 1.51335 1.41873 1.4274 1.26842 1.34222 1.41759 1.4249 1.3315 1.58535 1.4839 1.61391 1.64984 1.87165 1.81139 1.78224 1.85143 1.41377 1.23572 1.28436 1.11923 1.22059 1.1015 1.63605 1.56124 1.44706 1.53121 1.5974 1.7319 1.73759 1.64764 1.54837 1.4935 1.65526 1.61082 1.41521 1.46847 1.5319 1.50437 1.62565 1.59893 1.44043 1.5051 1.52111 1.45616 1.37077 1.46936 1.34843 1.31064 1.20984 1.14583 1.46275 1.55703 1.54689 1.4555 1.29772 1.19223 1.35931 1.36659 1.60386 1.5149 1.6101 1.52475 1.50057 1.55061 1.63655 1.6735 1.26593 1.23053 1.34254 1.38705 1.33082 1.26316 1.1371 1.18163 1.19009 1.05688 1.13846 1.4515 1.44519 1.29613 1.35584 1.33296 1.25427 1.20696 1.30827 1.2133 1.16483 1.27431 1.35545 1.37122 1.30322 1.1747 1.09224 1.20363 1.22706 1.41469 1.37369 1.37265 1.21425 1.30594 1.27381 1.17723 1.29725 1.20674 1.18131 1.22749 1.32525 1.36381 0.99314 0.895302 1.01117 1.05181 1.10974 1.05492 1.06791 0.954517 1.13588 1.00348 0.902975 1.05319 1.07678 1.03979 1.00584 0.924274 0.857178 0.838316 0.919027 1.14097 1.17011 1.14528 1.09003 1.01359 1.10807 1.04498 1.0437 0.969828 0.895438 0.906761 0.969393 0.97212 0.890419 0.875994 0.965695 1.13218 1.1118 0.987432 1.06901 0.900416 0.963048 1.03413 1.06441 0.859519 0.947445 0.958639 0.997954 0.963872 0.903585 0.862093 0.942282 0.974858 0.865043 0.955997 1.01493 1.03529 0.969639 0.879974 0.994124 0.806821 0.857301 0.795112 0.76853 0.588516 0.66225 0.617074 0.46742 0.463771 0.745808 0.762521 0.571364 0.646343 0.834444 0.856978 0.800609 0.641365 0.653902 0.729197 0.640529 0.611183 0.651506 0.657849 0.606901 0.635317 0.67961 0.746359 0.826262 0.721338 0.623145 0.662814 0.737936 0.602237 0.692315 0.783984 0.78705 0.726866 0.665266 0.644363 0.709107 0.696187 0.804021 0.861776 0.822207 0.670157 0.740309 0.810351 0.832509 0.736739 0.776815 0.416347 0.403869 0.577968 0.485719 0.389377 0.416903 0.502974 0.416868 0.595791 0.587723 0.488449 0.544219 0.714945 0.792584 0.840766 0.827026 0.756213 0.702387 0.404749 0.471008 0.535968 0.561959 0.453718 0.575201 0.552031 0.482822 0.411567 0.382131 0.463977 0.424512 0.811639 0.821861 0.756482 0.683141 0.538913 0.488643 0.513511 0.560952 0.58337 0.586828 0.41882 0.367017 0.362679 0.417801 0.520671 0.526956 0.288852 0.281494 0.289711 0.0942476 0.207717 0.0973594 0.215389 0.294184 0.283215 0.263503 0.266901 0.0922615 0.200502 0.602362 0.601147 0.559238 0.556836 0.597546 0.60068 0.292273 0.297969 0.215011 0.0974517 0.0948727 0.207196 0.635848 0.63623 0.660427 0.713264 0.738437 0.683064 1.39401 1.42125 1.37743 1.28879 1.23998 1.30855 1.43454 1.49138 1.42302 2.26013 2.18604 2.10263 2.09048 2.17216 2.26692 1.99481 2.03609 1.97572 1.88764 1.85469 1.91015 1.96103 1.91495 1.91829 1.98653 2.05636 2.03675 2.05428 2.04674 2.1415 2.20365 2.15276 2.07244 2.1509 2.15328 2.07189 1.16289 1.22872 1.27569 1.21043 1.78402 1.81036 1.8792 0.638157 0.572696 0.641422 0.702138 0.475627 0.559772 0.484245 0.705091 0.637532 0.5764 0.645757 1.17618 1.18222 1.1157 1.33794 1.33426 1.24654 1.18857 1.24633 1.83904 1.89903 1.95996 1.90173 2.29408 2.20902 2.20754 2.29389 1.89181 1.8945 1.8684 2.01069 1.98722 2.07688 1.99171 1.98491 2.03513 1.90775 1.92414 1.94815 1.96501 1.94982 1.1855 1.24079 1.20707 1.9439 1.89656 1.95992 2.00388 2.43651 2.43245 2.45693 2.46533 2.04787 2.10773 2.02825 1.99085 1.97563 1.96533 1.98784 1.1353 1.03524 1.02071 1.09492 1.16813 1.94941 1.98308 2.07126 2.09439 2.0233 1.90262 1.87612 1.80151 1.82191 1.69379 1.71607 1.8064 1.77954 1.85069 1.92131 1.89726 1.83177 2.29793 2.20822 2.27242 0.930677 0.906179 0.821882 0.849448 0.509934 0.548438 0.613512 0.58519 1.87495 1.88107 1.8243 1.79784 1.84237 1.93149 1.99114 1.94532 1.85787 1.84954 1.36274 1.41643 2.2999 2.21104 2.28779 1.9863 1.96043 1.94078 2.45187 2.41154 2.41545 2.46386 2.37517 2.42473 1.70392 1.71651 1.7948 1.77639 1.97454 1.92507 2.04656 1.81311 1.86124 1.81338 1.76171 0.462452 0.406968 0.403334 0.459287 0.379784 0.363519 0.276845 0.296857 0.614411 0.626711 0.714204 0.70578 1.12179 1.09629 1.00991 1.03663 1.28599 1.25728 1.33893 1.36408 0.653365 0.56334 0.514732 0.583156 0.665286 0.610661 0.712619 0.740626 0.648766 0.574461 0.657646 0.595651 1.30992 1.0662 0.664572 0.329527 0.428537 1.81096 1.74899 1.91401 1.84057 0.563963 0.875866 1.87959 1.74764 1.85011 2.02174 1.08788 1.97705 2.45099 1.95067 1.93357 2.03814 2.25021 1.89852 1.26739 0.642227 0.53429 0.639755 1.21813 2.11089 2.11427 1.97073 1.93993 2.18268 1.40687 1.33487 0.678511 0.184162 0.583467 0.167915 0.179722 0.178038 0.187225 0.508262 0.341121 0.54484 0.74929 0.466582 0.377821 0.476812 0.459126 0.374403 0.770702 0.546569 0.466401 0.388917 0.490698 0.391096 0.521396 0.681341 0.745317 0.661602 0.764545 0.718939 0.623743 0.645095 0.755011 0.62248 0.680102 0.610338 0.623412 0.696206 0.687785 0.625295 0.744738 0.6678 0.532793 0.539812 0.535555 0.543322 0.691639 0.732928 0.922597 0.909668 0.886712 0.908162 0.960647 0.868711 1.04681 0.890709 0.899559 0.97269 1.053 1.0745 0.837778 0.939272 0.982485 0.930167 1.01621 1.00659 0.953345 1.27029 1.20318 1.20099 1.30424 1.14345 1.28908 1.12478 1.2406 1.26179 1.37459 1.10736 1.09451 1.23036 1.27025 1.18798 1.58782 1.53034 1.25373 1.45668 1.24997 1.42444 1.40855 1.53083 1.46153 1.46335 1.34096 1.57503 1.6691 1.54312 1.5268 1.33039 1.14996 1.13741 1.18608 1.33171 1.4816 1.80321 1.56032 1.31092 1.25725 1.34331 1.50961 1.59761 1.51189 1.68887 1.66549 1.70046 1.6905 1.43731 1.88969 1.9938 1.85763 1.82253 1.56803 1.72826 1.87631 1.55828 2.02148 1.5941 1.6304 1.52026 1.46497 2.0549 2.14404 2.20967 2.12319 2.08626 1.5375 1.57057 2.05365 2.23678 2.28216 1.82742 1.76307 1.89616 1.75842 1.81459 1.93296 1.92855 1.75312 1.7307 1.87325 1.89076 2.08431 2.32944 1.6058 1.63434 1.81077 2.3379 2.40412 0.806985 0.952027 1.11007 1.13192 1.00907 0.831896 2.28255 2.35405 2.19875 2.12287 1.93347 1.89043 1.72615 1.88708 2.24988 2.10249 2.02642 1.71714 1.82191 1.67498 2.41639 2.26481 2.11909 2.25432 1.97578 2.16801 2.25329 2.11207 1.96435 1.83932 2.24471 2.40847 1.97985 2.04304 2.14272 2.23998 2.18252 2.00834 2.41712 2.34817 2.31939 2.47805 2.48613 2.4481 1.92292 2.22931 2.48812 2.40975 2.43435 2.25728 2.11461 1.97793 2.52602 2.52415 2.55413 2.57719 2.48855 2.56103 2.23722 2.18549 2.4768 2.39244 2.0955 2.40275 2.31311 2.17136 2.06945 1.9838 2.06428 2.07279 2.13286 2.55835 2.58159 2.46662 2.40993 2.4794 2.55997 2.55421 2.46438 2.5444 2.52875 2.42529 2.30104 2.32541 1.98693 1.95463 2.13852 2.21592 2.11871 1.93134 1.92075 1.87553 2.51072 2.41458 2.26113 2.25501 2.41627 2.52149 1.8579 1.93116 1.82598 1.71718 1.70748 0.848009 0.935968 1.03321 0.944095 1.81543 2.41923 2.02 2.44573 2.53607 2.57528 2.26661 1.99966 2.50777 2.2575 2.50095 2.19157 2.30487 2.556 2.5664 2.06613 2.35891 2.5144 2.54528 2.35235 2.53268 2.37988 2.12806 2.47392 2.28261 1.95878 2.0433 2.07101 2.33426 2.35843 2.39052 1.80358 2.08713 1.82271 2.06295 0.978232 2.43053 2.32613 1.79583 2.33252 2.2334 2.00508 1.80971 2.32761 1.91035 1.99718 1.97552 2.33834 2.15245 1.70089 2.01789 2.22526 2.1731 1.70349 1.99253 1.59201 1.80607 1.62738 1.66567 1.76492 1.42381 1.67232 1.90509 2.01583 1.33412 1.56516 1.38195 1.69517 1.37503 1.20865 1.41488 1.24411 1.58827 1.49578 1.40368 1.38017 1.64656 1.27087 1.71601 1.11123 1.43896 1.1853 1.1141 0.983238 1.18515 1.02856 1.07072 1.13856 1.01757 1.027 1.45215 1.90873 1.07791 1.10304 0.757211 0.744648 0.832295 0.790778 0.794591 0.657492 0.590052 0.629502 0.524636 0.540425 0.61166 0.787705 0.809366 0.911711 0.911612 0.463617 0.324233 0.310889 0.855359 0.593239 0.822955 0.319989 0.341667 0.602168 0.593494 0.339723 \ No newline at end of file +2.40859 2.42069 1.99303 2.45586 2.16306 0.466146 1.40423 2.02177 1.37759 1.29686 2.32016 2.22623 1.59334 1.47611 1.41387 1.95853 2.23253 2.07792 1.14877 2.03789 1.9058 1.10339 1.8427 0.676623 1.38191 1.75157 1.53567 2.26161 0.956311 0.966318 1.01918 0.909112 0.856988 0.857398 0.900106 1.67252 1.75152 1.7529 1.79088 1.89184 1.85869 1.79385 1.75354 1.93707 1.86946 2.49051 2.46053 2.31417 2.36798 2.31475 2.31693 2.37013 2.49597 2.53526 2.47881 2.45904 1.87341 2.20969 2.11226 2.2306 2.11977 1.93475 2.03631 2.04817 1.96867 2.26966 2.36125 2.45637 2.37304 2.33487 2.39411 2.49409 2.47243 2.55713 2.51288 2.41525 2.38257 2.52804 2.49078 2.55158 2.53629 2.53868 2.56266 2.57115 2.55841 2.50065 2.52058 2.31186 2.32399 2.4169 2.48524 2.52681 2.5138 2.39764 2.48009 2.57525 2.56793 2.57967 2.57047 2.54208 2.57071 2.20628 2.23106 2.19544 1.98421 1.9949 2.05896 2.15363 2.12532 2.05571 1.979 1.99809 2.01907 2.00641 2.08417 2.16842 2.24508 2.25381 2.37373 2.44083 2.37051 2.33289 2.14266 2.20605 2.38898 2.45671 2.51762 2.53333 2.40858 2.46147 2.14113 2.0896 2.28657 2.23092 2.30878 2.32897 2.13647 2.21471 2.50776 2.43884 2.52585 2.54065 2.57189 2.57443 2.57683 2.57969 2.56663 2.54772 2.55659 2.56349 2.55781 2.54686 2.48776 2.54314 1.9958 2.02021 2.04234 2.17967 2.28199 2.13847 2.42305 2.49192 2.50644 2.45335 2.36339 2.35256 2.47501 2.41813 2.47642 2.41425 2.53744 2.52716 2.25183 2.1448 2.32456 2.33129 1.99522 2.46151 2.51322 2.50295 2.51245 2.47894 2.51096 2.29513 2.34527 2.32223 2.35741 2.40919 2.44255 2.3725 2.38875 2.09904 2.11709 2.27275 2.28665 2.24331 2.19081 2.21423 2.18192 2.11514 2.04941 1.98537 2.0589 2.46512 2.41657 2.39298 2.44442 2.29761 2.31266 2.17496 2.24182 1.83326 2.02998 2.01973 2.2204 2.12095 2.33578 2.33914 2.24512 2.15591 2.17084 2.25039 2.25441 2.16538 1.99095 1.9078 2.07963 2.07652 2.37014 2.36009 2.14839 2.34855 2.35541 1.84708 1.91335 1.7272 1.76054 1.72434 1.6534 1.7805 1.77951 2.01338 2.20135 1.98987 1.90169 1.99757 1.74498 1.6683 1.99087 1.94407 1.95811 2.00919 2.03228 2.21199 2.10861 2.11019 2.18658 2.43135 2.2925 2.22415 2.18448 2.36715 2.2994 0.921016 0.943901 1.09546 1.03911 1.17128 1.07429 1.04511 1.0134 0.876638 0.767961 0.863664 0.916852 2.39376 2.35994 2.3672 2.39864 1.90683 1.7022 1.74251 1.62829 1.56003 1.67271 2.36538 2.36328 2.27406 2.30938 2.16464 2.08718 2.16942 1.9485 1.69115 1.75296 2.02227 1.93796 1.86885 1.96905 1.85376 1.89308 1.83237 1.74451 1.75432 1.83346 1.99633 1.99173 1.80452 1.9043 1.78479 1.9187 1.85908 1.74748 2.2902 2.3243 2.31181 2.23751 2.29515 2.15917 2.14591 1.67918 1.66245 1.59607 1.4898 1.59297 1.63189 2.07354 2.12954 2.25118 2.23118 2.17587 2.13621 2.08986 2.20208 2.17537 2.14874 2.08169 2.13715 1.44875 1.65314 1.583 1.53536 1.51111 1.66272 1.58971 2.08589 2.05227 2.10906 1.65424 1.61819 1.80663 1.69011 1.83085 1.76312 1.60197 1.5061 1.49281 1.56286 1.63139 1.65948 1.9617 1.81894 1.89735 1.94828 2.03783 1.90435 1.81724 1.93696 1.97262 1.51643 1.44627 1.49163 1.53784 1.72372 1.77838 1.77939 1.7342 1.65573 1.7386 1.73664 1.76618 1.77155 1.68214 1.59522 1.61425 1.69817 1.60519 1.52902 1.59464 1.51047 1.67987 1.67601 1.59695 1.51335 1.41873 1.4274 1.26842 1.34222 1.41759 1.4249 1.3315 1.58535 1.4839 1.61391 1.64984 1.87165 1.81139 1.78224 1.85143 1.41377 1.23572 1.28436 1.11923 1.22059 1.1015 1.63605 1.56124 1.44706 1.53121 1.5974 1.7319 1.73759 1.64764 1.54837 1.4935 1.65526 1.61082 1.41521 1.46847 1.5319 1.50437 1.62565 1.59893 1.44043 1.5051 1.52111 1.45616 1.37077 1.46936 1.34843 1.31064 1.20984 1.14583 1.46275 1.55703 1.54689 1.4555 1.29772 1.19223 1.35931 1.36659 1.60386 1.5149 1.6101 1.52475 1.50057 1.55061 1.63655 1.6735 1.26593 1.23053 1.34254 1.38705 1.33082 1.26316 1.1371 1.18163 1.19009 1.05688 1.13846 1.4515 1.44519 1.29613 1.35584 1.33296 1.25427 1.20696 1.30827 1.2133 1.16483 1.27431 1.35545 1.37122 1.30322 1.1747 1.09224 1.20363 1.22706 1.41469 1.37369 1.37265 1.21425 1.30594 1.27381 1.17723 1.29725 1.20674 1.18131 1.22749 1.32525 1.36381 0.99314 0.895302 1.01117 1.05181 1.10974 1.05492 1.06791 0.954517 1.13588 1.00348 0.902975 1.05319 1.07678 1.03979 1.00584 0.924274 0.857178 0.838316 0.919027 1.14097 1.17011 1.14528 1.09003 1.01359 1.10807 1.04498 1.0437 0.969828 0.895438 0.906761 0.969393 0.97212 0.890419 0.875994 0.965695 1.13218 1.1118 0.987432 1.06901 0.900416 0.963048 1.03413 1.06441 0.859519 0.947445 0.958639 0.997954 0.963872 0.903585 0.862093 0.942282 0.974858 0.865043 0.955997 1.01493 1.03529 0.969639 0.879974 0.994124 0.806821 0.857301 0.795112 0.76853 0.588516 0.66225 0.617074 0.46742 0.463771 0.745808 0.762521 0.571364 0.646343 0.834444 0.856978 0.800609 0.641365 0.653902 0.729197 0.640529 0.611183 0.651506 0.657849 0.606901 0.635317 0.67961 0.746359 0.826262 0.721338 0.623145 0.662814 0.737936 0.602237 0.692315 0.783984 0.78705 0.726866 0.665266 0.644363 0.709107 0.696187 0.804021 0.861776 0.822207 0.670157 0.740309 0.810351 0.832509 0.736739 0.776815 0.416347 0.403869 0.577968 0.485719 0.389377 0.416903 0.502974 0.416868 0.595791 0.587723 0.488449 0.544219 0.714945 0.792584 0.840766 0.827026 0.756213 0.702387 0.404749 0.471008 0.535968 0.561959 0.453718 0.575201 0.552031 0.482822 0.411567 0.382131 0.463977 0.424512 0.811639 0.821861 0.756482 0.683141 0.538913 0.488643 0.513511 0.560952 0.58337 0.586828 0.41882 0.367017 0.362679 0.417801 0.520671 0.526956 0.288852 0.281494 0.289711 0.0942476 0.207717 0.0973594 0.215389 0.294184 0.283215 0.263503 0.266901 0.0922615 0.200502 0.602362 0.601147 0.559238 0.556836 0.597546 0.60068 0.292273 0.297969 0.215011 0.0974517 0.0948727 0.207196 0.635848 0.63623 0.660427 0.713264 0.738437 0.683064 1.39401 1.42125 1.37743 1.28879 1.23998 1.30855 1.43454 1.49138 1.42302 2.26013 2.18604 2.10263 2.09048 2.17216 2.26692 1.99481 2.03609 1.97572 1.88764 1.85469 1.91015 1.96103 1.91495 1.91829 1.98653 2.05636 2.03675 2.05428 2.04674 2.1415 2.20365 2.15276 2.07244 2.1509 2.15328 2.07189 1.16289 1.22872 1.27569 1.21043 1.78402 1.81036 1.8792 0.638157 0.572696 0.641422 0.702138 0.475627 0.559772 0.484245 0.705091 0.637532 0.5764 0.645757 1.17618 1.18222 1.1157 1.33794 1.33426 1.24654 1.18857 1.24633 1.83904 1.89903 1.95996 1.90173 2.29408 2.20902 2.20754 2.29389 1.89181 1.8945 1.8684 2.01069 1.98722 2.07688 1.99171 1.98491 2.03513 1.90775 1.92414 1.94815 1.96501 1.94982 1.1855 1.24079 1.20707 1.9439 1.89656 1.95992 2.00388 2.43651 2.43245 2.45693 2.46533 2.04787 2.10773 2.02825 1.99085 1.97563 1.96533 1.98784 1.1353 1.03524 1.02071 1.09492 1.16813 1.94941 1.98308 2.07126 2.09439 2.0233 1.90262 1.87612 1.80151 1.82191 1.69379 1.71607 1.8064 1.77954 1.85069 1.92131 1.89726 1.83177 2.29793 2.20822 2.27242 0.930677 0.906179 0.821882 0.849448 0.509934 0.548438 0.613512 0.58519 1.87495 1.88107 1.8243 1.79784 1.84237 1.93149 1.99114 1.94532 1.85787 1.84954 1.36274 1.41643 2.2999 2.21104 2.28779 1.9863 1.96043 1.94078 2.45187 2.41154 2.41545 2.46386 2.37517 2.42473 1.70392 1.71651 1.7948 1.77639 1.97454 1.92507 2.04656 1.81311 1.86124 1.81338 1.76171 0.462452 0.406968 0.403334 0.459287 0.379784 0.363519 0.276845 0.296857 0.614411 0.626711 0.714204 0.70578 1.12179 1.09629 1.00991 1.03663 1.28599 1.25728 1.33893 1.36408 0.653365 0.56334 0.514732 0.583156 0.665286 0.610661 0.712619 0.740626 0.648766 0.574461 0.657646 0.595651 1.30992 1.0662 0.664572 0.329527 0.428537 1.81096 1.74899 1.91401 1.84057 0.563963 0.875866 1.87959 1.74764 1.85011 2.02174 1.08788 1.97705 2.45099 1.95067 1.93357 2.03814 2.25021 1.89852 1.26739 0.642227 0.53429 0.639755 1.21813 2.11089 2.11427 1.97073 1.93993 2.18268 1.40687 1.33487 0.678511 0.184162 0.583467 0.167915 0.179722 0.178038 0.187225 0.508262 0.341121 0.54484 0.74929 0.466582 0.377821 0.476812 0.459126 0.374403 0.770702 0.546569 0.466401 0.388917 0.490698 0.391096 0.521396 0.681341 0.745317 0.661602 0.764545 0.718939 0.623743 0.645095 0.755011 0.62248 0.680102 0.610338 0.623412 0.696206 0.687785 0.625295 0.744738 0.6678 0.532793 0.539812 0.535555 0.543322 0.691639 0.732928 0.922597 0.909668 0.886712 0.908162 0.960647 0.868711 1.04681 0.890709 0.899559 0.97269 1.053 1.0745 0.837778 0.939272 0.982485 0.930167 1.01621 1.00659 0.953345 1.27029 1.20318 1.20099 1.30424 1.14345 1.28908 1.12478 1.2406 1.26179 1.37459 1.10736 1.09451 1.23036 1.27025 1.18798 1.58782 1.53034 1.25373 1.45668 1.24997 1.42444 1.40855 1.53083 1.46153 1.46335 1.34096 1.57503 1.6691 1.54312 1.5268 1.33039 1.14996 1.13741 1.18608 1.33171 1.4816 1.80321 1.56032 1.31092 1.25725 1.34331 1.50961 1.59761 1.51189 1.68887 1.66549 1.70046 1.6905 1.43731 1.88969 1.9938 1.85763 1.82253 1.56803 1.72826 1.87631 1.55828 2.02148 1.5941 1.6304 1.52026 1.46497 2.0549 2.14404 2.20967 2.12319 2.08626 1.5375 1.57057 2.05365 2.23678 2.28216 1.82742 1.76307 1.89616 1.75842 1.81459 1.93296 1.92855 1.75312 1.7307 1.87325 1.89076 2.08431 2.32944 1.6058 1.63434 1.81077 2.3379 2.40412 0.806985 0.952027 1.11007 1.13192 1.00907 0.831896 2.28255 2.35405 2.19875 2.12287 1.93347 1.89043 1.72615 1.88708 2.24988 2.10249 2.02642 1.71714 1.82191 1.67498 2.41639 2.26481 2.11909 2.25432 1.97578 2.16801 2.25329 2.11207 1.96435 1.83932 2.24471 2.40847 1.97985 2.04304 2.14272 2.23998 2.18252 2.00834 2.41712 2.34817 2.31939 2.47805 2.48613 2.4481 1.92292 2.22931 2.48812 2.40975 2.43435 2.25728 2.11461 1.97793 2.52602 2.52415 2.55413 2.57719 2.48855 2.56103 2.23722 2.18549 2.4768 2.39244 2.0955 2.40275 2.31311 2.17136 2.06945 1.9838 2.06428 2.07279 2.13286 2.55835 2.58159 2.46662 2.40993 2.4794 2.55997 2.55421 2.46438 2.5444 2.52875 2.42529 2.30104 2.32541 1.98693 1.95463 2.13852 2.21592 2.11871 1.93134 1.92075 1.87553 2.51072 2.41458 2.26113 2.25501 2.41627 2.52149 1.8579 1.93116 1.82598 1.71718 1.70748 0.848009 0.935968 1.03321 0.944095 1.81543 2.41923 2.02 2.44573 2.53607 2.57528 2.26661 1.99966 2.50777 2.2575 2.50095 2.19157 2.30487 2.556 2.5664 2.06613 2.35891 2.5144 2.54528 2.35235 2.53268 2.37988 2.12806 2.47392 2.28261 1.95878 2.0433 2.07101 2.33426 2.35843 2.39052 1.80358 2.08713 1.82271 2.06295 0.978232 2.43053 2.32613 1.79583 2.33252 2.2334 2.00508 1.80971 2.32761 1.91035 1.99718 1.97552 2.33834 2.15245 1.70089 2.01789 2.22526 2.1731 1.70349 1.99253 1.59201 1.80607 1.62738 1.66567 1.76492 1.42381 1.67232 1.90509 2.01583 1.33412 1.56516 1.38195 1.69517 1.37503 1.20865 1.41488 1.24411 1.58827 1.49578 1.40368 1.38017 1.64656 1.27087 1.71601 1.11123 1.43896 1.1853 1.1141 0.983238 1.18515 1.02856 1.07072 1.13856 1.01757 1.027 1.45215 1.90873 1.07791 1.10304 0.757211 0.744648 0.832295 0.790778 0.794591 0.657492 0.590052 0.629502 0.524636 0.540425 0.61166 0.787705 0.809366 0.911711 0.911612 0.463617 0.324233 0.310889 0.855359 0.593239 0.822955 0.319989 0.341667 0.602168 0.593494 0.339723 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b7992e03b8..9ea1392e0a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -36,6 +36,7 @@ add_gudhi_module(Hasse_complex) add_gudhi_module(Persistence_representations) add_gudhi_module(Persistent_cohomology) add_gudhi_module(Rips_complex) +add_gudhi_module(Ripser) add_gudhi_module(Simplex_tree) add_gudhi_module(Skeleton_blocker) add_gudhi_module(Spatial_searching) diff --git a/src/Ripser/include/gudhi/ripser.h b/src/Ripser/include/gudhi/ripser.h new file mode 100644 index 0000000000..1e712b397e --- /dev/null +++ b/src/Ripser/include/gudhi/ripser.h @@ -0,0 +1,1419 @@ +/* Based on Ripser commit 140670f2c76997404601e43d8054151f46be9fd7 + * Modification(s): + * - YYYY/MM Author: Description of the modification + * - 2024 Marc Glisse: Heavy refactoring +*/ + +/* + + Ripser: a lean C++ code for computation of Vietoris-Rips persistence barcodes + + MIT License + + Copyright (c) 2015–2021 Ulrich Bauer + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + You are under no obligation whatsoever to provide any bug fixes, patches, or + upgrades to the features, functionality or performance of the source code + ("Enhancements") to anyone; however, if you choose to make your Enhancements + available either publicly, or directly to the author of this software, without + imposing a separate written license agreement for such Enhancements, then you + hereby grant the following license: a non-exclusive, royalty-free perpetual + license to install, use, modify, prepare derivative works, incorporate into + other computer software, distribute, and sublicense such enhancements or + derivative works thereof, in binary and source code form. + +*/ + +//#define GUDHI_INDICATE_PROGRESS + +// #define GUDHI_RIPSER_USE_BOOST_HEAP // only useful when heap::push dominates? +// #define GUDHI_RIPSER_USE_HASHMAP_FOR_SPARSE_DIST_MAT // only useful in cases where edge-collapse is more important? + +/* TODO: + * from branch representative-cocycles + - for vertices: brute force check all vertices that are in the same connected component (could do better, but there is already quadraticness elsewhere in most cases, even the output for dim 0 may be quadratic) + - for others: print_chain just calls iteratively get_pivot on working_reduction_column + * from branch representative-cycles + - dim 0: trivial + - parametrize a number of functions (like add_coboundary) by the (co)boundary iterator so they can be also used for homology + - once cohomology is computed for some dim, assemble the relevant simplices (don't forget the essential ones) and reduce them homology-style. I think we have 2 choices: reduce the birth and check which columns we add (only possibility for essential classes, but do we really need to do cohomology first if we are going to do that?), or reduce the death and look at the column after reduction (Ripser(er) chose this). + * check out the persistence image branch + + * allow non-0 filtration value on vertices, so we can handle all flag-type filtrations, not just plain Rips. cf scikit-tda +*/ + +#ifndef GUDHI_RIPSER_H +#define GUDHI_RIPSER_H + +#include +#include // sqrt +#include +#include +#include +#include +#ifdef GUDHI_INDICATE_PROGRESS +#include +#endif + +#include +#include +#if BOOST_VERSION >= 108100 +#include +#else +#include +#endif + +#ifdef GUDHI_RIPSER_USE_BOOST_HEAP +#include +#endif + +#include +#include + + +namespace Gudhi::ripser { + +#define GUDHI_assert(X) GUDHI_CHECK(X, std::logic_error("")) + +#ifdef GUDHI_RIPSER_USE_BOOST_HEAP +template +using Heap = boost::heap::d_ary_heap, boost::heap::compare>; +#else +template +struct Heap : std::priority_queue { + typedef std::priority_queue Base; + using Base::Base; + void clear() { this->c.clear(); } +}; +#endif + +template +class Union_find { + public: + typedef vertex_t_ vertex_t; + private: + std::vector parent; + std::vector rank; + public: + Union_find(const vertex_t n) : parent(n), rank(n, 0) { + for (vertex_t i = 0; i < n; ++i) parent[i] = i; + } + + // TODO: check which one is faster (probably doesn't matter) + vertex_t find(vertex_t x) { +#if 0 + vertex_t y = x, z; + while ((z = parent[y]) != y) y = z; + while ((z = parent[x]) != y) { + parent[x] = y; + x = z; + } + return z; +#else + // Path halving + vertex_t y = parent[x]; + vertex_t z = parent[y]; + while (y != z) + { + parent[x] = z; + x = z; + y = parent[x]; + z = parent[y]; + } + return y; +#endif + } + + void link(vertex_t x, vertex_t y) { + // this line is redundant, the caller already does it + if ((x = find(x)) == (y = find(y))) return; + if (rank[x] > rank[y]) + parent[y] = x; + else { + parent[x] = y; + if (rank[x] == rank[y]) ++rank[y]; + } + } +}; + +template +bool is_prime(const coefficient_t n) { + if (!(n & 1) || n < 2) return n == 2; + for (coefficient_t p = 3; p * p <= n; p += 2) + if (!(n % p)) return false; + return true; +} + +// For pretty printing, modulo 11, we prefer -1 to 10. +template +coefficient_t normalize(const coefficient_t n, const coefficient_t modulus) { + return n > modulus / 2 ? n - modulus : n; +} + +template +std::vector multiplicative_inverse_vector(const coefficient_t m) { + std::vector inverse(m); + if (!is_prime(m)) + throw std::domain_error("Modulus must be a prime number"); + if ((m - 1) != (coefficient_storage_t)(m - 1)) + throw std::overflow_error("Modulus is too large"); + inverse[1] = 1; + // m = a * (m / a) + m % a + // Multipying with inverse(a) * inverse(m % a): + // 0 = inverse(m % a) * (m / a) + inverse(a) (mod m) + for (coefficient_t a = 2; a < m; ++a) inverse[a] = m - (inverse[m % a] * (m / a)) % m; + return inverse; +} + +#ifdef GUDHI_INDICATE_PROGRESS +constexpr std::chrono::milliseconds time_step(40); +constexpr const char* clear_line="\r\033[K"; +#endif + +/* concept DistanceMatrix +struct DistanceMatrix { + typedef Category; + typedef vertex_t; + typedef value_t; + value_t operator()(vertex_t i, vertex_t j) const; + vertex_t size() const; + // Optional: + static const bool is_sparse; + vector> neighbors; +}; +*/ + +class Tag_dense {}; // Use directly, iterate on vertices +class Tag_sparse {}; // Use directly, iterate on edges +class Tag_other {}; // Could use directly as dense, but prefer converting it. + +template +struct Full_distance_matrix { + public: + typedef Tag_dense Category; + typedef typename Params::vertex_t vertex_t; + typedef typename Params::value_t value_t; + std::vector distances; // TODO: private + private: + vertex_t n; + public: + //Full_distance_matrix(std::vector&& _distances) + // : distances(std::move(_distances)), n(std::sqrt(_distances.size())) {} + + template + Full_distance_matrix(const DistanceMatrix& mat) + : distances(static_cast(mat.size()) * mat.size()), n(mat.size()) { // vertex_t is meant for vertices. Using it for edges could be unsafe, so we cast to size_t. + for (vertex_t i = 0; i < size(); ++i) + for (vertex_t j = 0; j < size(); ++j) + distances[i * n + j] = mat(i, j); // If mat::operator() involves computations, should we try to take advantage of the symmetry? + } + + // Confusing: why is the order j,i significantly faster than i,j? + value_t operator()(const vertex_t j, const vertex_t i) const { + return distances[i * n + j]; + } + vertex_t size() const { return n; } +}; + +enum Compressed_matrix_layout { LOWER_TRIANGULAR, UPPER_TRIANGULAR }; + +template +struct Compressed_distance_matrix { + public: + typedef Tag_dense Category; + typedef typename Params::vertex_t vertex_t; + typedef typename Params::value_t value_t; + std::vector distances; // TODO: private + private: + std::vector rows; // Surprisingly, this is more efficient than computing i*(i-1)/2 + + public: + Compressed_distance_matrix(std::vector&& _distances) + : distances(std::move(_distances)), rows((1 + std::sqrt(1 + 8 * distances.size())) / 2) { + GUDHI_assert(distances.size() == (std::size_t)size() * (size() - 1) / 2); + init_rows(); + } + + template + Compressed_distance_matrix(const DistanceMatrix& mat) + : distances(static_cast(mat.size()) * (mat.size() - 1) / 2), rows(mat.size()) { // vertex_t is meant for vertices. Using it for edges could be unsafe, so we cast to size_t. + init_rows(); + + for (vertex_t i = 1; i < size(); ++i) + for (vertex_t j = 0; j < i; ++j) rows[i][j] = mat(i, j); + } + + value_t operator()(const vertex_t i, const vertex_t j) const { + if (i == j) return 0; + if ((Layout == LOWER_TRIANGULAR) ? (i < j) : (i > j)) + return rows[j][i]; + else + return rows[i][j]; + } + vertex_t size() const { return rows.size(); } + private: + void init_rows() { + if constexpr (Layout == LOWER_TRIANGULAR) { + value_t* pointer = &distances[0]; + for (vertex_t i = 1; i < size(); ++i) { + rows[i] = pointer; + pointer += i; + } + } else { // UPPER_TRIANGULAR + value_t* pointer = &distances[0] - 1; + for (vertex_t i = 0; i < size() - 1; ++i) { + rows[i] = pointer; + pointer += size() - i - 2; + } + } + } +}; + +template +struct Sparse_distance_matrix { + public: + typedef Tag_sparse Category; + static constexpr bool is_sparse = true; + typedef typename Params::vertex_t vertex_t; + typedef typename Params::value_t value_t; + struct vertex_diameter_t { + vertex_diameter_t() =default; + vertex_diameter_t(vertex_t i_, value_t d_) : i(i_), d(d_) {} +#if 1 + // gcc is faster with those 2 lines (or with a std::pair) :-( + vertex_diameter_t(vertex_diameter_t const&o)noexcept :i(o.i),d(o.d){} + vertex_diameter_t&operator=(vertex_diameter_t const&o) noexcept{i=o.i;d=o.d;return*this;} +#endif + vertex_t i; value_t d; + friend vertex_t get_vertex(const vertex_diameter_t& i) { return i.i; } + friend value_t get_diameter(const vertex_diameter_t& i) { return i.d; } + friend bool operator<(vertex_diameter_t const& a, vertex_diameter_t const& b) { + if (a.i < b.i) return true; + if (a.i > b.i) return false; + return a.d < b.d; + } + }; + + std::vector> neighbors; + std::size_t num_edges; // TODO: useless, remove + + private: +#ifdef GUDHI_RIPSER_USE_HASHMAP_FOR_SPARSE_DIST_MAT +#if BOOST_VERSION >= 108100 + boost::unordered_flat_map,value_t> m; +#else + boost::unordered_map,value_t> m; +#endif + // Would a vector (one map per vertex) have any advantage? +#endif + + public: + Sparse_distance_matrix(std::vector>&& _neighbors, + std::size_t _num_edges = 0) + : neighbors(std::move(_neighbors)), num_edges(_num_edges) {init();} + + template + Sparse_distance_matrix(const DistanceMatrix& mat, const value_t threshold) + : neighbors(mat.size()), num_edges(0) { + + for (vertex_t i = 0; i < size(); ++i) + for (vertex_t j = 0; j < size(); ++j) + if (i != j) { + auto d = mat(i, j); + if (d <= threshold) { + ++num_edges; + neighbors[i].emplace_back(j, d); + } + } + init(); + } + + value_t operator()(const vertex_t i, const vertex_t j) const { +#ifdef GUDHI_RIPSER_USE_HASHMAP_FOR_SPARSE_DIST_MAT + // We could insert in both orders to save the minmax for each query. + return m.at(std::minmax(i,j)); + //// We never hit the infinity case? + // auto it = m.find(std::minmax(i,j)); + // return (it != m.end()) ? *it : std::numeric_limits::infinity(); +#else + auto neighbor = + std::lower_bound(neighbors[i].begin(), neighbors[i].end(), vertex_diameter_t{j, 0}); + return (neighbor != neighbors[i].end() && get_vertex(*neighbor) == j) + ? get_diameter(*neighbor) + : std::numeric_limits::infinity(); +#endif + } + vertex_t size() const { return neighbors.size(); } + private: + void init() { +#ifdef GUDHI_RIPSER_USE_HASHMAP_FOR_SPARSE_DIST_MAT + for(vertex_t i=0; i +struct Euclidean_distance_matrix { + public: + typedef Tag_other Category; + typedef typename Params::vertex_t vertex_t; + typedef typename Params::value_t value_t; + + Euclidean_distance_matrix(std::vector>&& _points) + : points(std::move(_points)) { + for (auto p : points) { GUDHI_assert(p.size() == points.front().size()); } + } + + value_t operator()(const vertex_t i, const vertex_t j) const { + GUDHI_assert((std::size_t)i < points.size()); + GUDHI_assert((std::size_t)j < points.size()); + return std::sqrt(std::inner_product( + points[i].begin(), points[i].end(), points[j].begin(), value_t(), std::plus(), + [](value_t u, value_t v) { return (u - v) * (u - v); })); + } + + vertex_t size() const { return points.size(); } + private: + std::vector> points; +}; + +// The gratuitous restrictions on what can be specialized in C++ are annoying. +template > struct Is_sparse_impl : std::bool_constant {}; +template struct Is_sparse_impl> : std::bool_constant {}; +template constexpr bool is_sparse () { return Is_sparse_impl::value; } + +template class Compressed_sparse_matrix_ { + std::vector bounds; + std::vector entries; + + typedef typename std::vector::const_iterator iterator; + typedef boost::iterator_range iterator_pair; + + public: + iterator_pair subrange(const size_t index) const { + return {entries.begin() + (index == 0 ? 0 : bounds[index - 1]), + entries.begin() + bounds[index]}; + } + + // Close the current column, the next push_back will be for a new column + void append_column() { bounds.push_back(entries.size()); } + + void push_back(const ValueType e) { + GUDHI_assert(0 < bounds.size()); + entries.push_back(e); + ++bounds.back(); + } +}; + +/* concept SimplexEncoding +struct SimplexEncoding { + typedef dimension_t; + typedef vertex_t; + typedef simplex_t; // has to be an integer + SimplexEncoding(vertex_t n_vertices, dimension_t max_dim_plus_one); // max_vertices_per_simplex + simplex_t operator()(vertex_t v, dimension_t position) const; // position starts at 1? + vertex_t get_max_vertex(simplex_t s, dimension_t position, vertex_t n_vertices) const; + int num_extra_bits() const; +}; +*/ + +// number of bits necessary to store x with 0 <= x < n +template +constexpr int log2up(vertex_t n) { + --n; + int k = 0; + while(n>0) { n>>=1; ++k; } + return k; +} + +template +class Cns_encoding { + public: + typedef typename Params::dimension_t dimension_t; + typedef typename Params::vertex_t vertex_t; + typedef typename Params::simplex_t simplex_t; + + private: + std::vector> B; // table of binomial coefficients + int extra_bits; + + public: + Cns_encoding(vertex_t n, dimension_t k) : B(k + 1, std::vector(n + 1, 0)) { + static_assert(std::numeric_limits::radix == 2); + const int available_bits = std::numeric_limits::digits; + simplex_t max_simplex_index = 0; + for (vertex_t i = 0; i <= n; ++i) { + B[0][i] = 1; + for (dimension_t j = 1; (vertex_t)j < std::min(i, k + 1); ++j) + B[j][i] = B[j - 1][i - 1] + B[j][i - 1]; + if (i <= k) B[i][i] = 1; + vertex_t mi = std::min(i >> 1, (vertex_t)k); // max + max_simplex_index = B[mi][i]; + if (i > 1 && max_simplex_index < B[mi][i-1]) { // overflow + throw std::overflow_error("cannot encode all simplices of dimension " + std::to_string(k) + " with " + std::to_string(n) + " vertices using only " + std::to_string(available_bits) + " bits"); + } + } + extra_bits = available_bits - log2up(max_simplex_index + 1); + } + + simplex_t operator()(vertex_t n, dimension_t k) const { + GUDHI_assert(n >= k - 1); + return B[k][n]; + } + + // We could get `n` from B and avoid passing it as argument + vertex_t get_max_vertex(const simplex_t idx, const dimension_t k, const vertex_t n) const { + return get_max(n, k - 1, [&](vertex_t w) -> bool { return (*this)(w, k) <= idx; }); + } + + int num_extra_bits() const { return extra_bits; } + + private: + template + static vertex_t get_max(vertex_t top, const vertex_t bottom, const Predicate pred) { + if (!pred(top)) { + vertex_t count = top - bottom; + while (count > 0) { + vertex_t step = count >> 1, mid = top - step; + if (!pred(mid)) { + top = mid - 1; + count -= step + 1; + } else + count = step; + } + } + return top; + } +}; + +template +class Bitfield_encoding { + public: + typedef typename Params::dimension_t dimension_t; + typedef typename Params::vertex_t vertex_t; + typedef typename Params::simplex_t simplex_t; + + private: + int bits_per_vertex; + int extra_bits; + + public: + Bitfield_encoding(vertex_t n, dimension_t k) : bits_per_vertex(log2up(n)) { + static_assert(std::numeric_limits::radix == 2); + const int available_bits = std::numeric_limits::digits; + extra_bits = available_bits - bits_per_vertex * k; + if (extra_bits < 0) + throw std::overflow_error("cannot encode all simplices of dimension " + std::to_string(k - 1) + " with " + std::to_string(n) + " vertices using only " + std::to_string(available_bits) + " bits"); + // The message is a bit misleading, it is tuples that we cannot encode, and just with this representation. + } + + simplex_t operator()(vertex_t n, dimension_t k) const { + if(k==0) return 1; // because of odd use in (co)boundary... + --k; + // USE_N_MINUS_K only useful if it somehow helps remove the test k==0 above +#ifdef USE_N_MINUS_K + return (simplex_t)(n - k) << (bits_per_vertex * k); +#else + return (simplex_t)n << (bits_per_vertex * k); +#endif + } + + vertex_t get_max_vertex(const simplex_t idx, dimension_t k, const vertex_t) const { + GUDHI_assert(k > 0); + --k; +#ifdef USE_N_MINUS_K + return static_cast(idx >> (bits_per_vertex * k)) + k; +#else + return static_cast(idx >> (bits_per_vertex * k)); +#endif + } + + int num_extra_bits() const { return extra_bits; } +}; + +template struct Rips_filtration { + using size_t = typename Params::size_t; + using vertex_t = typename SimplexEncoding::vertex_t; + // static_assert(std::is_same_v); // too strict + using simplex_t = typename SimplexEncoding::simplex_t; + using dimension_t = typename SimplexEncoding::dimension_t; + using value_t = typename DistanceMatrix::value_t; + using coefficient_storage_t = typename Params::coefficient_storage_t; + using coefficient_t = typename Params::coefficient_t; + static constexpr bool use_coefficients = Params::use_coefficients; + + // The definition of entry_t could be added in some intermediate layer between SimplexEncoding and here + struct entry_with_coeff_t { + simplex_t content; + entry_with_coeff_t(simplex_t _index, coefficient_t _coefficient, int bits_for_coeff) + : content((_index << bits_for_coeff) | (_coefficient - 1)) { GUDHI_assert(_coefficient != 0); } + entry_with_coeff_t() {} + // We never store a coefficient of 0, so we can store coef-1 so %2 requires 0 bit and %3 only 1 bit + friend const entry_with_coeff_t& get_entry(const entry_with_coeff_t& e) { return e; } + }; + simplex_t get_index(const entry_with_coeff_t& e) const { return e.content >> num_bits_for_coeff(); } + coefficient_t get_coefficient(const entry_with_coeff_t& e) const { return static_cast(e.content & (((simplex_t)1 << num_bits_for_coeff()) - 1)) + 1; } + void set_coefficient(entry_with_coeff_t& e, const coefficient_t c) const { GUDHI_assert(c!=0); e.content = (e.content & ((simplex_t)(-1) << num_bits_for_coeff())) | (c - 1); } + // Should we cache the masks derived from num_bits_for_coeff? + + struct entry_plain_t { + simplex_t index; + entry_plain_t(simplex_t _index, coefficient_t, int) : index(_index) {} + entry_plain_t() {} + friend const entry_plain_t& get_entry(const entry_plain_t& e) { return e; } + }; + static simplex_t get_index(const entry_plain_t& i) { return i.index; } + static coefficient_t get_coefficient(const entry_plain_t& i) { return 1; } + static void set_coefficient(entry_plain_t& e, const coefficient_t c) { GUDHI_assert(c==1); } + + typedef std::conditional_t entry_t; + entry_t make_entry(simplex_t i, coefficient_t c) const { return entry_t(i, c, num_bits_for_coeff()); } + + static_assert(sizeof(entry_t) == sizeof(simplex_t), "size of entry_t is not the same as simplex_t"); + + // TODO: avoid storing filtp when !use_coefficients (same for Equal_index and greater_*) + struct Entry_hash { + Entry_hash(Rips_filtration const& filt) : filtp(&filt) {} + Rips_filtration const* filtp; + std::size_t operator()(const entry_t& e) const { return boost::hash()(filtp->get_index(e)); } + }; + + struct Equal_index { + Equal_index(Rips_filtration const& filt) : filtp(&filt) {} + Rips_filtration const* filtp; + bool operator()(const entry_t& e, const entry_t& f) const { + return filtp->get_index(e) == filtp->get_index(f); + } + }; + + struct diameter_simplex_t { + value_t diameter; + simplex_t index; + friend value_t get_diameter(const diameter_simplex_t& i) { return i.diameter; } + }; + static simplex_t get_index(const diameter_simplex_t& i) { return i.index; } + + struct diameter_entry_t : std::pair { + using std::pair::pair; + friend const entry_t& get_entry(const diameter_entry_t& p) { return p.second; } + friend entry_t& get_entry(diameter_entry_t& p) { return p.second; } + friend value_t get_diameter(const diameter_entry_t& p) { return p.first; } + }; + simplex_t get_index(const diameter_entry_t& p) const { return get_index(get_entry(p)); } + coefficient_t get_coefficient(const diameter_entry_t& p) const { + return get_coefficient(get_entry(p)); + } + void set_coefficient(diameter_entry_t& p, const coefficient_t c) const { + set_coefficient(get_entry(p), c); + } + diameter_entry_t make_diameter_entry(value_t diameter, simplex_t index, coefficient_t coefficient) const { + return diameter_entry_t(diameter, make_entry(index, coefficient)); + } + diameter_entry_t make_diameter_entry(const diameter_simplex_t& diameter_index, coefficient_t coefficient) const { + return diameter_entry_t(get_diameter(diameter_index), make_entry(get_index(diameter_index), coefficient)); + } + + template struct Greater_diameter_or_smaller_index { + Greater_diameter_or_smaller_index(Rips_filtration const& filt) : filtp(&filt) {} + Rips_filtration const* filtp; + bool operator()(const Entry& a, const Entry& b) const { + return (get_diameter(a) > get_diameter(b)) || + ((get_diameter(a) == get_diameter(b)) && (filtp->get_index(a) < filtp->get_index(b))); + } + }; + + const DistanceMatrix dist; // only store a reference instead? + const vertex_t n; // redundant with dist? + const dimension_t dim_max; + const value_t threshold; // It would be nice if this was only in DistanceMatrix, but inconvenient. Only used to list the edges of dense distance matrices. + const coefficient_t modulus; + const SimplexEncoding simplex_encoding; // only store a reference instead? + mutable std::vector vertices; // we must not have several threads looking at the same complex + int bits_for_coeff; + + Rips_filtration(DistanceMatrix&& _dist, dimension_t _dim_max, value_t _threshold, coefficient_t _modulus) + : dist(std::move(_dist)), n(dist.size()), + dim_max(std::min(_dim_max, dist.size() - 2)), threshold(_threshold), + modulus(_modulus), simplex_encoding(n, dim_max + 2), bits_for_coeff(log2up(modulus-1)) { + // See entry_with_coeff_t for the logic for log2up(modulus-1) (storing coeff-1) + if (use_coefficients && simplex_encoding.num_extra_bits() < num_bits_for_coeff()) + // TODO: include relevant numbers in the message + throw std::overflow_error("Not enough spare bits in the simplex encoding to store a coefficient"); + } + + vertex_t num_vertices() const { return n; } + int num_bits_for_coeff() const { return bits_for_coeff; } + + simplex_t get_edge_index(const vertex_t i, const vertex_t j) const { + return simplex_encoding(i, 2) + j; + } + + template + OutputIterator get_simplex_vertices(simplex_t idx, const dimension_t dim, vertex_t n, + OutputIterator out) const { + --n; + for (dimension_t k = dim + 1; k > 1; --k) { + n = simplex_encoding.get_max_vertex(idx, k, n); + *out++ = n; + idx -= simplex_encoding(n, k); + } + *out = static_cast(idx); + return out; + } + + value_t compute_diameter(const simplex_t index, const dimension_t dim) const { + value_t diam = -std::numeric_limits::infinity(); + + vertices.resize(dim + 1); + get_simplex_vertices(index, dim, dist.size(), vertices.rbegin()); + + for (dimension_t i = 0; i <= dim; ++i) + for (dimension_t j = 0; j < i; ++j) { + diam = std::max(diam, dist(vertices[i], vertices[j])); + } + return diam; + } + + std::vector get_edges() { + if constexpr (!std::is_same_v) { // Compressed_lower_distance_matrix + // TODO: it would be convenient to have DistanceMatrix provide a range of neighbors at dist<=threshold even in the dense case (as a filtered_range) + std::vector edges; + for (vertex_t i = 0; i < n; ++i) { + for (vertex_t j = 0; j < i; ++j) { + value_t length = dist(i, j); + if (length <= threshold) edges.push_back({length, get_edge_index(i, j)}); + } + } + return edges; + } else { // Sparse_distance_matrix + std::vector edges; + for (vertex_t i = 0; i < n; ++i) + for (auto n : dist.neighbors[i]) { + vertex_t j = get_vertex(n); + if (i > j) edges.push_back({get_diameter(n), get_edge_index(i, j)}); + } + return edges; + } + } + + // TODO: document in what way (if any) the order matters + template class Simplex_coboundary_enumerator_ { // Compressed_lower_distance_matrix + simplex_t idx_below, idx_above; + vertex_t j; + dimension_t k; + std::vector vertices; + diameter_entry_t simplex; + const DistanceMatrix2& dist; + const SimplexEncoding& simplex_encoding; + const Rips_filtration& parent; // for n and get_simplex_vertices + // at least dist and simplex_encoding are redundant with parent, but using parent.dist and parent.simplex_encoding seems to have a bad impact on performance. + + public: + Simplex_coboundary_enumerator_(const Rips_filtration& _parent) : dist(_parent.dist), + simplex_encoding(_parent.simplex_encoding), parent(_parent) {} + + void set_simplex(const diameter_entry_t _simplex, const dimension_t _dim) { + idx_below = parent.get_index(_simplex); + idx_above = 0; + j = dist.size() - 1; + k = _dim + 1; + simplex = _simplex; + vertices.resize(_dim + 1); + parent.get_simplex_vertices(parent.get_index(_simplex), _dim, dist.size(), vertices.rbegin()); + } + + bool has_next(bool all_cofacets = true) { + return (j >= k && (all_cofacets || simplex_encoding(j, k) > idx_below)); + } + + std::optional next_raw(bool all_cofacets = true) { + if (!has_next(all_cofacets)) return std::nullopt; + // this requires simplex_encoding(x,0)>0 + while (simplex_encoding(j, k) <= idx_below) { + idx_below -= simplex_encoding(j, k); + idx_above += simplex_encoding(j, k + 1); + --j; + --k; + GUDHI_assert(k != -1); + } + value_t cofacet_diameter = get_diameter(simplex); + // The order of j and i matters for performance + for (vertex_t i : vertices) cofacet_diameter = std::max(cofacet_diameter, dist(j, i)); + simplex_t cofacet_index = idx_above + simplex_encoding(j--, k + 1) + idx_below; + coefficient_t cofacet_coefficient = parent.get_coefficient(simplex); + if (k & 1) cofacet_coefficient = parent.modulus - cofacet_coefficient; + return parent.make_diameter_entry(cofacet_diameter, cofacet_index, cofacet_coefficient); + } + std::optional next(bool all_cofacets = true) { + while(true) { + std::optional res = next_raw(all_cofacets); + if(!res || get_diameter(*res) <= parent.threshold) return res; + } + } + }; + + template class Simplex_coboundary_enumerator_ { + typedef typename DistanceMatrix2::vertex_diameter_t vertex_diameter_t; + simplex_t idx_below, idx_above; + dimension_t k; + std::vector vertices; + diameter_entry_t simplex; + const DistanceMatrix2& dist; + const SimplexEncoding& simplex_encoding; + std::vector::const_reverse_iterator> neighbor_it; + std::vector::const_reverse_iterator> neighbor_end; + vertex_diameter_t neighbor; + const Rips_filtration& parent; // for n and get_simplex_vertices + + public: + Simplex_coboundary_enumerator_(const Rips_filtration& _parent) + : dist(_parent.dist), + simplex_encoding(_parent.simplex_encoding), parent(_parent) {} + + void set_simplex(const diameter_entry_t _simplex, const dimension_t _dim) { + idx_below = parent.get_index(_simplex); + idx_above = 0; + k = _dim + 1; + simplex = _simplex; + vertices.resize(_dim + 1); + parent.get_simplex_vertices(idx_below, _dim, dist.size(), vertices.rbegin()); + + neighbor_it.resize(_dim + 1); + neighbor_end.resize(_dim + 1); + for (dimension_t i = 0; i <= _dim; ++i) { + auto v = vertices[i]; + neighbor_it[i] = dist.neighbors[v].rbegin(); + neighbor_end[i] = dist.neighbors[v].rend(); + } + } + + bool has_next(bool all_cofacets = true) { + for (auto &it0 = neighbor_it[0], &end0 = neighbor_end[0]; it0 != end0; ++it0) { + neighbor = *it0; + for (size_t idx = 1; idx < neighbor_it.size(); ++idx) { + auto &it = neighbor_it[idx], end = neighbor_end[idx]; + while (get_vertex(*it) > get_vertex(neighbor)) + if (++it == end) return false; + if (get_vertex(*it) != get_vertex(neighbor)) + goto continue_outer; + else + neighbor = std::max(neighbor, *it); + } + while (k > 0 && vertices[k - 1] > get_vertex(neighbor)) { + if (!all_cofacets) return false; + idx_below -= simplex_encoding(vertices[k - 1], k); + idx_above += simplex_encoding(vertices[k - 1], k + 1); + --k; + } + return true; +continue_outer:; + } + return false; + } + + std::optional next_raw(bool all_cofacets = true) { + if (!has_next(all_cofacets)) return std::nullopt; + ++neighbor_it[0]; + value_t cofacet_diameter = std::max(get_diameter(simplex), get_diameter(neighbor)); + simplex_t cofacet_index = idx_above + simplex_encoding(get_vertex(neighbor), k + 1) + idx_below; + const coefficient_t modulus = parent.modulus; + coefficient_t cofacet_coefficient = + (k & 1 ? modulus - 1 : 1) * parent.get_coefficient(simplex) % modulus; + return parent.make_diameter_entry(cofacet_diameter, cofacet_index, cofacet_coefficient); + } + std::optional next(bool all_cofacets = true) { + return next_raw(all_cofacets); + } + }; + + typedef Simplex_coboundary_enumerator_ Simplex_coboundary_enumerator; + + class Simplex_boundary_enumerator { + private: + simplex_t idx_below, idx_above; + vertex_t j; + dimension_t k; + diameter_entry_t simplex; + dimension_t dim; + const SimplexEncoding& simplex_encoding; + const Rips_filtration& parent; // for n, get_max_vertex, compute_diameter + + public: + Simplex_boundary_enumerator(const Rips_filtration& _parent) + : simplex_encoding(_parent.simplex_encoding), parent(_parent) {} + + void set_simplex(const diameter_entry_t _simplex, const dimension_t _dim) { + idx_below = parent.get_index(_simplex); + idx_above = 0; + j = parent.n - 1; + k = _dim; + simplex = _simplex; + dim = _dim; + } + + bool has_next() { return (k >= 0); } + + std::optional next() { + if (!has_next()) return std::nullopt; + j = simplex_encoding.get_max_vertex(idx_below, k + 1, j); + + simplex_t face_index = idx_above - simplex_encoding(j, k + 1) + idx_below; + + // It would make sense to extract the vertices once in set_simplex + // and pass the proper subset to compute_diameter, but even in cases + // where this dominates it does not seem to help (probably because we + // stop at the first coface). + value_t face_diameter = parent.compute_diameter(face_index, dim - 1); + + const coefficient_t modulus = parent.modulus; + coefficient_t face_coefficient = + (k & 1 ? -1 + modulus : 1) * parent.get_coefficient(simplex) % modulus; + + idx_below -= simplex_encoding(j, k + 1); + idx_above += simplex_encoding(j, k); + + --k; + + return parent.make_diameter_entry(face_diameter, face_index, face_coefficient); + } + }; +}; + +#if BOOST_VERSION >= 108100 +template using Hash_map = boost::unordered_flat_map; +#else +template using Hash_map = boost::unordered_map; +#endif + +template class Persistent_cohomology { + using size_t = typename Filtration::size_t; + using coefficient_t = typename Filtration::coefficient_t; + using coefficient_storage_t = typename Filtration::coefficient_storage_t; + using dimension_t = typename Filtration::dimension_t; + using value_t = typename Filtration::value_t; + using vertex_t = typename Filtration::vertex_t; + using simplex_t = typename Filtration::simplex_t; + using diameter_simplex_t = typename Filtration::diameter_simplex_t; + using entry_t = typename Filtration::entry_t; + using diameter_entry_t = typename Filtration::diameter_entry_t; + using Entry_hash = typename Filtration::Entry_hash; + using Equal_index = typename Filtration::Equal_index; + using Simplex_boundary_enumerator = typename Filtration::Simplex_boundary_enumerator; + using Simplex_coboundary_enumerator = typename Filtration::Simplex_coboundary_enumerator; + templateusing Greater_diameter_or_smaller_index = typename Filtration::template Greater_diameter_or_smaller_index; + + typedef Compressed_sparse_matrix_ Compressed_sparse_matrix; + typedef Hash_map entry_hash_map; + + Filtration filt; + const vertex_t n; + const dimension_t dim_max; + const coefficient_t modulus; + const std::vector multiplicative_inverse_; + mutable std::vector cofacet_entries; + mutable std::vector vertices; + Simplex_boundary_enumerator facets; + // Creating a new one in each function that needs it wastes a bit of time, but we may need 2 at the same time. + Simplex_coboundary_enumerator cofacets1, cofacets2; + + coefficient_t multiplicative_inverse(coefficient_t c) const { + return multiplicative_inverse_[c]; + } + public: + Persistent_cohomology(Filtration&& _filt, dimension_t _dim_max, coefficient_t _modulus) + : filt(std::move(_filt)), n(filt.num_vertices()), + dim_max(std::min(_dim_max, n - 2)), + modulus(_modulus), + multiplicative_inverse_(multiplicative_inverse_vector(_modulus)), + facets(filt), cofacets1(filt), cofacets2(filt) + { + } + + + std::optional get_zero_pivot_facet(const diameter_entry_t simplex, const dimension_t dim) { + facets.set_simplex(simplex, dim); + while(true) { + std::optional facet = facets.next(); + if (!facet) break; + if (get_diameter(*facet) == get_diameter(simplex)) return *facet; + } + return std::nullopt; + } + + std::optional get_zero_pivot_cofacet(const diameter_entry_t simplex, const dimension_t dim) { + cofacets1.set_simplex(simplex, dim); + while(true) { + std::optional cofacet = cofacets1.next_raw(); + if (!cofacet) break; + if (get_diameter(*cofacet) == get_diameter(simplex)) return *cofacet; + } + return std::nullopt; + } + + // Apparent pairs are implicit in Ripser. + // pro: we don't need to store them + // con: we may have to recompute them many times, and each test is more expensive than emergent pairs + std::optional get_zero_apparent_facet(const diameter_entry_t simplex, const dimension_t dim) { + std::optional facet = get_zero_pivot_facet(simplex, dim); + if (!facet) return std::nullopt; + std::optional cofacet = get_zero_pivot_cofacet(*facet, dim - 1); + if (!cofacet || filt.get_index(*cofacet) != filt.get_index(simplex)) return std::nullopt; + return *facet; + } + + std::optional get_zero_apparent_cofacet(const diameter_entry_t simplex, const dimension_t dim) { + std::optional cofacet = get_zero_pivot_cofacet(simplex, dim); + if (!cofacet) return std::nullopt; + std::optional facet = get_zero_pivot_facet(*cofacet, dim + 1); + if (!facet || filt.get_index(*facet) != filt.get_index(simplex)) return std::nullopt; + return *cofacet; + } + + bool is_in_zero_apparent_pair(const diameter_entry_t simplex, const dimension_t dim) { + return get_zero_apparent_cofacet(simplex, dim) || get_zero_apparent_facet(simplex, dim); + } + + void assemble_columns_to_reduce(std::vector& simplices, + std::vector& columns_to_reduce, + entry_hash_map& pivot_column_index, dimension_t dim) { + +#ifdef GUDHI_INDICATE_PROGRESS + std::cerr << clear_line << "assembling columns" << std::flush; + std::chrono::steady_clock::time_point next = std::chrono::steady_clock::now() + time_step; +#endif + + columns_to_reduce.clear(); + std::vector next_simplices; + + for (diameter_simplex_t& simplex : simplices) { + cofacets2.set_simplex(filt.make_diameter_entry(simplex, 1), dim - 1); + + while(true) { + std::optional cofacet = cofacets2.next(false); + if (!cofacet) break; +#ifdef GUDHI_INDICATE_PROGRESS + if (std::chrono::steady_clock::now() > next) { + std::cerr << clear_line << "assembling " << next_simplices.size() + << " columns (processing " << std::distance(&simplices[0], &simplex) + << "/" << simplices.size() << " simplices)" << std::flush; + next = std::chrono::steady_clock::now() + time_step; + } +#endif + if (dim < dim_max) next_simplices.push_back({get_diameter(*cofacet), filt.get_index(*cofacet)}); + // Wouldn't it be cheaper in the reverse order? Seems negligible + if (!is_in_zero_apparent_pair(*cofacet, dim) && + (pivot_column_index.find(get_entry(*cofacet)) == pivot_column_index.end())) + columns_to_reduce.push_back({get_diameter(*cofacet), filt.get_index(*cofacet)}); + } + } + + if (dim < dim_max) simplices.swap(next_simplices); + +#ifdef GUDHI_INDICATE_PROGRESS + std::cerr << clear_line << "sorting " << columns_to_reduce.size() << " columns" + << std::flush; +#endif + + std::sort(columns_to_reduce.begin(), columns_to_reduce.end(), + Greater_diameter_or_smaller_index(filt)); +#ifdef GUDHI_INDICATE_PROGRESS + std::cerr << clear_line << std::flush; +#endif + } + + template + void compute_dim_0_pairs(std::vector& edges, + std::vector& columns_to_reduce, OutPair& output_pair) { + Union_find dset(n); + + edges = filt.get_edges(); + std::sort(edges.rbegin(), edges.rend(), + Greater_diameter_or_smaller_index(filt)); + std::vector vertices_of_edge(2); + for (auto e : edges) { + // Should we work with pairs of vertices instead of edges, to skip get_simplex_vertices? + filt.get_simplex_vertices(filt.get_index(e), 1, n, vertices_of_edge.rbegin()); + vertex_t u = dset.find(vertices_of_edge[0]), v = dset.find(vertices_of_edge[1]); + + if (u != v) { + if (get_diameter(e) != 0) + output_pair(0, get_diameter(e)); + dset.link(u, v); + } else if ((dim_max > 0) && !get_zero_apparent_cofacet(filt.make_diameter_entry(e, 1), 1)) + columns_to_reduce.push_back(e); + } + if (dim_max > 0) std::reverse(columns_to_reduce.begin(), columns_to_reduce.end()); + + for (vertex_t i = 0; i < n; ++i) + if (dset.find(i) == i) output_pair(0, std::numeric_limits::infinity()); + } + + template std::optional pop_pivot(Column& column) { + while(!column.empty()) { // At this stage the partial sum is 0 + diameter_entry_t pivot = column.top(); + column.pop(); + while(true) { // At this stage the partial sum is led by pivot + if (column.empty() || filt.get_index(column.top()) != filt.get_index(pivot)) return pivot; + coefficient_t sum = (filt.get_coefficient(pivot) + filt.get_coefficient(column.top())) % modulus; + column.pop(); + if (sum == 0) { + break; + } + filt.set_coefficient(pivot, sum); + } + } + return std::nullopt; + } + + template std::optional get_pivot(Column& column) { + // We could look for the pivot without needing to push it back, but it does not seem to help in benchmarks. + std::optional result = pop_pivot(column); + if (result) column.push(*result); + return result; + } + + // Either return the pivot in an emergent pair, or fill working_coboundary with the full coboundary (and return its pivot) + template + std::optional init_coboundary_and_get_pivot(const diameter_entry_t simplex, + Column& working_coboundary, const dimension_t dim, + entry_hash_map& pivot_column_index) { + bool check_for_emergent_pair = true; + cofacet_entries.clear(); + cofacets2.set_simplex(simplex, dim); + while(true) { + std::optional cofacet = cofacets2.next(); + if (!cofacet) break; + cofacet_entries.push_back(*cofacet); + if (check_for_emergent_pair && (get_diameter(simplex) == get_diameter(*cofacet))) { + if ((pivot_column_index.find(get_entry(*cofacet)) == pivot_column_index.end()) && + !get_zero_apparent_facet(*cofacet, dim + 1)) + return *cofacet; + check_for_emergent_pair = false; + } + } + for (auto cofacet : cofacet_entries) working_coboundary.push(cofacet); + return get_pivot(working_coboundary); + } + + // Beyond apparent/emergent pairs, Ripser does the column reduction eagerly. + // To keep with the lazy paradigm, it would be possible to represent a column as a heap of coboundary_iterator, using the order of the current simplices pointed to by the iterators. The equivalent of `pop` would be ++ on the top iterator, which decreases its priority (or removes it if it reached the end). If we do it right, it could also help us notice if we have twice the same iterator and avoid computing its full coboundary twice (although we may still end up computing the first simplex of the coboundary for both, since it may be the easiest way to detect duplicates without maintaining yet another structure on the side). Another advantage is that its size would be bounded by the number of simplices of dimension d instead of d+1 currently. (Dory seems to do something related but too complicated for me.) + template + void add_simplex_coboundary(const diameter_entry_t simplex, const dimension_t dim, + Column& working_reduction_column, Column& working_coboundary) { + working_reduction_column.push(simplex); + cofacets1.set_simplex(simplex, dim); + while(true) { // stupid C++ + std::optional cofacet = cofacets1.next(); + if (!cofacet) break; + working_coboundary.push(*cofacet); + } + } + + // add an already reduced column, i.e. add all the simplex coboundaries that were involved in that reduction + template + void add_coboundary(Compressed_sparse_matrix& reduction_matrix, + const std::vector& columns_to_reduce, + const size_t index_column_to_add, const coefficient_t factor, + const dimension_t dim, Column& working_reduction_column, + Column& working_coboundary) { + diameter_entry_t column_to_add = filt.make_diameter_entry(columns_to_reduce[index_column_to_add], factor); + add_simplex_coboundary(column_to_add, dim, working_reduction_column, working_coboundary); + + for (diameter_entry_t simplex : reduction_matrix.subrange(index_column_to_add)) { + filt.set_coefficient(simplex, filt.get_coefficient(simplex) * factor % modulus); + add_simplex_coboundary(simplex, dim, working_reduction_column, working_coboundary); + } + } + + template + void compute_pairs(const std::vector& columns_to_reduce, + entry_hash_map& pivot_column_index, const dimension_t dim, OutPair& output_pair) { + Compressed_sparse_matrix reduction_matrix; + Greater_diameter_or_smaller_index cmp(filt); + Heap, + Greater_diameter_or_smaller_index> + working_reduction_column(cmp), working_coboundary(cmp); + +#ifdef GUDHI_INDICATE_PROGRESS + std::chrono::steady_clock::time_point next = std::chrono::steady_clock::now() + time_step; +#endif + for (size_t index_column_to_reduce = 0; index_column_to_reduce < columns_to_reduce.size(); + ++index_column_to_reduce) { + + diameter_entry_t column_to_reduce = filt.make_diameter_entry(columns_to_reduce[index_column_to_reduce], 1); + value_t diameter = get_diameter(column_to_reduce); + + reduction_matrix.append_column(); + + working_reduction_column.clear(); working_coboundary.clear(); + + std::optional pivot = init_coboundary_and_get_pivot( + column_to_reduce, working_coboundary, dim, pivot_column_index); + // When we found an emergent pair, we could avoid checking again below, but it does not seem to gain anything in practice. + + while (true) { +#ifdef GUDHI_INDICATE_PROGRESS + if (std::chrono::steady_clock::now() > next) { + std::cerr << clear_line << "reducing column " << index_column_to_reduce + 1 + << "/" << columns_to_reduce.size() << " (diameter " << diameter << ")" + << std::flush; + next = std::chrono::steady_clock::now() + time_step; + } +#endif + if (pivot) { + auto pair = pivot_column_index.find(get_entry(*pivot)); + if (pair != pivot_column_index.end()) { + entry_t other_pivot = pair->first; + size_t index_column_to_add = pair->second; + coefficient_t factor = + modulus - filt.get_coefficient(*pivot) * + multiplicative_inverse(filt.get_coefficient(other_pivot)) % + modulus; + + // It saves a little bit (3% on an example, 0% on another) if we pass pivot to add_coboundary and avoid pushing entries smaller than pivot in working_coboundary + add_coboundary(reduction_matrix, columns_to_reduce, index_column_to_add, + factor, dim, working_reduction_column, working_coboundary); + + pivot = get_pivot(working_coboundary); + } else if (std::optional e = get_zero_apparent_facet(*pivot, dim + 1); e) { + filt.set_coefficient(*e, modulus - filt.get_coefficient(*e)); + + add_simplex_coboundary(*e, dim, working_reduction_column, working_coboundary); + + pivot = get_pivot(working_coboundary); + } else { + value_t death = get_diameter(*pivot); + output_pair(diameter, death); + pivot_column_index.insert({get_entry(*pivot), index_column_to_reduce}); + // CubicalRipser suggests caching the column here, at least if it took many operations to reduce it. + + while (true) { + std::optional e = pop_pivot(working_reduction_column); + if (!e) break; + GUDHI_assert(filt.get_coefficient(*e) > 0); + reduction_matrix.push_back(*e); + } + break; + } + } else { + output_pair(diameter, std::numeric_limits::infinity()); + break; + } + } + } +#ifdef GUDHI_INDICATE_PROGRESS + std::cerr << clear_line << std::flush; +#endif + } + + // Add a separate output_essential? + // TODO: Should output_pair also take a simplex_t argument? + template + void compute_barcodes(OutDim&& output_dim, OutPair&& output_pair) { + std::vector simplices, columns_to_reduce; + + output_dim(0); + compute_dim_0_pairs(simplices, columns_to_reduce, output_pair); + + for (dimension_t dim = 1; dim <= dim_max; ++dim) { + entry_hash_map pivot_column_index(0, filt, filt); + pivot_column_index.reserve(columns_to_reduce.size()); + + output_dim(dim); + compute_pairs(columns_to_reduce, pivot_column_index, dim, output_pair); + + if (dim < dim_max) + assemble_columns_to_reduce(simplices, columns_to_reduce, pivot_column_index, + dim + 1); + // If for some odd reason one wanted all the infinite intervals in the last dimension, assemble_columns_to_reduce should give us that. + } + } +}; + +// An example of what Params can be +#if 0 +struct Params1 { + // size_t (not always from Params...) is used for counting (ok) and storage for the index of columns in a Hash_map. + // To gain on a pair by reducing size_t, simplex_t has to be smaller than size_t I guess, which is very small, not worth it. + typedef std::size_t size_t; + typedef float value_t; + typedef int8_t dimension_t; // Does it need to be signed? Experimentally no. + typedef int vertex_t; // Currently needs to be signed for Simplex_coboundary_enumerator_::has_next. Reducing to int16_t helps perf a bit. + typedef Gudhi::numbers::uint128_t simplex_t; + // We could introduce a smaller edge_t, but it is not trivial to separate and probably not worth it + typedef uint16_t coefficient_storage_t; // For the table of multiplicative inverses + typedef uint_least32_t coefficient_t; // We need x * y % z to work, but promotion from uint16_t to int is not enough + static const bool use_coefficients = false; + + // Assumptions used in the code: + // * dimension_t smaller than vertex_t + // Check which ones need to be signed, and which ones could be unsigned instead +}; +#endif + +// Trying to write a magic function +template +void help2(DistanceMatrix&& dist, int dim_max, typename DistanceMatrix::value_t threshold, unsigned modulus, OutDim&& output_dim, OutPair&& output_pair) { + typedef Rips_filtration Filt; + typedef Persistent_cohomology Pcoh; + Filt filt(std::move(dist), dim_max, threshold, modulus); + Pcoh(std::move(filt), dim_max, modulus).compute_barcodes(output_dim, output_pair); +} +template struct TParams { + // hardcode most options + typedef std::size_t size_t; + typedef value_t_ value_t; + typedef int8_t dimension_t; + typedef int vertex_t; + typedef simplex_t_ simplex_t; + typedef uint16_t coefficient_storage_t; + typedef uint_least32_t coefficient_t; + static const bool use_coefficients = use_coefficients_; +}; +template struct TParams2 { + typedef int vertex_t; + typedef value_t_ value_t; +}; +// Choose simplex encoding +template +void help1(DistanceMatrix&& dist, int dim_max, typename DistanceMatrix::value_t threshold, unsigned modulus, OutDim&& output_dim, OutPair&& output_pair) { + auto n = dist.size(); + // TODO: if n>=3 we could even go to n-3, because the Rips cannot have homology in dimension n-2 + // (e.g. for 3 points, there is no 1-homology) + if (dim_max > n - 2) dim_max = n - 2; // FIXME: duplicated. problem if n unsigned and 0 or 1. + int bits_per_vertex = log2up(n); + int bits_for_coeff = log2up(modulus - 1); // duplicating logic :-( Also, if modulus is something absurd, the diagnostic is too late + int bitfield_size = bits_per_vertex * (dim_max + 2) + bits_for_coeff; + if (bitfield_size <= 64) { // use bitfield-64 + typedef TParams P; + help2>(std::move(dist), dim_max, threshold, modulus, output_dim, output_pair); + } else if (bitfield_size <= 128) { // use bitfield-128 + typedef TParams P; + help2>(std::move(dist), dim_max, threshold, modulus, output_dim, output_pair); + } else { // use cns-128 + typedef TParams P; + help2>(std::move(dist), dim_max, threshold, modulus, output_dim, output_pair); + } + // Does cns-64 have its place? +} +// Select hardcoded Z/2Z or runtime Z/pZ +template +void ripser(DistanceMatrix dist, int dim_max, typename DistanceMatrix::value_t threshold, unsigned modulus, OutDim&& output_dim, OutPair&& output_pair) { + if (modulus == 2) + help1(std::move(dist), dim_max, threshold, modulus, output_dim, output_pair); + else + help1(std::move(dist), dim_max, threshold, modulus, output_dim, output_pair); +} +#if 0 +template +void ripser_auto(Sparse_distance_matrix dist, int dim_max, typename DMParams::value_t threshold, unsigned modulus, OutDim&& output_dim, OutPair&& output_pair) { + ripser(std::move(dist), dim_max, threshold, modulus, output_dim, output_pair); +} +template +void ripser_auto(Compressed_distance_matrix dist, int dim_max, typename DMParams::value_t threshold, unsigned modulus, OutDim&& output_dim, OutPair&& output_pair) { + typedef typename DMParams::value_t value_t; + typedef typename DMParams::vertex_t vertex_t; + if (threshold < std::numeric_limits::max()) { // or infinity() + Sparse_distance_matrix new_dist(dist, threshold); + ripser(std::move(new_dist), dim_max, threshold, modulus, output_dim, output_pair); + } else { + for (vertex_t i = 0; i < dist.size(); ++i) { + value_t r_i = -std::numeric_limits::infinity(); + for (vertex_t j = 0; j < dist.size(); ++j) + r_i = std::max(r_i, dist(i, j)); + threshold = std::min(threshold, r_i); + // Should we also compute this when an explicit threshold is passed, in case the user passed an unnecessarily large threshold? + } + ripser(std::move(dist), dim_max, threshold, modulus, output_dim, output_pair); + } +} +// Other = Euclidean. TODO: more robust dispatching... (how?) +template +void ripser_auto(DistanceMatrix dist, int dim_max, typename DistanceMatrix::value_t threshold, unsigned modulus, OutDim&& output_dim, OutPair&& output_pair) { + typedef typename DistanceMatrix::value_t value_t; + typedef TParams2 P; + if (threshold < std::numeric_limits::max()) { // or infinity() + Sparse_distance_matrix

new_dist(dist, threshold); + ripser(std::move(new_dist), dim_max, threshold, modulus, output_dim, output_pair); + } else { + Compressed_distance_matrix new_dist(dist); + ripser(std::move(new_dist), dim_max, threshold, modulus, output_dim, output_pair); + } +} +#endif +template +void ripser_auto(DistanceMatrix dist, int dim_max, typename DistanceMatrix::value_t threshold, unsigned modulus, OutDim&& output_dim, OutPair&& output_pair) { + typedef typename DistanceMatrix::vertex_t vertex_t; + typedef typename DistanceMatrix::value_t value_t; + typedef TParams2 P; + if constexpr (std::is_same_v) { + ripser(std::move(dist), dim_max, threshold, modulus, output_dim, output_pair); + } else if (threshold < std::numeric_limits::max()) { // or infinity() + Sparse_distance_matrix

new_dist(dist, threshold); + ripser(std::move(new_dist), dim_max, threshold, modulus, output_dim, output_pair); + } else if constexpr (std::is_same_v) { + for (vertex_t i = 0; i < dist.size(); ++i) { + value_t r_i = -std::numeric_limits::infinity(); + for (vertex_t j = 0; j < dist.size(); ++j) + r_i = std::max(r_i, dist(i, j)); + threshold = std::min(threshold, r_i); + // Should we also compute this when an explicit threshold is passed, in case the user passed an unnecessarily large threshold? + } + ripser(std::move(dist), dim_max, threshold, modulus, output_dim, output_pair); + } else { + Compressed_distance_matrix new_dist(dist); + ripser_auto(std::move(new_dist), dim_max, threshold, modulus, output_dim, output_pair); + } +} +// - sparse input -> sparse matrix +// - euclidean input & threshold -> sparse matrix (don't build dense matrix) +// - euclidean input & !threshold -> dense matrix +// - dense matrix & threshold -> sparse matrix +// - dense matrix & !threshold -> compute minmax, keep dense +} +#undef GUDHI_assert +#endif // GUDHI_RIPSER_H + +/* Relevant benchmarks where different functions dominate the profile +# push +ripser --format point-cloud ripser/examples/o3_1024.txt +# pop +ripser --format point-cloud ripser/examples/o3_4096.txt --threshold 1.6 +# apparent_pair (get_simplex_vertices + dist) - edge_collapse would help +ripser --format point-cloud --dim 2 --threshold .7 tore +# apparent_pair (get_simplex_vertices) - no edge collapse possible +ripser --format point-cloud circle24 --dim 25 + +where equivalent datasets can be obtained through + tore -> tore3D_1307.off + circle24: + t=np.linspace(0, 2*np.pi, 24, endpoint=False) + np.stack((np.cos(t),np.sin(t))).T + OR + gudhi.datasets.generators.points.torus(24,1,'grid') + o3 (?): + scipy.stats.ortho_group.rvs(3,4096).reshape(-1,9) +*/ diff --git a/src/Ripser/utilities/CMakeLists.txt b/src/Ripser/utilities/CMakeLists.txt new file mode 100644 index 0000000000..fac8513523 --- /dev/null +++ b/src/Ripser/utilities/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(ripser ripser.cc) +install(TARGETS ripser DESTINATION bin) +add_test(NAME ripser_lower COMMAND $ --format lower --dim 2 --threshold .7 "${CMAKE_SOURCE_DIR}/data/distance_matrix/tore3D_1307_distance_matrix.csv") diff --git a/src/Ripser/utilities/ripser.cc b/src/Ripser/utilities/ripser.cc new file mode 100644 index 0000000000..6dabba826b --- /dev/null +++ b/src/Ripser/utilities/ripser.cc @@ -0,0 +1,391 @@ +/* Based on Ripser commit 140670f2c76997404601e43d8054151f46be9fd7 + * Modification(s): + * - YYYY/MM Author: Description of the modification + * - 2024 Marc Glisse: Heavy refactoring +*/ + +/* + + Ripser: a lean C++ code for computation of Vietoris-Rips persistence barcodes + + MIT License + + Copyright (c) 2015–2021 Ulrich Bauer + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + You are under no obligation whatsoever to provide any bug fixes, patches, or + upgrades to the features, functionality or performance of the source code + ("Enhancements") to anyone; however, if you choose to make your Enhancements + available either publicly, or directly to the author of this software, without + imposing a separate written license agreement for such Enhancements, then you + hereby grant the following license: a non-exclusive, royalty-free perpetual + license to install, use, modify, prepare derivative works, incorporate into + other computer software, distribute, and sublicense such enhancements or + derivative works thereof, in binary and source code form. + +*/ + +//#define GUDHI_INDICATE_PROGRESS + +#include +#include +#include +#include + +using Gudhi::ripser::ripser; + +struct Params { + typedef float value_t; + typedef int8_t dimension_t; + typedef int vertex_t; + typedef uint_least32_t coefficient_t; +}; + +typedef Params::value_t value_t; +typedef Params::dimension_t dimension_t; +typedef Params::vertex_t vertex_t; +typedef Params::coefficient_t coefficient_t; + +typedef Gudhi::ripser::Full_distance_matrix Full_distance_matrix; +typedef Gudhi::ripser::Compressed_distance_matrix Compressed_lower_distance_matrix; +typedef Gudhi::ripser::Compressed_distance_matrix Compressed_upper_distance_matrix; +typedef Gudhi::ripser::Sparse_distance_matrix Sparse_distance_matrix; +typedef Gudhi::ripser::Euclidean_distance_matrix Euclidean_distance_matrix; + +enum file_format { + LOWER_DISTANCE_MATRIX, + UPPER_DISTANCE_MATRIX, + DISTANCE_MATRIX, + POINT_CLOUD, + DIPHA, + SPARSE, + BINARY +}; + +static constexpr uint16_t endian_check=0xff00; +static bool is_big_endian() { return *reinterpret_cast(&endian_check); } + +template T read(std::istream& input_stream) { + T result; + char* p = reinterpret_cast(&result); + if (input_stream.read(p, sizeof(T)).gcount() != sizeof(T)) return T(); + if (is_big_endian()) std::reverse(p, p + sizeof(T)); + return result; +} + +Euclidean_distance_matrix read_point_cloud(std::istream& input_stream) { + std::vector> points; + + std::string line; + value_t value; + while (std::getline(input_stream, line)) { + std::vector point; + std::istringstream s(line); + while (s >> value) { + point.push_back(value); + s.ignore(); + } + if (!point.empty()) points.push_back(point); + assert(point.size() == points.front().size()); + } + + std::size_t d = points.front().size(); + Euclidean_distance_matrix eucl_dist(std::move(points)); + vertex_t n = eucl_dist.size(); + std::cout << "point cloud with " << n << " points in dimension " + << d << std::endl; + + return eucl_dist; +} + +Sparse_distance_matrix read_sparse_distance_matrix(std::istream& input_stream) { + typedef typename Sparse_distance_matrix::vertex_diameter_t vertex_diameter_t; + std::vector> neighbors; + std::size_t num_edges = 0; + + std::string line; + while (std::getline(input_stream, line)) { + std::istringstream s(line); + std::size_t i, j; + value_t value; + s >> i; + s.ignore(); + s >> j; + s.ignore(); + s >> value; + s.ignore(); + if (i != j) { + neighbors.resize(std::max({neighbors.size(), i + 1, j + 1})); + neighbors[i].emplace_back(j, value); + neighbors[j].emplace_back(i, value); + ++num_edges; + } + } + + for (std::size_t i = 0; i < neighbors.size(); ++i) + std::sort(neighbors[i].begin(), neighbors[i].end()); + + return Sparse_distance_matrix(std::move(neighbors), num_edges); +} + +Compressed_lower_distance_matrix read_lower_distance_matrix(std::istream& input_stream) { + std::vector distances; + value_t value; + while (input_stream >> value) { + distances.push_back(value); + input_stream.ignore(); + } + + return Compressed_lower_distance_matrix(std::move(distances)); +} + +Compressed_lower_distance_matrix read_upper_distance_matrix(std::istream& input_stream) { + std::vector distances; + value_t value; + while (input_stream >> value) { + distances.push_back(value); + input_stream.ignore(); + } + + return Compressed_lower_distance_matrix(Compressed_upper_distance_matrix(std::move(distances))); +} + +Compressed_lower_distance_matrix read_distance_matrix(std::istream& input_stream) { + std::vector distances; + + std::string line; + value_t value; + for (int i = 0; std::getline(input_stream, line); ++i) { + std::istringstream s(line); + for (int j = 0; j < i && s >> value; ++j) { + distances.push_back(value); + s.ignore(); + } + } + + return Compressed_lower_distance_matrix(std::move(distances)); +} + +Compressed_lower_distance_matrix read_dipha(std::istream& input_stream) { + if (read(input_stream) != 8067171840) { + std::cerr << "input is not a Dipha file (magic number: 8067171840)" << std::endl; + exit(-1); + } + + if (read(input_stream) != 7) { + std::cerr << "input is not a Dipha distance matrix (file type: 7)" << std::endl; + exit(-1); + } + + vertex_t n = read(input_stream); + + std::vector distances; + + for (vertex_t i = 0; i < n; ++i) + for (vertex_t j = 0; j < n; ++j) + if (i > j) + distances.push_back(read(input_stream)); + else + read(input_stream); + + return Compressed_lower_distance_matrix(std::move(distances)); +} + +Compressed_lower_distance_matrix read_binary(std::istream& input_stream) { + std::vector distances; + while (!input_stream.eof()) distances.push_back(read(input_stream)); + return Compressed_lower_distance_matrix(std::move(distances)); +} + +Compressed_lower_distance_matrix read_file(std::istream& input_stream, const file_format format) { + switch (format) { + case LOWER_DISTANCE_MATRIX: + return read_lower_distance_matrix(input_stream); + case UPPER_DISTANCE_MATRIX: + return read_upper_distance_matrix(input_stream); + case DISTANCE_MATRIX: + return read_distance_matrix(input_stream); + case POINT_CLOUD: + return read_point_cloud(input_stream); + case DIPHA: + return read_dipha(input_stream); + default: + return read_binary(input_stream); + } +} + +void print_usage_and_exit(int exit_code) { + std::cerr + << "Usage: " + << "ripser " + << "[options] [filename]" << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " --help print this screen" << std::endl + << " --format use the specified file format for the input. Options are:" + << std::endl + << " lower-distance (lower triangular distance matrix)" + << std::endl + << " upper-distance (upper triangular distance matrix)" << std::endl + << " (default:) distance (distance matrix; only lower triangular part is read)" << std::endl + << " point-cloud (point cloud in Euclidean space)" << std::endl + << " dipha (distance matrix in DIPHA file format)" << std::endl + << " sparse (sparse distance matrix in sparse triplet format)" + << std::endl + << " binary (lower triangular distance matrix in binary format)" + << std::endl + << " --dim compute persistent homology up to dimension k" << std::endl + << " --threshold compute Rips complexes up to diameter t" << std::endl + << " --modulus

compute homology with coefficients in the prime field Z/pZ" + << std::endl + << " --ratio only show persistence pairs with death/birth ratio > r" << std::endl + << std::endl; + exit(exit_code); +} + +int main(int argc, char** argv) { + const char* filename = nullptr; + + file_format format = DISTANCE_MATRIX; + + dimension_t dim_max = 1; + value_t threshold = std::numeric_limits::max(); + float ratio = 1; + coefficient_t modulus = 2; + + for (int i = 1; i < argc; ++i) { + const std::string arg(argv[i]); + if (arg == "--help") { + print_usage_and_exit(0); + } else if (arg == "--dim") { + std::string parameter = std::string(argv[++i]); + std::size_t next_pos; + dim_max = std::stol(parameter, &next_pos); + if (next_pos != parameter.size()) print_usage_and_exit(-1); + } else if (arg == "--threshold") { + std::string parameter = std::string(argv[++i]); + std::size_t next_pos; + threshold = std::stof(parameter, &next_pos); + if (next_pos != parameter.size()) print_usage_and_exit(-1); + } else if (arg == "--ratio") { + std::string parameter = std::string(argv[++i]); + std::size_t next_pos; + ratio = std::stof(parameter, &next_pos); + if (next_pos != parameter.size()) print_usage_and_exit(-1); + } else if (arg == "--format") { + std::string parameter = std::string(argv[++i]); + if (parameter.rfind("lower", 0) == 0) + format = LOWER_DISTANCE_MATRIX; + else if (parameter.rfind("upper", 0) == 0) + format = UPPER_DISTANCE_MATRIX; + else if (parameter.rfind("dist", 0) == 0) + format = DISTANCE_MATRIX; + else if (parameter.rfind("point", 0) == 0) + format = POINT_CLOUD; + else if (parameter == "dipha") + format = DIPHA; + else if (parameter == "sparse") + format = SPARSE; + else if (parameter == "binary") + format = BINARY; + else + print_usage_and_exit(-1); + } else if (arg == "--modulus") { + std::string parameter = std::string(argv[++i]); + std::size_t next_pos; + modulus = std::stol(parameter, &next_pos); + if (next_pos != parameter.size() || !Gudhi::ripser::is_prime(modulus)) print_usage_and_exit(-1); + } else { + if (filename) { print_usage_and_exit(-1); } + filename = argv[i]; + } + } + + std::ifstream file_stream(filename); + if (filename && file_stream.fail()) { + std::cerr << "couldn't open file " << filename << std::endl; + exit(-1); + } + + auto output_dim = [](dimension_t dim) { + std::cout << "persistence intervals in dim " << (int)dim << ":" << std::endl; + }; + auto output_pair = [ratio](value_t birth, value_t death) { +#ifdef GUDHI_INDICATE_PROGRESS + // Not necessary if we redirect stdout + std::cerr << Gudhi::ripser::clear_line << std::flush; +#endif + if (death == std::numeric_limits::infinity()) + std::cout << " [" << birth << ", )" << std::endl; + else if (death > birth * ratio) + std::cout << " [" << birth << "," << death << ")" << std::endl; + }; + if (format == SPARSE) { + Sparse_distance_matrix dist = + read_sparse_distance_matrix(filename ? file_stream : std::cin); + std::cout << "sparse distance matrix with " << dist.size() << " points and " + << dist.num_edges << "/" << (dist.size() * (dist.size() - 1)) / 2 << " entries" + << std::endl; + + ripser(std::move(dist), dim_max, threshold, modulus, output_dim, output_pair); + } else if (format == POINT_CLOUD && threshold < std::numeric_limits::max()) { + Sparse_distance_matrix dist(read_point_cloud(filename ? file_stream : std::cin), threshold); + ripser(std::move(dist), dim_max, threshold, modulus, output_dim, output_pair); + } else { + Compressed_lower_distance_matrix dist = + read_file(filename ? file_stream : std::cin, format); + + value_t min = std::numeric_limits::infinity(), + max = -std::numeric_limits::infinity(), max_finite = max; + std::size_t num_edges = 0; + + value_t enclosing_radius = std::numeric_limits::infinity(); + if (threshold >= std::numeric_limits::max()) { + for (vertex_t i = 0; i < dist.size(); ++i) { + value_t r_i = -std::numeric_limits::infinity(); + for (vertex_t j = 0; j < dist.size(); ++j) r_i = std::max(r_i, dist(i, j)); + enclosing_radius = std::min(enclosing_radius, r_i); + } + } + + for (auto d : dist.distances) { + min = std::min(min, d); + max = std::max(max, d); + if (d != std::numeric_limits::infinity()) max_finite = std::max(max_finite, d); + if (d <= threshold) ++num_edges; + } + std::cout << "value range: [" << min << "," << max_finite << "]" << std::endl; + + if (threshold >= std::numeric_limits::max()) { + std::cout << "distance matrix with " << dist.size() + << " points, using threshold at enclosing radius " << enclosing_radius + << std::endl; + ripser(std::move(dist), dim_max, enclosing_radius, modulus, output_dim, output_pair); + } else { + std::cout << "sparse distance matrix with " << dist.size() << " points and " + << num_edges << "/" << (dist.size() * (dist.size() - 1)) / 2 << " entries" + << std::endl; + + ripser(Sparse_distance_matrix(std::move(dist), threshold), dim_max, threshold, modulus, output_dim, output_pair); + } + } + return 0; +} diff --git a/src/common/include/gudhi/uint128.h b/src/common/include/gudhi/uint128.h new file mode 100644 index 0000000000..2a9407205c --- /dev/null +++ b/src/common/include/gudhi/uint128.h @@ -0,0 +1,147 @@ +/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. + * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. + * Author(s): Marc Glisse + * + * Copyright (C) 2024 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + +#ifndef GUDHI_UINT128_H_ +#define GUDHI_UINT128_H_ +#include +#include +#include +#include + +// GUDHI_FORCE_FAKE_UINT128 is only used for tests +#if !defined __SIZEOF_INT128__ || defined GUDHI_FORCE_FAKE_UINT128 +namespace Gudhi::numbers { +class Fake_uint128 { + // Debug + #ifdef __SIZEOF_INT128__ + unsigned __int128 native() const { return ((unsigned __int128)high << 64) + low; } + #define GUDHI_VERIF(X) GUDHI_CHECK(res.native() == (X), "") + #else + #define GUDHI_VERIF(X) + #endif + public: + constexpr Fake_uint128(): high(0), low(0) {} + constexpr Fake_uint128(std::uint64_t a): high(0), low(a) {} + // Arithmetic + // (multiplication and division are not needed for now) + friend Fake_uint128 operator+(Fake_uint128 a, Fake_uint128 b){ + Fake_uint128 res; + res.low = a.low + b.low; + res.high = a.high + b.high + (res.low < a.low); + GUDHI_VERIF (a.native() + b.native()); + return res; + } + friend Fake_uint128 operator-(Fake_uint128 a, Fake_uint128 b){ + Fake_uint128 res; + res.low = a.low - b.low; + res.high = a.high - b.high - (res.low > a.low); + GUDHI_VERIF (a.native() - b.native()); + return res; + } + friend Fake_uint128 operator<<(Fake_uint128 a, uint8_t b){ + Fake_uint128 res; + GUDHI_CHECK(b < 128, ""); + if (b >= 64) { res.low = 0; res.high = a.low << (b-64); } + else if (b == 0) { res = a; } + else { res.low = a.low << b; res.high = a.high << b | a.low >> (64-b); } + GUDHI_VERIF (a.native() << b); + return res; + } + friend Fake_uint128 operator>>(Fake_uint128 a, uint8_t b){ + Fake_uint128 res; + GUDHI_CHECK(b < 128, ""); + if (b >= 64) { res.high = 0; res.low = a.high >> (b-64); } + else if (b == 0) { res = a; } + else { res.high = a.high >> b; res.low = a.low >> b | a.high << (64-b); } + GUDHI_VERIF (a.native() >> b); + return res; + } + friend Fake_uint128 operator&(Fake_uint128 a, Fake_uint128 b){ + Fake_uint128 res; + res.low = a.low & b.low; + res.high = a.high & b.high; + GUDHI_VERIF (a.native() & b.native()); + return res; + } + friend Fake_uint128 operator|(Fake_uint128 a, Fake_uint128 b){ + Fake_uint128 res; + res.low = a.low | b.low; + res.high = a.high | b.high; + GUDHI_VERIF (a.native() | b.native()); + return res; + } + friend Fake_uint128 operator~(Fake_uint128 a){ + Fake_uint128 res; + res.low = ~a.low; + res.high = ~a.high; + return res; + } + // In-place arithmetic + Fake_uint128& operator+=(Fake_uint128 a) { *this = *this + a; return *this; } + Fake_uint128& operator-=(Fake_uint128 a) { *this = *this - a; return *this; } + Fake_uint128& operator++() { if (++low == 0) ++high; return *this; } + Fake_uint128& operator--() { if (low-- == 0) --high; return *this; } + Fake_uint128& operator<<=(uint8_t a) { *this = *this << a; return *this; } + Fake_uint128& operator>>=(uint8_t a) { *this = *this >> a; return *this; } + Fake_uint128& operator&=(Fake_uint128 a) { *this = *this & a; return *this; } + Fake_uint128& operator|=(Fake_uint128 a) { *this = *this | a; return *this; } + // Comparisons + friend bool operator==(Fake_uint128 a, Fake_uint128 b){ + return a.low == b.low && a.high == b.high; + } + friend bool operator!=(Fake_uint128 a, Fake_uint128 b){ + return a.low != b.low || a.high != b.high; + } + friend bool operator<(Fake_uint128 a, Fake_uint128 b){ + return a.high < b.high || (a.high == b.high && a.low < b.low); + } + friend bool operator>(Fake_uint128 a, Fake_uint128 b){ + return a.high > b.high || (a.high == b.high && a.low > b.low); + } + friend bool operator<=(Fake_uint128 a, Fake_uint128 b){ + return a.high < b.high || (a.high == b.high && a.low <= b.low); + } + friend bool operator>=(Fake_uint128 a, Fake_uint128 b){ + return a.high > b.high || (a.high == b.high && a.low >= b.low); + } + // Misc + friend std::size_t hash_value(Fake_uint128 a) { + typedef std::pair P; + return boost::hash_value(P(a.high, a.low)); + } + template >> + explicit operator T() const { + GUDHI_CHECK(high == 0 && low <= std::numeric_limits::max(), ""); + return static_cast(low); + } + private: + std::uint64_t high, low; // does the order matter? + #undef GUDHI_VERIF +}; +typedef Fake_uint128 uint128_t; +} // namespace Gudhi::numbers +template<> class std::numeric_limits { + public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool has_infinity = false; + static constexpr bool is_modulo = true; + static constexpr int digits = 128; + static constexpr int radix = 2; + // etc +}; +#else +namespace Gudhi::numbers { +typedef unsigned __int128 uint128_t; +} // namespace Gudhi::numbers +#endif +#endif // GUDHI_UINT128_H_ diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index e953fee2b7..e09b741820 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -187,6 +187,7 @@ if(PYTHONINTERP_FOUND) endif () set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'_pers_cub_low_dim', ") set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'_edge_collapse', ") + set(GUDHI_PYBIND11_MODULES "${GUDHI_PYBIND11_MODULES}'_ripser', ") # from windows vcpkg eigen 3.4.0#2 : build fails with # error C2440: '': cannot convert from 'Eigen::EigenBase::Index' to '__gmp_expr' diff --git a/src/python/gudhi/_ripser.cc b/src/python/gudhi/_ripser.cc new file mode 100644 index 0000000000..56e528f248 --- /dev/null +++ b/src/python/gudhi/_ripser.cc @@ -0,0 +1,200 @@ +/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. + * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. + * Author(s): Marc Glisse + * + * Copyright (C) 2024 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +using namespace Gudhi::ripser; + +namespace py = pybind11; +typedef std::vector< int> Vi; +typedef std::vector Vd; +typedef std::vector> V2f; +typedef std::vector> V2d; +PYBIND11_MAKE_OPAQUE(Vi); +PYBIND11_MAKE_OPAQUE(Vd); +PYBIND11_MAKE_OPAQUE(V2f); +PYBIND11_MAKE_OPAQUE(V2d); + +templatestruct Full { + typedef Tag_dense Category; + typedef int vertex_t; + typedef T value_t; + decltype(std::declval&>().template unchecked<2>()) data; + int size() const { return data.shape(0); } + T operator()(int i, int j) const { + return data(i, j); + } +}; + +templatestruct DParams { + typedef vertex_t_ vertex_t; + typedef value_t_ value_t; +}; + +template +py::list doit(DistanceMatrix&& dist, int max_dimension, typename DistanceMatrix::value_t max_edge_length, unsigned homology_coeff_field) { + //static_assert(!std::is_lvalue_reference_v); + typedef typename DistanceMatrix::value_t T; + // We could put everything in a single vector, and return slices of it, but I don't think there is much advantage. + std::vector>> dgms; + { + py::gil_scoped_release release; + auto output = [&](T birth, T death){ + // Skip empty intervals + if (birth < death) + dgms.back().push_back({birth, death}); + }; + auto switch_dim = [&](int new_dim){ + dgms.emplace_back(); + }; + ripser_auto(std::move(dist), max_dimension, max_edge_length, homology_coeff_field, switch_dim, output); + } + py::list ret; + for (auto&& dgm : dgms) + ret.append(py::array(py::cast(std::move(dgm)))); + return ret; +} + +template +py::list full(py::array_t matrix, int max_dimension, T max_edge_length, unsigned homology_coeff_field) { + Full dist{matrix.template unchecked<2>()}; + if(dist.data.ndim() != 2 || dist.data.shape(0) != dist.data.shape(1)) + throw std::runtime_error("Distance matrix must be a square 2-dimensional array"); + return doit(std::move(dist), max_dimension, max_edge_length, homology_coeff_field); +} + +py::list lower(py::object low_mat, int max_dimension, double max_edge_length, unsigned homology_coeff_field) { + using Dist = Compressed_distance_matrix, LOWER_TRIANGULAR>; + std::vector distances; + int rowi = 0; + for (auto&& row : low_mat) { + if (rowi == 0) { ++rowi; continue; } + int coli = 0; + for (auto&& elem : row) { + distances.push_back(elem.cast()); // need a cast? + if (++coli == rowi) break; + } + if (coli < rowi) throw std::invalid_argument("Not enough elements for a lower triangular matrix"); + ++rowi; + }; + + // optional as a trick to allow destruction where I want it + std::optional release_local(std::in_place); + Dist dist(std::move(distances)); + release_local.reset(); + + return doit(std::move(dist), max_dimension, max_edge_length, homology_coeff_field); +} + +template +py::list sparse(py::array_t is_, py::array_t js_, py::array_t fs_, int num_vertices, int max_dimension, T max_edge_length, unsigned homology_coeff_field) { + // Duplicate entries and self loops are forbidden + auto is = is_.unchecked(); + auto js = js_.unchecked(); + auto fs = fs_.unchecked(); + if (is.ndim() != 1 || js.ndim() != 1 || fs.ndim() != 1) + throw std::runtime_error("vertices and filtrations must be 1-dimensional arrays"); + if (is.shape(0) != js.shape(0) || is.shape(0) != js.shape(0)) + throw std::runtime_error("vertices and filtrations must have the same shape"); + + typedef DParams P; + typedef Sparse_distance_matrix

Dist; + typedef typename Dist::vertex_diameter_t vertex_diameter_t; + + std::optional release_local(std::in_place); + std::vector> neighbors(num_vertices); + for (py::ssize_t e = 0; e < is.shape(0); ++e) { + neighbors[is(e)].emplace_back(js(e), fs(e)); + neighbors[js(e)].emplace_back(is(e), fs(e)); + } + // We could easily parallelize this loop, but it is unlikely to be worth it. + for (size_t i = 0; i < neighbors.size(); ++i) + std::sort(neighbors[i].begin(), neighbors[i].end()); + Dist dist(std::move(neighbors)); + release_local.reset(); + + return doit(std::move(dist), max_dimension, max_edge_length, homology_coeff_field); +} + +py::list lower_to_coo(py::object low_mat, double max_edge_length) { + // Cannot release the GIL since we keep accessing Python objects. + // TODO: full_to_coo for numpy arrays? + // Should we compute the cone radius at the same time? + std::vector is, js; + std::vector fs; + int rowi = 0; + for (auto&& row : low_mat) { + if (rowi == 0) { ++rowi; continue; } + int coli = 0; + for (auto&& elem : row) { + double d = elem.cast(); // need a cast? + if (d <= max_edge_length) { + is.push_back(rowi); + js.push_back(coli); + fs.push_back(d); + } + if (++coli == rowi) break; + } + if (coli < rowi) throw std::invalid_argument("Not enough elements for a lower triangular matrix"); + ++rowi; + }; + return py::make_tuple( + py::array(py::cast(std::move(is))), + py::array(py::cast(std::move(js))), + py::array(py::cast(std::move(fs)))); +} + +double lower_cone_radius(py::object low_mat) { + // It would be more efficient to read the matrix only once + auto n = py::len(low_mat); + std::vector maxs(n, -std::numeric_limits::infinity()); + int rowi = 0; + for (auto&& row : low_mat) { + if (rowi == 0) { ++rowi; continue; } + int coli = 0; + for (auto&& elem : row) { + double d = elem.cast(); + maxs[rowi] = std::max(maxs[rowi], d); + maxs[coli] = std::max(maxs[coli], d); + if (++coli == rowi) break; + } + if (coli < rowi) throw std::invalid_argument("Not enough elements for a lower triangular matrix"); + ++rowi; + }; + return *std::max_element(maxs.begin(), maxs.end()); +} + +PYBIND11_MODULE(_ripser, m) { + py::bind_vector(m, "VectorInt" , py::buffer_protocol()); + py::bind_vector(m, "VectorDouble" , py::buffer_protocol()); + py::bind_vector(m, "VectorPairFloat" , py::buffer_protocol()); + py::bind_vector(m, "VectorPairDouble", py::buffer_protocol()); + // Remove the default for max_dimension? + m.def("_full", full, py::arg("matrix").noconvert(), py::arg("max_dimension") = std::numeric_limits::max(), py::arg("max_edge_length") = std::numeric_limits::infinity(), py::arg("homology_coeff_field") = 2); + m.def("_full", full, py::arg("matrix"), py::arg("max_dimension") = std::numeric_limits::max(), py::arg("max_edge_length") = std::numeric_limits::infinity(), py::arg("homology_coeff_field") = 2); + m.def("_lower", lower, py::arg("matrix"), py::arg("max_dimension") = std::numeric_limits::max(), py::arg("max_edge_length") = std::numeric_limits::infinity(), py::arg("homology_coeff_field") = 2); + // We could do a version with long, but copying the arrays of integers shouldn't be too costly + m.def("_sparse", sparse, py::arg("row"), py::arg("col"), py::arg("data").noconvert(), py::arg("num_vertices"), py::arg("max_dimension") = std::numeric_limits::max(), py::arg("max_edge_length") = std::numeric_limits::infinity(), py::arg("homology_coeff_field") = 2); + m.def("_sparse", sparse, py::arg("row"), py::arg("col"), py::arg("data"), py::arg("num_vertices"), py::arg("max_dimension") = std::numeric_limits::max(), py::arg("max_edge_length") = std::numeric_limits::infinity(), py::arg("homology_coeff_field") = 2); + // Not directly an interface to Ripser... + m.def("_lower_to_coo", lower_to_coo, py::arg("matrix"), py::arg("max_edge_length")); + m.def("_lower_cone_radius", lower_cone_radius, py::arg("matrix")); +} + +// We could also create a RipsComplex class, that allows looking at a simplex, querying its (co)boundary, etc. But I am not convinced it is worth the effort. diff --git a/src/python/gudhi/sklearn/rips_persistence.py b/src/python/gudhi/sklearn/rips_persistence.py index f34af5a464..73a98e4300 100644 --- a/src/python/gudhi/sklearn/rips_persistence.py +++ b/src/python/gudhi/sklearn/rips_persistence.py @@ -7,8 +7,14 @@ # Modification(s): # - YYYY/MM Author: Description of the modification -from .. import RipsComplex +from .._ripser import _lower, _full, _sparse, _lower_to_coo, _lower_cone_radius +from ..flag_filtration.edge_collapse import reduce_graph +import math +import numpy as np from sklearn.base import BaseEstimator, TransformerMixin +from scipy.sparse import coo_matrix +from scipy.spatial import cKDTree +from scipy.spatial.distance import pdist, squareform # joblib is required by scikit-learn from joblib import Parallel, delayed @@ -38,7 +44,7 @@ def __init__( homology_dimensions, threshold=float('inf'), input_type='point cloud', - num_collapses=1, + num_collapses='auto', homology_coeff_field=11, n_jobs=None, ): @@ -49,12 +55,14 @@ def __init__( homology_dimensions (int or list of int): The returned persistence diagrams dimension(s). Short circuit the use of :class:`~gudhi.representations.preprocessing.DimensionSelector` when only one dimension matters (in other words, when `homology_dimensions` is an int). - threshold (float): Rips maximal edge length value. Default is +Inf. - input_type (str): Can be 'point cloud' when inputs are point clouds, or 'lower distance matrix', when - inputs are lower triangular distance matrix (can be full square, but the upper part of the distance - matrix will not be considered). Default is 'point cloud'. - num_collapses (int): Specify the number of :func:`~gudhi.SimplexTree.collapse_edges` iterations to perform - on the SimplexTree. Default value is 1 (a relatively good enough number of iterations). + threshold (float): Rips maximal edge length value. Default is +Inf. Ignored if input_type is 'distance coo_matrix'. + input_type (str): Can be 'point cloud' when inputs are point clouds, 'full distance matrix', + 'lower distance matrix' when inputs are lower triangular distance matrix (can be full square, + but the upper part will not be considered), or 'distance coo_matrix' for a distance matrix in SciPy's + sparse format, which should contain each edge at most once (avoid the symmetric) and no diagonal entry. + Default is 'point cloud'. + num_collapses (int|str): Specify the number of iterations of :func:`~gudhi.flag_filtration.edge_collapse.reduce_graph` + (edge collapse) to perform on the graph. Default value is 'auto'. homology_coeff_field (int): The homology coefficient field. Must be a prime number. Default value is 11. n_jobs (int): Number of jobs to run in parallel. `None` (default value) means `n_jobs = 1` unless in a joblib.parallel_backend context. `-1` means using all processors. cf. @@ -73,36 +81,90 @@ def fit(self, X, Y=None): """ return self - def __transform(self, inputs): - max_dimension = max(self.dim_list_) + 1 - - if self.input_type == 'point cloud': - rips = RipsComplex(points=inputs, max_edge_length = self.threshold) - elif self.input_type == 'lower distance matrix': - rips = RipsComplex(distance_matrix=inputs, max_edge_length = self.threshold) + def __transform(self, inp): + # TODO: give the user more control over the strategy + # Should we use threshold in the sparse case? + num_collapses = self.num_collapses + input_type = self.input_type + threshold = self.threshold + n = inp.shape[0] if input_type == 'distance coo_matrix' else len(inp) + max_dimension = min(max(self.dim_list_), max(0, n-3)) + # Ripser needs to encode simplices and coefficients in 128 bits, which may not always fit + # Instead of a 256 bit version which may not always suffice either, fall back to SimplexTree + use_simplex_tree = math.comb(n, min(n // 2, max_dimension + 2)) >= (1 << (128 - (self.homology_coeff_field - 2).bit_length())) + if num_collapses == 'auto': + num_collapses = 1 if max_dimension > (not use_simplex_tree) else 0 + # or num_collapses=max_dimension-1 maybe? + elif max_dimension == 0: + num_collapses = 0 + + # Points -> distance matrix + if input_type == 'point cloud': + if threshold < float('inf'): + # Hope that the user gave a useful threshold + tree = cKDTree(inp) + + ## V1: Returns self-loops and every edge twice (symmetry) + # inp = tree.sparse_distance_matrix(tree, max_distance=threshold, output_type="coo_matrix") + # mask = inp.row < inp.col + # inp = coo_matrix((inp.data[mask], (inp.row[mask], inp.col[mask])), shape=inp.shape) + + # V2: Gets the right edges, but forgets the distances + pairs = tree.query_pairs(r=threshold, output_type='ndarray') + data = np.ravel(np.linalg.norm(np.diff(inp[pairs], axis=1), axis=-1)) + inp = coo_matrix((data, (pairs[:,0], pairs[:,1])), shape=(n,)*2) + + input_type = 'distance coo_matrix' + else: + inp = squareform(pdist(inp)) + input_type = 'full distance matrix' + + # Dense -> sparse + if input_type in ('full distance matrix', 'lower distance matrix'): + # After this filtration value, all complexes are cones, nothing happens + if input_type == 'full distance matrix': + inp = np.asarray(inp) + cone_radius = inp.max(-1).min() + else: + cone_radius = _lower_cone_radius(inp) + sparsify = use_simplex_tree or num_collapses > 0 or threshold < cone_radius # heuristic + threshold = min(threshold, cone_radius) + if sparsify: + # For 'full' we could use i, j = np.triu_indices_from(inp, k=1), etc + i, j, f = _lower_to_coo(inp, threshold) + inp = coo_matrix((f, (i, j)), shape=(n,) * 2) + input_type = 'distance coo_matrix' + + if num_collapses > 0: + assert input_type == 'distance coo_matrix' + inp = reduce_graph(inp, num_collapses) + + if use_simplex_tree: + from gudhi import SimplexTree + st = SimplexTree() + # Use create_from_array in case of full matrix? + # (not important since this fallback mostly matters in high dimension, where we use edge-collapse anyway) + st.insert_batch(np.arange(n).reshape(1,-1), np.zeros(n)) + st.insert_edges_from_coo_matrix(inp) + st.expansion(max_dimension + 1) + st.compute_persistence(homology_coeff_field=self.homology_coeff_field, persistence_dim_max=max_dimension>=st.dimension()) + return [ st.persistence_intervals_in_dimension(dim) for dim in self.dim_list_ ] + + if input_type == 'full distance matrix': + ## Possibly transpose for performance? + # if inp.strides[0] > inp.strides[1]: # or the reverse? + # inp = inp.T + dgm = _full(inp, max_dimension=max_dimension, max_edge_length=threshold, homology_coeff_field=self.homology_coeff_field) + elif input_type == 'lower distance matrix': + dgm = _lower(inp, max_dimension=max_dimension, max_edge_length=threshold, homology_coeff_field=self.homology_coeff_field) + elif input_type == 'distance coo_matrix': + # Switch to coo_array (danger: row/col seem deprecated)? + dgm = _sparse(inp.row, inp.col, inp.data, inp.shape[0], max_dimension=max_dimension, max_edge_length=threshold, homology_coeff_field=self.homology_coeff_field) else: - raise ValueError("Only 'point cloud' and 'lower distance matrix' are valid input_type") + raise ValueError("Only 'point cloud', 'lower distance matrix', 'full distance matrix' and 'distance coo_matrix' are valid input_type") # move to __init__? - if max_dimension > 1: - stree = rips.create_simplex_tree(max_dimension=1) - stree.collapse_edges(nb_iterations = self.num_collapses) - stree.expansion(max_dimension) - else: - stree = rips.create_simplex_tree(max_dimension=max_dimension) - - persistence_dim_max = False - # Specific case where, despite expansion(max_dimension), stree has a lower dimension - if max_dimension > stree.dimension(): - persistence_dim_max = True - - stree.compute_persistence( - homology_coeff_field=self.homology_coeff_field, - persistence_dim_max=persistence_dim_max - ) - - return [ - stree.persistence_intervals_in_dimension(dim) for dim in self.dim_list_ - ] + # dgm stops at n-2 + return [dgm[dim] if dim < len(dgm) else np.empty((0,2)) for dim in self.dim_list_] def transform(self, X, Y=None): """Compute all the Vietoris-Rips complexes and their associated persistence diagrams. @@ -117,7 +179,7 @@ def transform(self, X, Y=None): `[[array( Hi(X[0]) ), array( Hj(X[0]) )], [array( Hi(X[1]) ), array( Hj(X[1]) )], ...]` :rtype: list of numpy ndarray of shape (,2) or list of list of numpy ndarray of shape (,2) """ - # Depends on homology_dimensions is an integer or a list of integer (else case) + # Depends if homology_dimensions is an integer or a list of integers (else case) if isinstance(self.homology_dimensions, int): unwrap = True self.dim_list_ = [ self.homology_dimensions ] diff --git a/src/python/test/test_sklearn_rips_persistence.py b/src/python/test/test_sklearn_rips_persistence.py index 2ca0c313e0..8687292b8c 100644 --- a/src/python/test/test_sklearn_rips_persistence.py +++ b/src/python/test/test_sklearn_rips_persistence.py @@ -10,6 +10,7 @@ from gudhi.datasets.generators import points from gudhi.sklearn.rips_persistence import RipsPersistence +import numpy as np import random import pytest @@ -73,3 +74,14 @@ def test_set_output(): assert len(diags_pandas.index) == NB_PC except ImportError: print("Missing pandas, skipping set_output test") + + +def test_big(): + # A circle + many isolated points + n=1000000 + X=np.zeros((n,2)) + X[:,0]=np.arange(n)*100 + X[:24]=points.torus(24,1,'grid') + # Ripser cannot handle it, have to fall back to SimplexTree + # Computing the full distance matrix would require too much memory -> kd-tree + RipsPersistence(range(25), threshold=10).fit_transform([X]) From 01ea034ca93734a08f162a5d643fad12d4628a55 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Mon, 12 Aug 2024 17:14:48 +0200 Subject: [PATCH 02/34] PersistenceLengths and its unitary tests --- .../gudhi/representations/vector_methods.py | 63 ++++++++++++++++++- src/python/test/test_representations.py | 15 ++++- 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/src/python/gudhi/representations/vector_methods.py b/src/python/gudhi/representations/vector_methods.py index 14d2802e71..112b372438 100644 --- a/src/python/gudhi/representations/vector_methods.py +++ b/src/python/gudhi/representations/vector_methods.py @@ -729,7 +729,7 @@ class Atol(BaseEstimator, TransformerMixin): This class allows to vectorise measures (e.g. point clouds, persistence diagrams, etc) after a quantisation step. ATOL paper: :cite:`royer2019atol` - +:paramref:`~gudhi.representations.PersistenceLengths. Example -------- >>> from sklearn.cluster import KMeans @@ -885,3 +885,64 @@ def transform(self, X, sample_weight=None): def get_feature_names_out(self): return self._running_transform_names + +class PersistenceLengths(BaseEstimator, TransformerMixin): + """ + This is a class that returns the N-longest persistence lengths. + """ + def __init__(self, num_lengths=5): + """ + Constructor for the PersistenceLengths class. + + Parameters: + num_lengths (int): number of persistence lengths to return (default 5). + """ + self.num_lengths = num_lengths + + def fit(self, X, y=None): + """ + Fit the PersistenceLengths class on a list of persistence diagrams (this function actually does nothing but is + useful when PersistenceLengths is included in a scikit-learn Pipeline). + + Parameters: + X (list of n x 2 or n x 1 numpy arrays): input persistence diagrams. + y (n x 1 array): persistence diagram lengths (unused). + """ + return self + + def transform(self, X): + """ + Compute the persistence landscape for each persistence diagram individually and concatenate the results. + + Parameters: + X (list of n x 2 numpy arrays): input persistence diagrams. + + Returns: + numpy array with shape (number of diagrams) x (num_lengths): output persistence lengths. + """ + + pers_lengths = [] + for pd in X: + # Sort in reverse order persistence lengths (where length = death - birth) + lengths = np.flip(np.sort(pd[:,1] - pd[:,0])) + if len(lengths) >= self.num_lengths: + pers_lengths.append(lengths[:self.num_lengths]) + else: + # Fill with zeros if necessary + lengths_with_zeros = np.zeros((self.num_lengths)) + lengths_with_zeros[:len(lengths)] = lengths + pers_lengths.append(lengths_with_zeros) + + return pers_lengths + + def __call__(self, diag): + """ + Apply PersistenceLengths on a single persistence diagram and outputs the result. + + Parameters: + diag (n x 2 numpy array): input persistence diagram. + + Returns: + numpy 1d array of length num_lengths: output persistence landscape. + """ + return self.transform([diag])[0] diff --git a/src/python/test/test_representations.py b/src/python/test/test_representations.py index 594be4e64c..e1695cc4a4 100644 --- a/src/python/test/test_representations.py +++ b/src/python/test/test_representations.py @@ -9,7 +9,7 @@ # Vectorization from gudhi.representations import (Landscape, Silhouette, BettiCurve, ComplexPolynomial,\ - TopologicalVector, PersistenceImage, Entropy) + TopologicalVector, PersistenceImage, Entropy, PersistenceLengths) # Preprocessing from gudhi.representations import (BirthPersistenceTransform, Clamping, DiagramScaler, Padding, ProminentPoints, \ @@ -318,3 +318,16 @@ def test_endpoints(): def test_get_params(): for vec in [ Landscape(), Silhouette(), BettiCurve(), Entropy(mode="vector") ]: vec.get_params() + +def test_persistence_lengths(): + diag = np.array([[3., 5.], [0, np.inf], [4., 4.], [2., 6.]]) + for nl in range(6): + pl = PersistenceLengths(num_lengths=nl)(diag) + # test the result is sorted + assert np.all(sorted(pl, reverse=True) == pl) + if len(pl) > 0: + assert np.isinf(pl[0]) + for idx in range(len(pl)): + if idx >= len(diag): + # test it is filled with zeros when going further the input + assert pl[idx] == 0. From d30299f9f78f05630c356acb2c4faeb77830d2a7 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Mon, 12 Aug 2024 17:56:58 +0200 Subject: [PATCH 03/34] typo --- src/python/gudhi/representations/vector_methods.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/gudhi/representations/vector_methods.py b/src/python/gudhi/representations/vector_methods.py index 112b372438..4f0e4f6f38 100644 --- a/src/python/gudhi/representations/vector_methods.py +++ b/src/python/gudhi/representations/vector_methods.py @@ -729,7 +729,7 @@ class Atol(BaseEstimator, TransformerMixin): This class allows to vectorise measures (e.g. point clouds, persistence diagrams, etc) after a quantisation step. ATOL paper: :cite:`royer2019atol` -:paramref:`~gudhi.representations.PersistenceLengths. + Example -------- >>> from sklearn.cluster import KMeans From 8cab8c9e3695846278f3b8fd8095715bbc8e5950 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 23 Aug 2024 18:50:38 +0200 Subject: [PATCH 04/34] Add type hints --- src/python/gudhi/sklearn/rips_persistence.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/python/gudhi/sklearn/rips_persistence.py b/src/python/gudhi/sklearn/rips_persistence.py index 73a98e4300..54bf969611 100644 --- a/src/python/gudhi/sklearn/rips_persistence.py +++ b/src/python/gudhi/sklearn/rips_persistence.py @@ -11,6 +11,7 @@ from ..flag_filtration.edge_collapse import reduce_graph import math import numpy as np +from typing import Union, Iterable, Literal, Optional from sklearn.base import BaseEstimator, TransformerMixin from scipy.sparse import coo_matrix from scipy.spatial import cKDTree @@ -41,12 +42,14 @@ class RipsPersistence(BaseEstimator, TransformerMixin): def __init__( self, - homology_dimensions, - threshold=float('inf'), - input_type='point cloud', - num_collapses='auto', - homology_coeff_field=11, - n_jobs=None, + homology_dimensions: Union[int, Iterable[int]], + threshold: float = float('inf'), + input_type: Literal[ + "point cloud", "full distance matrix", "lower distance matrix", "distance coo_matrix" + ] = 'point cloud', + num_collapses: Union[int, Literal["auto"]] = 'auto', + homology_coeff_field: int = 11, + n_jobs: Optional[int] = None, ): """ Constructor for the RipsPersistence class. @@ -64,7 +67,7 @@ def __init__( num_collapses (int|str): Specify the number of iterations of :func:`~gudhi.flag_filtration.edge_collapse.reduce_graph` (edge collapse) to perform on the graph. Default value is 'auto'. homology_coeff_field (int): The homology coefficient field. Must be a prime number. Default value is 11. - n_jobs (int): Number of jobs to run in parallel. `None` (default value) means `n_jobs = 1` unless in a + n_jobs (Optional[int]): Number of jobs to run in parallel. `None` (default value) means `n_jobs = 1` unless in a joblib.parallel_backend context. `-1` means using all processors. cf. https://joblib.readthedocs.io/en/latest/generated/joblib.Parallel.html for more details. """ From 768774a184139fcddd168d0ee6e5e4f5ce8eaa15 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Fri, 30 Aug 2024 14:45:23 +0200 Subject: [PATCH 05/34] code review: use numpy partition and bad/copy paste/replace of documentation --- .../gudhi/representations/vector_methods.py | 71 ++++++++++--------- src/python/test/test_representations.py | 14 ++-- 2 files changed, 47 insertions(+), 38 deletions(-) diff --git a/src/python/gudhi/representations/vector_methods.py b/src/python/gudhi/representations/vector_methods.py index 4f0e4f6f38..e9314d18ca 100644 --- a/src/python/gudhi/representations/vector_methods.py +++ b/src/python/gudhi/representations/vector_methods.py @@ -73,7 +73,7 @@ def transform(self, X): Parameters: X (list of n x 2 numpy arrays): input persistence diagrams. - + Returns: numpy array with shape (number of diagrams) x (number of pixels = **resolution[0]** x **resolution[1]**): output persistence images. """ @@ -196,7 +196,7 @@ def transform(self, X): Parameters: X (list of n x 2 numpy arrays): input persistence diagrams. - + Returns: numpy array with shape (number of diagrams) x (number of samples = **num_landscapes** x **resolution**): output persistence landscapes. """ @@ -271,7 +271,7 @@ def transform(self, X): Parameters: X (list of n x 2 numpy arrays): input persistence diagrams. - + Returns: numpy array with shape (number of diagrams) x (**resolution**): output persistence silhouettes. """ @@ -363,7 +363,7 @@ def fit(self, X, y = None): if self.predefined_grid is None: if self.resolution is None: # Flexible/exact version - self.grid_ = np.unique(np.concatenate([pd.ravel() for pd in X] + [[-np.inf]], axis=0)) + self.grid_ = np.unique(np.concatenate([pd.ravel() for pd in X] + [[-np.inf]], axis=0)) else: _grid_from_sample_range(self, X) else: @@ -391,7 +391,7 @@ def transform(self, X): print("Empty list: output has shape [0, len(grid)]") return np.zeros((N, len(self.grid_))) - + else: events = np.concatenate([pd.ravel(order="F") for pd in X], axis=0) @@ -413,7 +413,7 @@ def transform(self, X): i += 1 for k in range(0, N): bettis[k].append(bettis[k][-1]) - + return np.array(bettis, dtype=int)[:, 0:-1] def fit_transform(self, X, y = None): @@ -485,7 +485,7 @@ def __init__(self, mode="scalar", normalized=True, resolution=100, sample_range= Parameters: mode (string): what entropy to compute: either "scalar" for computing the entropy statistics, or "vector" for computing the entropy summary functions (default "scalar"). - normalized (bool): whether to normalize the entropy summary function (default True). Used only if **mode** = "vector". + normalized (bool): whether to normalize the entropy summary function (default True). Used only if **mode** = "vector". resolution (int): number of sample for the entropy summary function (default 100). Used only if **mode** = "vector". sample_range ([double, double]): minimum and maximum of the entropy summary function domain, of the form [x_min, x_max] (default [numpy.nan, numpy.nan]). It is the interval on which samples will be drawn evenly. If one of the values is numpy.nan, it can be computed from the persistence diagrams with the fit() method. Used only if **mode** = "vector". keep_endpoints (bool): when computing `sample_range`, use the exact extremities. This is mostly useful for plotting, the default is to use a slightly smaller range. @@ -515,16 +515,16 @@ def transform(self, X): Parameters: X (list of n x 2 numpy arrays): input persistence diagrams. - + Returns: numpy array with shape (number of diagrams) x (1 if **mode** = "scalar" else **resolution**): output entropy. """ num_diag, Xfit = len(X), [] - new_X = BirthPersistenceTransform().fit_transform(X) + new_X = BirthPersistenceTransform().fit_transform(X) for i in range(num_diag): orig_diagram, new_diagram, num_pts_in_diag = X[i], new_X[i], X[i].shape[0] - + p = new_diagram[:,1] p = p/np.sum(p) if self.mode == "scalar": @@ -566,7 +566,7 @@ def __init__(self, threshold=10): Constructor for the TopologicalVector class. Parameters: - threshold (int): number of distances to keep (default 10). This is the dimension of the topological vector. If -1, this threshold is computed from the list of persistence diagrams by considering the one with the largest number of points and using the dimension of its corresponding topological vector as threshold. + threshold (int): number of distances to keep (default 10). This is the dimension of the topological vector. If -1, this threshold is computed from the list of persistence diagrams by considering the one with the largest number of points and using the dimension of its corresponding topological vector as threshold. """ self.threshold = threshold @@ -586,7 +586,7 @@ def transform(self, X): Parameters: X (list of n x 2 numpy arrays): input persistence diagrams. - + Returns: numpy array with shape (number of diagrams) x (**threshold**): output topological vectors. """ @@ -638,7 +638,7 @@ def __init__(self, polynomial_type="R", threshold=10): Parameters: polynomial_type (char): either "R", "S" or "T" (default "R"). Type of complex polynomial that is going to be computed (explained in https://link.springer.com/chapter/10.1007%2F978-3-319-23231-7_27). - threshold (int): number of coefficients (default 10). This is the dimension of the complex vector of coefficients, i.e. the number of coefficients corresponding to the largest degree terms of the polynomial. If -1, this threshold is computed from the list of persistence diagrams by considering the one with the largest number of points and using the dimension of its corresponding complex vector of coefficients as threshold. + threshold (int): number of coefficients (default 10). This is the dimension of the complex vector of coefficients, i.e. the number of coefficients corresponding to the largest degree terms of the polynomial. If -1, this threshold is computed from the list of persistence diagrams by considering the one with the largest number of points and using the dimension of its corresponding complex vector of coefficients as threshold. """ self.threshold, self.polynomial_type = threshold, polynomial_type @@ -658,7 +658,7 @@ def transform(self, X): Parameters: X (list of n x 2 numpy arrays): input persistence diagrams. - + Returns: numpy array with shape (number of diagrams) x (**threshold**): output complex vectors of coefficients. """ @@ -681,9 +681,9 @@ def transform(self, X): roots = np.multiply( (D[:,1]-D[:,0])/2, np.cos(alpha) - np.sin(alpha) + 1j * (np.cos(alpha) + np.sin(alpha)) ) coeff = [0] * (N+1) coeff[N] = 1 - for i in range(1, N+1): - for j in range(N-i-1, N): - coeff[j] += ((-1) * roots[i-1] * coeff[j+1]) + for i in range(1, N+1): + for j in range(N-i-1, N): + coeff[j] += ((-1) * roots[i-1] * coeff[j+1]) coeff = np.array(coeff[::-1])[1:] Xfit[d, :min(thresh, coeff.shape[0])] = coeff[:min(thresh, coeff.shape[0])] return Xfit @@ -888,16 +888,22 @@ def get_feature_names_out(self): class PersistenceLengths(BaseEstimator, TransformerMixin): """ - This is a class that returns the N-longest persistence lengths. + This is a class that returns the sorted N-longest persistence lengths. If the input does not contain enough values, + the output will be filled with zeros. """ + def __init__(self, num_lengths=5): """ Constructor for the PersistenceLengths class. Parameters: num_lengths (int): number of persistence lengths to return (default 5). + + :raises ValueError: If num_lengths is lower or equal to 0. """ - self.num_lengths = num_lengths + if num_lengths <= 0: + raise ValueError("num_lengths must be greater than 0.") + self.num_lengths = num_lengths def fit(self, X, y=None): """ @@ -912,28 +918,29 @@ def fit(self, X, y=None): def transform(self, X): """ - Compute the persistence landscape for each persistence diagram individually and concatenate the results. + Compute the persistence lengths for each persistence diagram individually and concatenate the results. Parameters: X (list of n x 2 numpy arrays): input persistence diagrams. - + Returns: numpy array with shape (number of diagrams) x (num_lengths): output persistence lengths. """ - pers_lengths = [] + pers_length_list = [] for pd in X: - # Sort in reverse order persistence lengths (where length = death - birth) - lengths = np.flip(np.sort(pd[:,1] - pd[:,0])) - if len(lengths) >= self.num_lengths: - pers_lengths.append(lengths[:self.num_lengths]) + pl = pd[:, 1] - pd[:, 0] + if len(pl) >= self.num_lengths: + pers_length = np.partition(pl, -self.num_lengths)[-self.num_lengths :] else: # Fill with zeros if necessary - lengths_with_zeros = np.zeros((self.num_lengths)) - lengths_with_zeros[:len(lengths)] = lengths - pers_lengths.append(lengths_with_zeros) - - return pers_lengths + pers_length = np.zeros((self.num_lengths)) + pers_length[: len(pl)] = pl + + # Sort in reverse order persistence lengths (where length = death - birth) + pers_length_list.append(np.flip(np.sort(pers_length))) + + return pers_length_list def __call__(self, diag): """ @@ -943,6 +950,6 @@ def __call__(self, diag): diag (n x 2 numpy array): input persistence diagram. Returns: - numpy 1d array of length num_lengths: output persistence landscape. + numpy 1d array of length num_lengths: output persistence lengths. """ return self.transform([diag])[0] diff --git a/src/python/test/test_representations.py b/src/python/test/test_representations.py index e1695cc4a4..e219adea5e 100644 --- a/src/python/test/test_representations.py +++ b/src/python/test/test_representations.py @@ -128,8 +128,8 @@ def test_atol_doc(): # Check the center of the first_cluster and second_cluster are in Atol centers centers = atol_vectoriser.fit(X=[a, b, c]).centers - np.isclose(centers, first_cluster.mean(axis=0)).all(1).any() - np.isclose(centers, second_cluster.mean(axis=0)).all(1).any() + np.isclose(centers, first_cluster.mean(axis=0)).all(1).any() + np.isclose(centers, second_cluster.mean(axis=0)).all(1).any() vectorization = atol_vectoriser.transform(X=[a, b, c]) assert np.allclose(vectorization[0], atol_vectoriser(a)) @@ -203,7 +203,7 @@ def test_vectorization_empty_diagrams(): scv = Entropy(mode="vector", normalized=False, resolution=random_resolution)(empty_diag) assert not np.any(scv) assert scv.shape[0] == random_resolution - + def test_entropy_miscalculation(): diag_ex = np.array([[0.0,1.0], [0.0,1.0], [0.0,2.0]]) def pe(pd): @@ -215,14 +215,14 @@ def pe(pd): sce = Entropy(mode="vector", resolution=4, normalized=False, keep_endpoints=True) pef = [-1/4*np.log(1/4)-1/4*np.log(1/4)-1/2*np.log(1/2), -1/4*np.log(1/4)-1/4*np.log(1/4)-1/2*np.log(1/2), - -1/2*np.log(1/2), + -1/2*np.log(1/2), 0.0] assert all(([pef] == sce.fit_transform([diag_ex]))[0]) sce = Entropy(mode="vector", resolution=4, normalized=True) pefN = (sce.fit_transform([diag_ex]))[0] area = np.linalg.norm(pefN, ord=1) assert area==pytest.approx(1) - + def test_kernel_empty_diagrams(): empty_diag = np.empty(shape = [0, 2]) assert SlicedWassersteinDistance(num_directions=100)(empty_diag, empty_diag) == 0. @@ -321,7 +321,7 @@ def test_get_params(): def test_persistence_lengths(): diag = np.array([[3., 5.], [0, np.inf], [4., 4.], [2., 6.]]) - for nl in range(6): + for nl in range(1, 6): pl = PersistenceLengths(num_lengths=nl)(diag) # test the result is sorted assert np.all(sorted(pl, reverse=True) == pl) @@ -331,3 +331,5 @@ def test_persistence_lengths(): if idx >= len(diag): # test it is filled with zeros when going further the input assert pl[idx] == 0. + with pytest.raises(ValueError): + pl = PersistenceLengths(num_lengths=0)(diag) From 1f1309d60e2308858a92aeb435ff12ab0f76d73b Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 2 Sep 2024 18:36:16 +0200 Subject: [PATCH 06/34] Move import to toplevel --- src/python/gudhi/sklearn/rips_persistence.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/gudhi/sklearn/rips_persistence.py b/src/python/gudhi/sklearn/rips_persistence.py index 54bf969611..68f0646e14 100644 --- a/src/python/gudhi/sklearn/rips_persistence.py +++ b/src/python/gudhi/sklearn/rips_persistence.py @@ -9,6 +9,7 @@ from .._ripser import _lower, _full, _sparse, _lower_to_coo, _lower_cone_radius from ..flag_filtration.edge_collapse import reduce_graph +from .. import SimplexTree import math import numpy as np from typing import Union, Iterable, Literal, Optional @@ -143,7 +144,6 @@ def __transform(self, inp): inp = reduce_graph(inp, num_collapses) if use_simplex_tree: - from gudhi import SimplexTree st = SimplexTree() # Use create_from_array in case of full matrix? # (not important since this fallback mostly matters in high dimension, where we use edge-collapse anyway) From aa4410a22a577262408feb1260ce6218ef5be732 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Mon, 2 Sep 2024 18:59:52 +0200 Subject: [PATCH 07/34] comment about boost::multiprecision::uint128_t --- src/common/include/gudhi/uint128.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/common/include/gudhi/uint128.h b/src/common/include/gudhi/uint128.h index 2a9407205c..1907314b96 100644 --- a/src/common/include/gudhi/uint128.h +++ b/src/common/include/gudhi/uint128.h @@ -15,6 +15,16 @@ #include #include +/* What about boost::multiprecision::uint128_t? + * It works on linux, mac, windows, etc. + * On linux x86_64, it has low overhead since it delegates to unsigned __int128. + * It is a bit slower than Fake_uint128, probably because of checks in << and >>, but I only noticed a 10% + * overhead compared to unsigned __int128 on 1 testcase. + * On windows, it is implemented as { size_t; uint64_t[2]; }, that's 50% overhead on storage. On the same + * testcase, forcing linux-gcc to use the windows code led to 4x slowdown. Other testcases were not affected. + * The pathological testcase is computing homology in all dimensions for the vertices of a regular 24-gon. + */ + // GUDHI_FORCE_FAKE_UINT128 is only used for tests #if !defined __SIZEOF_INT128__ || defined GUDHI_FORCE_FAKE_UINT128 namespace Gudhi::numbers { From 3bbd3af834902e79e83b990ae246dc9f1469e2d7 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Tue, 3 Sep 2024 15:56:35 +0200 Subject: [PATCH 08/34] code review: PersistenceLengths to return numpy array. Some doc also --- .../gudhi/representations/vector_methods.py | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/python/gudhi/representations/vector_methods.py b/src/python/gudhi/representations/vector_methods.py index e9314d18ca..da76acc405 100644 --- a/src/python/gudhi/representations/vector_methods.py +++ b/src/python/gudhi/representations/vector_methods.py @@ -918,7 +918,7 @@ def fit(self, X, y=None): def transform(self, X): """ - Compute the persistence lengths for each persistence diagram individually and concatenate the results. + Compute the persistence lengths for each persistence diagram individually. Parameters: X (list of n x 2 numpy arrays): input persistence diagrams. @@ -926,21 +926,21 @@ def transform(self, X): Returns: numpy array with shape (number of diagrams) x (num_lengths): output persistence lengths. """ - - pers_length_list = [] + pers_length_array = np.zeros((len(X), self.num_lengths)) + idx = 0 for pd in X: pl = pd[:, 1] - pd[:, 0] if len(pl) >= self.num_lengths: - pers_length = np.partition(pl, -self.num_lengths)[-self.num_lengths :] - else: - # Fill with zeros if necessary - pers_length = np.zeros((self.num_lengths)) - pers_length[: len(pl)] = pl + # Select the num_lengths biggest persistence bars length + pl = np.partition(pl, -self.num_lengths)[-self.num_lengths :] # Sort in reverse order persistence lengths (where length = death - birth) - pers_length_list.append(np.flip(np.sort(pers_length))) + pl = np.flip(np.sort(pl)) + # Filled with zeros if not enough values + pers_length_array[idx][:len(pl)] = pl + idx = idx + 1 - return pers_length_list + return pers_length_array def __call__(self, diag): """ From af4175427275a7fc82632d657962b3093c402fba Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Tue, 3 Sep 2024 17:05:24 +0200 Subject: [PATCH 09/34] code review: enumerate instead of for loop + index increment --- src/python/gudhi/representations/vector_methods.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/python/gudhi/representations/vector_methods.py b/src/python/gudhi/representations/vector_methods.py index da76acc405..246e9b803b 100644 --- a/src/python/gudhi/representations/vector_methods.py +++ b/src/python/gudhi/representations/vector_methods.py @@ -927,8 +927,7 @@ def transform(self, X): numpy array with shape (number of diagrams) x (num_lengths): output persistence lengths. """ pers_length_array = np.zeros((len(X), self.num_lengths)) - idx = 0 - for pd in X: + for idx, pd in enumerate(X): pl = pd[:, 1] - pd[:, 0] if len(pl) >= self.num_lengths: # Select the num_lengths biggest persistence bars length @@ -938,7 +937,6 @@ def transform(self, X): pl = np.flip(np.sort(pl)) # Filled with zeros if not enough values pers_length_array[idx][:len(pl)] = pl - idx = idx + 1 return pers_length_array From 009748ca5b3ad81712c33bfcd169239c5a4f0cd5 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Tue, 3 Sep 2024 17:49:23 +0200 Subject: [PATCH 10/34] doc review: no need to be that specific for a fit that does nothing --- src/python/gudhi/representations/vector_methods.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/gudhi/representations/vector_methods.py b/src/python/gudhi/representations/vector_methods.py index 246e9b803b..8790c73e30 100644 --- a/src/python/gudhi/representations/vector_methods.py +++ b/src/python/gudhi/representations/vector_methods.py @@ -912,7 +912,7 @@ def fit(self, X, y=None): Parameters: X (list of n x 2 or n x 1 numpy arrays): input persistence diagrams. - y (n x 1 array): persistence diagram lengths (unused). + y (None): Ignored. """ return self From e984496218c0ee4b463a57e3ca6ceb2ffabe1945 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Tue, 3 Sep 2024 17:51:01 +0200 Subject: [PATCH 11/34] doc review: bad input description for fit --- src/python/gudhi/representations/vector_methods.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/gudhi/representations/vector_methods.py b/src/python/gudhi/representations/vector_methods.py index 8790c73e30..97892c7af8 100644 --- a/src/python/gudhi/representations/vector_methods.py +++ b/src/python/gudhi/representations/vector_methods.py @@ -911,7 +911,7 @@ def fit(self, X, y=None): useful when PersistenceLengths is included in a scikit-learn Pipeline). Parameters: - X (list of n x 2 or n x 1 numpy arrays): input persistence diagrams. + X (list of n x 2 numpy arrays): input persistence diagrams. y (None): Ignored. """ return self From 7a282a1ed567f52b855b560550ab2dc86cdafb0c Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 13 Sep 2024 21:49:07 +0200 Subject: [PATCH 12/34] reformat test file with black --- .../test/test_sklearn_rips_persistence.py | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/python/test/test_sklearn_rips_persistence.py b/src/python/test/test_sklearn_rips_persistence.py index 8687292b8c..ff06dd9b6b 100644 --- a/src/python/test/test_sklearn_rips_persistence.py +++ b/src/python/test/test_sklearn_rips_persistence.py @@ -37,12 +37,12 @@ def test_h1_only_rips_persistence_of_points_on_a_circle(): rips = RipsPersistence(homology_dimensions=1, n_jobs=-2) diags = rips.fit_transform([points.sphere(n_samples=150, ambient_dim=2)])[0] assert len(diags) == 1 - assert 0. < diags[0][0] < 0.6 - assert 1. < diags[0][1] < 2. + assert 0.0 < diags[0][0] < 0.6 + assert 1.0 < diags[0][1] < 2.0 def test_invalid_input_type(): - rips = RipsPersistence(homology_dimensions=0, input_type='whatsoever') + rips = RipsPersistence(homology_dimensions=0, input_type="whatsoever") with pytest.raises(ValueError): rips.fit_transform([points.sphere(n_samples=10, ambient_dim=2)]) @@ -50,13 +50,14 @@ def test_invalid_input_type(): def test_distance_matrix_rips_persistence_of_points_on_a_circle(): try: from scipy.spatial.distance import cdist + pts = points.sphere(n_samples=150, ambient_dim=2) distance_matrix = cdist(pts, pts) - rips = RipsPersistence(homology_dimensions=1, input_type='lower distance matrix') + rips = RipsPersistence(homology_dimensions=1, input_type="lower distance matrix") diags = rips.fit_transform([distance_matrix])[0] assert len(diags) == 1 - assert 0. < diags[0][0] < 0.6 - assert 1. < diags[0][1] < 2. + assert 0.0 < diags[0][0] < 0.6 + assert 1.0 < diags[0][1] < 2.0 except ValueError: pass @@ -64,13 +65,14 @@ def test_distance_matrix_rips_persistence_of_points_on_a_circle(): def test_set_output(): try: import pandas + NB_PC = 5 point_clouds = [points.sphere(n_samples=random.randint(100, 150), ambient_dim=2) for _ in range(NB_PC)] rips = RipsPersistence(homology_dimensions=[0, 2], n_jobs=-2) diags_pandas = rips.set_output(transform="pandas").fit_transform(point_clouds) - assert 'H0' == diags_pandas.columns[0] - assert 'H2' == diags_pandas.columns[1] + assert "H0" == diags_pandas.columns[0] + assert "H2" == diags_pandas.columns[1] assert len(diags_pandas.index) == NB_PC except ImportError: print("Missing pandas, skipping set_output test") @@ -78,10 +80,10 @@ def test_set_output(): def test_big(): # A circle + many isolated points - n=1000000 - X=np.zeros((n,2)) - X[:,0]=np.arange(n)*100 - X[:24]=points.torus(24,1,'grid') + n = 1000000 + X = np.zeros((n, 2)) + X[:, 0] = np.arange(n) * 100 + X[:24] = points.torus(24, 1, "grid") # Ripser cannot handle it, have to fall back to SimplexTree # Computing the full distance matrix would require too much memory -> kd-tree RipsPersistence(range(25), threshold=10).fit_transform([X]) From 30b194c1449946bf1c722642063ee68e37691f73 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 13 Sep 2024 22:08:52 +0200 Subject: [PATCH 13/34] Import Vincent's test --- .../test/test_sklearn_rips_persistence.py | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/python/test/test_sklearn_rips_persistence.py b/src/python/test/test_sklearn_rips_persistence.py index ff06dd9b6b..74971ac56b 100644 --- a/src/python/test/test_sklearn_rips_persistence.py +++ b/src/python/test/test_sklearn_rips_persistence.py @@ -10,6 +10,11 @@ from gudhi.datasets.generators import points from gudhi.sklearn.rips_persistence import RipsPersistence +from gudhi import RipsComplex, SimplexTree +from gudhi._ripser import _lower, _full, _sparse, _lower_to_coo, _lower_cone_radius +from scipy.sparse import coo_matrix +from scipy.spatial.distance import pdist, squareform +from scipy.spatial import cKDTree import numpy as np import random import pytest @@ -87,3 +92,58 @@ def test_big(): # Ripser cannot handle it, have to fall back to SimplexTree # Computing the full distance matrix would require too much memory -> kd-tree RipsPersistence(range(25), threshold=10).fit_transform([X]) + + +def test_ripser_interfaces(): + primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] + random_prime = primes[random.randint(0, 9)] + print(f"random prime = {random_prime}") + + point_cloud = points.sphere(n_samples=random.randint(100, 150), ambient_dim=2) + print(f"nb points = {len(point_cloud)}") + inp = squareform(pdist(point_cloud)) + + # Check cone radius + assert inp.max(-1).min() < 2.0 + assert _lower_cone_radius(inp) < 2.0 + + ## As there is no easy way to force the use of SimplexTree, let's build it + stree = RipsComplex(distance_matrix=inp).create_simplex_tree(max_dimension=2) + stree.compute_persistence(homology_coeff_field=random_prime, persistence_dim_max=True) + dgm0 = stree.persistence_intervals_in_dimension(0) + dgm1 = stree.persistence_intervals_in_dimension(1) + + dgm = _full(inp, max_dimension=2, max_edge_length=float("inf"), homology_coeff_field=random_prime) + np.testing.assert_almost_equal(dgm0, dgm[0]) + np.testing.assert_almost_equal(dgm1, dgm[1]) + + dgm = _lower(inp, max_dimension=2, max_edge_length=float("inf"), homology_coeff_field=random_prime) + np.testing.assert_almost_equal(dgm0, dgm[0]) + np.testing.assert_almost_equal(dgm1, dgm[1]) + + # From a coo matrix + n = len(point_cloud) + tree = cKDTree(point_cloud) + pairs = tree.query_pairs(r=float("inf"), output_type="ndarray") + data = np.ravel(np.linalg.norm(np.diff(point_cloud[pairs], axis=1), axis=-1)) + inp = coo_matrix((data, (pairs[:, 0], pairs[:, 1])), shape=(n,) * 2) + ## As there is no easy way to force the use of SimplexTree, let's build it + stree = SimplexTree() + stree.insert_batch(np.arange(n).reshape(1, -1), np.zeros(n)) + stree.insert_edges_from_coo_matrix(inp) + stree.expansion(2) + stree.compute_persistence(homology_coeff_field=random_prime, persistence_dim_max=True) + dgm0 = stree.persistence_intervals_in_dimension(0) + dgm1 = stree.persistence_intervals_in_dimension(1) + + dgm = _sparse( + inp.row, + inp.col, + inp.data, + inp.shape[0], + max_dimension=2, + max_edge_length=float("inf"), + homology_coeff_field=random_prime, + ) + np.testing.assert_almost_equal(dgm0, dgm[0]) + np.testing.assert_almost_equal(dgm1, dgm[1]) From e0f413606d508261d57d6d492b67abe3fc6a7c10 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 13 Sep 2024 22:45:42 +0200 Subject: [PATCH 14/34] improve ripser test, fix cone radius --- src/python/gudhi/_ripser.cc | 2 +- .../test/test_sklearn_rips_persistence.py | 61 ++++++++++--------- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/python/gudhi/_ripser.cc b/src/python/gudhi/_ripser.cc index 56e528f248..36e84ae9ec 100644 --- a/src/python/gudhi/_ripser.cc +++ b/src/python/gudhi/_ripser.cc @@ -177,7 +177,7 @@ double lower_cone_radius(py::object low_mat) { if (coli < rowi) throw std::invalid_argument("Not enough elements for a lower triangular matrix"); ++rowi; }; - return *std::max_element(maxs.begin(), maxs.end()); + return *std::min_element(maxs.begin(), maxs.end()); } PYBIND11_MODULE(_ripser, m) { diff --git a/src/python/test/test_sklearn_rips_persistence.py b/src/python/test/test_sklearn_rips_persistence.py index 74971ac56b..8865f0ff01 100644 --- a/src/python/test/test_sklearn_rips_persistence.py +++ b/src/python/test/test_sklearn_rips_persistence.py @@ -13,7 +13,7 @@ from gudhi import RipsComplex, SimplexTree from gudhi._ripser import _lower, _full, _sparse, _lower_to_coo, _lower_cone_radius from scipy.sparse import coo_matrix -from scipy.spatial.distance import pdist, squareform +from scipy.spatial.distance import cdist from scipy.spatial import cKDTree import numpy as np import random @@ -96,54 +96,57 @@ def test_big(): def test_ripser_interfaces(): primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] - random_prime = primes[random.randint(0, 9)] - print(f"random prime = {random_prime}") + field = primes[random.randint(0, 9)] + print(f"random prime = {field}") point_cloud = points.sphere(n_samples=random.randint(100, 150), ambient_dim=2) - print(f"nb points = {len(point_cloud)}") - inp = squareform(pdist(point_cloud)) + # point_cloud = np.random.rand(random.randint(100, 150), random.randint(2, 3)) + print(f"nb points = {len(point_cloud)}, dim = {point_cloud.shape[1]}") + dists = cdist(point_cloud, point_cloud) # Check cone radius - assert inp.max(-1).min() < 2.0 - assert _lower_cone_radius(inp) < 2.0 + cr = dists.max(-1).min() + assert cr == _lower_cone_radius(dists) + assert cr < 2.0 ## As there is no easy way to force the use of SimplexTree, let's build it - stree = RipsComplex(distance_matrix=inp).create_simplex_tree(max_dimension=2) - stree.compute_persistence(homology_coeff_field=random_prime, persistence_dim_max=True) + stree = RipsComplex(distance_matrix=dists).create_simplex_tree(max_dimension=2) + stree.compute_persistence(homology_coeff_field=field, persistence_dim_max=True) dgm0 = stree.persistence_intervals_in_dimension(0) dgm1 = stree.persistence_intervals_in_dimension(1) - dgm = _full(inp, max_dimension=2, max_edge_length=float("inf"), homology_coeff_field=random_prime) + dgm = _full(dists, max_dimension=1, max_edge_length=float("inf"), homology_coeff_field=field) np.testing.assert_almost_equal(dgm0, dgm[0]) np.testing.assert_almost_equal(dgm1, dgm[1]) - dgm = _lower(inp, max_dimension=2, max_edge_length=float("inf"), homology_coeff_field=random_prime) + dgm = _lower(dists, max_dimension=1, max_edge_length=float("inf"), homology_coeff_field=field) np.testing.assert_almost_equal(dgm0, dgm[0]) np.testing.assert_almost_equal(dgm1, dgm[1]) # From a coo matrix n = len(point_cloud) - tree = cKDTree(point_cloud) - pairs = tree.query_pairs(r=float("inf"), output_type="ndarray") - data = np.ravel(np.linalg.norm(np.diff(point_cloud[pairs], axis=1), axis=-1)) - inp = coo_matrix((data, (pairs[:, 0], pairs[:, 1])), shape=(n,) * 2) + dists_copy = np.array(dists, copy=True) + dists_copy[np.triu_indices_from(dists_copy)] = 0 # Keep only the lower entries + dists_sparse = coo_matrix(dists_copy) ## As there is no easy way to force the use of SimplexTree, let's build it stree = SimplexTree() stree.insert_batch(np.arange(n).reshape(1, -1), np.zeros(n)) - stree.insert_edges_from_coo_matrix(inp) + stree.insert_edges_from_coo_matrix(dists_sparse) stree.expansion(2) - stree.compute_persistence(homology_coeff_field=random_prime, persistence_dim_max=True) - dgm0 = stree.persistence_intervals_in_dimension(0) - dgm1 = stree.persistence_intervals_in_dimension(1) - - dgm = _sparse( - inp.row, - inp.col, - inp.data, - inp.shape[0], - max_dimension=2, + stree.compute_persistence(homology_coeff_field=field, persistence_dim_max=True) + sp_dgm0 = stree.persistence_intervals_in_dimension(0) + sp_dgm1 = stree.persistence_intervals_in_dimension(1) + + sp_dgm = _sparse( + dists_sparse.row, + dists_sparse.col, + dists_sparse.data, + dists_sparse.shape[0], + max_dimension=1, max_edge_length=float("inf"), - homology_coeff_field=random_prime, + homology_coeff_field=field, ) - np.testing.assert_almost_equal(dgm0, dgm[0]) - np.testing.assert_almost_equal(dgm1, dgm[1]) + np.testing.assert_almost_equal(sp_dgm0, sp_dgm[0]) + np.testing.assert_almost_equal(sp_dgm1, sp_dgm[1]) + np.testing.assert_almost_equal(sp_dgm0, dgm0) + np.testing.assert_almost_equal(sp_dgm1, dgm1) From 896ba1042068951b489ca0bd81bae91f8862e3b3 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 13 Sep 2024 23:32:47 +0200 Subject: [PATCH 15/34] More tweaks to ripser test --- .../test/test_sklearn_rips_persistence.py | 46 ++++++++++++------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/python/test/test_sklearn_rips_persistence.py b/src/python/test/test_sklearn_rips_persistence.py index 8865f0ff01..928c82c313 100644 --- a/src/python/test/test_sklearn_rips_persistence.py +++ b/src/python/test/test_sklearn_rips_persistence.py @@ -12,9 +12,9 @@ from gudhi.sklearn.rips_persistence import RipsPersistence from gudhi import RipsComplex, SimplexTree from gudhi._ripser import _lower, _full, _sparse, _lower_to_coo, _lower_cone_radius +from gudhi import bottleneck_distance from scipy.sparse import coo_matrix from scipy.spatial.distance import cdist -from scipy.spatial import cKDTree import numpy as np import random import pytest @@ -94,13 +94,11 @@ def test_big(): RipsPersistence(range(25), threshold=10).fit_transform([X]) -def test_ripser_interfaces(): - primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] - field = primes[random.randint(0, 9)] +def cmp_rips(point_cloud): + primes = [2, 3, 11, 17, 29] # Small list so 2 is often selected + field = random.choice(primes) print(f"random prime = {field}") - point_cloud = points.sphere(n_samples=random.randint(100, 150), ambient_dim=2) - # point_cloud = np.random.rand(random.randint(100, 150), random.randint(2, 3)) print(f"nb points = {len(point_cloud)}, dim = {point_cloud.shape[1]}") dists = cdist(point_cloud, point_cloud) @@ -109,26 +107,34 @@ def test_ripser_interfaces(): assert cr == _lower_cone_radius(dists) assert cr < 2.0 - ## As there is no easy way to force the use of SimplexTree, let's build it + ## Compute with the SimplexTree stree = RipsComplex(distance_matrix=dists).create_simplex_tree(max_dimension=2) stree.compute_persistence(homology_coeff_field=field, persistence_dim_max=True) dgm0 = stree.persistence_intervals_in_dimension(0) dgm1 = stree.persistence_intervals_in_dimension(1) + # Compute with Ripser dgm = _full(dists, max_dimension=1, max_edge_length=float("inf"), homology_coeff_field=field) - np.testing.assert_almost_equal(dgm0, dgm[0]) - np.testing.assert_almost_equal(dgm1, dgm[1]) + # The order of the intervals may differ, so we cannot compare the arrays with np.testing.assert_almost_equal + assert bottleneck_distance(dgm0, dgm[0]) < 1e-8 + assert bottleneck_distance(dgm1, dgm[1]) < 1e-8 dgm = _lower(dists, max_dimension=1, max_edge_length=float("inf"), homology_coeff_field=field) - np.testing.assert_almost_equal(dgm0, dgm[0]) - np.testing.assert_almost_equal(dgm1, dgm[1]) + assert bottleneck_distance(dgm0, dgm[0]) < 1e-8 + assert bottleneck_distance(dgm1, dgm[1]) < 1e-8 - # From a coo matrix + # Convert to coo matrix n = len(point_cloud) dists_copy = np.array(dists, copy=True) dists_copy[np.triu_indices_from(dists_copy)] = 0 # Keep only the lower entries dists_sparse = coo_matrix(dists_copy) - ## As there is no easy way to force the use of SimplexTree, let's build it + s1 = _lower_to_coo(dists, float("inf")) + s2 = _lower_to_coo(dists_copy, float("inf")) + s1 = coo_matrix((s1[2], (s1[0], s1[1])), shape=(n, n)) + s2 = coo_matrix((s2[2], (s2[0], s2[1])), shape=(n, n)) + assert np.array_equal(s1.toarray(), s2.toarray()) + assert np.array_equal(dists_sparse.toarray(), s1.toarray()) + ## Compute with the SimplexTree stree = SimplexTree() stree.insert_batch(np.arange(n).reshape(1, -1), np.zeros(n)) stree.insert_edges_from_coo_matrix(dists_sparse) @@ -137,6 +143,7 @@ def test_ripser_interfaces(): sp_dgm0 = stree.persistence_intervals_in_dimension(0) sp_dgm1 = stree.persistence_intervals_in_dimension(1) + # Compute with Ripser sp_dgm = _sparse( dists_sparse.row, dists_sparse.col, @@ -146,7 +153,12 @@ def test_ripser_interfaces(): max_edge_length=float("inf"), homology_coeff_field=field, ) - np.testing.assert_almost_equal(sp_dgm0, sp_dgm[0]) - np.testing.assert_almost_equal(sp_dgm1, sp_dgm[1]) - np.testing.assert_almost_equal(sp_dgm0, dgm0) - np.testing.assert_almost_equal(sp_dgm1, dgm1) + assert bottleneck_distance(sp_dgm0, sp_dgm[0]) < 1e-8 + assert bottleneck_distance(sp_dgm1, sp_dgm[1]) < 1e-8 + assert bottleneck_distance(sp_dgm0, dgm0) < 1e-8 + assert bottleneck_distance(sp_dgm1, dgm1) < 1e-8 + + +def test_ripser_interfaces(): + cmp_rips(points.sphere(n_samples=random.randint(100, 150), ambient_dim=2)) + cmp_rips(np.random.rand(random.randint(100, 150), random.randint(2, 3))) From ff3750f115c0588d9e3b923827476a0c40e5833c Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Tue, 17 Sep 2024 16:43:56 +0200 Subject: [PATCH 16/34] Symbolic links for cython and pybind11 compilation --- .../new_gudhi_version_creation.md | 4 ++-- .github/workflows/pip-packaging-linux.yml | 5 ----- .gitignore | 3 --- src/python/CMakeLists.txt | 22 ++++++++++++++++--- src/python/setup.py.in | 2 +- 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/.github/for_maintainers/new_gudhi_version_creation.md b/.github/for_maintainers/new_gudhi_version_creation.md index 1bb6382bba..d094615bdd 100644 --- a/.github/for_maintainers/new_gudhi_version_creation.md +++ b/.github/for_maintainers/new_gudhi_version_creation.md @@ -25,7 +25,7 @@ nor [unlabelled closed PRs](https://github.com/GUDHI/gudhi-devel/pulls?q=is%3Apr **Edit the file CMakeGUDHIVersion.txt**, and increment major, minor, or patch version number, in function of the version new delivery. ```bash # cf. .gitignore - ignore this if it is a fresh clone version -rm -rf data/points/COIL_database/lucky_cat.off_dist data/points/COIL_database/lucky_cat.off_sc.dot data/points/KleinBottle5D.off_dist data/points/KleinBottle5D.off_sc.dot data/points/human.off_dist data/points/human.off_sc.off data/points/human.off_sc.txt src/python/test/__pycache__ src/python/gudhi/*.cpp +rm -rf data/points/COIL_database/lucky_cat.off_dist data/points/COIL_database/lucky_cat.off_sc.dot data/points/KleinBottle5D.off_dist data/points/KleinBottle5D.off_sc.dot data/points/human.off_dist data/points/human.off_sc.off data/points/human.off_sc.txt src/python/test/__pycache__ ``` Checkin the modifications, build and test the version: @@ -154,4 +154,4 @@ Send version mail to the following lists : **Edit the file CMakeGUDHIVersion.txt**, and increment major, minor, or patch version number, in function of the future version (something like `3.X+1.0a0`). -Reset [.github/next_release.md](.github/next_release.md) with [.github/for_maintainers/next_release_template.md](.github/for_maintainers/next_release_template.md). \ No newline at end of file +Reset [.github/next_release.md](.github/next_release.md) with [.github/for_maintainers/next_release_template.md](.github/for_maintainers/next_release_template.md). diff --git a/.github/workflows/pip-packaging-linux.yml b/.github/workflows/pip-packaging-linux.yml index bec8e4a62b..f93d4fbf85 100644 --- a/.github/workflows/pip-packaging-linux.yml +++ b/.github/workflows/pip-packaging-linux.yml @@ -19,7 +19,6 @@ jobs: # numpy~=1.21.4 means any numpy=1.21.*, but also numpy>=1.21.4 (numpy~=1.21 do not work as it means any numpy==1.*) - name: Build wheel for Python 3.8 run: | - rm -rf src/python/gudhi/*.cpp mkdir build_38 cd build_38 cmake -DCMAKE_BUILD_TYPE=Release -DPython_EXECUTABLE=$PYTHON38/bin/python .. @@ -38,7 +37,6 @@ jobs: $PYTHON38/bin/python -m pytest -v src/python/test/test_rips_complex.py - name: Build wheel for Python 3.9 run: | - rm -rf src/python/gudhi/*.cpp mkdir build_39 cd build_39 cmake -DCMAKE_BUILD_TYPE=Release -DPython_EXECUTABLE=$PYTHON39/bin/python .. @@ -61,7 +59,6 @@ jobs: $PYTHON39/bin/python -m pytest -v src/python/test/test_rips_complex.py - name: Build wheel for Python 3.10 run: | - rm -rf src/python/gudhi/*.cpp mkdir build_310 cd build_310 cmake -DCMAKE_BUILD_TYPE=Release -DPython_EXECUTABLE=$PYTHON310/bin/python .. @@ -80,7 +77,6 @@ jobs: $PYTHON310/bin/python -m pytest -v src/python/test/test_rips_complex.py - name: Build wheel for Python 3.11 run: | - rm -rf src/python/gudhi/*.cpp mkdir build_311 cd build_311 cmake -DCMAKE_BUILD_TYPE=Release -DPython_EXECUTABLE=$PYTHON311/bin/python .. @@ -99,7 +95,6 @@ jobs: $PYTHON311/bin/python -m pytest -v src/python/test/test_rips_complex.py - name: Build wheel for Python 3.12 run: | - rm -rf src/python/gudhi/*.cpp mkdir build_312 cd build_312 cmake -DCMAKE_BUILD_TYPE=Release -DPython_EXECUTABLE=$PYTHON312/bin/python .. diff --git a/.gitignore b/.gitignore index 14e4a62e89..bcf839cb8b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,6 @@ # Classical CMake build directory /*build* -# Generated by Cython -src/python/gudhi/*.cpp - # Generated by tests data/points/COIL_database/lucky_cat.off_dist data/points/COIL_database/lucky_cat.off_sc.dot diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index c60f7b9460..273a4c6c2b 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -56,6 +56,14 @@ function( add_gudhi_py_test THE_TEST ) endif() endfunction( add_gudhi_py_test ) +function( add_gudhi_symbolic_links GLOBBING_EXPRESSION ) + file(GLOB GUDHI_GLOB_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${GLOBBING_EXPRESSION}) + foreach(GUDHI_GLOB_FILENAME ${GUDHI_GLOB_FILES}) + message("link ${CMAKE_CURRENT_SOURCE_DIR}/${GUDHI_GLOB_FILENAME} to ${CMAKE_CURRENT_BINARY_DIR}/${GUDHI_GLOB_FILENAME}") + file(CREATE_LINK "${CMAKE_CURRENT_SOURCE_DIR}/${GUDHI_GLOB_FILENAME}" "${CMAKE_CURRENT_BINARY_DIR}/${GUDHI_GLOB_FILENAME}" SYMBOLIC) + endforeach() +endfunction( add_gudhi_symbolic_links ) + # Set gudhi.__debug_info__ # WARNING : to be done before setup.py.in configure_file function( add_gudhi_debug_info DEBUG_INFO ) @@ -382,6 +390,14 @@ file(COPY "gudhi/flag_filtration" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/gudhi # Some files for pip package file(COPY "pyproject.toml" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/") +# Symbolic links to cython and Pybind11 sources to be built. "MAKE_DIRECTORY gudhi" must be done before +add_gudhi_symbolic_links("gudhi/*.pxd") +add_gudhi_symbolic_links("gudhi/*.pyx") +add_gudhi_symbolic_links("gudhi/*.cc") +add_gudhi_symbolic_links("gudhi/clustering/_tomato.cc") +add_gudhi_symbolic_links("gudhi/hera/*.cc") +add_gudhi_symbolic_links("gudhi/datasets/generators/_points.cc") + add_custom_command( OUTPUT gudhi.so WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} @@ -438,7 +454,7 @@ add_test(NAME random_cubical_complex_persistence_example_py_test add_gudhi_py_test(test_cubical_complex) -# Datasets are fetched for these tests +# Datasets are fetched for these tests if(SKLEARN_FOUND AND WITH_GUDHI_REMOTE_TEST) add_gudhi_py_test(test_sklearn_cubical_persistence) @@ -574,7 +590,7 @@ if(SKLEARN_FOUND) add_gudhi_py_test(test_sklearn_rips_persistence) endif() - # Datasets are fetched for these tests + # Datasets are fetched for these tests if(WITH_GUDHI_REMOTE_TEST) add_test(NAME rips_complex_sklearn_itf_py_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} @@ -690,4 +706,4 @@ if(MATPLOTLIB_FOUND) endif() # Set missing or not modules -set(GUDHI_MODULES ${GUDHI_MODULES} "python" CACHE INTERNAL "GUDHI_MODULES") \ No newline at end of file +set(GUDHI_MODULES ${GUDHI_MODULES} "python" CACHE INTERNAL "GUDHI_MODULES") diff --git a/src/python/setup.py.in b/src/python/setup.py.in index 0746536e12..3bc8d0805e 100644 --- a/src/python/setup.py.in +++ b/src/python/setup.py.in @@ -17,7 +17,7 @@ import pybind11 cython_modules = [@GUDHI_CYTHON_MODULES@] pybind11_modules = [@GUDHI_PYBIND11_MODULES@] -source_dir='@CMAKE_CURRENT_SOURCE_DIR@/gudhi/' +source_dir='gudhi/' extra_compile_args=[@GUDHI_PYTHON_EXTRA_COMPILE_ARGS@] extra_link_args=[@GUDHI_PYTHON_EXTRA_LINK_ARGS@] libraries=[@GUDHI_PYTHON_LIBRARIES@] From 1e15367716624ee743f6b1ca627504d74218a9d2 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Thu, 19 Sep 2024 14:14:15 +0200 Subject: [PATCH 17/34] Manage case where python module is built in sources. No need to create symbolic link (and cmake fails to link a file to itself) --- src/python/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 273a4c6c2b..cce1ea77de 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -57,9 +57,12 @@ function( add_gudhi_py_test THE_TEST ) endfunction( add_gudhi_py_test ) function( add_gudhi_symbolic_links GLOBBING_EXPRESSION ) + # No symbolic links if build in sources (aka. 'cmake .' in sources) + if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) + return() + endif() file(GLOB GUDHI_GLOB_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${GLOBBING_EXPRESSION}) foreach(GUDHI_GLOB_FILENAME ${GUDHI_GLOB_FILES}) - message("link ${CMAKE_CURRENT_SOURCE_DIR}/${GUDHI_GLOB_FILENAME} to ${CMAKE_CURRENT_BINARY_DIR}/${GUDHI_GLOB_FILENAME}") file(CREATE_LINK "${CMAKE_CURRENT_SOURCE_DIR}/${GUDHI_GLOB_FILENAME}" "${CMAKE_CURRENT_BINARY_DIR}/${GUDHI_GLOB_FILENAME}" SYMBOLIC) endforeach() endfunction( add_gudhi_symbolic_links ) From 51e658713ba186b31d6b96d4d043d2094778f2f7 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Fri, 20 Sep 2024 16:20:36 +0200 Subject: [PATCH 18/34] copy_on_error if symbolic link failed to be created --- src/python/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index cce1ea77de..c6c8ab9db0 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -63,7 +63,9 @@ function( add_gudhi_symbolic_links GLOBBING_EXPRESSION ) endif() file(GLOB GUDHI_GLOB_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${GLOBBING_EXPRESSION}) foreach(GUDHI_GLOB_FILENAME ${GUDHI_GLOB_FILES}) - file(CREATE_LINK "${CMAKE_CURRENT_SOURCE_DIR}/${GUDHI_GLOB_FILENAME}" "${CMAKE_CURRENT_BINARY_DIR}/${GUDHI_GLOB_FILENAME}" SYMBOLIC) + # COPY_ON_ERROR is activated because on windows, user needs to be root or in dev mode to be able to make symbolic links + # This case can be problematic, because if you modify the sources, build is still done on the copy + file(CREATE_LINK "${CMAKE_CURRENT_SOURCE_DIR}/${GUDHI_GLOB_FILENAME}" "${CMAKE_CURRENT_BINARY_DIR}/${GUDHI_GLOB_FILENAME}" COPY_ON_ERROR SYMBOLIC) endforeach() endfunction( add_gudhi_symbolic_links ) From bfdbaeca78a5fd1b281720300ee98cdc59612167 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau <10407034+VincentRouvreau@users.noreply.github.com> Date: Mon, 23 Sep 2024 10:33:55 +0200 Subject: [PATCH 19/34] [comment review] symlinks creation restriction is only for win10 cf. https://www.howtogeek.com/16226/complete-guide-to-symbolic-links-symlinks-on-windows-or-linux/ Co-authored-by: Marc Glisse --- src/python/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index c6c8ab9db0..e913af6b3f 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -63,7 +63,7 @@ function( add_gudhi_symbolic_links GLOBBING_EXPRESSION ) endif() file(GLOB GUDHI_GLOB_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${GLOBBING_EXPRESSION}) foreach(GUDHI_GLOB_FILENAME ${GUDHI_GLOB_FILES}) - # COPY_ON_ERROR is activated because on windows, user needs to be root or in dev mode to be able to make symbolic links + # COPY_ON_ERROR is activated because on windows 10, user needs to be root or in dev mode to be able to make symbolic links # This case can be problematic, because if you modify the sources, build is still done on the copy file(CREATE_LINK "${CMAKE_CURRENT_SOURCE_DIR}/${GUDHI_GLOB_FILENAME}" "${CMAKE_CURRENT_BINARY_DIR}/${GUDHI_GLOB_FILENAME}" COPY_ON_ERROR SYMBOLIC) endforeach() From 7dd5177936b1a17562cd1d035a96730694205b64 Mon Sep 17 00:00:00 2001 From: hschreiber Date: Mon, 23 Sep 2024 11:01:00 +0200 Subject: [PATCH 20/34] renaming matrix cell as matrix entry --- .../concept/PersistenceMatrixColumn.h | 134 ++++--- .../concept/PersistenceMatrixOptions.h | 6 +- src/Persistence_matrix/include/gudhi/Matrix.h | 249 ++++++------ .../gudhi/Persistence_matrix/Base_matrix.h | 126 +++--- .../Base_matrix_with_column_compression.h | 101 ++--- .../Persistence_matrix/Boundary_matrix.h | 75 ++-- .../gudhi/Persistence_matrix/Chain_matrix.h | 107 ++--- .../Persistence_matrix/Id_to_index_overlay.h | 93 ++--- .../Position_to_index_overlay.h | 49 +-- .../gudhi/Persistence_matrix/RU_matrix.h | 79 ++-- .../allocators/cell_constructors.h | 139 ------- .../allocators/entry_constructors.h | 139 +++++++ .../gudhi/Persistence_matrix/base_swap.h | 4 +- .../Persistence_matrix/chain_vine_swap.h | 8 +- .../Persistence_matrix/columns/cell_types.h | 327 ---------------- .../columns/column_utilities.h | 126 +++--- .../Persistence_matrix/columns/entry_types.h | 327 ++++++++++++++++ .../Persistence_matrix/columns/heap_column.h | 324 ++++++++-------- .../columns/intrusive_list_column.h | 220 +++++------ .../columns/intrusive_set_column.h | 244 ++++++------ .../Persistence_matrix/columns/list_column.h | 286 +++++++------- .../columns/naive_vector_column.h | 328 ++++++++-------- .../Persistence_matrix/columns/row_access.h | 48 +-- .../Persistence_matrix/columns/set_column.h | 266 ++++++------- .../columns/unordered_set_column.h | 344 ++++++++-------- .../columns/vector_column.h | 366 +++++++++--------- .../Persistence_matrix/matrix_row_access.h | 4 +- .../gudhi/Persistence_matrix/ru_rep_cycles.h | 8 +- .../gudhi/Persistence_matrix/ru_vine_swap.h | 18 +- .../gudhi/persistence_matrix_options.h | 16 +- src/Persistence_matrix/test/pm_column_tests.h | 238 ++++++------ .../test/pm_column_tests_mastermatrix.h | 59 +-- src/Persistence_matrix/test/pm_matrix_tests.h | 84 ++-- .../test/pm_test_utilities.h | 40 +- ...test_persistence_matrix_matrix_z2_base.cpp | 2 +- ...rsistence_matrix_matrix_z2_compression.cpp | 2 +- ...test_persistence_matrix_matrix_zp_base.cpp | 2 +- ...rsistence_matrix_matrix_zp_compression.cpp | 2 +- 38 files changed, 2510 insertions(+), 2480 deletions(-) delete mode 100644 src/Persistence_matrix/include/gudhi/Persistence_matrix/allocators/cell_constructors.h create mode 100644 src/Persistence_matrix/include/gudhi/Persistence_matrix/allocators/entry_constructors.h delete mode 100644 src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/cell_types.h create mode 100644 src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/entry_types.h diff --git a/src/Persistence_matrix/concept/PersistenceMatrixColumn.h b/src/Persistence_matrix/concept/PersistenceMatrixColumn.h index dbbca9bdbb..6eaf75f7c9 100644 --- a/src/Persistence_matrix/concept/PersistenceMatrixColumn.h +++ b/src/Persistence_matrix/concept/PersistenceMatrixColumn.h @@ -63,18 +63,18 @@ class PersistenceMatrixColumn : using Master = unspecified; /**< Master matrix, that is a templated @ref Matrix. */ using Index = unspecified; /**< Type of @ref MatIdx index. */ using ID_index = unspecified; /**< Type of @ref IDIdx index. */ - using Dimension = unspecified; /**< Type for dimension value. */ - using Field_element = unspecified; /**< Type of a field element. */ - using Cell = unspecified; /**< @ref Cell. */ + using Dimension = unspecified; /**< Type for dimension value. */ + using Field_element = unspecified; /**< Type of a field element. */ + using Entry = unspecified; /**< @ref Entry. */ using Column_settings = unspecified; /**< Structure giving access to external classes eventually necessary, - like a cell pool for example. */ + like an entry pool for example. */ using iterator = unspecified; /**< Column iterator type. */ using const_iterator = unspecified; /**< Column const_iterator type. */ using reverse_iterator = unspecified; /**< Column reverse_iterator type. */ using const_reverse_iterator = unspecified; /**< Column const_reverse_iterator type. */ /** - * @brief Constructs an empty column. If @p cellConstructor is not specified or is set to `nullptr`, the column + * @brief Constructs an empty column. If @p entryConstructor is not specified or is set to `nullptr`, the column * can only be used as a dummy, i.e., no modifying method should be used or there will be a segmentation fault. * Same goes for @p operators if @ref PersistenceMatrixOptions::is_z2 is false. * @@ -85,12 +85,13 @@ class PersistenceMatrixColumn : */ PersistenceMatrixColumn(Column_settings* colSettings = nullptr); /** - * @brief Constructs a column from the given range of @ref Matrix::Cell_representative. If the dimension is stored, + * @brief Constructs a column from the given range of @ref Matrix::Entry_representative. If the dimension is stored, * the face is assumed to be simplicial and its dimension to be `nonZeroRowIndices length - 1` or `0`. * Otherwise, the dimension should be specified with another constructor. * - * @tparam Container Range of @ref Matrix::Cell_representative. Assumed to have a %begin(), %end() and %size() method. - * @param nonZeroRowIndices Range of @ref Matrix::Cell_representative representing all rows with non zero values. + * @tparam Container Range of @ref Matrix::Entry_representative. Assumed to have a %begin(), %end() and %size() + * method. + * @param nonZeroRowIndices Range of @ref Matrix::Entry_representative representing all rows with non zero values. * @param colSettings Pointer to an existing setting structure. The structure should contain all the necessary * classes specific to the column type, such as custom allocators. The specificities are this way hidden behind * a commun interface for all column types. @@ -99,16 +100,17 @@ class PersistenceMatrixColumn : PersistenceMatrixColumn(const Container& nonZeroRowIndices, Column_settings* colSettings); /** - * @brief Constructs a column from the given range of @ref Matrix::Cell_representative such that the rows can be accessed. - * Each new cell in the column is also inserted in a row using @ref Row_access::insert_cell. + * @brief Constructs a column from the given range of @ref Matrix::Entry_representative such that the rows can be + * accessed. Each new entry in the column is also inserted in a row using @ref Row_access::insert_entry. * If the dimension is stored, the face is assumed to be simplicial and its dimension to be * `nonZeroRowIndices length - 1` or `0`. Otherwise, the dimension should be specified with another constructor. * - * @tparam Container Range of @ref Matrix::Cell_representative. Assumed to have a %begin(), %end() and %size() method. + * @tparam Container Range of @ref Matrix::Entry_representative. Assumed to have a %begin(), %end() and %size() + * method. * @tparam Row_container Either std::map if @ref PersistenceMatrixOptions::has_removable_rows is true or * std::vector. - * @param columnIndex @ref MatIdx column index that should be specified to the cells. - * @param nonZeroRowIndices Range of @ref Matrix::Cell_representative representing all rows with non zero values. + * @param columnIndex @ref MatIdx column index that should be specified to the entries. + * @param nonZeroRowIndices Range of @ref Matrix::Entry_representative representing all rows with non zero values. * @param rowContainer Pointer to the row container that will be forwarded to @ref Row_access at construction. * @param colSettings Pointer to an existing setting structure. The structure should contain all the necessary * classes specific to the column type, such as custom allocators. The specificities are this way hidden behind @@ -120,11 +122,13 @@ class PersistenceMatrixColumn : Row_container* rowContainer, Column_settings* colSettings); /** - * @brief Constructs a column from the given range of @ref Matrix::Cell_representative and stores the given dimension + * @brief Constructs a column from the given range of @ref Matrix::Entry_representative and stores the given dimension * if @ref Column_dimension_option is not a dummy. * - * @tparam Container Range of @ref Matrix::Cell_representative. Assumed to have a %begin(), %end() and %size() method. - * @param nonZeroChainRowIndices Range of @ref Matrix::Cell_representative representing all rows with non zero values. + * @tparam Container Range of @ref Matrix::Entry_representative. Assumed to have a %begin(), %end() and %size() + * method. + * @param nonZeroChainRowIndices Range of @ref Matrix::Entry_representative representing all rows with non zero + * values. * @param dimension Dimension of the column. Is ignored if the dimension is not stored. * @param colSettings Pointer to an existing setting structure. The structure should contain all the necessary * classes specific to the column type, such as custom allocators. The specificities are this way hidden behind @@ -135,15 +139,17 @@ class PersistenceMatrixColumn : Dimension dimension, Column_settings* colSettings); /** - * @brief Constructs a column from the given range of @ref Matrix::Cell_representative such that the rows can be accessed. - * Each new cell in the column is also inserted in a row using @ref Row_access::insert_cell. + * @brief Constructs a column from the given range of @ref Matrix::Entry_representative such that the rows can be + * accessed. Each new entry in the column is also inserted in a row using @ref Row_access::insert_entry. * Stores the given dimension if @ref Column_dimension_option is not a dummy. * - * @tparam Container Range of @ref Matrix::Cell_representative. Assumed to have a %begin(), %end() and %size() method. + * @tparam Container Range of @ref Matrix::Entry_representative. Assumed to have a %begin(), %end() and %size() + * method. * @tparam Row_container Either std::map if @ref PersistenceMatrixOptions::has_removable_rows is true or * std::vector. - * @param columnIndex @ref MatIdx column index that should be specified to the cells. - * @param nonZeroChainRowIndices Range of @ref Matrix::Cell_representative representing all rows with non zero values. + * @param columnIndex @ref MatIdx column index that should be specified to the entries. + * @param nonZeroChainRowIndices Range of @ref Matrix::Entry_representative representing all rows with non zero + * values. * @param dimension Dimension of the column. Is ignored if the dimension is not stored. * @param rowContainer Pointer to the row container that will be forwarded to @ref Row_access at construction. * @param colSettings Pointer to an existing setting structure. The structure should contain all the necessary @@ -157,7 +163,7 @@ class PersistenceMatrixColumn : Row_container* rowContainer, Column_settings* colSettings); /** - * @brief Copy constructor. If @p operators or @p cellConstructor is not a null pointer, its value is kept + * @brief Copy constructor. If @p operators or @p entryConstructor is not a null pointer, its value is kept * instead of the one in the copied column. * * @param column Column to copy. @@ -170,7 +176,7 @@ class PersistenceMatrixColumn : Column_settings* colSettings = nullptr); /** * @brief Copy constructor with row access. - * If @p operators or @p cellConstructor is not a null pointer, its value is kept + * If @p operators or @p entryConstructor stored in @p colSettings is not a null pointer, its value is kept * instead of the one in the copied column. * * @tparam Row_container Either std::map if @ref PersistenceMatrixOptions::has_removable_rows is true or @@ -209,10 +215,10 @@ class PersistenceMatrixColumn : */ std::vector get_content(int columnLength = -1) const; /** - * @brief Indicates if the cell at given row index has value zero. + * @brief Indicates if the entry at given row index has value zero. * * @param rowIndex Row index to look at. - * @return true If the cell has value zero. + * @return true If the entry has value zero. * @return false Otherwise. */ bool is_non_zero(ID_index rowIndex) const; @@ -226,7 +232,7 @@ class PersistenceMatrixColumn : /** * @brief Returns the size of the underlying container. * - * @warning Depending of the column type, the container does not have to contain only the non-zero cells. + * @warning Depending of the column type, the container does not have to contain only the non-zero entries. * Even if for most of the types, the size of the container will correspond to the number of non-zero values * in the column, it is not always the case. See description of the actual Column class for more details. * @@ -236,12 +242,12 @@ class PersistenceMatrixColumn : /** * @brief Reorders the column with the given map of row indices. Also changes the column index stored in the - * cells if row access is enabled and @p columnIndex is not -1. + * entries if row access is enabled and @p columnIndex is not -1. * * Only useful for @ref basematrix "base" and @ref boundarymatrix "boundary matrices" using lazy swaps. * * @tparam Row_index_map Map with an %at() method. - * @param valueMap Map such that `valueMap.at(i)` indicates the new row index of the cell + * @param valueMap Map such that `valueMap.at(i)` indicates the new row index of the entry * at current row index `i`. * @param columnIndex New @ref MatIdx column index of the column. If -1, the index does not change. Ignored if * the row access is not enabled. Default value: -1. @@ -256,15 +262,15 @@ class PersistenceMatrixColumn : */ void clear(); /** - * @brief Zeros the cell at given row index. + * @brief Zeros the entry at given row index. * * Only useful for @ref basematrix "base" and @ref boundarymatrix "boundary matrices". - * Used in @ref Matrix::zero_cell and during vine swaps. + * Used in @ref Matrix::zero_entry and during vine swaps. * - * @warning For @ref Vector_column, do not clear a cell that was already at zero or the results of @ref size and + * @warning For @ref Vector_column, do not clear an entry that was already at zero or the results of @ref size and * @ref is_empty will be wrong. * - * @param rowIndex Row index of the cell to zero. + * @param rowIndex Row index of the entry to zero. */ void clear(ID_index rowIndex); @@ -288,92 +294,94 @@ class PersistenceMatrixColumn : Field_element get_pivot_value(); /** - * @brief Returns a begin @ref Cell iterator to iterate over all cells contained in the underlying container. + * @brief Returns a begin @ref Entry iterator to iterate over all entries contained in the underlying container. * * @warning The iterators really just iterate over the underlying container. Depending of the column type, * neither the content nor the order is guaranteed. See description of the actual Column class for more details. * - * @return @ref Cell iterator. + * @return @ref Entry iterator. */ iterator begin() noexcept; /** - * @brief Returns a begin @ref Cell const iterator to iterate over all cells contained in the underlying container. + * @brief Returns a begin @ref Entry const iterator to iterate over all entries contained in the underlying container. * * @warning The iterators really just iterate over the underlying container. Depending of the column type, * neither the content nor the order is guaranteed. See description of the actual Column class for more details. * - * @return @ref Cell const iterator. + * @return @ref Entry const iterator. */ const_iterator begin() const noexcept; /** - * @brief Returns a end @ref Cell iterator, iterating over all cells contained in the underlying container. + * @brief Returns an end @ref Entry iterator, iterating over all entries contained in the underlying container. * * @warning The iterators really just iterate over the underlying container. Depending of the column type, * neither the content nor the order is guaranteed. See description of the actual Column class for more details. * - * @return @ref Cell iterator. + * @return @ref Entry iterator. */ iterator end() noexcept; /** - * @brief Returns a end @ref Cell const iterator, iterating over all cells contained in the underlying container. + * @brief Returns an end @ref Entry const iterator, iterating over all entries contained in the underlying container. * * @warning The iterators really just iterate over the underlying container. Depending of the column type, * neither the content nor the order is guaranteed. See description of the actual Column class for more details. * - * @return @ref Cell const iterator. + * @return @ref Entry const iterator. */ const_iterator end() const noexcept; /** - * @brief Returns a begin @ref Cell reverse iterator to iterate over all cells contained in the underlying container. + * @brief Returns a begin @ref Entry reverse iterator to iterate over all entries contained in the underlying + * container. * * @warning The iterators really just iterate over the underlying container. Depending of the column type, * neither the content nor the order is guaranteed. See description of the actual Column class for more details. * - * @return @ref Cell reverse iterator. + * @return @ref Entry reverse iterator. */ reverse_iterator rbegin() noexcept; /** - * @brief Returns a begin @ref Cell const reverse iterator to iterate over all cells contained in the underlying + * @brief Returns a begin @ref Entry const reverse iterator to iterate over all entries contained in the underlying * container. * * @warning The iterators really just iterate over the underlying container. Depending of the column type, * neither the content nor the order is guaranteed. See description of the actual Column class for more details. * - * @return @ref Cell const reverse iterator. + * @return @ref Entry const reverse iterator. */ const_reverse_iterator rbegin() const noexcept; /** - * @brief Returns a end @ref Cell reverse iterator, iterating over all cells contained in the underlying container. + * @brief Returns an end @ref Entry reverse iterator, iterating over all entries contained in the underlying + * container. * * @warning The iterators really just iterate over the underlying container. Depending of the column type, * neither the content nor the order is guaranteed. See description of the actual Column class for more details. * - * @return @ref Cell reverse iterator. + * @return @ref Entry reverse iterator. */ reverse_iterator rend() noexcept; /** - * @brief Returns a end @ref Cell const reverse iterator, iterating over all cells contained in the underlying + * @brief Returns an end @ref Entry const reverse iterator, iterating over all entries contained in the underlying * container. * * @warning The iterators really just iterate over the underlying container. Depending of the column type, * neither the content nor the order is guaranteed. See description of the actual Column class for more details. * - * @return @ref Cell const reverse iterator. + * @return @ref Entry const reverse iterator. */ const_reverse_iterator rend() const noexcept; /** - * @brief Adds the given @ref Cell range onto the column. + * @brief Adds the given @ref Entry range onto the column. * - * @tparam Cell_range @ref Cell range with %begin() and %end() method. + * @tparam Entry_range @ref Entry range with %begin() and %end() method. * Has to be ordered by row index if not specified otherwise. - * @param column @ref Cell range. Only the stored row index and the stored element value + * @param column @ref Entry range. Only the stored row index and the stored element value * (if @ref PersistenceMatrixOptions::is_z2 is false) are token into account for this method. * Even if @ref PersistenceMatrixOptions::has_row_access is true, the column index does not need to be correct. * @return Reference to this column. */ - template - PersistenceMatrixColumn& operator+=(const Cell_range& column); + template + PersistenceMatrixColumn& operator+=(const Entry_range& column); /** * @brief Adds the given column onto this column. * @@ -393,35 +401,35 @@ class PersistenceMatrixColumn : /** * @brief `this = val * this + column` * - * @tparam Cell_range @ref Cell range with %begin() and %end() method. + * @tparam Entry_range @ref Entry range with %begin() and %end() method. * Has to be ordered by row index if not specified otherwise. * @param val Value to multiply. - * @param column @ref Cell range. Only the stored row index and the stored element value + * @param column @ref Entry range. Only the stored row index and the stored element value * (if @ref PersistenceMatrixOptions::is_z2 is false) are token into account for this method. * Even if @ref PersistenceMatrixOptions::has_row_access is true, the column index does not need to be correct. * @return Reference to this column. */ - template - PersistenceMatrixColumn& multiply_target_and_add(const Field_element& val, const Cell_range& column); + template + PersistenceMatrixColumn& multiply_target_and_add(const Field_element& val, const Entry_range& column); /** * @brief `this = this + column * val` * - * @tparam Cell_range @ref Cell range with %begin() and %end() method. + * @tparam Entry_range @ref Entry range with %begin() and %end() method. * Has to be ordered by row index if not specified otherwise. - * @param column @ref Cell range. Only the stored row index and the stored element value + * @param column @ref Entry range. Only the stored row index and the stored element value * (if @ref PersistenceMatrixOptions::is_z2 is false) are token into account for this method. * Even if @ref PersistenceMatrixOptions::has_row_access is true, the column index does not need to be correct. * @param val Value to multiply. * @return Reference to this column. */ - template - PersistenceMatrixColumn& multiply_source_and_add(const Cell_range& column, const Field_element& val); + template + PersistenceMatrixColumn& multiply_source_and_add(const Entry_range& column, const Field_element& val); /** * @brief Equality comparator. Equal in the sense that what is "supposed" to be contained in the columns is equal, * not what is actually stored in the underlying container. For example, the underlying container of - * @ref Vector_column can contain cells which were erased explicitly by @ref clear(Index). Those cells should not + * @ref Vector_column can contain entries which were erased explicitly by @ref clear(Index). Those entries should not * be taken into account while comparing. * * @param c1 First column to compare. @@ -434,7 +442,7 @@ class PersistenceMatrixColumn : * @brief "Strictly smaller than" comparator. Usually a lexicographical order, but what matters is that the * order is total. The order should apply on what is "supposed" to be contained in the columns, * not what is actually stored in the underlying container. For example, the underlying container of - * @ref Vector_column can contain cells which were erased explicitly by @ref clear(Index). Those cells should not + * @ref Vector_column can contain entries which were erased explicitly by @ref clear(Index). Those entries should not * be taken into account while comparing. * * @param c1 First column to compare. diff --git a/src/Persistence_matrix/concept/PersistenceMatrixOptions.h b/src/Persistence_matrix/concept/PersistenceMatrixOptions.h index 3d42555dc4..b4d72dc82b 100644 --- a/src/Persistence_matrix/concept/PersistenceMatrixOptions.h +++ b/src/Persistence_matrix/concept/PersistenceMatrixOptions.h @@ -74,7 +74,7 @@ struct PersistenceMatrixOptions * Note that some methods of the @ref basematrix "base matrix" are not available when true: * - @ref Matrix::insert_column(const Container&, Index) "insert_column(const Container&, Index)", * - @ref Matrix::zero_column(Index) "zero_column(Index)", - * - @ref Matrix::zero_cell(Index, Index) "zero_cell(Index, ID_index)", + * - @ref Matrix::zero_entry(Index, Index) "zero_entry(Index, ID_index)", * - @ref Matrix::swap_columns(Index, Index) "swap_columns(Index, Index)", * - @ref Matrix::swap_rows(Index, Index) "swap_rows(Index, Index)", * - @ref Matrix::remove_column(Index) "remove_column(Index)", @@ -111,8 +111,8 @@ struct PersistenceMatrixOptions static const bool has_row_access; /** * @brief Only enabled if @ref has_row_access is true, ignored otherwise. - * If set to true, the underlying container representing a row is an boost::intrusive::list. - * If set to false, the container is a std::set. It is usually recommended to set it to true. + * If set to true, the underlying container representing a row is an boost::intrusive::list. + * If set to false, the container is a std::set. It is usually recommended to set it to true. */ static const bool has_intrusive_rows; /** diff --git a/src/Persistence_matrix/include/gudhi/Matrix.h b/src/Persistence_matrix/include/gudhi/Matrix.h index 1c9b8fa8be..a403ccaa81 100644 --- a/src/Persistence_matrix/include/gudhi/Matrix.h +++ b/src/Persistence_matrix/include/gudhi/Matrix.h @@ -51,8 +51,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -168,7 +168,7 @@ class Matrix { */ using Bar = Persistence_interval; - //tags for boost to associate a row and a column to a same cell + //tags for boost to associate a row and a column to a same entry struct Matrix_row_tag; struct Matrix_column_tag; @@ -182,7 +182,7 @@ class Matrix { boost::intrusive::set_base_hook, boost::intrusive::link_mode >; - //Two dummies are necessary to avoid double inheritance as a cell can inherit both a row and a column hook. + //Two dummies are necessary to avoid double inheritance as an entry can inherit both a row and a column hook. struct Dummy_row_hook {}; struct Dummy_column_hook {}; @@ -200,69 +200,69 @@ class Matrix { >::type >::type; - //Option to store the column index within the cell (additionally to the row index). Necessary only with row access. - using Cell_column_index_option = + //Option to store the column index within the entry (additionally to the row index). Necessary only with row access. + using Entry_column_index_option = typename std::conditional, - Dummy_cell_column_index_mixin + Entry_column_index, + Dummy_entry_column_index_mixin >::type; - //Option to store the value of the cell. - //Unnecessary for values in Z_2 as there are always 1 (0-valued cells are never stored). - using Cell_field_element_option = + //Option to store the value of the entry. + //Unnecessary for values in Z_2 as there are always 1 (0-valued entries are never stored). + using Entry_field_element_option = typename std::conditional + Dummy_entry_field_element_mixin, + Entry_field_element >::type; /** - * @brief Type of a matrix cell. See @ref Cell for a more detailed description. + * @brief Type of a matrix entry. See @ref Entry for a more detailed description. */ - using Matrix_cell = Cell >; + using Matrix_entry = Entry >; /** - * @brief Default cell constructor/destructor, using classic new and delete. + * @brief Default entry constructor/destructor, using classic new and delete. * For now, only used as default value for columns constructed independently outside of the matrix by the user. * Could be used in the future when parallel options are implemented, as usual pools are not thread safe. */ - inline static New_cell_constructor defaultCellConstructor; + inline static New_entry_constructor defaultEntryConstructor; /** - * @brief Cell constructor/destructor used by the matrix. Uses a pool of cells to accelerate memory management, - * as cells are constructed and destroyed a lot during reduction, swaps or additions. + * @brief Entry constructor/destructor used by the matrix. Uses a pool of entries to accelerate memory management, + * as entries are constructed and destroyed a lot during reduction, swaps or additions. */ - using Cell_constructor = Pool_cell_constructor; + using Entry_constructor = Pool_entry_constructor; /** - * @brief Type used to identify a cell, for example when inserting a boundary. + * @brief Type used to identify an entry, for example when inserting a boundary. * If @ref PersistenceMatrixOptions::is_z2 is true, the type is an @ref IDIdx and corresponds to the row index of the - * cell (the cell value is assumed to be 1). If @ref PersistenceMatrixOptions::is_z2 is false, the type is a pair - * whose first element is the row index of the cell and the second element is the value of the cell (which again is + * entry (the entry value is assumed to be 1). If @ref PersistenceMatrixOptions::is_z2 is false, the type is a pair + * whose first element is the row index of the entry and the second element is the value of the entry (which again is * assumed to be non-zero). The column index of the row is always deduced from the context in which the type is used. */ - using Cell_representative = typename std::conditional >::type; /** - * @brief Compares two cells by their position in the row. They are assume to be in the same row. + * @brief Compares two entries by their position in the row. They are assume to be in the same row. */ - struct RowCellComp { - bool operator()(const Matrix_cell& c1, const Matrix_cell& c2) const { + struct RowEntryComp { + bool operator()(const Matrix_entry& c1, const Matrix_entry& c2) const { return c1.get_column_index() < c2.get_column_index(); } }; /** - * @brief Type of the rows stored in the matrix. Is either an intrusive list of @ref Matrix_cell (not ordered) if - * @ref PersistenceMatrixOptions::has_intrusive_rows is true, or a set of @ref Matrix_cell (ordered by + * @brief Type of the rows stored in the matrix. Is either an intrusive list of @ref Matrix_entry (not ordered) if + * @ref PersistenceMatrixOptions::has_intrusive_rows is true, or a set of @ref Matrix_entry (ordered by * column index) otherwise. */ using Row = typename std::conditional, boost::intrusive::base_hook >, - std::set + std::set >::type; using Row_container = @@ -355,43 +355,43 @@ class Matrix { >::type; struct Column_z2_settings{ - Column_z2_settings() : cellConstructor() {} - Column_z2_settings([[maybe_unused]] Characteristic characteristic) : cellConstructor() {} - Column_z2_settings(const Column_z2_settings& toCopy) : cellConstructor() {} + Column_z2_settings() : entryConstructor() {} + Column_z2_settings([[maybe_unused]] Characteristic characteristic) : entryConstructor() {} + Column_z2_settings(const Column_z2_settings& toCopy) : entryConstructor() {} - Cell_constructor cellConstructor; //will be replaced by more specific allocators depending on the column type. + Entry_constructor entryConstructor; //will be replaced by more specific allocators depending on the column type. }; struct Column_zp_settings { - Column_zp_settings() : operators(), cellConstructor() {} + Column_zp_settings() : operators(), entryConstructor() {} //purposely triggers operators() instead of operators(characteristic) as the "dummy" values for the different //operators can be different from -1. - Column_zp_settings(Characteristic characteristic) : operators(), cellConstructor() { + Column_zp_settings(Characteristic characteristic) : operators(), entryConstructor() { if (characteristic != static_cast(-1)) operators.set_characteristic(characteristic); } Column_zp_settings(const Column_zp_settings& toCopy) - : operators(toCopy.operators.get_characteristic()), cellConstructor() {} + : operators(toCopy.operators.get_characteristic()), entryConstructor() {} Field_operators operators; - Cell_constructor cellConstructor; //will be replaced by more specific allocators depending on the column type. + Entry_constructor entryConstructor; //will be replaced by more specific allocators depending on the column type. }; // struct Column_z2_with_rows_settings { - // Column_z2_with_rows_settings() : cellConstructor(), rows(nullptr) {} + // Column_z2_with_rows_settings() : entryConstructor(), rows(nullptr) {} // Column_z2_with_rows_settings([[maybe_unused]] Characteristic characteristic) - // : cellConstructor(), rows(nullptr) {} + // : entryConstructor(), rows(nullptr) {} - // Cell_constructor cellConstructor; + // Entry_constructor entryConstructor; // Row_container* rows; // }; // struct Column_zp_with_rows_settings { - // Column_zp_with_rows_settings() : operators(), cellConstructor(), rows(nullptr) {} + // Column_zp_with_rows_settings() : operators(), entryConstructor(), rows(nullptr) {} // Column_zp_with_rows_settings(Characteristic characteristic) - // : operators(characteristic), cellConstructor(), rows(nullptr) {} + // : operators(characteristic), entryConstructor(), rows(nullptr) {} // Field_operators operators; - // Cell_constructor cellConstructor; + // Entry_constructor entryConstructor; // Row_container* rows; // }; @@ -548,7 +548,7 @@ class Matrix { PersistenceMatrixOptions::column_indexation_type == Column_indexation_types::POSITION, void, - std::vector + std::vector >::type; /** @@ -556,14 +556,14 @@ class Matrix { */ Matrix(); /** - * @brief Constructs a new matrix from the given ranges of @ref Cell_representative. Each range corresponds to a column (the - * order of the ranges are preserved). The content of the ranges is assumed to be sorted by increasing IDs. If the - * columns are representing a boundary matrix, the IDs of the simplices are also assumed to be consecutive, ordered by - * filtration value, starting with 0. + * @brief Constructs a new matrix from the given ranges of @ref Entry_representative. Each range corresponds to a + * column (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by increasing + * IDs. If the columns are representing a boundary matrix, the IDs of the simplices are also assumed to be + * consecutive, ordered by filtration value, starting with 0. * * See @ref mp_matrices "matrix descriptions" for further details on how the given matrix is handled. * - * @tparam Container Range type for @ref Cell_representative ranges. Assumed to have a begin(), end() and size() + * @tparam Container Range type for @ref Entry_representative ranges. Assumed to have a begin(), end() and size() * method. * @param columns For a @ref basematrix "base matrix", the columns are copied as is. If options related to homology * are activated, @p columns is interpreted as a boundary matrix of a **simplicial** complex. In this case, @@ -629,7 +629,8 @@ class Matrix { * @ref Matrix(const std::function&, const std::function&) * for more information about the comparators. * - * @tparam Boundary_range Range type for @ref Cell_representative ranges. Assumed to have a begin(), end() and size() method. + * @tparam Boundary_range Range type for @ref Entry_representative ranges. Assumed to have a begin(), end() and size() + * method. * @param orderedBoundaries Vector of ordered boundaries in filtration order. Indexed continuously starting at 0. * @param birthComparator Method taking two @ref PosIdx indices as parameter and returns true if and only if the first * face is associated to a bar with strictly smaller birth than the bar associated to the second one. @@ -697,7 +698,7 @@ class Matrix { * Do not change the value of the characteristic once used. * * @warning The coefficient values stored in the matrix are stored after computing the corresponding modulo. - * Therefore, changing the characteristic after is very likely to invalidate all cell values. + * Therefore, changing the characteristic after is very likely to invalidate all entry values. * * @param characteristic The characteristic to set. */ @@ -706,25 +707,25 @@ class Matrix { // (TODO: if there is no row access and the column type corresponds to the internal column type of the matrix, // moving the column instead of copying it should be possible. Is it worth implementing it?) /** - * @brief Inserts a new ordered column at the end of the matrix by copying the given range of @ref Cell_representative. - * The content of the range is assumed to be sorted by increasing ID value. + * @brief Inserts a new ordered column at the end of the matrix by copying the given range of + * @ref Entry_representative. The content of the range is assumed to be sorted by increasing ID value. * * Only available for @ref basematrix "base matrices". * Otherwise use @ref insert_boundary which will deduce a new column from the boundary given. * - * @tparam Container Range of @ref Cell_representative. Assumed to have a begin(), end() and size() method. + * @tparam Container Range of @ref Entry_representative. Assumed to have a begin(), end() and size() method. * @param column Column to be inserted. */ template void insert_column(const Container& column); /** - * @brief Inserts a new ordered column at the given index by copying the given range of @ref Cell_representative. + * @brief Inserts a new ordered column at the given index by copying the given range of @ref Entry_representative. * There should not be any other column inserted at that index which was not explicitly removed before. * The content of the range is assumed to be sorted by increasing ID value. * * Only available for @ref basematrix "base matrices" without column compression and without row access. * - * @tparam Container Range of @ref Cell_representative. Assumed to have a begin(), end() and size() method. + * @tparam Container Range of @ref Entry_representative. Assumed to have a begin(), end() and size() method. * @param column Column to be inserted. * @param columnIndex @ref MatIdx index to which the column has to be inserted. */ @@ -741,7 +742,7 @@ class Matrix { * instead by indicating the face ID used in the boundaries when the face is inserted. * * Different to the constructor, the boundaries do not have to come from a simplicial complex, but also from - * a more general cell complex. This includes cubical complexes or Morse complexes for example. + * a more general entry complex. This includes cubical complexes or Morse complexes for example. * * The content of the new column will vary depending on the underlying @ref mp_matrices "type of the matrix": * - If it is a @ref basematrix "basic matrix" type, the boundary is copied as it is, i.e., the method is equivalent @@ -756,7 +757,7 @@ class Matrix { * older column IDIdxs`, where the combination is deduced while reducing the given boundary. If the barcode is stored, * it will also be updated. * - * @tparam Boundary_range Range of @ref Cell_representative. Assumed to have a begin(), end() and size() method. + * @tparam Boundary_range Range of @ref Entry_representative. Assumed to have a begin(), end() and size() method. * @param boundary Boundary generating the new column. The content should be ordered by ID. * @param dim Dimension of the face whose boundary is given. If the complex is simplicial, * this parameter can be omitted as it can be deduced from the size of the boundary. @@ -775,7 +776,7 @@ class Matrix { * for @ref mp_matrices "non-basic matrices", the faces are inserted by order of filtration), it is sufficient to * indicate the ID of the face being inserted. * - * @tparam Boundary_range Range of @ref Cell_representative. Assumed to have a begin(), end() and size() method. + * @tparam Boundary_range Range of @ref Entry_representative. Assumed to have a begin(), end() and size() method. * @param faceIndex @ref IDIdx index to use to identify the new face. * @param boundary Boundary generating the new column. The indices of the boundary have to correspond to the * @p faceIndex values of precedent calls of the method for the corresponding faces and should be ordered in @@ -859,8 +860,8 @@ class Matrix { /** * @brief Only available for @ref basematrix "base matrices" without column compression and if * @ref PersistenceMatrixOptions::has_map_column_container is true. Otherwise, see @ref remove_last. Erases the given - * column from the matrix. If @ref PersistenceMatrixOptions::has_row_access is also true, the deleted column cells are - * also automatically removed from their respective rows. + * column from the matrix. If @ref PersistenceMatrixOptions::has_row_access is also true, the deleted column entries + * are also automatically removed from their respective rows. * * @param columnIndex @ref MatIdx index of the column to remove. */ @@ -879,11 +880,11 @@ class Matrix { * - @ref chainmatrix "chain matrix": only available if @ref PersistenceMatrixOptions::has_row_access and * @ref PersistenceMatrixOptions::has_removable_rows are true. Assumes that the row is empty and removes it. * - * @warning The removed rows are always assumed to be empty. If it is not the case, the deleted row cells are not + * @warning The removed rows are always assumed to be empty. If it is not the case, the deleted row entries are not * removed from their columns. And in the case of intrusive rows, this will generate a segmentation fault when - * the column cells are destroyed later. The row access is just meant as a "read only" access to the rows and the + * the column entries are destroyed later. The row access is just meant as a "read only" access to the rows and the * @ref erase_empty_row method just as a way to specify that a row is empty and can therefore be removed from - * dictionaries. This allows to avoid testing the emptiness of a row at each column cell removal, what can be quite + * dictionaries. This allows to avoid testing the emptiness of a row at each column entry removal, what can be quite * frequent. * * @param rowIndex @ref rowindex "Row index" of the empty row to remove. @@ -992,19 +993,19 @@ class Matrix { std::enable_if_t > add_to(Integer_index sourceColumnIndex, Integer_index targetColumnIndex); /** - * @brief Adds the given range of @ref Cell onto the column at @p targetColumnIndex in the matrix. Only available + * @brief Adds the given range of @ref Entry onto the column at @p targetColumnIndex in the matrix. Only available * for @ref basematrix "basic matrices". * * For @ref basematrix "basic matrices" with column compression, the range is summed onto the representative, which * means that all column compressed together with the target column are affected by the change, not only the target. * - * @tparam Cell_range Range of @ref Cell. Needs a begin() and end() method. A column index does not need to be - * stored in the cells, even if @ref PersistenceMatrixOptions::has_row_access is true. - * @param sourceColumn Source @ref Cell range. + * @tparam Entry_range Range of @ref Entry. Needs a begin() and end() method. A column index does not need to be + * stored in the entries, even if @ref PersistenceMatrixOptions::has_row_access is true. + * @param sourceColumn Source @ref Entry range. * @param targetColumnIndex @ref MatIdx index of the target column. */ - template - std::enable_if_t > add_to(const Cell_range& sourceColumn, Index targetColumnIndex); + template + std::enable_if_t > add_to(const Entry_range& sourceColumn, Index targetColumnIndex); /** * @brief Multiplies the target column with the coefficient and then adds the source column to it. @@ -1027,21 +1028,21 @@ class Matrix { int coefficient, Integer_index targetColumnIndex); /** - * @brief Multiplies the target column with the coefficient and then adds the given range of @ref Cell to it. + * @brief Multiplies the target column with the coefficient and then adds the given range of @ref Entry to it. * That is: `targetColumn = (targetColumn * coefficient) + sourceColumn`. Only available for * @ref basematrix "basic matrices". * * For @ref basematrix "basic matrices" with column compression, the range is summed onto the representative, which * means that all column compressed together with the target column are affected by the change, not only the target. * - * @tparam Cell_range Range of @ref Cell. Needs a begin() and end() method. A column index does not need to be - * stored in the cells, even if @ref PersistenceMatrixOptions::has_row_access is true. - * @param sourceColumn Source @ref Cell range. + * @tparam Entry_range Range of @ref Entry. Needs a begin() and end() method. A column index does not need to be + * stored in the entries, even if @ref PersistenceMatrixOptions::has_row_access is true. + * @param sourceColumn Source @ref Entry range. * @param coefficient Value to multiply. * @param targetColumnIndex @ref MatIdx index of the target column. */ - template - std::enable_if_t > multiply_target_and_add_to(const Cell_range& sourceColumn, + template + std::enable_if_t > multiply_target_and_add_to(const Entry_range& sourceColumn, int coefficient, Index targetColumnIndex); @@ -1073,40 +1074,40 @@ class Matrix { * For @ref basematrix "basic matrices" with column compression, the range is summed onto the representative, which * means that all column compressed together with the target column are affected by the change, not only the target. * - * @tparam Cell_range Range of @ref Cell. Needs a begin() and end() method. A column index does not need to be - * stored in the cells, even if @ref PersistenceMatrixOptions::has_row_access is true. + * @tparam Entry_range Range of @ref Entry. Needs a begin() and end() method. A column index does not need to be + * stored in the entries, even if @ref PersistenceMatrixOptions::has_row_access is true. * @param coefficient Value to multiply. - * @param sourceColumn Source @ref Cell range. + * @param sourceColumn Source @ref Entry range. * @param targetColumnIndex @ref MatIdx index of the target column. */ - template - std::enable_if_t > multiply_source_and_add_to(int coefficient, - const Cell_range& sourceColumn, + template + std::enable_if_t > multiply_source_and_add_to(int coefficient, + const Entry_range& sourceColumn, Index targetColumnIndex); /** - * @brief Zeroes the cell at the given coordinates. Not available for @ref chainmatrix "chain matrices" and for + * @brief Zeroes the entry at the given coordinates. Not available for @ref chainmatrix "chain matrices" and for * @ref basematrix "base matrices" with column compression. In general, should be used with care with * @ref mp_matrices "non-basic matrices" to not destroy the validity of the persistence related properties of the * matrix. * * For @ref boundarymatrix "RU matrices", equivalent to - * @ref zero_cell(Index columnIndex, ID_index rowIndex, bool inR) "zero_cell(columnIndex, rowIndex, true)". + * @ref zero_entry(Index columnIndex, ID_index rowIndex, bool inR) "zero_entry(columnIndex, rowIndex, true)". * - * @param columnIndex @ref MatIdx index of the column of the cell. - * @param rowIndex @ref rowindex "Row index" of the row of the cell. + * @param columnIndex @ref MatIdx index of the column of the entry. + * @param rowIndex @ref rowindex "Row index" of the row of the entry. */ - void zero_cell(Index columnIndex, ID_index rowIndex); + void zero_entry(Index columnIndex, ID_index rowIndex); /** - * @brief Only available for @ref boundarymatrix "RU matrices". Zeroes the cell at the given coordinates in \f$ R \f$ + * @brief Only available for @ref boundarymatrix "RU matrices". Zeroes the entry at the given coordinates in \f$ R \f$ * if @p inR is true or in \f$ U \f$ if @p inR is false. Should be used with care to not destroy the validity of the * persistence related properties of the matrix. * - * @param columnIndex @ref MatIdx index of the column of the cell. - * @param rowIndex @ref rowindex "Row index" of the row of the cell. + * @param columnIndex @ref MatIdx index of the column of the entry. + * @param rowIndex @ref rowindex "Row index" of the row of the entry. * @param inR Boolean indicating in which matrix to zero: if true in \f$ R \f$ and if false in \f$ U \f$. */ - void zero_cell(Index columnIndex, ID_index rowIndex, bool inR); + void zero_entry(Index columnIndex, ID_index rowIndex, bool inR); /** * @brief Zeroes the column at the given index. Not available for @ref chainmatrix "chain matrices" and for * @ref basematrix "base matrices" with column compression. In general, should be used with care with @@ -1129,29 +1130,29 @@ class Matrix { */ void zero_column(Index columnIndex, bool inR); /** - * @brief Indicates if the cell at given coordinates has value zero. + * @brief Indicates if the entry at given coordinates has value zero. * * For @ref boundarymatrix "RU matrices", equivalent to - * @ref is_zero_cell(Index columnIndex, ID_index rowIndex, bool inR) const - * "is_zero_cell(columnIndex, rowIndex, true)". + * @ref is_zero_entry(Index columnIndex, ID_index rowIndex, bool inR) const + * "is_zero_entry(columnIndex, rowIndex, true)". * - * @param columnIndex @ref MatIdx index of the column of the cell. - * @param rowIndex @ref rowindex "Row index" of the row of the cell. - * @return true If the cell has value zero. + * @param columnIndex @ref MatIdx index of the column of the entry. + * @param rowIndex @ref rowindex "Row index" of the row of the entry. + * @return true If the entry has value zero. * @return false Otherwise. */ - bool is_zero_cell(Index columnIndex, ID_index rowIndex); + bool is_zero_entry(Index columnIndex, ID_index rowIndex); /** - * @brief Only available for @ref boundarymatrix "RU matrices". Indicates if the cell at given coordinates has value + * @brief Only available for @ref boundarymatrix "RU matrices". Indicates if the entry at given coordinates has value * zero in \f$ R \f$ if @p inR is true or in \f$ U \f$ if @p inR is false. * - * @param columnIndex @ref MatIdx index of the column of the cell. - * @param rowIndex @ref rowindex "Row index" of the row of the cell. + * @param columnIndex @ref MatIdx index of the column of the entry. + * @param rowIndex @ref rowindex "Row index" of the row of the entry. * @param inR Boolean indicating in which matrix to look: if true in \f$ R \f$ and if false in \f$ U \f$. - * @return true If the cell has value zero. + * @return true If the entry has value zero. * @return false Otherwise. */ - bool is_zero_cell(Index columnIndex, ID_index rowIndex, bool inR) const; + bool is_zero_entry(Index columnIndex, ID_index rowIndex, bool inR) const; /** * @brief Indicates if the column at given index has value zero. * @@ -1394,7 +1395,7 @@ class Matrix { >::type; // Field_operators* operators_; - // Cell_constructor* cellPool_; + // Entry_constructor* entryPool_; Column_settings* colSettings_; //pointer because the of swap operator on matrix_ which also stores the pointer Underlying_matrix matrix_; @@ -1746,9 +1747,9 @@ inline std::enable_if_t > Matrix -template -inline std::enable_if_t > Matrix::add_to( - const Cell_range& sourceColumn, Index targetColumnIndex) +template +inline std::enable_if_t > Matrix::add_to( + const Entry_range& sourceColumn, Index targetColumnIndex) { static_assert(!isNonBasic, "For boundary or chain matrices, only additions with columns inside the matrix is allowed to maintain " @@ -1771,9 +1772,9 @@ inline std::enable_if_t > Matrix -template -inline std::enable_if_t > Matrix::multiply_target_and_add_to( - const Cell_range& sourceColumn, int coefficient, Index targetColumnIndex) +template +inline std::enable_if_t > Matrix::multiply_target_and_add_to( + const Entry_range& sourceColumn, int coefficient, Index targetColumnIndex) { static_assert(!isNonBasic, "For boundary or chain matrices, only additions with columns inside the matrix is allowed to maintain " @@ -1801,9 +1802,9 @@ inline std::enable_if_t > Matrix -template -inline std::enable_if_t > Matrix::multiply_source_and_add_to( - int coefficient, const Cell_range& sourceColumn, Index targetColumnIndex) +template +inline std::enable_if_t > Matrix::multiply_source_and_add_to( + int coefficient, const Entry_range& sourceColumn, Index targetColumnIndex) { static_assert(!isNonBasic, "For boundary or chain matrices, only additions with columns inside the matrix is allowed to maintain " @@ -1818,16 +1819,16 @@ inline std::enable_if_t > Matrix -inline void Matrix::zero_cell(Index columnIndex, ID_index rowIndex) +inline void Matrix::zero_entry(Index columnIndex, ID_index rowIndex) { static_assert(PersistenceMatrixOptions::is_of_boundary_type && !PersistenceMatrixOptions::has_column_compression, - "'zero_cell' is not available for the chosen options."); + "'zero_entry' is not available for the chosen options."); - return matrix_.zero_cell(columnIndex, rowIndex); + return matrix_.zero_entry(columnIndex, rowIndex); } template -inline void Matrix::zero_cell(Index columnIndex, ID_index rowIndex, bool inR) +inline void Matrix::zero_entry(Index columnIndex, ID_index rowIndex, bool inR) { // TODO: I don't think there is a particular reason why the indexation is forced, should be removed. static_assert( @@ -1836,7 +1837,7 @@ inline void Matrix::zero_cell(Index columnIndex, ID_in PersistenceMatrixOptions::column_indexation_type != Column_indexation_types::IDENTIFIER, "Only enabled for RU matrices."); - return matrix_.zero_cell(columnIndex, rowIndex, inR); + return matrix_.zero_entry(columnIndex, rowIndex, inR); } template @@ -1862,13 +1863,13 @@ inline void Matrix::zero_column(Index columnIndex, boo } template -inline bool Matrix::is_zero_cell(Index columnIndex, ID_index rowIndex) +inline bool Matrix::is_zero_entry(Index columnIndex, ID_index rowIndex) { - return matrix_.is_zero_cell(columnIndex, rowIndex); + return matrix_.is_zero_entry(columnIndex, rowIndex); } template -inline bool Matrix::is_zero_cell(Index columnIndex, ID_index rowIndex, bool inR) const +inline bool Matrix::is_zero_entry(Index columnIndex, ID_index rowIndex, bool inR) const { // TODO: I don't think there is a particular reason why the indexation is forced, should be removed. static_assert( @@ -1877,7 +1878,7 @@ inline bool Matrix::is_zero_cell(Index columnIndex, ID PersistenceMatrixOptions::column_indexation_type != Column_indexation_types::IDENTIFIER, "Only enabled for RU matrices."); - return matrix_.is_zero_cell(columnIndex, rowIndex, inR); + return matrix_.is_zero_entry(columnIndex, rowIndex, inR); } template diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/Base_matrix.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/Base_matrix.h index 9eff178fc5..c78cf41107 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/Base_matrix.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/Base_matrix.h @@ -29,7 +29,7 @@ namespace persistence_matrix { * @ingroup persistence_matrix * * @brief A @ref basematrix "basic matrix" structure allowing to easily manipulate and access entire columns and rows, - * but not individual cells. + * but not individual entries. * * @tparam Master_matrix An instantiation of @ref Matrix from which all types and options are deduced. */ @@ -44,14 +44,14 @@ class Base_matrix : public Master_matrix::template Base_swap_option void insert_column(const Container& column); /** - * @brief Inserts a new ordered column at the given index by copying the given range of @ref Matrix::Cell_representative. + * @brief Inserts a new ordered column at the given index by copying the given range of + * @ref Matrix::Entry_representative. * There should not be any other column inserted at that index which was not explicitly removed before. * The content of the range is assumed to be sorted by increasing ID value. * Not available when row access is enabled. * - * @tparam Container Range of @ref Matrix::Cell_representative. Assumed to have a begin(), end() and size() method. - * @param column Range of @ref Matrix::Cell_representative from which the column has to be constructed. Assumed to be + * @tparam Container Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() method. + * @param column Range of @ref Matrix::Entry_representative from which the column has to be constructed. Assumed to be * ordered by increasing ID value. * @param columnIndex @ref MatIdx index to which the column has to be inserted. */ @@ -125,9 +126,10 @@ class Base_matrix : public Master_matrix::template Base_swap_option @@ -136,7 +138,7 @@ class Base_matrix : public Master_matrix::template Base_swap_option - void add_to(const Cell_range_or_column_index& sourceColumn, Index targetColumnIndex); + template + void add_to(const Entry_range_or_column_index& sourceColumn, Index targetColumnIndex); /** * @brief Multiplies the target column with the coefficient and then adds the source column to it. * That is: `targetColumn = (targetColumn * coefficient) + sourceColumn`. * - * @tparam Cell_range_or_column_index Either a range of @ref Cell with a begin() and end() method, + * @tparam Entry_range_or_column_index Either a range of @ref Entry with a begin() and end() method, * or any integer type. - * @param sourceColumn Either a cell range or the @ref MatIdx index of the column to add. + * @param sourceColumn Either an entry range or the @ref MatIdx index of the column to add. * @param coefficient Value to multiply. * @param targetColumnIndex @ref MatIdx index of the target column. */ - template - void multiply_target_and_add_to(const Cell_range_or_column_index& sourceColumn, + template + void multiply_target_and_add_to(const Entry_range_or_column_index& sourceColumn, const Field_element& coefficient, Index targetColumnIndex); /** * @brief Multiplies the source column with the coefficient before adding it to the target column. * That is: `targetColumn += (coefficient * sourceColumn)`. The source column will **not** be modified. * - * @tparam Cell_range_or_column_index Either a range of @ref Cell with a begin() and end() method, + * @tparam Entry_range_or_column_index Either a range of @ref Entry with a begin() and end() method, * or any integer type. * @param coefficient Value to multiply. - * @param sourceColumn Either a cell range or the @ref MatIdx index of the column to add. + * @param sourceColumn Either an entry range or the @ref MatIdx index of the column to add. * @param targetColumnIndex @ref MatIdx index of the target column. */ - template + template void multiply_source_and_add_to(const Field_element& coefficient, - const Cell_range_or_column_index& sourceColumn, + const Entry_range_or_column_index& sourceColumn, Index targetColumnIndex); /** - * @brief Zeroes the cell at the given coordinates. + * @brief Zeroes the entry at the given coordinates. * - * @param columnIndex @ref MatIdx index of the column of the cell. - * @param rowIndex @ref rowindex "Row index" of the row of the cell. + * @param columnIndex @ref MatIdx index of the column of the entry. + * @param rowIndex @ref rowindex "Row index" of the row of the entry. */ - void zero_cell(Index columnIndex, Index rowIndex); + void zero_entry(Index columnIndex, Index rowIndex); /** * @brief Zeroes the column at the given index. * @@ -265,14 +267,14 @@ class Base_matrix : public Master_matrix::template Base_swap_option >; using RA_opt = typename Master_matrix::Matrix_row_access_option; using Column_container = typename Master_matrix::Column_container; - using Cell_representative = + using Entry_representative = typename std::conditional @@ -330,7 +332,7 @@ class Base_matrix : public Master_matrix::template Base_swap_option void _insert(const Container& column, Index columnIndex, Dimension dim); @@ -513,11 +515,11 @@ inline typename Base_matrix::Index Base_matrix::ge } template -template -inline void Base_matrix::add_to(const Cell_range_or_column_index& sourceColumn, +template +inline void Base_matrix::add_to(const Entry_range_or_column_index& sourceColumn, Index targetColumnIndex) { - if constexpr (std::is_integral_v) { + if constexpr (std::is_integral_v) { _get_column(targetColumnIndex) += _get_column(sourceColumn); } else { _get_column(targetColumnIndex) += sourceColumn; @@ -525,12 +527,12 @@ inline void Base_matrix::add_to(const Cell_range_or_column_index& } template -template -inline void Base_matrix::multiply_target_and_add_to(const Cell_range_or_column_index& sourceColumn, +template +inline void Base_matrix::multiply_target_and_add_to(const Entry_range_or_column_index& sourceColumn, const Field_element& coefficient, Index targetColumnIndex) { - if constexpr (std::is_integral_v) { + if constexpr (std::is_integral_v) { _get_column(targetColumnIndex).multiply_target_and_add(coefficient, _get_column(sourceColumn)); } else { _get_column(targetColumnIndex).multiply_target_and_add(coefficient, sourceColumn); @@ -538,12 +540,12 @@ inline void Base_matrix::multiply_target_and_add_to(const Cell_ra } template -template +template inline void Base_matrix::multiply_source_and_add_to(const Field_element& coefficient, - const Cell_range_or_column_index& sourceColumn, + const Entry_range_or_column_index& sourceColumn, Index targetColumnIndex) { - if constexpr (std::is_integral_v) { + if constexpr (std::is_integral_v) { _get_column(targetColumnIndex).multiply_source_and_add(_get_column(sourceColumn), coefficient); } else { _get_column(targetColumnIndex).multiply_source_and_add(sourceColumn, coefficient); @@ -551,7 +553,7 @@ inline void Base_matrix::multiply_source_and_add_to(const Field_e } template -inline void Base_matrix::zero_cell(Index columnIndex, Index rowIndex) +inline void Base_matrix::zero_entry(Index columnIndex, Index rowIndex) { _get_column(columnIndex).clear(_get_real_row_index(rowIndex)); } @@ -562,7 +564,7 @@ inline void Base_matrix::zero_column(Index columnIndex) { } template -inline bool Base_matrix::is_zero_cell(Index columnIndex, Index rowIndex) const +inline bool Base_matrix::is_zero_entry(Index columnIndex, Index rowIndex) const { return !(_get_column(columnIndex).is_non_zero(_get_real_row_index(rowIndex))); } @@ -614,8 +616,8 @@ inline void Base_matrix::print() std::cout << "Row Matrix:\n"; for (Index i = 0; i < nextInsertIndex_; ++i) { const auto& row = RA_opt::rows_[i]; - for (const auto& cell : row) { - std::cout << cell.get_column_index() << " "; + for (const auto& entry : row) { + std::cout << entry.get_column_index() << " "; } std::cout << "(" << i << ")\n"; } diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/Base_matrix_with_column_compression.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/Base_matrix_with_column_compression.h index 009e016517..cdb3efb6e8 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/Base_matrix_with_column_compression.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/Base_matrix_with_column_compression.h @@ -45,18 +45,18 @@ template class Base_matrix_with_column_compression : protected Master_matrix::Matrix_row_access_option { public: - using Index = typename Master_matrix::Index; /**< Container index type. */ - using Dimension = typename Master_matrix::Dimension; /**< Dimension value type. */ + using Index = typename Master_matrix::Index; /**< Container index type. */ + using Dimension = typename Master_matrix::Dimension; /**< Dimension value type. */ /** * @brief Field operators class. Necessary only if @ref PersistenceMatrixOptions::is_z2 is false. */ using Field_operators = typename Master_matrix::Field_operators; - using Field_element = typename Master_matrix::Element; /**< Field element value type. */ - using Row = typename Master_matrix::Row; /**< Row type, - only necessary with row access option. */ - using Cell_constructor = typename Master_matrix::Cell_constructor; /**< Factory of @ref Cell classes. */ - using Column_settings = typename Master_matrix::Column_settings; /**< Structure giving access to the columns to - necessary external classes. */ + using Field_element = typename Master_matrix::Element; /**< Field element value type. */ + using Row = typename Master_matrix::Row; /**< Row type, + only necessary with row access option. */ + using Entry_constructor = typename Master_matrix::Entry_constructor; /**< Factory of @ref Entry classes. */ + using Column_settings = typename Master_matrix::Column_settings; /**< Structure giving access to the columns to + necessary external classes. */ /** * @brief Type for columns. Only one for each "column class" is explicitly constructed. @@ -119,9 +119,9 @@ class Base_matrix_with_column_compression : protected Master_matrix::Matrix_row_ * If no identical column already existed, a copy of the column is stored. If an identical one existed, no new * column is constructed and the relationship between the two is registered in an union-find structure. * - * @tparam Container Range type for @ref Matrix::Cell_representative ranges. + * @tparam Container Range type for @ref Matrix::Entry_representative ranges. * Assumed to have a begin(), end() and size() method. - * @param columns A vector of @ref Matrix::Cell_representative ranges to construct the columns from. + * @param columns A vector of @ref Matrix::Entry_representative ranges to construct the columns from. * The content of the ranges are assumed to be sorted by increasing ID value. * @param colSettings Pointer to an existing setting structure for the columns. The structure should contain all * the necessary external classes specifically necessary for the choosen column type, such as custom allocators. @@ -162,10 +162,10 @@ class Base_matrix_with_column_compression : protected Master_matrix::Matrix_row_ /** * @brief Inserts a new ordered column at the end of the matrix by copying the given range of - * @ref Matrix::Cell_representative. The content of the range is assumed to be sorted by increasing ID value. + * @ref Matrix::Entry_representative. The content of the range is assumed to be sorted by increasing ID value. * - * @tparam Container Range of @ref Matrix::Cell_representative. Assumed to have a begin(), end() and size() method. - * @param column Range of @ref Matrix::Cell_representative from which the column has to be constructed. Assumed to be + * @tparam Container Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() method. + * @param column Range of @ref Matrix::Entry_representative from which the column has to be constructed. Assumed to be * ordered by increasing ID value. */ template @@ -173,9 +173,10 @@ class Base_matrix_with_column_compression : protected Master_matrix::Matrix_row_ /** * @brief Same as @ref insert_column, only for interface purposes. The given dimension is ignored and not stored. * - * @tparam Boundary_range Range of @ref Matrix::Cell_representative. Assumed to have a begin(), end() and size() method. - * @param boundary Range of @ref Matrix::Cell_representative from which the column has to be constructed. Assumed to be - * ordered by increasing ID value. + * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() + * method. + * @param boundary Range of @ref Matrix::Entry_representative from which the column has to be constructed. Assumed to + * be ordered by increasing ID value. * @param dim Ignored. */ template @@ -205,11 +206,11 @@ class Base_matrix_with_column_compression : protected Master_matrix::Matrix_row_ * @brief If @ref PersistenceMatrixOptions::has_row_access and @ref PersistenceMatrixOptions::has_removable_rows * are true: assumes that the row is empty and removes it. Otherwise, does nothing. * - * @warning The removed rows are always assumed to be empty. If it is not the case, the deleted row cells are not + * @warning The removed rows are always assumed to be empty. If it is not the case, the deleted row entries are not * removed from their columns. And in the case of intrusive rows, this will generate a segmentation fault when - * the column cells are destroyed later. The row access is just meant as a "read only" access to the rows and the + * the column entries are destroyed later. The row access is just meant as a "read only" access to the rows and the * @ref erase_empty_row method just as a way to specify that a row is empty and can therefore be removed from - * dictionaries. This allows to avoid testing the emptiness of a row at each column cell removal, what can be + * dictionaries. This allows to avoid testing the emptiness of a row at each column entry removal, what can be * quite frequent. * * @param rowIndex @ref rowindex "Row index" of the empty row. @@ -229,13 +230,13 @@ class Base_matrix_with_column_compression : protected Master_matrix::Matrix_row_ * The representatives of redundant columns are summed together, which means that * all column compressed together with the target column are affected by the change, not only the target. * - * @tparam Cell_range_or_column_index Either a range of @ref Cell with a begin() and end() method, + * @tparam Entry_range_or_column_index Either a range of @ref Entry with a begin() and end() method, * or any integer type. - * @param sourceColumn Either a cell range or the @ref MatIdx index of the column to add. + * @param sourceColumn Either an entry range or the @ref MatIdx index of the column to add. * @param targetColumnIndex @ref MatIdx index of the target column. */ - template - void add_to(const Cell_range_or_column_index& sourceColumn, Index targetColumnIndex); + template + void add_to(const Entry_range_or_column_index& sourceColumn, Index targetColumnIndex); /** * @brief Multiplies the target column with the coefficient and then adds the source column to it. * That is: `targetColumn = (targetColumn * coefficient) + sourceColumn`. @@ -243,14 +244,14 @@ class Base_matrix_with_column_compression : protected Master_matrix::Matrix_row_ * The representatives of redundant columns are summed together, which means that * all column compressed together with the target column are affected by the change, not only the target. * - * @tparam Cell_range_or_column_index Either a range of @ref Cell with a begin() and end() method, + * @tparam Entry_range_or_column_index Either a range of @ref Entry with a begin() and end() method, * or any integer type. - * @param sourceColumn Either a @ref Cell range or the @ref MatIdx index of the column to add. + * @param sourceColumn Either a @ref Entry range or the @ref MatIdx index of the column to add. * @param coefficient Value to multiply. * @param targetColumnIndex @ref MatIdx index of the target column. */ - template - void multiply_target_and_add_to(const Cell_range_or_column_index& sourceColumn, + template + void multiply_target_and_add_to(const Entry_range_or_column_index& sourceColumn, const Field_element& coefficient, Index targetColumnIndex); /** @@ -260,26 +261,26 @@ class Base_matrix_with_column_compression : protected Master_matrix::Matrix_row_ * The representatives of redundant columns are summed together, which means that * all column compressed together with the target column are affected by the change, not only the target. * - * @tparam Cell_range_or_column_index Either a range of @ref Cell with a begin() and end() method, + * @tparam Entry_range_or_column_index Either a range of @ref Entry with a begin() and end() method, * or any integer type. * @param coefficient Value to multiply. - * @param sourceColumn Either a @ref Cell range or the @ref MatIdx index of the column to add. + * @param sourceColumn Either a @ref Entry range or the @ref MatIdx index of the column to add. * @param targetColumnIndex @ref MatIdx index of the target column. */ - template + template void multiply_source_and_add_to(const Field_element& coefficient, - const Cell_range_or_column_index& sourceColumn, + const Entry_range_or_column_index& sourceColumn, Index targetColumnIndex); /** - * @brief Indicates if the cell at given coordinates has value zero. + * @brief Indicates if the entry at given coordinates has value zero. * - * @param columnIndex @ref MatIdx index of the column of the cell. - * @param rowIndex @ref rowindex "Row index" of the row of the cell. - * @return true If the cell has value zero. + * @param columnIndex @ref MatIdx index of the column of the entry. + * @param rowIndex @ref rowindex "Row index" of the row of the entry. + * @return true If the entry has value zero. * @return false Otherwise. */ - bool is_zero_cell(Index columnIndex, Index rowIndex); + bool is_zero_entry(Index columnIndex, Index rowIndex); /** * @brief Indicates if the column at given index has value zero. * @@ -292,7 +293,7 @@ class Base_matrix_with_column_compression : protected Master_matrix::Matrix_row_ /** * @brief Resets the matrix to an empty matrix. * - * @param colSettings Pointer to the cell factory. + * @param colSettings Pointer to the entry factory. */ void reset(Column_settings* colSettings) { columnToRep_.clear_and_dispose(Delete_disposer(this)); @@ -346,7 +347,7 @@ class Base_matrix_with_column_compression : protected Master_matrix::Matrix_row_ std::vector repToColumn_; /**< Map from the representative index to the representative Column. */ Index nextColumnIndex_; /**< Next unused column index. */ - Column_settings* colSettings_; /**< Cell factory. */ + Column_settings* colSettings_; /**< Entry factory. */ /** * @brief Column factory. Has to be a pointer as Simple_object_pool is not swappable, so their addresses have to be * exchanged instead. @@ -519,15 +520,15 @@ Base_matrix_with_column_compression::get_number_of_columns() cons } template -template -inline void Base_matrix_with_column_compression::add_to(const Cell_range_or_column_index& sourceColumn, +template +inline void Base_matrix_with_column_compression::add_to(const Entry_range_or_column_index& sourceColumn, Index targetColumnIndex) { // handle case where targetRep == sourceRep? Index targetRep = columnClasses_.find_set(targetColumnIndex); Column& target = *repToColumn_[targetRep]; columnToRep_.erase(target); - if constexpr (std::is_integral_v) { + if constexpr (std::is_integral_v) { target += get_column(sourceColumn); } else { target += sourceColumn; @@ -536,15 +537,15 @@ inline void Base_matrix_with_column_compression::add_to(const Cel } template -template +template inline void Base_matrix_with_column_compression::multiply_target_and_add_to( - const Cell_range_or_column_index& sourceColumn, const Field_element& coefficient, Index targetColumnIndex) + const Entry_range_or_column_index& sourceColumn, const Field_element& coefficient, Index targetColumnIndex) { // handle case where targetRep == sourceRep? Index targetRep = columnClasses_.find_set(targetColumnIndex); Column& target = *repToColumn_[targetRep]; columnToRep_.erase(target); - if constexpr (std::is_integral_v) { + if constexpr (std::is_integral_v) { target.multiply_target_and_add(coefficient, get_column(sourceColumn)); } else { target.multiply_target_and_add(coefficient, sourceColumn); @@ -553,15 +554,15 @@ inline void Base_matrix_with_column_compression::multiply_target_ } template -template +template inline void Base_matrix_with_column_compression::multiply_source_and_add_to( - const Field_element& coefficient, const Cell_range_or_column_index& sourceColumn, Index targetColumnIndex) + const Field_element& coefficient, const Entry_range_or_column_index& sourceColumn, Index targetColumnIndex) { // handle case where targetRep == sourceRep? Index targetRep = columnClasses_.find_set(targetColumnIndex); Column& target = *repToColumn_[targetRep]; columnToRep_.erase(target); - if constexpr (std::is_integral_v) { + if constexpr (std::is_integral_v) { target.multiply_source_and_add(get_column(sourceColumn), coefficient); } else { target.multiply_source_and_add(sourceColumn, coefficient); @@ -570,7 +571,7 @@ inline void Base_matrix_with_column_compression::multiply_source_ } template -inline bool Base_matrix_with_column_compression::is_zero_cell(Index columnIndex, Index rowIndex) +inline bool Base_matrix_with_column_compression::is_zero_entry(Index columnIndex, Index rowIndex) { auto col = repToColumn_[columnClasses_.find_set(columnIndex)]; if (col == nullptr) return true; @@ -636,8 +637,8 @@ inline void Base_matrix_with_column_compression::print() std::cout << "Row Matrix:\n"; for (Index i = 0; i < RA_opt::rows_->size(); ++i) { const Row& row = RA_opt::rows_[i]; - for (const auto& cell : row) { - std::cout << cell.get_column_index() << " "; + for (const auto& entry : row) { + std::cout << entry.get_column_index() << " "; } std::cout << "(" << i << ")\n"; } diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/Boundary_matrix.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/Boundary_matrix.h index e9f6b07756..29c6f87d93 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/Boundary_matrix.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/Boundary_matrix.h @@ -50,14 +50,14 @@ class Boundary_matrix : public Master_matrix::Matrix_dimension_option, * @brief Field operators class. Necessary only if @ref PersistenceMatrixOptions::is_z2 is false. */ using Field_operators = typename Master_matrix::Field_operators; - using Field_element = typename Master_matrix::Element; /**< Type of an field element. */ - using Column = typename Master_matrix::Column; /**< Column type. */ - using Boundary = typename Master_matrix::Boundary; /**< Type of an input column. */ - using Row = typename Master_matrix::Row; /**< Row type, - only necessary with row access option. */ - using Cell_constructor = typename Master_matrix::Cell_constructor; /**< Factory of @ref Cell classes. */ - using Column_settings = typename Master_matrix::Column_settings; /**< Structure giving access to the columns to - necessary external classes. */ + using Field_element = typename Master_matrix::Element; /**< Type of an field element. */ + using Column = typename Master_matrix::Column; /**< Column type. */ + using Boundary = typename Master_matrix::Boundary; /**< Type of an input column. */ + using Row = typename Master_matrix::Row; /**< Row type, + only necessary with row access option. */ + using Entry_constructor = typename Master_matrix::Entry_constructor; /**< Factory of @ref Entry classes. */ + using Column_settings = typename Master_matrix::Column_settings; /**< Structure giving access to the columns to + necessary external classes. */ /** * @brief Constructs an empty matrix. @@ -67,11 +67,12 @@ class Boundary_matrix : public Master_matrix::Matrix_dimension_option, */ Boundary_matrix(Column_settings* colSettings); /** - * @brief Constructs a new matrix from the given ranges of @ref Matrix::Cell_representative. Each range corresponds to - * a column (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by increasing - * IDs. The IDs of the simplices are also assumed to be consecutive, ordered by filtration value, starting with 0. + * @brief Constructs a new matrix from the given ranges of @ref Matrix::Entry_representative. Each range corresponds + * to a column (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by + * increasing IDs. The IDs of the simplices are also assumed to be consecutive, ordered by filtration value, starting + * with 0. * - * @tparam Boundary_range Range type for @ref Matrix::Cell_representative ranges. + * @tparam Boundary_range Range type for @ref Matrix::Entry_representative ranges. * Assumed to have a begin(), end() and size() method. * @param orderedBoundaries Range of boundaries: @p orderedBoundaries is interpreted as a boundary matrix of a * filtered **simplicial** complex, whose boundaries are ordered by filtration order. @@ -125,14 +126,15 @@ class Boundary_matrix : public Master_matrix::Matrix_dimension_option, * instead by indicating the face ID used in the boundaries when the face is inserted. * * Different to the constructor, the boundaries do not have to come from a simplicial complex, but also from - * a more general cell complex. This includes cubical complexes or Morse complexes for example. + * a more general entry complex. This includes cubical complexes or Morse complexes for example. * * At the insertion, the boundary will be copied as is. The column will only be reduced later when the barcode * is requested in order to apply some optimizations with the additional knowledge. Hence, the barcode will also * not be updated, so call @ref Base_pairing::get_current_barcode "get_current_barcode" only when the matrix is * complete. * - * @tparam Boundary_range Range of @ref Matrix::Cell_representative. Assumed to have a begin(), end() and size() method. + * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() + * method. * @param boundary Boundary generating the new column. The content should be ordered by ID. * @param dim Dimension of the face whose boundary is given. If the complex is simplicial, * this parameter can be omitted as it can be deduced from the size of the boundary. @@ -148,7 +150,8 @@ class Boundary_matrix : public Master_matrix::Matrix_dimension_option, * As a face has to be inserted before one of its cofaces in a valid filtration (recall that it is assumed that * the faces are inserted by order of filtration), it is sufficient to indicate the ID of the face being inserted. * - * @tparam Boundary_range Range of @ref Matrix::Cell_representative. Assumed to have a begin(), end() and size() method. + * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() + * method. * @param faceIndex @ref IDIdx index to use to identify the new face. * @param boundary Boundary generating the new column. The indices of the boundary have to correspond to the * @p faceIndex values of precedent calls of the method for the corresponding faces and should be ordered in @@ -163,7 +166,7 @@ class Boundary_matrix : public Master_matrix::Matrix_dimension_option, * @brief Returns the column at the given @ref MatIdx index. * The type of the column depends on the choosen options, see @ref PersistenceMatrixOptions::column_type. * - * Note that before returning the column, all column cells can eventually be reordered, if lazy swaps occurred. + * Note that before returning the column, all column entries can eventually be reordered, if lazy swaps occurred. * It is therefore recommended to avoid calling @ref get_column between column or row swaps, otherwise the benefits * of the the laziness is lost. * @@ -176,7 +179,7 @@ class Boundary_matrix : public Master_matrix::Matrix_dimension_option, * Returns the row at the given @ref rowindex "row index" of the matrix. * The type of the row depends on the choosen options, see @ref PersistenceMatrixOptions::has_intrusive_rows. * - * Note that before returning the row, all column cells can eventually be reordered, if lazy swaps occurred. + * Note that before returning the row, all column entries can eventually be reordered, if lazy swaps occurred. * It is therefore recommended to avoid calling @ref get_row between column or row swaps, otherwise the benefits * of the the laziness is lost. * @@ -197,11 +200,11 @@ class Boundary_matrix : public Master_matrix::Matrix_dimension_option, * and @ref PersistenceMatrixOptions::has_column_and_row_swaps are true: cleans up maps used for the lazy row swaps. * Otherwise, does nothing. * - * @warning The removed rows are always assumed to be empty. If it is not the case, the deleted row cells are not + * @warning The removed rows are always assumed to be empty. If it is not the case, the deleted row entries are not * removed from their columns. And in the case of intrusive rows, this will generate a segmentation fault when - * the column cells are destroyed later. The row access is just meant as a "read only" access to the rows and the + * the column entries are destroyed later. The row access is just meant as a "read only" access to the rows and the * @ref erase_empty_row method just as a way to specify that a row is empty and can therefore be removed from - * dictionaries. This allows to avoid testing the emptiness of a row at each column cell removal, what can be + * dictionaries. This allows to avoid testing the emptiness of a row at each column entry removal, what can be * quite frequent. * * @param rowIndex @ref rowindex "Row index" of the empty row. @@ -266,15 +269,15 @@ class Boundary_matrix : public Master_matrix::Matrix_dimension_option, Index targetColumnIndex); /** - * @brief Zeroes the cell at the given coordinates. + * @brief Zeroes the entry at the given coordinates. * * @warning They will be no verification to ensure that the zeroing makes sense for the validity of a * boundary matrix of a filtered complex. So should be used while knowing what one is doing. * - * @param columnIndex @ref MatIdx index of the column of the cell. - * @param rowIndex @ref rowindex "Row index" of the row of the cell. + * @param columnIndex @ref MatIdx index of the column of the entry. + * @param rowIndex @ref rowindex "Row index" of the row of the entry. */ - void zero_cell(Index columnIndex, Index rowIndex); + void zero_entry(Index columnIndex, Index rowIndex); /** * @brief Zeroes the column at the given index. * @@ -285,14 +288,14 @@ class Boundary_matrix : public Master_matrix::Matrix_dimension_option, */ void zero_column(Index columnIndex); /** - * @brief Indicates if the cell at given coordinates has value zero. + * @brief Indicates if the entry at given coordinates has value zero. * - * @param columnIndex @ref MatIdx index of the column of the cell. - * @param rowIndex @ref rowindex "Row index" of the row of the cell. - * @return true If the cell has value zero. + * @param columnIndex @ref MatIdx index of the column of the entry. + * @param rowIndex @ref rowindex "Row index" of the row of the entry. + * @return true If the entry has value zero. * @return false Otherwise. */ - bool is_zero_cell(Index columnIndex, Index rowIndex) const; + bool is_zero_entry(Index columnIndex, Index rowIndex) const; /** * @brief Indicates if the column at given index has value zero. * @@ -358,9 +361,9 @@ class Boundary_matrix : public Master_matrix::Matrix_dimension_option, friend Swap_opt; friend Pair_opt; - Column_container matrix_; /**< Column container. */ - Index nextInsertIndex_; /**< Next unused column index. */ - Column_settings* colSettings_; /**< Cell factory. */ + Column_container matrix_; /**< Column container. */ + Index nextInsertIndex_; /**< Next unused column index. */ + Column_settings* colSettings_; /**< Entry factory. */ static constexpr bool activeDimOption = Master_matrix::Option_list::has_matrix_maximal_dimension_access || Master_matrix::maxDimensionIsNeeded; @@ -650,7 +653,7 @@ inline void Boundary_matrix::multiply_source_and_add_to(const Fie } template -inline void Boundary_matrix::zero_cell(Index columnIndex, Index rowIndex) +inline void Boundary_matrix::zero_entry(Index columnIndex, Index rowIndex) { _get_column(columnIndex).clear(_get_real_row_index(rowIndex)); } @@ -662,7 +665,7 @@ inline void Boundary_matrix::zero_column(Index columnIndex) } template -inline bool Boundary_matrix::is_zero_cell(Index columnIndex, Index rowIndex) const +inline bool Boundary_matrix::is_zero_entry(Index columnIndex, Index rowIndex) const { return !(_get_column(columnIndex).is_non_zero(_get_real_row_index(rowIndex))); } @@ -727,8 +730,8 @@ inline void Boundary_matrix::print() std::cout << "Row Matrix:\n"; for (ID_index i = 0; i < nextInsertIndex_; ++i) { const auto& row = RA_opt::rows_[i]; - for (const auto& cell : row) { - std::cout << cell.get_column_index() << " "; + for (const auto& entry : row) { + std::cout << entry.get_column_index() << " "; } std::cout << "(" << i << ")\n"; } diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/Chain_matrix.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/Chain_matrix.h index c1f0af1cf6..e113fb61b5 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/Chain_matrix.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/Chain_matrix.h @@ -57,12 +57,12 @@ class Chain_matrix : public Master_matrix::Matrix_dimension_option, using Column = typename Master_matrix::Column; /**< Column type. */ using Row = typename Master_matrix::Row; /**< Row type, only necessary with row access option. */ - using Cell = typename Master_matrix::Matrix_cell; /**< @ref Cell "Matrix cell" type. */ - using Cell_constructor = typename Master_matrix::Cell_constructor; /**< Factory of @ref Cell classes. */ + using Entry = typename Master_matrix::Matrix_entry; /**< @ref Entry "Matrix entry" type. */ + using Entry_constructor = typename Master_matrix::Entry_constructor; /**< Factory of @ref Entry classes. */ using Column_settings = typename Master_matrix::Column_settings; /**< Structure giving access to the columns to necessary external classes. */ using Boundary = typename Master_matrix::Boundary; /**< Type of an input column. */ - using Cell_representative = typename Master_matrix::Cell_representative; /**< %Cell content representative. */ + using Entry_representative = typename Master_matrix::Entry_representative; /**< %Entry content representative. */ using Index = typename Master_matrix::Index; /**< @ref MatIdx index type. */ using ID_index = typename Master_matrix::ID_index; /**< @ref IDIdx index type. */ using Pos_index = typename Master_matrix::Pos_index; /**< @ref PosIdx index type. */ @@ -78,14 +78,14 @@ class Chain_matrix : public Master_matrix::Matrix_dimension_option, */ Chain_matrix(Column_settings* colSettings); /** - * @brief Constructs a new matrix from the given ranges of @ref Matrix::Cell_representative. Each range corresponds to a - * column (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by increasing - * IDs. The IDs of the simplices are also assumed to be consecutive, ordered by filtration value, starting with 0. - * Only available if @ref PersistenceMatrixOptions::has_column_pairings is true or + * @brief Constructs a new matrix from the given ranges of @ref Matrix::Entry_representative. Each range corresponds + * to a column (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by + * increasing IDs. The IDs of the simplices are also assumed to be consecutive, ordered by filtration value, starting + * with 0. Only available if @ref PersistenceMatrixOptions::has_column_pairings is true or * @ref PersistenceMatrixOptions::has_vine_update is false. Otherwise, birth and death * comparators have to be provided. * - * @tparam Boundary_range Range type for @ref Matrix::Cell_representative ranges. + * @tparam Boundary_range Range type for @ref Matrix::Entry_representative ranges. * Assumed to have a begin(), end() and size() method. * @param orderedBoundaries Range of boundaries: @p orderedBoundaries is interpreted as a boundary matrix of a * filtered **simplicial** complex, whose boundaries are ordered by filtration order. @@ -140,9 +140,10 @@ class Chain_matrix : public Master_matrix::Matrix_dimension_option, const BirthComparatorFunction& birthComparator, const DeathComparatorFunction& deathComparator); /** - * @brief Constructs a new matrix from the given ranges of @ref Matrix::Cell_representative. Each range corresponds to a - * column (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by increasing - * IDs. The IDs of the simplices are also assumed to be consecutive, ordered by filtration value, starting with 0. + * @brief Constructs a new matrix from the given ranges of @ref Matrix::Entry_representative. Each range corresponds + * to a column (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by + * increasing IDs. The IDs of the simplices are also assumed to be consecutive, ordered by filtration value, starting + * with 0. * * @warning If @ref PersistenceMatrixOptions::has_vine_update is false, the comparators are not used. * And if @ref PersistenceMatrixOptions::has_vine_update is true, but @@ -151,7 +152,7 @@ class Chain_matrix : public Master_matrix::Matrix_dimension_option, * * @tparam BirthComparatorFunction Type of the birth comparator: (@ref Pos_index, @ref Pos_index) -> bool * @tparam DeathComparatorFunction Type of the death comparator: (@ref Pos_index, @ref Pos_index) -> bool - * @tparam Boundary_range Range type for @ref Matrix::Cell_representative ranges. + * @tparam Boundary_range Range type for @ref Matrix::Entry_representative ranges. * Assumed to have a begin(), end() and size() method. * @param orderedBoundaries Range of boundaries: @p orderedBoundaries is interpreted as a boundary matrix of a * filtered **simplicial** complex, whose boundaries are ordered by filtration order. @@ -233,19 +234,20 @@ class Chain_matrix : public Master_matrix::Matrix_dimension_option, * instead by indicating the face ID used in the boundaries when the face is inserted. * * Different to the constructor, the boundaries do not have to come from a simplicial complex, but also from - * a more general cell complex. This includes cubical complexes or Morse complexes for example. + * a more general entry complex. This includes cubical complexes or Morse complexes for example. * * When inserted, the given boundary is reduced and from the reduction process, the column is deduced in the form of: * `IDIdx + linear combination of older column IDIdxs`. If the barcode is stored, it will be updated. * - * @tparam Boundary_range Range of @ref Matrix::Cell_representative. Assumed to have a begin(), end() and size() method. + * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() + * method. * @param boundary Boundary generating the new column. The content should be ordered by ID. * @param dim Dimension of the face whose boundary is given. If the complex is simplicial, * this parameter can be omitted as it can be deduced from the size of the boundary. * @return The @ref MatIdx indices of the unpaired chains used to reduce the boundary. */ template - std::vector insert_boundary(const Boundary_range& boundary, Dimension dim = -1); + std::vector insert_boundary(const Boundary_range& boundary, Dimension dim = -1); /** * @brief It does the same as the other version, but allows the boundary faces to be identified without restrictions * except that all IDs have to be strictly increasing in the order of filtration. Note that you should avoid then @@ -254,7 +256,8 @@ class Chain_matrix : public Master_matrix::Matrix_dimension_option, * As a face has to be inserted before one of its cofaces in a valid filtration (recall that it is assumed that * the faces are inserted by order of filtration), it is sufficient to indicate the ID of the face being inserted. * - * @tparam Boundary_range Range of @ref Matrix::Cell_representative. Assumed to have a begin(), end() and size() method. + * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() + * method. * @param faceID @ref IDIdx index to use to identify the new face. * @param boundary Boundary generating the new column. The indices of the boundary have to correspond to the * @p faceID values of precedent calls of the method for the corresponding faces and should be ordered in @@ -264,7 +267,9 @@ class Chain_matrix : public Master_matrix::Matrix_dimension_option, * @return The @ref MatIdx index of the inserted boundary. */ template - std::vector insert_boundary(ID_index faceID, const Boundary_range& boundary, Dimension dim = -1); + std::vector insert_boundary(ID_index faceID, + const Boundary_range& boundary, + Dimension dim = -1); /** * @brief Returns the column at the given @ref MatIdx index. * The type of the column depends on the choosen options, see @ref PersistenceMatrixOptions::column_type. @@ -396,14 +401,14 @@ class Chain_matrix : public Master_matrix::Matrix_dimension_option, Index targetColumnIndex); /** - * @brief Indicates if the cell at given coordinates has value zero. + * @brief Indicates if the entry at given coordinates has value zero. * - * @param columnIndex @ref MatIdx index of the column of the cell. - * @param rowIndex @ref rowindex "Row index" of the row of the cell. - * @return true If the cell has value zero. + * @param columnIndex @ref MatIdx index of the column of the entry. + * @param rowIndex @ref rowindex "Row index" of the row of the entry. + * @return true If the entry has value zero. * @return false Otherwise. */ - bool is_zero_cell(Index columnIndex, ID_index rowIndex) const; + bool is_zero_entry(Index columnIndex, ID_index rowIndex) const; /** * @brief Indicates if the column at given index has value zero. Note that if the matrix is valid, this method * should always return false. @@ -491,14 +496,14 @@ class Chain_matrix : public Master_matrix::Matrix_dimension_option, Column_container matrix_; /**< Column container. */ Dictionary pivotToColumnIndex_; /**< Map from @ref IDIdx to @ref MatIdx index. */ Index nextIndex_; /**< Next unused column index. */ - Column_settings* colSettings_; /**< Cell factory. */ + Column_settings* colSettings_; /**< Entry factory. */ template - std::vector _reduce_boundary(ID_index faceID, const Boundary_range& boundary, Dimension dim); - void _reduce_by_G(Tmp_column& column, std::vector& chainsInH, Index currentPivot); - void _reduce_by_F(Tmp_column& column, std::vector& chainsInF, Index currentPivot); - void _build_from_H(ID_index faceID, Tmp_column& column, std::vector& chainsInH); - void _update_largest_death_in_F(const std::vector& chainsInF); + std::vector _reduce_boundary(ID_index faceID, const Boundary_range& boundary, Dimension dim); + void _reduce_by_G(Tmp_column& column, std::vector& chainsInH, Index currentPivot); + void _reduce_by_F(Tmp_column& column, std::vector& chainsInF, Index currentPivot); + void _build_from_H(ID_index faceID, Tmp_column& column, std::vector& chainsInH); + void _update_largest_death_in_F(const std::vector& chainsInF); void _insert_chain(const Tmp_column& column, Dimension dimension); void _insert_chain(const Tmp_column& column, Dimension dimension, Index pair); void _add_to(const Column& column, Tmp_column& set, unsigned int coef); @@ -667,7 +672,7 @@ inline Chain_matrix::Chain_matrix(Chain_matrix&& other) noexcept template template -inline std::vector Chain_matrix::insert_boundary( +inline std::vector Chain_matrix::insert_boundary( const Boundary_range& boundary, Dimension dim) { return insert_boundary(nextIndex_, boundary, dim); @@ -675,7 +680,7 @@ inline std::vector Chain_matrix template -inline std::vector Chain_matrix::insert_boundary( +inline std::vector Chain_matrix::insert_boundary( ID_index faceID, const Boundary_range& boundary, Dimension dim) { if constexpr (!Master_matrix::Option_list::has_map_column_container) { @@ -851,7 +856,7 @@ inline void Chain_matrix::multiply_source_and_add_to(const Field_ } template -inline bool Chain_matrix::is_zero_cell(Index columnIndex, ID_index rowIndex) const +inline bool Chain_matrix::is_zero_entry(Index columnIndex, ID_index rowIndex) const { return !get_column(columnIndex).is_non_zero(rowIndex); } @@ -911,8 +916,8 @@ inline void Chain_matrix::print() const for (ID_index i = 0; i < pivotToColumnIndex_.size() && pivotToColumnIndex_[i] != static_cast(-1); ++i) { Index pos = pivotToColumnIndex_[i]; const Column& col = matrix_[pos]; - for (const auto& cell : col) { - std::cout << cell.get_row_index() << " "; + for (const auto& entry : col) { + std::cout << entry.get_row_index() << " "; } std::cout << "(" << i << ", " << pos << ")\n"; } @@ -922,8 +927,8 @@ inline void Chain_matrix::print() const for (ID_index i = 0; i < pivotToColumnIndex_.size() && pivotToColumnIndex_[i] != static_cast(-1); ++i) { Index pos = pivotToColumnIndex_[i]; const Row& row = RA_opt::get_row(pos); - for (const auto& cell : row) { - std::cout << cell.get_column_index() << " "; + for (const auto& entry : row) { + std::cout << entry.get_column_index() << " "; } std::cout << "(" << i << ", " << pos << ")\n"; } @@ -931,8 +936,8 @@ inline void Chain_matrix::print() const } else { for (const auto& p : pivotToColumnIndex_) { const Column& col = matrix_.at(p.second); - for (const auto& cell : col) { - std::cout << cell.get_row_index() << " "; + for (const auto& entry : col) { + std::cout << entry.get_row_index() << " "; } std::cout << "(" << p.first << ", " << p.second << ")\n"; } @@ -941,8 +946,8 @@ inline void Chain_matrix::print() const std::cout << "Row Matrix:\n"; for (const auto& p : pivotToColumnIndex_) { const Row& row = RA_opt::get_row(p.first); - for (const auto& cell : row) { - std::cout << cell.get_column_index() << " "; + for (const auto& entry : row) { + std::cout << entry.get_column_index() << " "; } std::cout << "(" << p.first << ", " << p.second << ")\n"; } @@ -953,13 +958,13 @@ inline void Chain_matrix::print() const template template -inline std::vector Chain_matrix::_reduce_boundary( +inline std::vector Chain_matrix::_reduce_boundary( ID_index faceID, const Boundary_range& boundary, Dimension dim) { Tmp_column column(boundary.begin(), boundary.end()); if (dim == static_cast(-1)) dim = boundary.begin() == boundary.end() ? 0 : boundary.size() - 1; - std::vector chainsInH; // for corresponding indices in H (paired columns) - std::vector chainsInF; // for corresponding indices in F (unpaired, essential columns) + std::vector chainsInH; // for corresponding indices in H (paired columns) + std::vector chainsInF; // for corresponding indices in F (unpaired, essential columns) auto get_last = [&column]() { if constexpr (Master_matrix::Option_list::is_z2) @@ -1020,7 +1025,7 @@ inline std::vector Chain_matrix inline void Chain_matrix::_reduce_by_G(Tmp_column& column, - std::vector& chainsInH, + std::vector& chainsInH, Index currentIndex) { Column& col = get_column(currentIndex); @@ -1040,7 +1045,7 @@ inline void Chain_matrix::_reduce_by_G(Tmp_column& column, template inline void Chain_matrix::_reduce_by_F(Tmp_column& column, - std::vector& chainsInF, + std::vector& chainsInF, Index currentIndex) { Column& col = get_column(currentIndex); @@ -1061,7 +1066,7 @@ inline void Chain_matrix::_reduce_by_F(Tmp_column& column, template inline void Chain_matrix::_build_from_H(ID_index faceID, Tmp_column& column, - std::vector& chainsInH) + std::vector& chainsInH) { if constexpr (Master_matrix::Option_list::is_z2) { column.insert(faceID); @@ -1077,7 +1082,7 @@ inline void Chain_matrix::_build_from_H(ID_index faceID, } template -inline void Chain_matrix::_update_largest_death_in_F(const std::vector& chainsInF) +inline void Chain_matrix::_update_largest_death_in_F(const std::vector& chainsInF) { if constexpr (Master_matrix::Option_list::is_z2) { Index toUpdate = chainsInF[0]; @@ -1131,20 +1136,20 @@ inline void Chain_matrix::_add_to(const Column& column, { if constexpr (Master_matrix::Option_list::is_z2) { std::pair::iterator, bool> res_insert; - for (const Cell& cell : column) { - res_insert = set.insert(cell.get_row_index()); + for (const Entry& entry : column) { + res_insert = set.insert(entry.get_row_index()); if (!res_insert.second) { set.erase(res_insert.first); } } } else { auto& operators = colSettings_->operators; - for (const Cell& cell : column) { - auto res = set.emplace(cell.get_row_index(), cell.get_element()); + for (const Entry& entry : column) { + auto res = set.emplace(entry.get_row_index(), entry.get_element()); if (res.second){ operators.multiply_inplace(res.first->second, coef); } else { - operators.multiply_and_add_inplace_back(cell.get_element(), coef, res.first->second); + operators.multiply_and_add_inplace_back(entry.get_element(), coef, res.first->second); if (res.first->second == Field_operators::get_additive_identity()) { set.erase(res.first); } diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/Id_to_index_overlay.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/Id_to_index_overlay.h index b5393083af..91b09f2659 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/Id_to_index_overlay.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/Id_to_index_overlay.h @@ -41,25 +41,25 @@ template class Id_to_index_overlay { public: - using Index = typename Master_matrix::Index; /**< @ref MatIdx index type. */ - using ID_index = typename Master_matrix::ID_index; /**< @ref IDIdx index type. */ - using Pos_index = typename Master_matrix::Pos_index; /**< @ref PosIdx index type. */ - using Dimension = typename Master_matrix::Dimension; /**< Dimension value type. */ + using Index = typename Master_matrix::Index; /**< @ref MatIdx index type. */ + using ID_index = typename Master_matrix::ID_index; /**< @ref IDIdx index type. */ + using Pos_index = typename Master_matrix::Pos_index; /**< @ref PosIdx index type. */ + using Dimension = typename Master_matrix::Dimension; /**< Dimension value type. */ /** * @brief Field operators class. Necessary only if @ref PersistenceMatrixOptions::is_z2 is false. */ using Field_operators = typename Master_matrix::Field_operators; - using Field_element = typename Master_matrix::Element; /**< Type of an field element. */ - using Boundary = typename Master_matrix::Boundary; /**< Type of an input column. */ - using Column = typename Master_matrix::Column; /**< Column type. */ - using Row = typename Master_matrix::Row; /**< Row type, - only necessary with row access option. */ - using Bar = typename Master_matrix::Bar; /**< Bar type. */ - using Barcode = typename Master_matrix::Barcode; /**< Barcode type. */ - using Cycle = typename Master_matrix::Cycle; /**< Cycle type. */ - using Cell_constructor = typename Master_matrix::Cell_constructor; /**< Factory of @ref Cell classes. */ - using Column_settings = typename Master_matrix::Column_settings; /**< Structure giving access to the columns to - necessary external classes. */ + using Field_element = typename Master_matrix::Element; /**< Type of an field element. */ + using Boundary = typename Master_matrix::Boundary; /**< Type of an input column. */ + using Column = typename Master_matrix::Column; /**< Column type. */ + using Row = typename Master_matrix::Row; /**< Row type, + only necessary with row access option. */ + using Bar = typename Master_matrix::Bar; /**< Bar type. */ + using Barcode = typename Master_matrix::Barcode; /**< Barcode type. */ + using Cycle = typename Master_matrix::Cycle; /**< Cycle type. */ + using Entry_constructor = typename Master_matrix::Entry_constructor; /**< Factory of @ref Entry classes. */ + using Column_settings = typename Master_matrix::Column_settings; /**< Structure giving access to the columns to + necessary external classes. */ /** * @brief Constructs an empty matrix. @@ -69,11 +69,12 @@ class Id_to_index_overlay */ Id_to_index_overlay(Column_settings* colSettings); /** - * @brief Constructs a new matrix from the given ranges of @ref Matrix::Cell_representative. Each range corresponds to a - * column (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by increasing - * IDs. The IDs of the simplices are also assumed to be consecutive, ordered by filtration value, starting with 0. + * @brief Constructs a new matrix from the given ranges of @ref Matrix::Entry_representative. Each range corresponds + * to a column (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by + * increasing IDs. The IDs of the simplices are also assumed to be consecutive, ordered by filtration value, starting + * with 0. * - * @tparam Boundary_range Range type for @ref Matrix::Cell_representative ranges. + * @tparam Boundary_range Range type for @ref Matrix::Entry_representative ranges. * Assumed to have a begin(), end() and size() method. * @param orderedBoundaries Range of boundaries: @p orderedBoundaries is interpreted as a boundary matrix of a * filtered **simplicial** complex, whose boundaries are ordered by filtration order. @@ -127,9 +128,9 @@ class Id_to_index_overlay const DeathComparatorFunction& deathComparator); /** * @brief Only available for @ref chainmatrix "chain matrices". - * Constructs a new matrix from the given ranges of @ref Matrix::Cell_representative. Each range corresponds to a column - * (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by increasing IDs. - * The IDs of the simplices are also assumed to be consecutive, ordered by filtration value, starting with 0. + * Constructs a new matrix from the given ranges of @ref Matrix::Entry_representative. Each range corresponds to a + * column (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by increasing + * IDs. The IDs of the simplices are also assumed to be consecutive, ordered by filtration value, starting with 0. * * @warning If @ref PersistenceMatrixOptions::has_vine_update is false, the comparators are not used. * And if @ref PersistenceMatrixOptions::has_vine_update is true, but @@ -138,7 +139,7 @@ class Id_to_index_overlay * * @tparam BirthComparatorFunction Type of the birth comparator: (@ref Pos_index, @ref Pos_index) -> bool * @tparam DeathComparatorFunction Type of the death comparator: (@ref Pos_index, @ref Pos_index) -> bool - * @tparam Boundary_range Range type for @ref Matrix::Cell_representative ranges. + * @tparam Boundary_range Range type for @ref Matrix::Entry_representative ranges. * Assumed to have a begin(), end() and size() method. * @param orderedBoundaries Range of boundaries: @p orderedBoundaries is interpreted as a boundary matrix of a * filtered **simplicial** complex, whose boundaries are ordered by filtration order. @@ -195,7 +196,7 @@ class Id_to_index_overlay const BirthComparatorFunction& birthComparator, const DeathComparatorFunction& deathComparator); /** - * @brief Copy constructor. If @p operators or @p cellConstructor is not a null pointer, its value is kept + * @brief Copy constructor. If @p operators or @p entryConstructor is not a null pointer, its value is kept * instead of the one in the copied matrix. * * @param matrixToCopy Matrix to copy. @@ -225,7 +226,7 @@ class Id_to_index_overlay * face ID used in the boundaries when the face is inserted. * * Different to the constructor, the boundaries do not have to come from a simplicial complex, but also from - * a more general cell complex. This includes cubical complexes or Morse complexes for example. + * a more general entry complex. This includes cubical complexes or Morse complexes for example. * * The content of the new column will vary depending on the underlying @ref mp_matrices "type of the matrix": * - If it is a boundary type matrix and only \f$ R \f$ is stored, the boundary is just copied. The column will only @@ -237,7 +238,8 @@ class Id_to_index_overlay * `IDIdx + linear combination of older column IDIdxs`, where the combination is deduced while reducing the * given boundary. If the barcode is stored, it will also be updated. * - * @tparam Boundary_range Range of @ref Matrix::Cell_representative. Assumed to have a begin(), end() and size() method. + * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() + * method. * @param boundary Boundary generating the new column. The content should be ordered by ID. * @param dim Dimension of the face whose boundary is given. If the complex is simplicial, * this parameter can be omitted as it can be deduced from the size of the boundary. @@ -252,7 +254,8 @@ class Id_to_index_overlay * As a face has to be inserted before one of its cofaces in a valid filtration (recall that it is assumed that * the faces are inserted by order of filtration), it is sufficient to indicate the ID of the face being inserted. * - * @tparam Boundary_range Range of @ref Matrix::Cell_representative. Assumed to have a begin(), end() and size() method. + * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() + * method. * @param faceIndex @ref IDIdx index to use to identify the new face. * @param boundary Boundary generating the new column. The indices of the boundary have to correspond to the * @p faceIndex values of precedent calls of the method for the corresponding faces and should be ordered in @@ -277,7 +280,7 @@ class Id_to_index_overlay * For @ref boundarymatrix "RU matrices", the returned row is from \f$ R \f$. * The type of the row depends on the choosen options, see @ref PersistenceMatrixOptions::has_intrusive_rows. * - * @warning The @ref Cell_column_index::get_column_index "get_column_index" method of the row cells returns the + * @warning The @ref Entry_column_index::get_column_index "get_column_index" method of the row entries returns the * original @ref PosIdx indices (before any swaps) for @ref boundarymatrix "boundary matrices" and * @ref MatIdx indices for @ref chainmatrix "chain matrices". * @@ -301,11 +304,11 @@ class Id_to_index_overlay * @ref PersistenceMatrixOptions::has_removable_rows are true. * Assumes that the row is empty and removes it. * - * @warning The removed rows are always assumed to be empty. If it is not the case, the deleted row cells are not + * @warning The removed rows are always assumed to be empty. If it is not the case, the deleted row entries are not * removed from their columns. And in the case of intrusive rows, this will generate a segmentation fault when - * the column cells are destroyed later. The row access is just meant as a "read only" access to the rows and the + * the column entries are destroyed later. The row access is just meant as a "read only" access to the rows and the * @ref erase_empty_row method just as a way to specify that a row is empty and can therefore be removed from - * dictionaries. This allows to avoid testing the emptiness of a row at each column cell removal, what can be + * dictionaries. This allows to avoid testing the emptiness of a row at each column entry removal, what can be * quite frequent. * * @param rowIndex @ref rowindex "Row index" of the empty row to remove. @@ -431,16 +434,16 @@ class Id_to_index_overlay void multiply_source_and_add_to(const Field_element& coefficient, ID_index sourceFaceID, ID_index targetFaceID); /** - * @brief Zeroes the cell at the given coordinates. Not available for @ref chainmatrix "chain matrices". + * @brief Zeroes the entry at the given coordinates. Not available for @ref chainmatrix "chain matrices". * In general, should be used with care to not destroy the validity * of the persistence related properties of the matrix. * - * For @ref boundarymatrix "RU matrices", zeros only the cell in \f$ R \f$. + * For @ref boundarymatrix "RU matrices", zeros only the entry in \f$ R \f$. * - * @param faceID @ref IDIdx index of the face corresponding to the column of the cell. - * @param rowIndex @ref rowindex "Row index" of the row of the cell. + * @param faceID @ref IDIdx index of the face corresponding to the column of the entry. + * @param rowIndex @ref rowindex "Row index" of the row of the entry. */ - void zero_cell(ID_index faceID, ID_index rowIndex); + void zero_entry(ID_index faceID, ID_index rowIndex); /** * @brief Zeroes the column at the given index. Not available for @ref chainmatrix "chain matrices". * In general, should be used with care to not destroy the validity @@ -452,16 +455,16 @@ class Id_to_index_overlay */ void zero_column(ID_index faceID); /** - * @brief Indicates if the cell at given coordinates has value zero. + * @brief Indicates if the entry at given coordinates has value zero. * * For @ref boundarymatrix "RU matrices", looks into \f$ R \f$. * - * @param faceID @ref IDIdx index of the face corresponding to the column of the cell. - * @param rowIndex @ref rowindex "Row index" of the row of the cell. - * @return true If the cell has value zero. + * @param faceID @ref IDIdx index of the face corresponding to the column of the entry. + * @param rowIndex @ref rowindex "Row index" of the row of the entry. + * @return true If the entry has value zero. * @return false Otherwise. */ - bool is_zero_cell(ID_index faceID, ID_index rowIndex) const; + bool is_zero_entry(ID_index faceID, ID_index rowIndex) const; /** * @brief Indicates if the column at given index has value zero. * @@ -904,9 +907,9 @@ inline void Id_to_index_overlay::multiply_sour } template -inline void Id_to_index_overlay::zero_cell(ID_index faceID, ID_index rowIndex) +inline void Id_to_index_overlay::zero_entry(ID_index faceID, ID_index rowIndex) { - return matrix_.zero_cell(_id_to_index(faceID), rowIndex); + return matrix_.zero_entry(_id_to_index(faceID), rowIndex); } template @@ -916,10 +919,10 @@ inline void Id_to_index_overlay::zero_column(I } template -inline bool Id_to_index_overlay::is_zero_cell(ID_index faceID, +inline bool Id_to_index_overlay::is_zero_entry(ID_index faceID, ID_index rowIndex) const { - return matrix_.is_zero_cell(_id_to_index(faceID), rowIndex); + return matrix_.is_zero_entry(_id_to_index(faceID), rowIndex); } template diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/Position_to_index_overlay.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/Position_to_index_overlay.h index d908675a54..56cd2c2d27 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/Position_to_index_overlay.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/Position_to_index_overlay.h @@ -55,8 +55,8 @@ class Position_to_index_overlay using Bar = typename Master_matrix::Bar; /**< Bar type. */ using Barcode = typename Master_matrix::Barcode; /**< Barcode type. */ using Cycle = typename Master_matrix::Cycle; /**< Cycle type. */ - using Cell_representative = typename Master_matrix::Cell_representative; /**< %Cell content representative. */ - using Cell_constructor = typename Master_matrix::Cell_constructor; /**< Factory of @ref Cell classes. */ + using Entry_representative = typename Master_matrix::Entry_representative; /**< %Entry content representative. */ + using Entry_constructor = typename Master_matrix::Entry_constructor; /**< Factory of @ref Entry classes. */ using Column_settings = typename Master_matrix::Column_settings; /**< Structure giving access to the columns to necessary external classes. */ @@ -68,11 +68,12 @@ class Position_to_index_overlay */ Position_to_index_overlay(Column_settings* colSettings); /** - * @brief Constructs a new matrix from the given ranges of @ref Matrix::Cell_representative. Each range corresponds to a - * column (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by increasing - * IDs. The IDs of the simplices are also assumed to be consecutive, ordered by filtration value, starting with 0. + * @brief Constructs a new matrix from the given ranges of @ref Matrix::Entry_representative. Each range corresponds + * to a column (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by + * increasing IDs. The IDs of the simplices are also assumed to be consecutive, ordered by filtration value, starting + * with 0. * - * @tparam Boundary_range Range type for @ref Matrix::Cell_representative ranges. + * @tparam Boundary_range Range type for @ref Matrix::Entry_representative ranges. * Assumed to have a begin(), end() and size() method. * @param orderedBoundaries Range of boundaries: @p orderedBoundaries is interpreted as a boundary matrix of a * filtered **simplicial** complex, whose boundaries are ordered by filtration order. @@ -127,9 +128,9 @@ class Position_to_index_overlay const DeathComparatorFunction& deathComparator); /** * @brief Only available for @ref chainmatrix "chain matrices". - * Constructs a new matrix from the given ranges of @ref Matrix::Cell_representative. Each range corresponds to a column - * (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by increasing IDs. - * The IDs of the simplices are also assumed to be consecutive, ordered by filtration value, starting with 0. + * Constructs a new matrix from the given ranges of @ref Matrix::Entry_representative. Each range corresponds to a + * column (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by increasing + * IDs. The IDs of the simplices are also assumed to be consecutive, ordered by filtration value, starting with 0. * * @warning If @ref PersistenceMatrixOptions::has_vine_update is false, the comparators are not used. * And if @ref PersistenceMatrixOptions::has_vine_update is true, but @@ -138,7 +139,7 @@ class Position_to_index_overlay * * @tparam BirthComparatorFunction Type of the birth comparator: (@ref Pos_index, @ref Pos_index) -> bool * @tparam DeathComparatorFunction Type of the death comparator: (@ref Pos_index, @ref Pos_index) -> bool - * @tparam Boundary_range Range type for @ref Matrix::Cell_representative ranges. + * @tparam Boundary_range Range type for @ref Matrix::Entry_representative ranges. * Assumed to have a begin(), end() and size() method. * @param orderedBoundaries Range of boundaries: @p orderedBoundaries is interpreted as a boundary matrix of a * filtered **simplicial** complex, whose boundaries are ordered by filtration order. @@ -221,12 +222,13 @@ class Position_to_index_overlay * face ID used in the boundaries when the face is inserted. * * Different to the constructor, the boundaries do not have to come from a simplicial complex, but also from - * a more general cell complex. This includes cubical complexes or Morse complexes for example. + * a more general entry complex. This includes cubical complexes or Morse complexes for example. * * When inserted, the given boundary is reduced and from the reduction process, the column is deduced in the form of: * `IDIdx + linear combination of older column IDIdxs`. If the barcode is stored, it will be updated. * - * @tparam Boundary_range Range of @ref Matrix::Cell_representative. Assumed to have a begin(), end() and size() method. + * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() + * method. * @param boundary Boundary generating the new column. The content should be ordered by ID. * @param dim Dimension of the face whose boundary is given. If the complex is simplicial, * this parameter can be omitted as it can be deduced from the size of the boundary. @@ -241,7 +243,8 @@ class Position_to_index_overlay * As a face has to be inserted before one of its cofaces in a valid filtration (recall that it is assumed that * the faces are inserted by order of filtration), it is sufficient to indicate the ID of the face being inserted. * - * @tparam Boundary_range Range of @ref Matrix::Cell_representative. Assumed to have a begin(), end() and size() method. + * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() + * method. * @param faceIndex @ref IDIdx index to use to identify the new face. * @param boundary Boundary generating the new column. The indices of the boundary have to correspond to the * @p faceID values of precedent calls of the method for the corresponding faces and should be ordered in @@ -290,11 +293,11 @@ class Position_to_index_overlay * @ref PersistenceMatrixOptions::has_removable_rows are true. * Assumes that the row is empty and removes it. * - * @warning The removed rows are always assumed to be empty. If it is not the case, the deleted row cells are not + * @warning The removed rows are always assumed to be empty. If it is not the case, the deleted row entries are not * removed from their columns. And in the case of intrusive rows, this will generate a segmentation fault when - * the column cells are destroyed later. The row access is just meant as a "read only" access to the rows and the + * the column entries are destroyed later. The row access is just meant as a "read only" access to the rows and the * @ref erase_empty_row method just as a way to specify that a row is empty and can therefore be removed from - * dictionaries. This allows to avoid testing the emptiness of a row at each column cell removal, what can be + * dictionaries. This allows to avoid testing the emptiness of a row at each column entry removal, what can be * quite frequent. * * @param rowIndex @ref rowindex "Row index" of the empty row to remove. @@ -388,14 +391,14 @@ class Position_to_index_overlay Pos_index targetPosition); /** - * @brief Indicates if the cell at given coordinates has value zero. + * @brief Indicates if the entry at given coordinates has value zero. * - * @param position @ref PosIdx index of the face corresponding to the column of the cell. - * @param rowIndex @ref rowindex "Row index" of the row of the cell. - * @return true If the cell has value zero. + * @param position @ref PosIdx index of the face corresponding to the column of the entry. + * @param rowIndex @ref rowindex "Row index" of the row of the entry. + * @return true If the entry has value zero. * @return false Otherwise. */ - bool is_zero_cell(Pos_index position, ID_index rowIndex) const; + bool is_zero_entry(Pos_index position, ID_index rowIndex) const; /** * @brief Indicates if the column at given index has value zero. * @@ -752,10 +755,10 @@ inline void Position_to_index_overlay::multipl } template -inline bool Position_to_index_overlay::is_zero_cell(Pos_index position, +inline bool Position_to_index_overlay::is_zero_entry(Pos_index position, ID_index rowIndex) const { - return matrix_.is_zero_cell(positionToIndex_[position], rowIndex); + return matrix_.is_zero_entry(positionToIndex_[position], rowIndex); } template diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/RU_matrix.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/RU_matrix.h index 28b7a1412a..f738404e42 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/RU_matrix.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/RU_matrix.h @@ -45,18 +45,18 @@ class RU_matrix : public Master_matrix::RU_pairing_option, * @brief Field operators class. Necessary only if @ref PersistenceMatrixOptions::is_z2 is false. */ using Field_operators = typename Master_matrix::Field_operators; - using Field_element = typename Master_matrix::Element; /**< Type of an field element. */ - using Column = typename Master_matrix::Column; /**< Column type. */ - using Row = typename Master_matrix::Row; /**< Row type, - only necessary with row access option. */ - using Cell_constructor = typename Master_matrix::Cell_constructor; /**< Factory of @ref Cell classes. */ - using Column_settings = typename Master_matrix::Column_settings; /**< Structure giving access to the columns to - necessary external classes. */ - using Boundary = typename Master_matrix::Boundary; /**< Type of an input column. */ - using Index = typename Master_matrix::Index; /**< @ref MatIdx index type. */ - using ID_index = typename Master_matrix::ID_index; /**< @ref IDIdx index type. */ - using Pos_index = typename Master_matrix::Pos_index; /**< @ref PosIdx index type. */ - using Dimension = typename Master_matrix::Dimension; /**< Dimension value type. */ + using Field_element = typename Master_matrix::Element; /**< Type of an field element. */ + using Column = typename Master_matrix::Column; /**< Column type. */ + using Row = typename Master_matrix::Row; /**< Row type, + only necessary with row access option. */ + using Entry_constructor = typename Master_matrix::Entry_constructor; /**< Factory of @ref Entry classes. */ + using Column_settings = typename Master_matrix::Column_settings; /**< Structure giving access to the columns to + necessary external classes. */ + using Boundary = typename Master_matrix::Boundary; /**< Type of an input column. */ + using Index = typename Master_matrix::Index; /**< @ref MatIdx index type. */ + using ID_index = typename Master_matrix::ID_index; /**< @ref IDIdx index type. */ + using Pos_index = typename Master_matrix::Pos_index; /**< @ref PosIdx index type. */ + using Dimension = typename Master_matrix::Dimension; /**< Dimension value type. */ /** * @brief Constructs an empty matrix. @@ -66,11 +66,12 @@ class RU_matrix : public Master_matrix::RU_pairing_option, */ RU_matrix(Column_settings* colSettings); /** - * @brief Constructs a new matrix from the given ranges of @ref Matrix::Cell_representative. Each range corresponds to - * a column (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by increasing - * IDs. The IDs of the simplices are also assumed to be consecutive, ordered by filtration value, starting with 0. + * @brief Constructs a new matrix from the given ranges of @ref Matrix::Entry_representative. Each range corresponds + * to a column (the order of the ranges are preserved). The content of the ranges is assumed to be sorted by + * increasing IDs. The IDs of the simplices are also assumed to be consecutive, ordered by filtration value, starting + * with 0. * - * @tparam Boundary_range Range type for @ref Matrix::Cell_representative ranges. + * @tparam Boundary_range Range type for @ref Matrix::Entry_representative ranges. * Assumed to have a begin(), end() and size() method. * @param orderedBoundaries Range of boundaries: @p orderedBoundaries is interpreted as a boundary matrix of a * filtered **simplicial** complex, whose boundaries are ordered by filtration order. @@ -120,11 +121,11 @@ class RU_matrix : public Master_matrix::RU_pairing_option, * face ID used in the boundaries when the face is inserted. * * Different to the constructor, the boundaries do not have to come from a simplicial complex, but also from - * a more general cell complex. This includes cubical complexes or Morse complexes for example. + * a more general entry complex. This includes cubical complexes or Morse complexes for example. * * At the insertion, the boundary is stored in its reduced form and the barcode, if enabled, is updated. * - * @tparam Boundary_range Range of @ref Matrix::Cell_representative. Assumed to have a begin(), end() and size() + * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() * method. * @param boundary Boundary generating the new column. The content should be ordered by ID. * @param dim Dimension of the face whose boundary is given. If the complex is simplicial, @@ -140,7 +141,7 @@ class RU_matrix : public Master_matrix::RU_pairing_option, * As a face has to be inserted before one of its cofaces in a valid filtration (recall that it is assumed that * the faces are inserted by order of filtration), it is sufficient to indicate the ID of the face being inserted. * - * @tparam Boundary_range Range of @ref Matrix::Cell_representative. Assumed to have a begin(), end() and size() + * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() * method. * @param faceIndex @ref IDIdx index to use to identify the new face. * @param boundary Boundary generating the new column. The indices of the boundary have to correspond to the @@ -156,7 +157,7 @@ class RU_matrix : public Master_matrix::RU_pairing_option, * in \f$ U \f$ if @p inR is false. * The type of the column depends on the choosen options, see @ref PersistenceMatrixOptions::column_type. * - * Note that before returning the column, all column cells can eventually be reordered, if lazy swaps occurred. + * Note that before returning the column, all column entries can eventually be reordered, if lazy swaps occurred. * It is therefore recommended to avoid calling @ref get_column between vine swaps, otherwise the benefits * of the the laziness is lost. * @@ -171,7 +172,7 @@ class RU_matrix : public Master_matrix::RU_pairing_option, * in \f$ U \f$ if @p inR is false. * The type of the row depends on the choosen options, see @ref PersistenceMatrixOptions::has_intrusive_rows. * - * Note that before returning the row, all column cells can eventually be reordered, if lazy swaps occurred. + * Note that before returning the row, all column entries can eventually be reordered, if lazy swaps occurred. * It is therefore recommended to avoid calling @ref get_row between vine swaps, otherwise the benefits * of the the laziness is lost. * @@ -190,10 +191,10 @@ class RU_matrix : public Master_matrix::RU_pairing_option, * Otherwise, does nothing. * * @warning The removed rows are always assumed to be empty in \f$ R \f$. If it is not the case, the deleted row - * cells are not removed from their columns. And in the case of intrusive rows, this will generate a segmentation - * fault when the column cells are destroyed later. The row access is just meant as a "read only" access to the + * entries are not removed from their columns. And in the case of intrusive rows, this will generate a segmentation + * fault when the column entries are destroyed later. The row access is just meant as a "read only" access to the * rows and the @ref erase_empty_row method just as a way to specify that a row is empty and can therefore be removed - * from dictionaries. This allows to avoid testing the emptiness of a row at each column cell removal, what can + * from dictionaries. This allows to avoid testing the emptiness of a row at each column entry removal, what can * be quite frequent. * * @param rowIndex @ref rowindex "Row index" of the empty row. @@ -280,16 +281,16 @@ class RU_matrix : public Master_matrix::RU_pairing_option, void multiply_source_and_add_to(const Field_element& coefficient, Index sourceColumnIndex, Index targetColumnIndex); /** - * @brief Zeroes the cell at the given coordinates in \f$ R \f$ if @p inR is true or in + * @brief Zeroes the entry at the given coordinates in \f$ R \f$ if @p inR is true or in * \f$ U \f$ if @p inR is false. Should be used with care to not destroy the validity of the persistence * related properties of the matrix. * - * @param columnIndex @ref MatIdx index of the column of the cell. - * @param rowIndex @ref rowindex "Row index" of the row of the cell. + * @param columnIndex @ref MatIdx index of the column of the entry. + * @param rowIndex @ref rowindex "Row index" of the row of the entry. * @param inR Boolean indicating in which matrix to zero: if true in \f$ R \f$ and if false in \f$ U \f$. * Default value: true. */ - void zero_cell(Index columnIndex, Index rowIndex, bool inR = true); + void zero_entry(Index columnIndex, Index rowIndex, bool inR = true); /** * @brief Zeroes the column at the given index in \f$ R \f$ if @p inR is true or in * \f$ U \f$ if @p inR is false. Should be used with care to not destroy the validity of the persistence @@ -301,17 +302,17 @@ class RU_matrix : public Master_matrix::RU_pairing_option, */ void zero_column(Index columnIndex, bool inR = true); /** - * @brief Indicates if the cell at given coordinates has value zero in \f$ R \f$ + * @brief Indicates if the entry at given coordinates has value zero in \f$ R \f$ * if @p inR is true or in \f$ U \f$ if @p inR is false. * - * @param columnIndex @ref MatIdx index of the column of the cell. - * @param rowIndex @ref rowindex "Row index" of the row of the cell. + * @param columnIndex @ref MatIdx index of the column of the entry. + * @param rowIndex @ref rowindex "Row index" of the row of the entry. * @param inR Boolean indicating in which matrix to look: if true in \f$ R \f$ and if false in \f$ U \f$. * Default value: true. - * @return true If the cell has value zero. + * @return true If the entry has value zero. * @return false Otherwise. */ - bool is_zero_cell(Index columnIndex, Index rowIndex, bool inR = true) const; + bool is_zero_entry(Index columnIndex, Index rowIndex, bool inR = true) const; /** * @brief Indicates if the column at given index has value zero in \f$ R \f$ * if @p inR is true or in \f$ U \f$ if @p inR is false. @@ -662,12 +663,12 @@ inline void RU_matrix::multiply_source_and_add_to(const Field_ele } template -inline void RU_matrix::zero_cell(Index columnIndex, Index rowIndex, bool inR) +inline void RU_matrix::zero_entry(Index columnIndex, Index rowIndex, bool inR) { if (inR) { - return reducedMatrixR_.zero_cell(columnIndex, rowIndex); + return reducedMatrixR_.zero_entry(columnIndex, rowIndex); } - return mirrorMatrixU_.zero_cell(columnIndex, rowIndex); + return mirrorMatrixU_.zero_entry(columnIndex, rowIndex); } template @@ -680,12 +681,12 @@ inline void RU_matrix::zero_column(Index columnIndex, bool inR) } template -inline bool RU_matrix::is_zero_cell(Index columnIndex, Index rowIndex, bool inR) const +inline bool RU_matrix::is_zero_entry(Index columnIndex, Index rowIndex, bool inR) const { if (inR) { - return reducedMatrixR_.is_zero_cell(columnIndex, rowIndex); + return reducedMatrixR_.is_zero_entry(columnIndex, rowIndex); } - return mirrorMatrixU_.is_zero_cell(columnIndex, rowIndex); + return mirrorMatrixU_.is_zero_entry(columnIndex, rowIndex); } template diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/allocators/cell_constructors.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/allocators/cell_constructors.h deleted file mode 100644 index f13d92256f..0000000000 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/allocators/cell_constructors.h +++ /dev/null @@ -1,139 +0,0 @@ -/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. - * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. - * Author(s): Hannah Schreiber - * - * Copyright (C) 2024 Inria - * - * Modification(s): - * - YYYY/MM Author: Description of the modification - */ - -/** - * @file cell_constructors.h - * @author Hannah Schreiber - * @brief Contains different versions of @ref Gudhi::persistence_matrix::Cell factories. - */ - -#ifndef PM_COLUMN_CELL_CONSTRUCTORS_H -#define PM_COLUMN_CELL_CONSTRUCTORS_H - -#include //std::swap - -#include - -namespace Gudhi { -namespace persistence_matrix { - -/** - * @private - * @ingroup persistence_matrix - * - * @brief @ref Cell factory. Constructs and destroys cell pointers with new and delete. - * - * @tparam Cell @ref Cell with the right templates. - */ -template -struct New_cell_constructor -{ - /** - * @brief Default constructor. - */ - New_cell_constructor() {} - - /** - * @brief Constructs a cell with the given cell arguments. - * - * @param u Arguments forwarded to the @ref Cell constructor. - * @return @ref Cell pointer. - */ - template - Cell* construct(U&&... u) const { - return new Cell(std::forward(u)...); - } - - /** - * @brief Destroys the given cell. - * - * @param cell @ref Cell pointer. - */ - void destroy(Cell* cell) const { delete cell; } - - /** - * @brief Swap operator. - */ - friend void swap(New_cell_constructor& col1, New_cell_constructor& col2) {} -}; - -/** - * @private - * @ingroup persistence_matrix - * - * @brief @ref Cell factory. Uses @ref Gudhi::Simple_object_pool, which is based on boost::object_pool, - * to construct and destroy cell pointer. - * - * @tparam Cell @ref Cell with the right templates. - */ -template -struct Pool_cell_constructor -{ - public: - /** - * @brief Default constructor. - * - */ - Pool_cell_constructor() : cellPool_() {} - //TODO: what does happen when the pool is copied? - /** - * @brief Copy constructor. - * - * @param col Factory to copy. - */ - Pool_cell_constructor(const Pool_cell_constructor& col) : cellPool_(col.cellPool_) {} - /** - * @brief Move constructor. - * - * @param col Factory to move. - */ - Pool_cell_constructor(Pool_cell_constructor&& col) : cellPool_(std::move(col.cellPool_)) {} - - /** - * @brief Constructs a cell with the given cell arguments. - * - * @param u Arguments forwarded to the @ref Cell constructor. - * @return @ref Cell pointer. - */ - template - Cell* construct(U&&... u) { - return cellPool_.construct(std::forward(u)...); - } - - /** - * @brief Destroys the given cell. - * - * @param cell @ref Cell pointer. - */ - void destroy(Cell* cell) { cellPool_.destroy(cell); } - - //TODO: Again, what does it mean to copy the pool? - /** - * @brief Assign operator. - */ - Pool_cell_constructor& operator=(const Pool_cell_constructor& other) { - cellPool_ = other.cellPool_; - return *this; - } - /** - * @brief Swap operator. - */ - friend void swap(Pool_cell_constructor& col1, Pool_cell_constructor& col2) { - std::swap(col1.cellPool_, col2.cellPool_); - } - - private: - Simple_object_pool cellPool_; /**< Cell pool. */ -}; - -} // namespace persistence_matrix -} // namespace Gudhi - -#endif // PM_COLUMN_CELL_CONSTRUCTORS_H diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/allocators/entry_constructors.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/allocators/entry_constructors.h new file mode 100644 index 0000000000..5062a985ec --- /dev/null +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/allocators/entry_constructors.h @@ -0,0 +1,139 @@ +/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. + * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. + * Author(s): Hannah Schreiber + * + * Copyright (C) 2024 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + +/** + * @file entry_constructors.h + * @author Hannah Schreiber + * @brief Contains different versions of @ref Gudhi::persistence_matrix::Entry factories. + */ + +#ifndef PM_COLUMN_CELL_CONSTRUCTORS_H +#define PM_COLUMN_CELL_CONSTRUCTORS_H + +#include //std::swap + +#include + +namespace Gudhi { +namespace persistence_matrix { + +/** + * @private + * @ingroup persistence_matrix + * + * @brief @ref Entry factory. Constructs and destroys entry pointers with new and delete. + * + * @tparam Entry @ref Entry with the right templates. + */ +template +struct New_entry_constructor +{ + /** + * @brief Default constructor. + */ + New_entry_constructor() {} + + /** + * @brief Constructs an entry with the given entry arguments. + * + * @param u Arguments forwarded to the @ref Entry constructor. + * @return @ref Entry pointer. + */ + template + Entry* construct(U&&... u) const { + return new Entry(std::forward(u)...); + } + + /** + * @brief Destroys the given entry. + * + * @param entry @ref Entry pointer. + */ + void destroy(Entry* entry) const { delete entry; } + + /** + * @brief Swap operator. + */ + friend void swap(New_entry_constructor& col1, New_entry_constructor& col2) {} +}; + +/** + * @private + * @ingroup persistence_matrix + * + * @brief @ref Entry factory. Uses @ref Gudhi::Simple_object_pool, which is based on boost::object_pool, + * to construct and destroy entry pointer. + * + * @tparam Entry @ref Entry with the right templates. + */ +template +struct Pool_entry_constructor +{ + public: + /** + * @brief Default constructor. + * + */ + Pool_entry_constructor() : entryPool_() {} + //TODO: what does happen when the pool is copied? + /** + * @brief Copy constructor. + * + * @param col Factory to copy. + */ + Pool_entry_constructor(const Pool_entry_constructor& col) : entryPool_(col.entryPool_) {} + /** + * @brief Move constructor. + * + * @param col Factory to move. + */ + Pool_entry_constructor(Pool_entry_constructor&& col) : entryPool_(std::move(col.entryPool_)) {} + + /** + * @brief Constructs an entry with the given entry arguments. + * + * @param u Arguments forwarded to the @ref Entry constructor. + * @return @ref Entry pointer. + */ + template + Entry* construct(U&&... u) { + return entryPool_.construct(std::forward(u)...); + } + + /** + * @brief Destroys the given entry. + * + * @param entry @ref Entry pointer. + */ + void destroy(Entry* entry) { entryPool_.destroy(entry); } + + //TODO: Again, what does it mean to copy the pool? + /** + * @brief Assign operator. + */ + Pool_entry_constructor& operator=(const Pool_entry_constructor& other) { + entryPool_ = other.entryPool_; + return *this; + } + /** + * @brief Swap operator. + */ + friend void swap(Pool_entry_constructor& col1, Pool_entry_constructor& col2) { + std::swap(col1.entryPool_, col2.entryPool_); + } + + private: + Simple_object_pool entryPool_; /**< Entry pool. */ +}; + +} // namespace persistence_matrix +} // namespace Gudhi + +#endif // PM_COLUMN_CELL_CONSTRUCTORS_H diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/base_swap.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/base_swap.h index e8f9bf412f..db6af1cc70 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/base_swap.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/base_swap.h @@ -77,7 +77,7 @@ class Base_swap { /** * @brief Swaps the two columns at given indices in the column container. Does not updates the column index value, - * potentially stored in the cells. This will be done when calling `_orderRows()`. + * potentially stored in the entries. This will be done when calling `_orderRows()`. * * @param columnIndex1 First @ref MatIdx column index. * @param columnIndex2 Second @ref MatIdx column index. @@ -145,7 +145,7 @@ template inline void Base_swap::swap_columns(Index columnIndex1, Index columnIndex2) { swap(_matrix()->matrix_.at(columnIndex1), _matrix()->matrix_.at(columnIndex2)); - if constexpr (Master_matrix::Option_list::has_row_access) rowSwapped_ = true; //to update column index in cells. + if constexpr (Master_matrix::Option_list::has_row_access) rowSwapped_ = true; //to update column index in entries. } template diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/chain_vine_swap.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/chain_vine_swap.h index 2956ba0e2e..887f89cb2c 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/chain_vine_swap.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/chain_vine_swap.h @@ -401,7 +401,7 @@ inline typename Chain_vine_swap::Index Chain_vine_swapis_zero_cell(columnIndex2, _matrix()->get_pivot(columnIndex1))) { + if (_matrix()->is_zero_entry(columnIndex2, _matrix()->get_pivot(columnIndex1))) { if constexpr (Master_matrix::Option_list::has_column_pairings) { ID_index pivot1 = _matrix()->get_pivot(columnIndex1); ID_index pivot2 = _matrix()->get_pivot(columnIndex2); @@ -415,7 +415,7 @@ inline typename Chain_vine_swap::Index Chain_vine_swapis_zero_cell(columnIndex2, _matrix()->get_pivot(columnIndex1))) { + if (_matrix()->is_zero_entry(columnIndex2, _matrix()->get_pivot(columnIndex1))) { if constexpr (Master_matrix::Option_list::has_column_pairings) { ID_index pivot1 = _matrix()->get_pivot(columnIndex1); ID_index pivot2 = _matrix()->get_pivot(columnIndex2); @@ -429,7 +429,7 @@ inline typename Chain_vine_swap::Index Chain_vine_swapis_zero_cell(columnIndex2, _matrix()->get_pivot(columnIndex1))) { + if (_matrix()->is_zero_entry(columnIndex2, _matrix()->get_pivot(columnIndex1))) { if constexpr (Master_matrix::Option_list::has_column_pairings) { ID_index pivot1 = _matrix()->get_pivot(columnIndex1); ID_index pivot2 = _matrix()->get_pivot(columnIndex2); @@ -442,7 +442,7 @@ inline typename Chain_vine_swap::Index Chain_vine_swapis_zero_cell(columnIndex2, _matrix()->get_pivot(columnIndex1))) { + if (_matrix()->is_zero_entry(columnIndex2, _matrix()->get_pivot(columnIndex1))) { if constexpr (Master_matrix::Option_list::has_column_pairings) { ID_index pivot1 = _matrix()->get_pivot(columnIndex1); ID_index pivot2 = _matrix()->get_pivot(columnIndex2); diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/cell_types.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/cell_types.h deleted file mode 100644 index 0bf59de134..0000000000 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/cell_types.h +++ /dev/null @@ -1,327 +0,0 @@ -/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. - * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. - * Author(s): Hannah Schreiber - * - * Copyright (C) 2022-24 Inria - * - * Modification(s): - * - YYYY/MM Author: Description of the modification - */ - -/** - * @file cell_types.h - * @author Hannah Schreiber - * @brief Contains the @ref Gudhi::persistence_matrix::Cell, @ref Gudhi::persistence_matrix::Cell_column_index and - * @ref Gudhi::persistence_matrix::Cell_field_element classes, as well as the - * @ref Gudhi::persistence_matrix::Dummy_cell_column_index_mixin and - * @ref Gudhi::persistence_matrix::Dummy_cell_field_element_mixin structures. - * Also defines the std::hash method for @ref Gudhi::persistence_matrix::Cell. - */ - -#ifndef PM_MATRIX_CELL_H -#define PM_MATRIX_CELL_H - -#include //std::swap, std::exchange & std::move -#include //std::hash - -namespace Gudhi { -namespace persistence_matrix { - -/** - * @ingroup persistence_matrix - * - * @brief Empty structure. - * Inherited instead of @ref Cell_column_index, when the row access is disabled. - */ -struct Dummy_cell_column_index_mixin -{ - Dummy_cell_column_index_mixin() {} - template - Dummy_cell_column_index_mixin([[maybe_unused]] Index columnIndex) {} -}; - -/** - * @ingroup persistence_matrix - * - * @brief Empty structure. - * Inherited instead of @ref Cell_field_element, when @ref PersistenceMatrixOptions::is_z2 is true. - */ -struct Dummy_cell_field_element_mixin -{ - Dummy_cell_field_element_mixin() {} - template - Dummy_cell_field_element_mixin([[maybe_unused]] Field_element t) {} -}; - -/** - * @ingroup persistence_matrix - * - * @brief Class managing the column index access of a cell. - * - * @tparam Index @ref MatIdx index type. - */ -template -class Cell_column_index -{ - public: - /** - * @brief Default constructor. Sets to the column index to -1. - */ - Cell_column_index() : columnIndex_(-1){}; - /** - * @brief Stores the given column index. - * - * @param columnIndex Column index of the cell. - */ - Cell_column_index(Index columnIndex) : columnIndex_(columnIndex){}; - /** - * @brief Copy constructor. - * - * @param cell Cell to copy. - */ - Cell_column_index(const Cell_column_index& cell) : columnIndex_(cell.columnIndex_){}; - /** - * @brief Move constructor. - * - * @param cell Cell to move. - */ - Cell_column_index(Cell_column_index&& cell) noexcept : columnIndex_(std::exchange(cell.columnIndex_, 0)){}; - - /** - * @brief Returns the @ref MatIdx column index stored in the cell. - * - * @return Column index of the cell. - */ - Index get_column_index() const { return columnIndex_; }; - /** - * @brief Sets the column index to the given value. - * - * @param columnIndex Column index of the cell. - */ - void set_column_index(Index columnIndex) { columnIndex_ = columnIndex; } - - /** - * @brief Assign operator. - */ - Cell_column_index& operator=(Cell_column_index other) { - std::swap(columnIndex_, other.columnIndex_); - return *this; - }; - - private: - Index columnIndex_; /**< Column index. */ -}; - -/** - * @ingroup persistence_matrix - * - * @brief Class managing the value access of a cell. - * - * @tparam Field_element Type of a cell value. - */ -template -class Cell_field_element -{ - public: - /** - * @brief Default constructor. Sets to the element to 0. - */ - Cell_field_element() : element_(0){}; - /** - * @brief Stores the given element. - * - * @param element Value to store. - */ - Cell_field_element(Field_element element) : element_(element){}; - /** - * @brief Copy constructor. - * - * @param cell Cell to copy. - */ - Cell_field_element(const Cell_field_element& cell) : element_(cell.element_){}; - /** - * @brief Move constructor. - * - * @param cell Cell to move. - */ - Cell_field_element(Cell_field_element&& cell) noexcept : element_(std::move(cell.element_)){}; - - /** - * @brief Returns the value stored in the cell. - * - * @return Reference to the value of the cell. - */ - Field_element& get_element() { return element_; }; - /** - * @brief Returns the value stored in the cell. - * - * @return Const reference to the value of the cell. - */ - const Field_element& get_element() const { return element_; }; - /** - * @brief Sets the value. - * - * @param element Value to store. - */ - void set_element(const Field_element& element) { element_ = element; } - - /** - * @brief Assign operator. - */ - Cell_field_element& operator=(Cell_field_element other) { - std::swap(element_, other.element_); - return *this; - }; - - private: - Field_element element_; /**< Value of the cell. */ -}; - -/** - * @class Cell cell_types.h gudhi/Persistence_matrix/columns/cell_types.h - * @ingroup persistence_matrix - * - * @brief %Matrix cell class. Stores by default only the row index it belongs to, but can also store its - * column index when the row access is enabled, as well as its value when they are different from only 0 and 1. - * Zero-valued cells are never made explicit in the matrix. - * - * @tparam Master_matrix An instantiation of @ref Matrix from which all types and options are deduced. - */ -template -class Cell : public Master_matrix::Cell_column_index_option, - public Master_matrix::Cell_field_element_option, - public Master_matrix::Row_hook, - public Master_matrix::Column_hook -{ - private: - using col_opt = typename Master_matrix::Cell_column_index_option; - using field_opt = typename Master_matrix::Cell_field_element_option; - - public: - using Master = Master_matrix; /**< Access to options from outside. */ - using Index = typename Master_matrix::Index; /**< Column index type. */ - using ID_index = typename Master_matrix::ID_index; /**< Row index type. */ - using Field_element = typename Master_matrix::Element; /**< Value type. */ - - /** - * @brief Constructs an cell with all attributes at default values. - */ - Cell(){}; - /** - * @brief Constructs a cell with given row index. Other possible attributes are set at default values. - * - * @param rowIndex @ref rowindex "Row index" of the cell. - */ - Cell(ID_index rowIndex) : col_opt(), field_opt(), rowIndex_(rowIndex){}; - /** - * @brief Constructs a cell with given row and column index. Other possible attributes are set at default values. - * - * @param columnIndex Column index of the cell. - * @param rowIndex @ref rowindex "Row index" of the cell. - */ - Cell(Index columnIndex, ID_index rowIndex) : col_opt(columnIndex), field_opt(), rowIndex_(rowIndex){}; - /** - * @brief Copy constructor. - * - * @param cell Cell to copy. - */ - Cell(const Cell& cell) - : col_opt(static_cast(cell)), - field_opt(static_cast(cell)), - rowIndex_(cell.rowIndex_){}; - /** - * @brief Move constructor. - * - * @param cell Cell to move. - */ - Cell(Cell&& cell) noexcept - : col_opt(std::move(static_cast(cell))), - field_opt(std::move(static_cast(cell))), - rowIndex_(std::exchange(cell.rowIndex_, 0)){}; - - /** - * @brief Returns the row index stored in the cell. - * - * @return @ref rowindex "Row index" of the cell. - */ - ID_index get_row_index() const { return rowIndex_; }; - /** - * @brief Sets the row index stored in the cell. - * - * @param rowIndex @ref rowindex "Row index" of the cell. - */ - void set_row_index(ID_index rowIndex) { rowIndex_ = rowIndex; }; - - /** - * @brief Assign operator. - */ - Cell& operator=(Cell other) { - col_opt::operator=(other); - field_opt::operator=(other); - std::swap(rowIndex_, other.rowIndex_); - return *this; - }; - - /** - * @brief Strictly smaller than comparator. - * - * @param c1 First cell to compare. - * @param c2 Second cell to compare. - * @return true If the row index of the first cell is strictly smaller than the row index of the second cell. - * @return false Otherwise. - */ - friend bool operator<(const Cell& c1, const Cell& c2) { return c1.get_row_index() < c2.get_row_index(); } - /** - * @brief Equality comparator. - * - * @param c1 First cell to compare. - * @param c2 Second cell to compare. - * @return true If the row index of the first cell is equal to the row index of the second cell. - * @return false Otherwise. - */ - friend bool operator==(const Cell& c1, const Cell& c2) { return c1.get_row_index() == c2.get_row_index(); } - - /** - * @brief Converts the cell into a row index. - * - * @return The row index of the cell. - */ - operator ID_index() const { return rowIndex_; } - /** - * @brief Converts the cell into a pair of row index and cell value. - * - * @return A std::pair with first element the row index and second element the value. - */ - operator std::pair() const { - if constexpr (Master_matrix::Option_list::is_z2) { - return {rowIndex_, 1}; - } else { - return {rowIndex_, field_opt::element_}; - } - } - - private: - ID_index rowIndex_; /**< Row index of the cell. */ -}; - -} // namespace persistence_matrix -} // namespace Gudhi - -/** - * @ingroup persistence_matrix - * - * @brief Hash method for @ref Gudhi::persistence_matrix::Cell. - * - * The cells are differentiated by their row indices only. For example, two cells with the same row index - * but different column indices have the same hash value. - * - * @tparam Master_matrix Template parameter of @ref Gudhi::persistence_matrix::Cell. - */ -template -struct std::hash > { - std::size_t operator()(const Gudhi::persistence_matrix::Cell& cell) const { - return std::hash()(cell.get_row_index()); - } -}; - -#endif // PM_MATRIX_CELL_H diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/column_utilities.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/column_utilities.h index 360ac37ec1..bb7670cf2e 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/column_utilities.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/column_utilities.h @@ -25,11 +25,11 @@ namespace Gudhi { namespace persistence_matrix { -template -Cell* _get_cell(const Cell_iterator& itTarget) +template +Entry* _get_entry(const Entry_iterator& itTarget) { - if constexpr (Cell::Master::Option_list::column_type == Column_types::INTRUSIVE_LIST || - Cell::Master::Option_list::column_type == Column_types::INTRUSIVE_SET) { + if constexpr (Entry::Master::Option_list::column_type == Column_types::INTRUSIVE_LIST || + Entry::Master::Option_list::column_type == Column_types::INTRUSIVE_SET) { return &*itTarget; } else { return *itTarget; @@ -37,41 +37,41 @@ Cell* _get_cell(const Cell_iterator& itTarget) } // works only for ordered columns -template -void _generic_merge_cell_to_column(Column& targetColumn, - Cell_iterator& itSource, - typename Column::Column_support::iterator& itTarget, - F1&& process_target, - F2&& process_source, - F3&& update_target1, - F4&& update_target2, - bool& pivotIsZeroed) +template +void _generic_merge_entry_to_column(Column& targetColumn, + Entry_iterator& itSource, + typename Column::Column_support::iterator& itTarget, + F1&& process_target, + F2&& process_source, + F3&& update_target1, + F4&& update_target2, + bool& pivotIsZeroed) { - typename Column::Cell* targetCell = _get_cell(itTarget); + typename Column::Entry* targetEntry = _get_entry(itTarget); - if (targetCell->get_row_index() < itSource->get_row_index()) { - process_target(targetCell); + if (targetEntry->get_row_index() < itSource->get_row_index()) { + process_target(targetEntry); ++itTarget; - } else if (targetCell->get_row_index() > itSource->get_row_index()) { + } else if (targetEntry->get_row_index() > itSource->get_row_index()) { process_source(itSource, itTarget); ++itSource; } else { if constexpr (Column::Master::Option_list::is_z2) { //_multiply_*_and_add never enters here so not treated if constexpr (Column::Master::isNonBasic && !Column::Master::Option_list::is_of_boundary_type) { - if (targetCell->get_row_index() == targetColumn.get_pivot()) pivotIsZeroed = true; + if (targetEntry->get_row_index() == targetColumn.get_pivot()) pivotIsZeroed = true; } - targetColumn._delete_cell(itTarget); + targetColumn._delete_entry(itTarget); } else { - update_target1(targetCell->get_element(), itSource); - if (targetCell->get_element() == Column::Field_operators::get_additive_identity()) { + update_target1(targetEntry->get_element(), itSource); + if (targetEntry->get_element() == Column::Field_operators::get_additive_identity()) { if constexpr (Column::Master::isNonBasic && !Column::Master::Option_list::is_of_boundary_type) { - if (targetCell->get_row_index() == targetColumn.get_pivot()) pivotIsZeroed = true; + if (targetEntry->get_row_index() == targetColumn.get_pivot()) pivotIsZeroed = true; } - targetColumn._delete_cell(itTarget); + targetColumn._delete_entry(itTarget); } else { - update_target2(targetCell); - if constexpr (Column::Master::Option_list::has_row_access) targetColumn.update_cell(*targetCell); + update_target2(targetEntry); + if constexpr (Column::Master::Option_list::has_row_access) targetColumn.update_entry(*targetEntry); ++itTarget; } } @@ -80,8 +80,8 @@ void _generic_merge_cell_to_column(Column& targetColumn, } // works only for ordered columns -template -bool _generic_add_to_column(const Cell_range& source, +template +bool _generic_add_to_column(const Entry_range& source, Column& targetColumn, F1&& process_target, F2&& process_source, @@ -95,9 +95,9 @@ bool _generic_add_to_column(const Cell_range& source, auto itTarget = target.begin(); auto itSource = source.begin(); while (itTarget != target.end() && itSource != source.end()) { - _generic_merge_cell_to_column(targetColumn, itSource, itTarget, - process_target, process_source, update_target1, update_target2, - pivotIsZeroed); + _generic_merge_entry_to_column(targetColumn, itSource, itTarget, + process_target, process_source, update_target1, update_target2, + pivotIsZeroed); } finish_target(itTarget); @@ -110,32 +110,32 @@ bool _generic_add_to_column(const Cell_range& source, return pivotIsZeroed; } -template -bool _add_to_column(const Cell_range& source, Column& targetColumn) +template +bool _add_to_column(const Entry_range& source, Column& targetColumn) { return _generic_add_to_column( source, targetColumn, - [&]([[maybe_unused]] typename Column::Cell* cellTarget) {}, - [&](typename Cell_range::const_iterator& itSource, const typename Column::Column_support::iterator& itTarget) { + [&]([[maybe_unused]] typename Column::Entry* entryTarget) {}, + [&](typename Entry_range::const_iterator& itSource, const typename Column::Column_support::iterator& itTarget) { if constexpr (Column::Master::Option_list::is_z2) { - targetColumn._insert_cell(itSource->get_row_index(), itTarget); + targetColumn._insert_entry(itSource->get_row_index(), itTarget); } else { - targetColumn._insert_cell(itSource->get_element(), itSource->get_row_index(), itTarget); + targetColumn._insert_entry(itSource->get_element(), itSource->get_row_index(), itTarget); } }, - [&](typename Column::Field_element& targetElement, typename Cell_range::const_iterator& itSource) { + [&](typename Column::Field_element& targetElement, typename Entry_range::const_iterator& itSource) { if constexpr (!Column::Master::Option_list::is_z2) targetColumn.operators_->add_inplace(targetElement, itSource->get_element()); }, - [&]([[maybe_unused]] typename Column::Cell* cellTarget) {}, + [&]([[maybe_unused]] typename Column::Entry* entryTarget) {}, [&]([[maybe_unused]] typename Column::Column_support::iterator& itTarget) {} ); } -template +template bool _multiply_target_and_add_to_column(const typename Column::Field_element& val, - const Cell_range& source, + const Entry_range& source, Column& targetColumn) { if (val == 0u) { @@ -150,33 +150,33 @@ bool _multiply_target_and_add_to_column(const typename Column::Field_element& va return _generic_add_to_column( source, targetColumn, - [&](typename Column::Cell* cellTarget) { - targetColumn.operators_->multiply_inplace(cellTarget->get_element(), val); - // targetColumn.RA_opt::update_cell(*itTarget) produces an internal compiler error + [&](typename Column::Entry* entryTarget) { + targetColumn.operators_->multiply_inplace(entryTarget->get_element(), val); + // targetColumn.RA_opt::update_entry(*itTarget) produces an internal compiler error // even though it works in _generic_add_to_column... Probably because of the lambda. - if constexpr (Column::Master::Option_list::has_row_access) targetColumn.update_cell(*cellTarget); + if constexpr (Column::Master::Option_list::has_row_access) targetColumn.update_entry(*entryTarget); }, - [&](typename Cell_range::const_iterator& itSource, const typename Column::Column_support::iterator& itTarget) { - targetColumn._insert_cell(itSource->get_element(), itSource->get_row_index(), itTarget); + [&](typename Entry_range::const_iterator& itSource, const typename Column::Column_support::iterator& itTarget) { + targetColumn._insert_entry(itSource->get_element(), itSource->get_row_index(), itTarget); }, - [&](typename Column::Field_element& targetElement, typename Cell_range::const_iterator& itSource) { + [&](typename Column::Field_element& targetElement, typename Entry_range::const_iterator& itSource) { targetColumn.operators_->multiply_and_add_inplace_front(targetElement, val, itSource->get_element()); }, - [&]([[maybe_unused]] typename Column::Cell* cellTarget) {}, + [&]([[maybe_unused]] typename Column::Entry* entryTarget) {}, [&](typename Column::Column_support::iterator& itTarget) { while (itTarget != targetColumn.column_.end()) { - typename Column::Cell* targetCell = _get_cell(itTarget); - targetColumn.operators_->multiply_inplace(targetCell->get_element(), val); - if constexpr (Column::Master::Option_list::has_row_access) targetColumn.update_cell(*targetCell); + typename Column::Entry* targetEntry = _get_entry(itTarget); + targetColumn.operators_->multiply_inplace(targetEntry->get_element(), val); + if constexpr (Column::Master::Option_list::has_row_access) targetColumn.update_entry(*targetEntry); itTarget++; } } ); } -template +template bool _multiply_source_and_add_to_column(const typename Column::Field_element& val, - const Cell_range& source, + const Entry_range& source, Column& targetColumn) { if (val == 0u) { @@ -186,17 +186,17 @@ bool _multiply_source_and_add_to_column(const typename Column::Field_element& va return _generic_add_to_column( source, targetColumn, - []([[maybe_unused]] typename Column::Cell* cellTarget) {}, - [&](typename Cell_range::const_iterator& itSource, const typename Column::Column_support::iterator& itTarget) { - typename Column::Cell* cell = - targetColumn._insert_cell(itSource->get_element(), itSource->get_row_index(), itTarget); - targetColumn.operators_->multiply_inplace(cell->get_element(), val); - if constexpr (Column::Master::Option_list::has_row_access) targetColumn.update_cell(*cell); + []([[maybe_unused]] typename Column::Entry* entryTarget) {}, + [&](typename Entry_range::const_iterator& itSource, const typename Column::Column_support::iterator& itTarget) { + typename Column::Entry* entry = + targetColumn._insert_entry(itSource->get_element(), itSource->get_row_index(), itTarget); + targetColumn.operators_->multiply_inplace(entry->get_element(), val); + if constexpr (Column::Master::Option_list::has_row_access) targetColumn.update_entry(*entry); }, - [&](typename Column::Field_element& targetElement, typename Cell_range::const_iterator& itSource) { + [&](typename Column::Field_element& targetElement, typename Entry_range::const_iterator& itSource) { targetColumn.operators_->multiply_and_add_inplace_back(itSource->get_element(), val, targetElement); }, - [&]([[maybe_unused]] typename Column::Cell* cellTarget) {}, + [&]([[maybe_unused]] typename Column::Entry* entryTarget) {}, []([[maybe_unused]] typename Column::Column_support::iterator& itTarget) {}); } @@ -206,8 +206,8 @@ template std::size_t hash_column(const Column& column) { std::size_t seed = 0; - for (auto& cell : column) { - seed ^= std::hash()(cell.get_row_index() * static_cast(cell.get_element())) + + for (auto& entry : column) { + seed ^= std::hash()(entry.get_row_index() * static_cast(entry.get_element())) + 0x9e3779b9 + (seed << 6) + (seed >> 2); } return seed; diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/entry_types.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/entry_types.h new file mode 100644 index 0000000000..ca9ad3389f --- /dev/null +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/entry_types.h @@ -0,0 +1,327 @@ +/* This file is part of the Gudhi Library - https://gudhi.inria.fr/ - which is released under MIT. + * See file LICENSE or go to https://gudhi.inria.fr/licensing/ for full license details. + * Author(s): Hannah Schreiber + * + * Copyright (C) 2022-24 Inria + * + * Modification(s): + * - YYYY/MM Author: Description of the modification + */ + +/** + * @file entry_types.h + * @author Hannah Schreiber + * @brief Contains the @ref Gudhi::persistence_matrix::Entry, @ref Gudhi::persistence_matrix::Entry_column_index and + * @ref Gudhi::persistence_matrix::Entry_field_element classes, as well as the + * @ref Gudhi::persistence_matrix::Dummy_entry_column_index_mixin and + * @ref Gudhi::persistence_matrix::Dummy_entry_field_element_mixin structures. + * Also defines the std::hash method for @ref Gudhi::persistence_matrix::Entry. + */ + +#ifndef PM_MATRIX_CELL_H +#define PM_MATRIX_CELL_H + +#include //std::swap, std::exchange & std::move +#include //std::hash + +namespace Gudhi { +namespace persistence_matrix { + +/** + * @ingroup persistence_matrix + * + * @brief Empty structure. + * Inherited instead of @ref Entry_column_index, when the row access is disabled. + */ +struct Dummy_entry_column_index_mixin +{ + Dummy_entry_column_index_mixin() {} + template + Dummy_entry_column_index_mixin([[maybe_unused]] Index columnIndex) {} +}; + +/** + * @ingroup persistence_matrix + * + * @brief Empty structure. + * Inherited instead of @ref Entry_field_element, when @ref PersistenceMatrixOptions::is_z2 is true. + */ +struct Dummy_entry_field_element_mixin +{ + Dummy_entry_field_element_mixin() {} + template + Dummy_entry_field_element_mixin([[maybe_unused]] Field_element t) {} +}; + +/** + * @ingroup persistence_matrix + * + * @brief Class managing the column index access of an entry. + * + * @tparam Index @ref MatIdx index type. + */ +template +class Entry_column_index +{ + public: + /** + * @brief Default constructor. Sets to the column index to -1. + */ + Entry_column_index() : columnIndex_(-1){}; + /** + * @brief Stores the given column index. + * + * @param columnIndex Column index of the entry. + */ + Entry_column_index(Index columnIndex) : columnIndex_(columnIndex){}; + /** + * @brief Copy constructor. + * + * @param entry Entry to copy. + */ + Entry_column_index(const Entry_column_index& entry) : columnIndex_(entry.columnIndex_){}; + /** + * @brief Move constructor. + * + * @param entry Entry to move. + */ + Entry_column_index(Entry_column_index&& entry) noexcept : columnIndex_(std::exchange(entry.columnIndex_, 0)){}; + + /** + * @brief Returns the @ref MatIdx column index stored in the entry. + * + * @return Column index of the entry. + */ + Index get_column_index() const { return columnIndex_; }; + /** + * @brief Sets the column index to the given value. + * + * @param columnIndex Column index of the entry. + */ + void set_column_index(Index columnIndex) { columnIndex_ = columnIndex; } + + /** + * @brief Assign operator. + */ + Entry_column_index& operator=(Entry_column_index other) { + std::swap(columnIndex_, other.columnIndex_); + return *this; + }; + + private: + Index columnIndex_; /**< Column index. */ +}; + +/** + * @ingroup persistence_matrix + * + * @brief Class managing the value access of an entry. + * + * @tparam Field_element Type of an entry value. + */ +template +class Entry_field_element +{ + public: + /** + * @brief Default constructor. Sets to the element to 0. + */ + Entry_field_element() : element_(0){}; + /** + * @brief Stores the given element. + * + * @param element Value to store. + */ + Entry_field_element(Field_element element) : element_(element){}; + /** + * @brief Copy constructor. + * + * @param entry Entry to copy. + */ + Entry_field_element(const Entry_field_element& entry) : element_(entry.element_){}; + /** + * @brief Move constructor. + * + * @param entry Entry to move. + */ + Entry_field_element(Entry_field_element&& entry) noexcept : element_(std::move(entry.element_)){}; + + /** + * @brief Returns the value stored in the entry. + * + * @return Reference to the value of the entry. + */ + Field_element& get_element() { return element_; }; + /** + * @brief Returns the value stored in the entry. + * + * @return Const reference to the value of the entry. + */ + const Field_element& get_element() const { return element_; }; + /** + * @brief Sets the value. + * + * @param element Value to store. + */ + void set_element(const Field_element& element) { element_ = element; } + + /** + * @brief Assign operator. + */ + Entry_field_element& operator=(Entry_field_element other) { + std::swap(element_, other.element_); + return *this; + }; + + private: + Field_element element_; /**< Value of the entry. */ +}; + +/** + * @class Entry entry_types.h gudhi/Persistence_matrix/columns/entry_types.h + * @ingroup persistence_matrix + * + * @brief %Matrix entry class. Stores by default only the row index it belongs to, but can also store its + * column index when the row access is enabled, as well as its value when they are different from only 0 and 1. + * Zero-valued entries are never made explicit in the matrix. + * + * @tparam Master_matrix An instantiation of @ref Matrix from which all types and options are deduced. + */ +template +class Entry : public Master_matrix::Entry_column_index_option, + public Master_matrix::Entry_field_element_option, + public Master_matrix::Row_hook, + public Master_matrix::Column_hook +{ + private: + using col_opt = typename Master_matrix::Entry_column_index_option; + using field_opt = typename Master_matrix::Entry_field_element_option; + + public: + using Master = Master_matrix; /**< Access to options from outside. */ + using Index = typename Master_matrix::Index; /**< Column index type. */ + using ID_index = typename Master_matrix::ID_index; /**< Row index type. */ + using Field_element = typename Master_matrix::Element; /**< Value type. */ + + /** + * @brief Constructs an entry with all attributes at default values. + */ + Entry(){}; + /** + * @brief Constructs an entry with given row index. Other possible attributes are set at default values. + * + * @param rowIndex @ref rowindex "Row index" of the entry. + */ + Entry(ID_index rowIndex) : col_opt(), field_opt(), rowIndex_(rowIndex){}; + /** + * @brief Constructs an entry with given row and column index. Other possible attributes are set at default values. + * + * @param columnIndex Column index of the entry. + * @param rowIndex @ref rowindex "Row index" of the entry. + */ + Entry(Index columnIndex, ID_index rowIndex) : col_opt(columnIndex), field_opt(), rowIndex_(rowIndex){}; + /** + * @brief Copy constructor. + * + * @param entry Entry to copy. + */ + Entry(const Entry& entry) + : col_opt(static_cast(entry)), + field_opt(static_cast(entry)), + rowIndex_(entry.rowIndex_){}; + /** + * @brief Move constructor. + * + * @param entry Entry to move. + */ + Entry(Entry&& entry) noexcept + : col_opt(std::move(static_cast(entry))), + field_opt(std::move(static_cast(entry))), + rowIndex_(std::exchange(entry.rowIndex_, 0)){}; + + /** + * @brief Returns the row index stored in the entry. + * + * @return @ref rowindex "Row index" of the entry. + */ + ID_index get_row_index() const { return rowIndex_; }; + /** + * @brief Sets the row index stored in the entry. + * + * @param rowIndex @ref rowindex "Row index" of the entry. + */ + void set_row_index(ID_index rowIndex) { rowIndex_ = rowIndex; }; + + /** + * @brief Assign operator. + */ + Entry& operator=(Entry other) { + col_opt::operator=(other); + field_opt::operator=(other); + std::swap(rowIndex_, other.rowIndex_); + return *this; + }; + + /** + * @brief Strictly smaller than comparator. + * + * @param c1 First entry to compare. + * @param c2 Second entry to compare. + * @return true If the row index of the first entry is strictly smaller than the row index of the second entry. + * @return false Otherwise. + */ + friend bool operator<(const Entry& c1, const Entry& c2) { return c1.get_row_index() < c2.get_row_index(); } + /** + * @brief Equality comparator. + * + * @param c1 First entry to compare. + * @param c2 Second entry to compare. + * @return true If the row index of the first entry is equal to the row index of the second entry. + * @return false Otherwise. + */ + friend bool operator==(const Entry& c1, const Entry& c2) { return c1.get_row_index() == c2.get_row_index(); } + + /** + * @brief Converts the entry into a row index. + * + * @return The row index of the entry. + */ + operator ID_index() const { return rowIndex_; } + /** + * @brief Converts the entry into a pair of row index and entry value. + * + * @return A std::pair with first element the row index and second element the value. + */ + operator std::pair() const { + if constexpr (Master_matrix::Option_list::is_z2) { + return {rowIndex_, 1}; + } else { + return {rowIndex_, field_opt::element_}; + } + } + + private: + ID_index rowIndex_; /**< Row index of the entry. */ +}; + +} // namespace persistence_matrix +} // namespace Gudhi + +/** + * @ingroup persistence_matrix + * + * @brief Hash method for @ref Gudhi::persistence_matrix::Entry. + * + * The entries are differentiated by their row indices only. For example, two entries with the same row index + * but different column indices have the same hash value. + * + * @tparam Master_matrix Template parameter of @ref Gudhi::persistence_matrix::Entry. + */ +template +struct std::hash > { + std::size_t operator()(const Gudhi::persistence_matrix::Entry& entry) const { + return std::hash()(entry.get_row_index()); + } +}; + +#endif // PM_MATRIX_CELL_H diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/heap_column.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/heap_column.h index 33e8558088..5a0e4dc5c2 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/heap_column.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/heap_column.h @@ -26,7 +26,7 @@ #include -#include +#include namespace Gudhi { namespace persistence_matrix { @@ -38,13 +38,13 @@ namespace persistence_matrix { * @brief Column class following the @ref PersistenceMatrixColumn concept. Not compatible with row access. * * Column based on a heap structure. The heap is represented as a vector sorted as a heap. The top of the heap is - * the cell with the biggest row index. The sum of two columns is lazy: the content of the source is simply inserted - * into the heap of the target. Therefore the underlying vector can contain several cells with the same row index. - * The real value of a cell at a row index corresponds to the sum in the coefficient field of all values with same - * row index. Additionally, the given cell range added into the heap does not need to be somehow ordered. + * the entry with the biggest row index. The sum of two columns is lazy: the content of the source is simply inserted + * into the heap of the target. Therefore the underlying vector can contain several entries with the same row index. + * The real value of an entry at a row index corresponds to the sum in the coefficient field of all values with same + * row index. Additionally, the given entry range added into the heap does not need to be somehow ordered. * * @tparam Master_matrix An instantiation of @ref Matrix from which all types and options are deduced. - * @tparam Cell_constructor Factory of @ref Cell classes. + * @tparam Entry_constructor Factory of @ref Entry classes. */ template class Heap_column : public Master_matrix::Column_dimension_option, public Master_matrix::Chain_column_option @@ -55,13 +55,13 @@ class Heap_column : public Master_matrix::Column_dimension_option, public Master using ID_index = typename Master_matrix::ID_index; using Dimension = typename Master_matrix::Dimension; using Field_element = typename Master_matrix::Element; - using Cell = typename Master_matrix::Matrix_cell; + using Entry = typename Master_matrix::Matrix_entry; using Column_settings = typename Master_matrix::Column_settings; private: using Field_operators = typename Master_matrix::Field_operators; - using Column_support = std::vector; - using Cell_constructor = typename Master_matrix::Cell_constructor; + using Column_support = std::vector; + using Entry_constructor = typename Master_matrix::Entry_constructor; public: using iterator = boost::indirect_iterator; @@ -119,19 +119,19 @@ class Heap_column : public Master_matrix::Column_dimension_option, public Master reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; - template - Heap_column& operator+=(const Cell_range& column); + template + Heap_column& operator+=(const Entry_range& column); Heap_column& operator+=(Heap_column& column); Heap_column& operator*=(unsigned int v); // this = v * this + column - template - Heap_column& multiply_target_and_add(const Field_element& val, const Cell_range& column); + template + Heap_column& multiply_target_and_add(const Field_element& val, const Entry_range& column); Heap_column& multiply_target_and_add(const Field_element& val, Heap_column& column); // this = this + column * v - template - Heap_column& multiply_source_and_add(const Cell_range& column, const Field_element& val); + template + Heap_column& multiply_source_and_add(const Entry_range& column, const Field_element& val); Heap_column& multiply_source_and_add(Heap_column& column, const Field_element& val); std::size_t compute_hash_value(); @@ -140,33 +140,33 @@ class Heap_column : public Master_matrix::Column_dimension_option, public Master if (&c1 == &c2) return true; Heap_column cc1(c1), cc2(c2); - Cell* p1 = cc1._pop_pivot(); - Cell* p2 = cc2._pop_pivot(); + Entry* p1 = cc1._pop_pivot(); + Entry* p2 = cc2._pop_pivot(); while (p1 != nullptr && p2 != nullptr) { if (p1->get_row_index() != p2->get_row_index()) { - c1.cellPool_->destroy(p1); - c2.cellPool_->destroy(p2); + c1.entryPool_->destroy(p1); + c2.entryPool_->destroy(p2); return false; } if constexpr (!Master_matrix::Option_list::is_z2) { if (p1->get_element() != p2->get_element()) { - c1.cellPool_->destroy(p1); - c2.cellPool_->destroy(p2); + c1.entryPool_->destroy(p1); + c2.entryPool_->destroy(p2); return false; } } - c1.cellPool_->destroy(p1); - c2.cellPool_->destroy(p2); + c1.entryPool_->destroy(p1); + c2.entryPool_->destroy(p2); p1 = cc1._pop_pivot(); p2 = cc2._pop_pivot(); } if (p1 == nullptr && p2 == nullptr) return true; if (p1 != nullptr) { - c1.cellPool_->destroy(p1); + c1.entryPool_->destroy(p1); return false; } - c2.cellPool_->destroy(p2); + c2.entryPool_->destroy(p2); return false; } friend bool operator<(const Heap_column& c1, const Heap_column& c2) { @@ -174,42 +174,42 @@ class Heap_column : public Master_matrix::Column_dimension_option, public Master // lexicographical order but starting from last value and not first Heap_column cc1(c1), cc2(c2); - Cell* p1 = cc1._pop_pivot(); - Cell* p2 = cc2._pop_pivot(); + Entry* p1 = cc1._pop_pivot(); + Entry* p2 = cc2._pop_pivot(); while (p1 != nullptr && p2 != nullptr) { if (p1->get_row_index() > p2->get_row_index()) { - c1.cellPool_->destroy(p1); - c2.cellPool_->destroy(p2); + c1.entryPool_->destroy(p1); + c2.entryPool_->destroy(p2); return false; } if (p1->get_row_index() < p2->get_row_index()) { - c1.cellPool_->destroy(p1); - c2.cellPool_->destroy(p2); + c1.entryPool_->destroy(p1); + c2.entryPool_->destroy(p2); return true; } if constexpr (!Master_matrix::Option_list::is_z2) { if (p1->get_element() > p2->get_element()) { - c1.cellPool_->destroy(p1); - c2.cellPool_->destroy(p2); + c1.entryPool_->destroy(p1); + c2.entryPool_->destroy(p2); return false; } if (p1->get_element() < p2->get_element()) { - c1.cellPool_->destroy(p1); - c2.cellPool_->destroy(p2); + c1.entryPool_->destroy(p1); + c2.entryPool_->destroy(p2); return true; } } - c1.cellPool_->destroy(p1); - c2.cellPool_->destroy(p2); + c1.entryPool_->destroy(p1); + c2.entryPool_->destroy(p2); p1 = cc1._pop_pivot(); p2 = cc2._pop_pivot(); } if (p2 == nullptr) { - c1.cellPool_->destroy(p1); + c1.entryPool_->destroy(p1); return false; } - c2.cellPool_->destroy(p2); + c2.entryPool_->destroy(p2); return true; } @@ -224,30 +224,30 @@ class Heap_column : public Master_matrix::Column_dimension_option, public Master col1.column_.swap(col2.column_); std::swap(col1.insertsSinceLastPrune_, col2.insertsSinceLastPrune_); std::swap(col1.operators_, col2.operators_); - std::swap(col1.cellPool_, col2.cellPool_); + std::swap(col1.entryPool_, col2.entryPool_); } private: using Dim_opt = typename Master_matrix::Column_dimension_option; using Chain_opt = typename Master_matrix::Chain_column_option; - struct CellPointerComp { - bool operator()(const Cell* c1, const Cell* c2) const { return *c1 < *c2; } - } cellPointerComp_; + struct EntryPointerComp { + bool operator()(const Entry* c1, const Entry* c2) const { return *c1 < *c2; } + } entryPointerComp_; Column_support column_; unsigned int insertsSinceLastPrune_; Field_operators* operators_; - Cell_constructor* cellPool_; + Entry_constructor* entryPool_; void _prune(); - Cell* _pop_pivot(); - template - bool _add(const Cell_range& column); - template - bool _multiply_target_and_add(const Field_element& val, const Cell_range& column); - template - bool _multiply_source_and_add(const Cell_range& column, const Field_element& val); + Entry* _pop_pivot(); + template + bool _add(const Entry_range& column); + template + bool _multiply_target_and_add(const Field_element& val, const Entry_range& column); + template + bool _multiply_source_and_add(const Entry_range& column, const Field_element& val); }; template @@ -256,7 +256,7 @@ inline Heap_column::Heap_column(Column_settings* colSettings) Chain_opt(), insertsSinceLastPrune_(0), operators_(nullptr), - cellPool_(colSettings == nullptr ? nullptr : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? nullptr : &(colSettings->entryConstructor)) { if (colSettings == nullptr) return; // to allow default constructor which gives a dummy column @@ -273,7 +273,7 @@ inline Heap_column::Heap_column(const Container& nonZeroRowIndice column_(nonZeroRowIndices.size(), nullptr), insertsSinceLastPrune_(0), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Constructor not available for chain columns, please specify the dimension of the chain."); @@ -285,15 +285,15 @@ inline Heap_column::Heap_column(const Container& nonZeroRowIndice Index i = 0; if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - column_[i++] = cellPool_->construct(id); + column_[i++] = entryPool_->construct(id); } } else { for (const auto& p : nonZeroRowIndices) { - column_[i] = cellPool_->construct(p.first); + column_[i] = entryPool_->construct(p.first); column_[i++]->set_element(operators_->get_value(p.second)); } } - std::make_heap(column_.begin(), column_.end(), cellPointerComp_); + std::make_heap(column_.begin(), column_.end(), entryPointerComp_); } template @@ -312,21 +312,21 @@ inline Heap_column::Heap_column(const Container& nonZeroRowIndice column_(nonZeroRowIndices.size(), nullptr), insertsSinceLastPrune_(0), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { Index i = 0; if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - column_[i++] = cellPool_->construct(id); + column_[i++] = entryPool_->construct(id); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - column_[i] = cellPool_->construct(p.first); + column_[i] = entryPool_->construct(p.first); column_[i++]->set_element(operators_->get_value(p.second)); } } - std::make_heap(column_.begin(), column_.end(), cellPointerComp_); + std::make_heap(column_.begin(), column_.end(), entryPointerComp_); } template @@ -336,7 +336,7 @@ inline Heap_column::Heap_column(const Heap_column& column, Column column_(column.column_.size(), nullptr), insertsSinceLastPrune_(0), operators_(colSettings == nullptr ? column.operators_ : nullptr), - cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor)) { static_assert(!Master_matrix::Option_list::has_row_access, "Simple copy constructor not available when row access option enabled. Please specify the new column " @@ -347,12 +347,12 @@ inline Heap_column::Heap_column(const Heap_column& column, Column } Index i = 0; - for (const Cell* cell : column.column_) { + for (const Entry* entry : column.column_) { if constexpr (Master_matrix::Option_list::is_z2) { - column_[i++] = cellPool_->construct(cell->get_row_index()); + column_[i++] = entryPool_->construct(entry->get_row_index()); } else { - column_[i] = cellPool_->construct(cell->get_row_index()); - column_[i++]->set_element(cell->get_element()); + column_[i] = entryPool_->construct(entry->get_row_index()); + column_[i++]->set_element(entry->get_element()); } } // column.column_ already ordered as a heap, so no need of make_heap. @@ -365,7 +365,7 @@ inline Heap_column::Heap_column(Heap_column&& column) noexcept column_(std::move(column.column_)), insertsSinceLastPrune_(std::exchange(column.insertsSinceLastPrune_, 0)), operators_(std::exchange(column.operators_, nullptr)), - cellPool_(std::exchange(column.cellPool_, nullptr)) + entryPool_(std::exchange(column.entryPool_, nullptr)) {} template @@ -385,7 +385,7 @@ inline Heap_column::Heap_column(Index columnIndex, column_(nonZeroRowIndices.size(), nullptr), insertsSinceLastPrune_(0), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Constructor not available for chain columns, please specify the dimension of the chain."); @@ -393,16 +393,16 @@ inline Heap_column::Heap_column(Index columnIndex, Index i = 0; if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - column_[i++] = cellPool_->construct(id); + column_[i++] = entryPool_->construct(id); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - column_[i] = cellPool_->construct(p.first); + column_[i] = entryPool_->construct(p.first); column_[i++]->set_element(operators_->get_value(p.second)); } } - std::make_heap(column_.begin(), column_.end(), cellPointerComp_); + std::make_heap(column_.begin(), column_.end(), entryPointerComp_); } template @@ -423,21 +423,21 @@ inline Heap_column::Heap_column(Index columnIndex, column_(nonZeroRowIndices.size(), nullptr), insertsSinceLastPrune_(0), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { Index i = 0; if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - column_[i++] = cellPool_->construct(id); + column_[i++] = entryPool_->construct(id); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - column_[i] = cellPool_->construct(p.first); + column_[i] = entryPool_->construct(p.first); column_[i++]->set_element(operators_->get_value(p.second)); } } - std::make_heap(column_.begin(), column_.end(), cellPointerComp_); + std::make_heap(column_.begin(), column_.end(), entryPointerComp_); } template @@ -451,19 +451,19 @@ inline Heap_column::Heap_column(const Heap_column& column, column_(column.column_.size(), nullptr), insertsSinceLastPrune_(0), operators_(colSettings == nullptr ? column.operators_ : nullptr), - cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor)) { if constexpr (!Master_matrix::Option_list::is_z2) { if (colSettings != nullptr) operators_ = &(colSettings->operators); } Index i = 0; - for (const Cell* cell : column.column_) { + for (const Entry* entry : column.column_) { if constexpr (Master_matrix::Option_list::is_z2) { - column_[i++] = cellPool_->construct(cell->get_row_index()); + column_[i++] = entryPool_->construct(entry->get_row_index()); } else { - column_[i] = cellPool_->construct(cell->get_row_index()); - column_[i++]->set_element(cell->get_element()); + column_[i] = entryPool_->construct(entry->get_row_index()); + column_[i++]->set_element(entry->get_element()); } } // column.column_ already ordered as a heap, so no need of make_heap. @@ -472,8 +472,8 @@ inline Heap_column::Heap_column(const Heap_column& column, template inline Heap_column::~Heap_column() { - for (auto* cell : column_) { - cellPool_->destroy(cell); + for (auto* entry : column_) { + entryPool_->destroy(entry); } } @@ -509,12 +509,12 @@ template inline bool Heap_column::is_non_zero(ID_index rowIndex) const { Field_element c(0); - for (const Cell* cell : column_) { - if (cell->get_row_index() == rowIndex) { + for (const Entry* entry : column_) { + if (entry->get_row_index() == rowIndex) { if constexpr (Master_matrix::Option_list::is_z2) c = !c; else - operators_->add_inplace(c, cell->get_element()); + operators_->add_inplace(c, entry->get_element()); } } return c != Field_operators::get_additive_identity(); @@ -523,10 +523,10 @@ inline bool Heap_column::is_non_zero(ID_index rowIndex) const template inline bool Heap_column::is_empty() { - Cell* pivot = _pop_pivot(); + Entry* pivot = _pop_pivot(); if (pivot != nullptr) { column_.push_back(pivot); - std::push_heap(column_.begin(), column_.end(), cellPointerComp_); + std::push_heap(column_.begin(), column_.end(), entryPointerComp_); return false; } return true; @@ -546,14 +546,14 @@ inline void Heap_column::reorder(const Row_index_map& valueMap, [ "Method not available for chain columns."); Column_support tempCol; - Cell* pivot = _pop_pivot(); + Entry* pivot = _pop_pivot(); while (pivot != nullptr) { pivot->set_row_index(valueMap.at(pivot->get_row_index())); tempCol.push_back(pivot); pivot = _pop_pivot(); } column_.swap(tempCol); - std::make_heap(column_.begin(), column_.end(), cellPointerComp_); + std::make_heap(column_.begin(), column_.end(), entryPointerComp_); insertsSinceLastPrune_ = 0; } @@ -564,8 +564,8 @@ inline void Heap_column::clear() static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Method not available for chain columns as a base element should not be empty."); - for (auto* cell : column_) { - cellPool_->destroy(cell); + for (auto* entry : column_) { + entryPool_->destroy(entry); } column_.clear(); @@ -579,12 +579,12 @@ inline void Heap_column::clear(ID_index rowIndex) "Method not available for chain columns."); Column_support tempCol; - Cell* pivot = _pop_pivot(); + Entry* pivot = _pop_pivot(); while (pivot != nullptr) { if (pivot->get_row_index() != rowIndex) { tempCol.push_back(pivot); } else { - cellPool_->destroy(pivot); + entryPool_->destroy(pivot); } pivot = _pop_pivot(); } @@ -600,10 +600,10 @@ inline typename Heap_column::ID_index Heap_column: "Method not available for base columns."); // could technically be, but is the notion useful then? if constexpr (Master_matrix::Option_list::is_of_boundary_type) { - Cell* pivot = _pop_pivot(); + Entry* pivot = _pop_pivot(); if (pivot != nullptr) { column_.push_back(pivot); - std::push_heap(column_.begin(), column_.end(), cellPointerComp_); + std::push_heap(column_.begin(), column_.end(), entryPointerComp_); return pivot->get_row_index(); } return -1; @@ -622,18 +622,18 @@ inline typename Heap_column::Field_element Heap_columnget_element(); } return 0; } else { Field_element sum(0); if (Chain_opt::get_pivot() == static_cast(-1)) return sum; - for (const Cell* cell : column_) { - if (cell->get_row_index() == Chain_opt::get_pivot()) operators_->add_inplace(sum, cell->get_element()); + for (const Entry* entry : column_) { + if (entry->get_row_index() == Chain_opt::get_pivot()) operators_->add_inplace(sum, entry->get_element()); } return sum; // should not be 0 if properly used. } @@ -689,10 +689,10 @@ inline typename Heap_column::const_reverse_iterator Heap_column -template -inline Heap_column& Heap_column::operator+=(const Cell_range& column) +template +inline Heap_column& Heap_column::operator+=(const Entry_range& column) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -744,8 +744,8 @@ inline Heap_column& Heap_column::operator*=(unsign if (val == Field_operators::get_multiplicative_identity()) return *this; - for (Cell* cell : column_) { - operators_->multiply_inplace(cell->get_element(), val); + for (Entry* entry : column_) { + operators_->multiply_inplace(entry->get_element(), val); } } @@ -753,11 +753,11 @@ inline Heap_column& Heap_column::operator*=(unsign } template -template +template inline Heap_column& Heap_column::multiply_target_and_add(const Field_element& val, - const Cell_range& column) + const Entry_range& column) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -815,11 +815,11 @@ inline Heap_column& Heap_column::multiply_target_a } template -template -inline Heap_column& Heap_column::multiply_source_and_add(const Cell_range& column, +template +inline Heap_column& Heap_column::multiply_source_and_add(const Entry_range& column, const Field_element& val) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -877,25 +877,25 @@ inline Heap_column& Heap_column::operator=(const H Chain_opt::operator=(other); while (column_.size() > other.column_.size()) { - if (column_.back() != nullptr) cellPool_->destroy(column_.back()); + if (column_.back() != nullptr) entryPool_->destroy(column_.back()); column_.pop_back(); } column_.resize(other.column_.size(), nullptr); Index i = 0; - for (const Cell* cell : other.column_) { + for (const Entry* entry : other.column_) { if (column_[i] != nullptr) { - cellPool_->destroy(column_[i]); + entryPool_->destroy(column_[i]); } - column_[i] = other.cellPool_->construct(cell->get_row_index()); + column_[i] = other.entryPool_->construct(entry->get_row_index()); if constexpr (!Master_matrix::Option_list::is_z2) { - column_[i]->set_element(cell->get_element()); + column_[i]->set_element(entry->get_element()); } ++i; } insertsSinceLastPrune_ = other.insertsSinceLastPrune_; operators_ = other.operators_; - cellPool_ = other.cellPool_; + entryPool_ = other.entryPool_; return *this; } @@ -913,7 +913,7 @@ inline void Heap_column::_prune() if (insertsSinceLastPrune_ == 0) return; Column_support tempCol; - Cell* pivot = _pop_pivot(); + Entry* pivot = _pop_pivot(); while (pivot != nullptr) { tempCol.push_back(pivot); pivot = _pop_pivot(); @@ -924,39 +924,39 @@ inline void Heap_column::_prune() } template -inline typename Heap_column::Cell* Heap_column::_pop_pivot() +inline typename Heap_column::Entry* Heap_column::_pop_pivot() { if (column_.empty()) { return nullptr; } - Cell* pivot = column_.front(); - std::pop_heap(column_.begin(), column_.end(), cellPointerComp_); + Entry* pivot = column_.front(); + std::pop_heap(column_.begin(), column_.end(), entryPointerComp_); column_.pop_back(); if constexpr (Master_matrix::Option_list::is_z2) { while (!column_.empty() && column_.front()->get_row_index() == pivot->get_row_index()) { - std::pop_heap(column_.begin(), column_.end(), cellPointerComp_); - cellPool_->destroy(column_.back()); + std::pop_heap(column_.begin(), column_.end(), entryPointerComp_); + entryPool_->destroy(column_.back()); column_.pop_back(); - cellPool_->destroy(pivot); + entryPool_->destroy(pivot); if (column_.empty()) { return nullptr; } pivot = column_.front(); - std::pop_heap(column_.begin(), column_.end(), cellPointerComp_); + std::pop_heap(column_.begin(), column_.end(), entryPointerComp_); column_.pop_back(); } } else { while (!column_.empty() && column_.front()->get_row_index() == pivot->get_row_index()) { operators_->add_inplace(pivot->get_element(), column_.front()->get_element()); - std::pop_heap(column_.begin(), column_.end(), cellPointerComp_); - cellPool_->destroy(column_.back()); + std::pop_heap(column_.begin(), column_.end(), entryPointerComp_); + entryPool_->destroy(column_.back()); column_.pop_back(); } if (pivot->get_element() == Field_operators::get_additive_identity()) { - cellPool_->destroy(pivot); + entryPool_->destroy(pivot); return _pop_pivot(); } } @@ -965,17 +965,17 @@ inline typename Heap_column::Cell* Heap_column::_p } template -template -inline bool Heap_column::_add(const Cell_range& column) +template +inline bool Heap_column::_add(const Entry_range& column) { if (column.begin() == column.end()) return false; if (column_.empty()) { // chain should never enter here. column_.resize(column.size()); Index i = 0; - for (const Cell& cell : column) { - column_[i] = cellPool_->construct(cell.get_row_index()); + for (const Entry& entry : column) { + column_[i] = entryPool_->construct(entry.get_row_index()); if constexpr (!Master_matrix::Option_list::is_z2) { - column_[i]->set_element(cell.get_element()); + column_[i]->set_element(entry.get_element()); } ++i; } @@ -988,21 +988,21 @@ inline bool Heap_column::_add(const Cell_range& column) if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) pivotVal = get_pivot_value(); - for (const Cell& cell : column) { + for (const Entry& entry : column) { ++insertsSinceLastPrune_; if constexpr (Master_matrix::Option_list::is_z2) { if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) { - if (cell.get_row_index() == Chain_opt::get_pivot()) pivotVal = !pivotVal; + if (entry.get_row_index() == Chain_opt::get_pivot()) pivotVal = !pivotVal; } - column_.push_back(cellPool_->construct(cell.get_row_index())); + column_.push_back(entryPool_->construct(entry.get_row_index())); } else { if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) { - if (cell.get_row_index() == Chain_opt::get_pivot()) operators_->add_inplace(pivotVal, cell.get_element()); + if (entry.get_row_index() == Chain_opt::get_pivot()) operators_->add_inplace(pivotVal, entry.get_element()); } - column_.push_back(cellPool_->construct(cell.get_row_index())); - column_.back()->set_element(cell.get_element()); + column_.push_back(entryPool_->construct(entry.get_row_index())); + column_.back()->set_element(entry.get_element()); } - std::push_heap(column_.begin(), column_.end(), cellPointerComp_); + std::push_heap(column_.begin(), column_.end(), entryPointerComp_); } if (2 * insertsSinceLastPrune_ > column_.size()) _prune(); @@ -1014,8 +1014,8 @@ inline bool Heap_column::_add(const Cell_range& column) } template -template -inline bool Heap_column::_multiply_target_and_add(const Field_element& val, const Cell_range& column) +template +inline bool Heap_column::_multiply_target_and_add(const Field_element& val, const Entry_range& column) { if (val == 0u) { if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) { @@ -1028,9 +1028,9 @@ inline bool Heap_column::_multiply_target_and_add(const Field_ele if (column_.empty()) { // chain should never enter here. column_.resize(column.size()); Index i = 0; - for (const Cell& cell : column) { - column_[i] = cellPool_->construct(cell.get_row_index()); - column_[i++]->set_element(cell.get_element()); + for (const Entry& entry : column) { + column_[i] = entryPool_->construct(entry.get_row_index()); + column_[i++]->set_element(entry.get_element()); } insertsSinceLastPrune_ = column_.size(); return true; @@ -1038,21 +1038,21 @@ inline bool Heap_column::_multiply_target_and_add(const Field_ele Field_element pivotVal(0); - for (Cell* cell : column_) { - operators_->multiply_inplace(cell->get_element(), val); + for (Entry* entry : column_) { + operators_->multiply_inplace(entry->get_element(), val); if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) { - if (cell->get_row_index() == Chain_opt::get_pivot()) operators_->add_inplace(pivotVal, cell->get_element()); + if (entry->get_row_index() == Chain_opt::get_pivot()) operators_->add_inplace(pivotVal, entry->get_element()); } } - for (const Cell& cell : column) { + for (const Entry& entry : column) { ++insertsSinceLastPrune_; if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) { - if (cell.get_row_index() == Chain_opt::get_pivot()) operators_->add_inplace(pivotVal, cell.get_element()); + if (entry.get_row_index() == Chain_opt::get_pivot()) operators_->add_inplace(pivotVal, entry.get_element()); } - column_.push_back(cellPool_->construct(cell.get_row_index())); - column_.back()->set_element(cell.get_element()); - std::push_heap(column_.begin(), column_.end(), cellPointerComp_); + column_.push_back(entryPool_->construct(entry.get_row_index())); + column_.back()->set_element(entry.get_element()); + std::push_heap(column_.begin(), column_.end(), entryPointerComp_); } if (2 * insertsSinceLastPrune_ > column_.size()) _prune(); @@ -1064,8 +1064,8 @@ inline bool Heap_column::_multiply_target_and_add(const Field_ele } template -template -inline bool Heap_column::_multiply_source_and_add(const Cell_range& column, const Field_element& val) +template +inline bool Heap_column::_multiply_source_and_add(const Entry_range& column, const Field_element& val) { if (val == 0u || column.begin() == column.end()) { return false; @@ -1073,9 +1073,9 @@ inline bool Heap_column::_multiply_source_and_add(const Cell_rang if (column_.empty()) { // chain should never enter here. column_.resize(column.size()); Index i = 0; - for (const Cell& cell : column) { - column_[i] = cellPool_->construct(cell.get_row_index()); - column_[i++]->set_element(cell.get_element()); + for (const Entry& entry : column) { + column_[i] = entryPool_->construct(entry.get_row_index()); + column_[i++]->set_element(entry.get_element()); } insertsSinceLastPrune_ = column_.size(); return true; @@ -1086,17 +1086,17 @@ inline bool Heap_column::_multiply_source_and_add(const Cell_rang if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) pivotVal = get_pivot_value(); - for (const Cell& cell : column) { + for (const Entry& entry : column) { ++insertsSinceLastPrune_; - column_.push_back(cellPool_->construct(cell.get_row_index())); - column_.back()->set_element(cell.get_element()); + column_.push_back(entryPool_->construct(entry.get_row_index())); + column_.back()->set_element(entry.get_element()); operators_->multiply_inplace(column_.back()->get_element(), val); if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) { - if (cell.get_row_index() == Chain_opt::get_pivot()) { + if (entry.get_row_index() == Chain_opt::get_pivot()) { operators_->add_inplace(pivotVal, column_.back()->get_element()); } } - std::push_heap(column_.begin(), column_.end(), cellPointerComp_); + std::push_heap(column_.begin(), column_.end(), entryPointerComp_); } if (2 * insertsSinceLastPrune_ > column_.size()) _prune(); @@ -1113,7 +1113,7 @@ inline bool Heap_column::_multiply_source_and_add(const Cell_rang * @brief Hash method for @ref Gudhi::persistence_matrix::Heap_column. * * @tparam Master_matrix Template parameter of @ref Gudhi::persistence_matrix::Heap_column. - * @tparam Cell_constructor Template parameter of @ref Gudhi::persistence_matrix::Heap_column. + * @tparam Entry_constructor Template parameter of @ref Gudhi::persistence_matrix::Heap_column. */ template struct std::hash > { diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/intrusive_list_column.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/intrusive_list_column.h index 01c6791de6..d041852a83 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/intrusive_list_column.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/intrusive_list_column.h @@ -25,7 +25,7 @@ #include -#include +#include #include namespace Gudhi { @@ -37,11 +37,11 @@ namespace persistence_matrix { * * @brief Column class following the @ref PersistenceMatrixColumn concept. * - * Column based on a intrusive list structure. The cells are always ordered by row index and only non-zero values + * Column based on a intrusive list structure. The entries are always ordered by row index and only non-zero values * are stored uniquely in the underlying container. * * @tparam Master_matrix An instantiation of @ref Matrix from which all types and options are deduced. - * @tparam Cell_constructor Factory of @ref Cell classes. + * @tparam Entry_constructor Factory of @ref Entry classes. */ template class Intrusive_list_column : public Master_matrix::Row_access_option, @@ -54,15 +54,15 @@ class Intrusive_list_column : public Master_matrix::Row_access_option, using ID_index = typename Master_matrix::ID_index; using Dimension = typename Master_matrix::Dimension; using Field_element = typename Master_matrix::Element; - using Cell = typename Master_matrix::Matrix_cell; + using Entry = typename Master_matrix::Matrix_entry; using Column_settings = typename Master_matrix::Column_settings; private: using Field_operators = typename Master_matrix::Field_operators; using Column_support = - boost::intrusive::list, + boost::intrusive::list, boost::intrusive::base_hook >; - using Cell_constructor = typename Master_matrix::Cell_constructor; + using Entry_constructor = typename Master_matrix::Entry_constructor; public: using iterator = typename Column_support::iterator; @@ -117,19 +117,19 @@ class Intrusive_list_column : public Master_matrix::Row_access_option, reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; - template - Intrusive_list_column& operator+=(const Cell_range& column); + template + Intrusive_list_column& operator+=(const Entry_range& column); Intrusive_list_column& operator+=(Intrusive_list_column& column); Intrusive_list_column& operator*=(const Field_element& val); // this = v * this + column - template - Intrusive_list_column& multiply_target_and_add(const Field_element& val, const Cell_range& column); + template + Intrusive_list_column& multiply_target_and_add(const Field_element& val, const Entry_range& column); Intrusive_list_column& multiply_target_and_add(const Field_element& val, Intrusive_list_column& column); // this = this + column * v - template - Intrusive_list_column& multiply_source_and_add(const Cell_range& column, const Field_element& val); + template + Intrusive_list_column& multiply_source_and_add(const Entry_range& column, const Field_element& val); Intrusive_list_column& multiply_source_and_add(Intrusive_list_column& column, const Field_element& val); friend bool operator==(const Intrusive_list_column& c1, const Intrusive_list_column& c2) { @@ -179,7 +179,7 @@ class Intrusive_list_column : public Master_matrix::Row_access_option, static_cast(col2)); col1.column_.swap(col2.column_); std::swap(col1.operators_, col2.operators_); - std::swap(col1.cellPool_, col2.cellPool_); + std::swap(col1.entryPool_, col2.entryPool_); } private: @@ -189,11 +189,11 @@ class Intrusive_list_column : public Master_matrix::Row_access_option, // Cloner object function for boost intrusive container struct New_cloner { - New_cloner(Cell_constructor* cellPool) : cellPool_(cellPool) {}; + New_cloner(Entry_constructor* entryPool) : entryPool_(entryPool) {}; - Cell* operator()(const Cell& clone_this) { return cellPool_->construct(clone_this); } + Entry* operator()(const Entry& clone_this) { return entryPool_->construct(clone_this); } - Cell_constructor* cellPool_; + Entry_constructor* entryPool_; }; // The disposer object function for boost intrusive container @@ -201,55 +201,55 @@ class Intrusive_list_column : public Master_matrix::Row_access_option, Delete_disposer() {}; Delete_disposer(Intrusive_list_column* col) : col_(col) {}; - void operator()(Cell* delete_this) { + void operator()(Entry* delete_this) { if constexpr (Master_matrix::Option_list::has_row_access) col_->unlink(delete_this); - col_->cellPool_->destroy(delete_this); + col_->entryPool_->destroy(delete_this); } Intrusive_list_column* col_; }; Field_operators* operators_; - Cell_constructor* cellPool_; + Entry_constructor* entryPool_; Column_support column_; - template - friend void _generic_merge_cell_to_column(Column& targetColumn, - Cell_iterator& itSource, + template + friend void _generic_merge_entry_to_column(Column& targetColumn, + Entry_iterator& itSource, typename Column::Column_support::iterator& itTarget, F1&& process_target, F2&& process_source, F3&& update_target1, F4&& update_target2, bool& pivotIsZeroed); - template - friend bool _generic_add_to_column(const Cell_range& source, + template + friend bool _generic_add_to_column(const Entry_range& source, Column& targetColumn, F1&& process_target, F2&& process_source, F3&& update_target1, F4&& update_target2, F5&& finish_target); - template - friend bool _add_to_column(const Cell_range& source, Column& targetColumn); - template + template + friend bool _add_to_column(const Entry_range& source, Column& targetColumn); + template friend bool _multiply_target_and_add_to_column(const typename Column::Field_element& val, - const Cell_range& source, + const Entry_range& source, Column& targetColumn); - template + template friend bool _multiply_source_and_add_to_column(const typename Column::Field_element& val, - const Cell_range& source, + const Entry_range& source, Column& targetColumn); - void _delete_cell(iterator& it); - Cell* _insert_cell(const Field_element& value, ID_index rowIndex, const iterator& position); - void _insert_cell(ID_index rowIndex, const iterator& position); - template - bool _add(const Cell_range& column); - template - bool _multiply_target_and_add(const Field_element& val, const Cell_range& column); - template - bool _multiply_source_and_add(const Cell_range& column, const Field_element& val); + void _delete_entry(iterator& it); + Entry* _insert_entry(const Field_element& value, ID_index rowIndex, const iterator& position); + void _insert_entry(ID_index rowIndex, const iterator& position); + template + bool _add(const Entry_range& column); + template + bool _multiply_target_and_add(const Field_element& val, const Entry_range& column); + template + bool _multiply_source_and_add(const Entry_range& column, const Field_element& val); }; template @@ -258,7 +258,7 @@ inline Intrusive_list_column::Intrusive_list_column(Column_settin Dim_opt(), Chain_opt(), operators_(nullptr), - cellPool_(colSettings == nullptr ? nullptr : &(colSettings->cellConstructor)), + entryPool_(colSettings == nullptr ? nullptr : &(colSettings->entryConstructor)), column_() { if (colSettings == nullptr) return; // to allow default constructor which gives a dummy column @@ -275,7 +275,7 @@ inline Intrusive_list_column::Intrusive_list_column(const Contain Dim_opt(nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1), Chain_opt(), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)), + entryPool_(&(colSettings->entryConstructor)), column_() { static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, @@ -283,12 +283,12 @@ inline Intrusive_list_column::Intrusive_list_column(const Contain if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _insert_cell(id, column_.end()); + _insert_entry(id, column_.end()); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _insert_cell(operators_->get_value(p.second), p.first, column_.end()); + _insert_entry(operators_->get_value(p.second), p.first, column_.end()); } } } @@ -309,7 +309,7 @@ inline Intrusive_list_column::Intrusive_list_column(Index columnI } }()), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)), + entryPool_(&(colSettings->entryConstructor)), column_() { static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, @@ -317,12 +317,12 @@ inline Intrusive_list_column::Intrusive_list_column(Index columnI if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _insert_cell(id, column_.end()); + _insert_entry(id, column_.end()); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _insert_cell(operators_->get_value(p.second), p.first, column_.end()); + _insert_entry(operators_->get_value(p.second), p.first, column_.end()); } } } @@ -342,17 +342,17 @@ inline Intrusive_list_column::Intrusive_list_column(const Contain } }()), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)), + entryPool_(&(colSettings->entryConstructor)), column_() { if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _insert_cell(id, column_.end()); + _insert_entry(id, column_.end()); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _insert_cell(operators_->get_value(p.second), p.first, column_.end()); + _insert_entry(operators_->get_value(p.second), p.first, column_.end()); } } } @@ -374,17 +374,17 @@ inline Intrusive_list_column::Intrusive_list_column(Index columnI } }()), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)), + entryPool_(&(colSettings->entryConstructor)), column_() { if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _insert_cell(id, column_.end()); + _insert_entry(id, column_.end()); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _insert_cell(operators_->get_value(p.second), p.first, column_.end()); + _insert_entry(operators_->get_value(p.second), p.first, column_.end()); } } } @@ -396,7 +396,7 @@ inline Intrusive_list_column::Intrusive_list_column(const Intrusi Dim_opt(static_cast(column)), Chain_opt(static_cast(column)), operators_(colSettings == nullptr ? column.operators_ : nullptr), - cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor)), + entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor)), column_() { static_assert(!Master_matrix::Option_list::has_row_access, @@ -406,7 +406,7 @@ inline Intrusive_list_column::Intrusive_list_column(const Intrusi if (colSettings != nullptr) operators_ = &(colSettings->operators); } - column_.clone_from(column.column_, New_cloner(cellPool_), Delete_disposer(this)); + column_.clone_from(column.column_, New_cloner(entryPool_), Delete_disposer(this)); } template @@ -419,18 +419,18 @@ inline Intrusive_list_column::Intrusive_list_column(const Intrusi Dim_opt(static_cast(column)), Chain_opt(static_cast(column)), operators_(colSettings == nullptr ? column.operators_ : nullptr), - cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor)), + entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor)), column_() { if constexpr (!Master_matrix::Option_list::is_z2) { if (colSettings != nullptr) operators_ = &(colSettings->operators); } - for (const Cell& cell : column.column_) { + for (const Entry& entry : column.column_) { if constexpr (Master_matrix::Option_list::is_z2) { - _insert_cell(cell.get_row_index(), column_.end()); + _insert_entry(entry.get_row_index(), column_.end()); } else { - _insert_cell(cell.get_element(), cell.get_row_index(), column_.end()); + _insert_entry(entry.get_element(), entry.get_row_index(), column_.end()); } } } @@ -441,7 +441,7 @@ inline Intrusive_list_column::Intrusive_list_column(Intrusive_lis Dim_opt(std::move(static_cast(column))), Chain_opt(std::move(static_cast(column))), operators_(std::exchange(column.operators_, nullptr)), - cellPool_(std::exchange(column.cellPool_, nullptr)), + entryPool_(std::exchange(column.entryPool_, nullptr)), column_(std::move(column.column_)) {} @@ -478,8 +478,8 @@ inline bool Intrusive_list_column::is_non_zero(ID_index rowIndex) // could be changed to dichotomic search as column is ordered by row index, // but I am not sure if it is really worth it as there is no random access // and the columns should not be that long anyway. - for (const Cell& cell : column_) - if (cell.get_row_index() == rowIndex) return true; + for (const Entry& entry : column_) + if (entry.get_row_index() == rowIndex) return true; return false; } @@ -505,21 +505,21 @@ inline void Intrusive_list_column::reorder(const Row_index_map& v "Method not available for chain columns."); for (auto it = column_.begin(); it != column_.end(); ++it) { - Cell* cell = &(*it); + Entry* entry = &(*it); if constexpr (Master_matrix::Option_list::has_row_access) { - RA_opt::unlink(cell); - if (columnIndex != static_cast(-1)) cell->set_column_index(columnIndex); + RA_opt::unlink(entry); + if (columnIndex != static_cast(-1)) entry->set_column_index(columnIndex); } - cell->set_row_index(valueMap.at(cell->get_row_index())); + entry->set_row_index(valueMap.at(entry->get_row_index())); if constexpr (Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access) - RA_opt::insert_cell(cell->get_row_index(), cell); + RA_opt::insert_entry(entry->get_row_index(), entry); } - // all cells have to be deleted first, to avoid problem with insertion when row is a set + // all entries have to be deleted first, to avoid problem with insertion when row is a set if constexpr (!Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access) { for (auto it = column_.begin(); it != column_.end(); ++it) { - Cell* cell = &(*it); - RA_opt::insert_cell(cell->get_row_index(), cell); + Entry* entry = &(*it); + RA_opt::insert_entry(entry->get_row_index(), entry); } } @@ -543,7 +543,7 @@ inline void Intrusive_list_column::clear(ID_index rowIndex) auto it = column_.begin(); while (it != column_.end() && it->get_row_index() != rowIndex) it++; - if (it != column_.end()) _delete_cell(it); + if (it != column_.end()) _delete_entry(it); } template @@ -575,8 +575,8 @@ Intrusive_list_column::get_pivot_value() const return column_.back().get_element(); } else { if (Chain_opt::get_pivot() == static_cast(-1)) return Field_element(); - for (const Cell& cell : column_) { - if (cell.get_row_index() == Chain_opt::get_pivot()) return cell.get_element(); + for (const Entry& entry : column_) { + if (entry.get_row_index() == Chain_opt::get_pivot()) return entry.get_element(); } return Field_element(); // should never happen if chain column is used properly } @@ -638,11 +638,11 @@ Intrusive_list_column::rend() const noexcept } template -template +template inline Intrusive_list_column& Intrusive_list_column::operator+=( - const Cell_range& column) + const Entry_range& column) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -696,9 +696,9 @@ inline Intrusive_list_column& Intrusive_list_columnmultiply_inplace(cell.get_element(), realVal); - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_cell(cell); + for (Entry& entry : column_) { + operators_->multiply_inplace(entry.get_element(), realVal); + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(entry); } } @@ -706,11 +706,11 @@ inline Intrusive_list_column& Intrusive_list_column -template +template inline Intrusive_list_column& Intrusive_list_column::multiply_target_and_add( - const Field_element& val, const Cell_range& column) + const Field_element& val, const Entry_range& column) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -768,11 +768,11 @@ inline Intrusive_list_column& Intrusive_list_column -template +template inline Intrusive_list_column& Intrusive_list_column::multiply_source_and_add( - const Cell_range& column, const Field_element& val) + const Entry_range& column, const Field_element& val) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -833,67 +833,67 @@ inline Intrusive_list_column& Intrusive_list_column -inline void Intrusive_list_column::_delete_cell(iterator& it) +inline void Intrusive_list_column::_delete_entry(iterator& it) { it = column_.erase_and_dispose(it, Delete_disposer(this)); } template -inline typename Intrusive_list_column::Cell* Intrusive_list_column::_insert_cell( +inline typename Intrusive_list_column::Entry* Intrusive_list_column::_insert_entry( const Field_element& value, ID_index rowIndex, const iterator& position) { if constexpr (Master_matrix::Option_list::has_row_access) { - Cell* newCell = cellPool_->construct(RA_opt::columnIndex_, rowIndex); - newCell->set_element(value); - column_.insert(position, *newCell); - RA_opt::insert_cell(rowIndex, newCell); - return newCell; + Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex); + newEntry->set_element(value); + column_.insert(position, *newEntry); + RA_opt::insert_entry(rowIndex, newEntry); + return newEntry; } else { - Cell* newCell = cellPool_->construct(rowIndex); - newCell->set_element(value); - column_.insert(position, *newCell); - return newCell; + Entry* newEntry = entryPool_->construct(rowIndex); + newEntry->set_element(value); + column_.insert(position, *newEntry); + return newEntry; } } template -inline void Intrusive_list_column::_insert_cell(ID_index rowIndex, const iterator& position) +inline void Intrusive_list_column::_insert_entry(ID_index rowIndex, const iterator& position) { if constexpr (Master_matrix::Option_list::has_row_access) { - Cell* newCell = cellPool_->construct(RA_opt::columnIndex_, rowIndex); - column_.insert(position, *newCell); - RA_opt::insert_cell(rowIndex, newCell); + Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex); + column_.insert(position, *newEntry); + RA_opt::insert_entry(rowIndex, newEntry); } else { - Cell* newCell = cellPool_->construct(rowIndex); - column_.insert(position, *newCell); + Entry* newEntry = entryPool_->construct(rowIndex); + column_.insert(position, *newEntry); } } template -template -inline bool Intrusive_list_column::_add(const Cell_range& column) +template +inline bool Intrusive_list_column::_add(const Entry_range& column) { return _add_to_column(column, *this); } template -template +template inline bool Intrusive_list_column::_multiply_target_and_add(const Field_element& val, - const Cell_range& column) + const Entry_range& column) { return _multiply_target_and_add_to_column(val, column, *this); } template -template -inline bool Intrusive_list_column::_multiply_source_and_add(const Cell_range& column, +template +inline bool Intrusive_list_column::_multiply_source_and_add(const Entry_range& column, const Field_element& val) { return _multiply_source_and_add_to_column(val, column, *this); @@ -908,7 +908,7 @@ inline bool Intrusive_list_column::_multiply_source_and_add(const * @brief Hash method for @ref Gudhi::persistence_matrix::Intrusive_list_column. * * @tparam Master_matrix Template parameter of @ref Gudhi::persistence_matrix::Intrusive_list_column. - * @tparam Cell_constructor Template parameter of @ref Gudhi::persistence_matrix::Intrusive_list_column. + * @tparam Entry_constructor Template parameter of @ref Gudhi::persistence_matrix::Intrusive_list_column. */ template struct std::hash > { diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/intrusive_set_column.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/intrusive_set_column.h index 983e4259ad..3d1d00d613 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/intrusive_set_column.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/intrusive_set_column.h @@ -26,7 +26,7 @@ #include #include -#include +#include #include namespace Gudhi { @@ -38,11 +38,11 @@ namespace persistence_matrix { * * @brief Column class following the @ref PersistenceMatrixColumn concept. * - * Column based on a intrusive set structure. The cells are ordered by row index and only non-zero values + * Column based on a intrusive set structure. The entries are ordered by row index and only non-zero values * are stored uniquely in the underlying container. * * @tparam Master_matrix An instantiation of @ref Matrix from which all types and options are deduced. - * @tparam Cell_constructor Factory of @ref Cell classes. + * @tparam Entry_constructor Factory of @ref Entry classes. */ template class Intrusive_set_column : public Master_matrix::Row_access_option, @@ -55,15 +55,15 @@ class Intrusive_set_column : public Master_matrix::Row_access_option, using ID_index = typename Master_matrix::ID_index; using Dimension = typename Master_matrix::Dimension; using Field_element = typename Master_matrix::Element; - using Cell = typename Master_matrix::Matrix_cell; + using Entry = typename Master_matrix::Matrix_entry; using Column_settings = typename Master_matrix::Column_settings; private: using Field_operators = typename Master_matrix::Field_operators; using Column_support = - boost::intrusive::set, + boost::intrusive::set, boost::intrusive::base_hook >; - using Cell_constructor = typename Master_matrix::Cell_constructor; + using Entry_constructor = typename Master_matrix::Entry_constructor; public: using iterator = typename Column_support::iterator; @@ -118,19 +118,19 @@ class Intrusive_set_column : public Master_matrix::Row_access_option, reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; - template - Intrusive_set_column& operator+=(const Cell_range& column); + template + Intrusive_set_column& operator+=(const Entry_range& column); Intrusive_set_column& operator+=(Intrusive_set_column& column); Intrusive_set_column& operator*=(unsigned int v); // this = v * this + column - template - Intrusive_set_column& multiply_target_and_add(const Field_element& val, const Cell_range& column); + template + Intrusive_set_column& multiply_target_and_add(const Field_element& val, const Entry_range& column); Intrusive_set_column& multiply_target_and_add(const Field_element& val, Intrusive_set_column& column); // this = this + column * v - template - Intrusive_set_column& multiply_source_and_add(const Cell_range& column, const Field_element& val); + template + Intrusive_set_column& multiply_source_and_add(const Entry_range& column, const Field_element& val); Intrusive_set_column& multiply_source_and_add(Intrusive_set_column& column, const Field_element& val); friend bool operator==(const Intrusive_set_column& c1, const Intrusive_set_column& c2) { @@ -180,7 +180,7 @@ class Intrusive_set_column : public Master_matrix::Row_access_option, static_cast(col2)); col1.column_.swap(col2.column_); std::swap(col1.operators_, col2.operators_); - std::swap(col1.cellPool_, col2.cellPool_); + std::swap(col1.entryPool_, col2.entryPool_); } private: @@ -190,11 +190,11 @@ class Intrusive_set_column : public Master_matrix::Row_access_option, // Cloner object function for boost intrusive container struct New_cloner { - New_cloner(Cell_constructor* cellPool) : cellPool_(cellPool) {}; + New_cloner(Entry_constructor* entryPool) : entryPool_(entryPool) {}; - Cell* operator()(const Cell& clone_this) { return cellPool_->construct(clone_this); } + Entry* operator()(const Entry& clone_this) { return entryPool_->construct(clone_this); } - Cell_constructor* cellPool_; + Entry_constructor* entryPool_; }; // The disposer object function for boost intrusive container @@ -202,9 +202,9 @@ class Intrusive_set_column : public Master_matrix::Row_access_option, Delete_disposer() {}; Delete_disposer(Intrusive_set_column* col) : col_(col) {}; - void operator()(Cell* delete_this) { + void operator()(Entry* delete_this) { if constexpr (Master_matrix::Option_list::has_row_access) col_->unlink(delete_this); - col_->cellPool_->destroy(delete_this); + col_->entryPool_->destroy(delete_this); } Intrusive_set_column* col_; @@ -212,45 +212,45 @@ class Intrusive_set_column : public Master_matrix::Row_access_option, Column_support column_; Field_operators* operators_; - Cell_constructor* cellPool_; - - template - friend void _generic_merge_cell_to_column(Column& targetColumn, - Cell_iterator& itSource, - typename Column::Column_support::iterator& itTarget, - F1&& process_target, - F2&& process_source, - F3&& update_target1, - F4&& update_target2, - bool& pivotIsZeroed); - template - friend bool _generic_add_to_column(const Cell_range& source, + Entry_constructor* entryPool_; + + template + friend void _generic_merge_entry_to_column(Column& targetColumn, + Entry_iterator& itSource, + typename Column::Column_support::iterator& itTarget, + F1&& process_target, + F2&& process_source, + F3&& update_target1, + F4&& update_target2, + bool& pivotIsZeroed); + template + friend bool _generic_add_to_column(const Entry_range& source, Column& targetColumn, F1&& process_target, F2&& process_source, F3&& update_target1, F4&& update_target2, F5&& finish_target); - template - friend bool _add_to_column(const Cell_range& source, Column& targetColumn); - template + template + friend bool _add_to_column(const Entry_range& source, Column& targetColumn); + template friend bool _multiply_target_and_add_to_column(const typename Column::Field_element& val, - const Cell_range& source, + const Entry_range& source, Column& targetColumn); - template + template friend bool _multiply_source_and_add_to_column(const typename Column::Field_element& val, - const Cell_range& source, + const Entry_range& source, Column& targetColumn); - void _delete_cell(iterator& it); - Cell* _insert_cell(const Field_element& value, ID_index rowIndex, const iterator& position); - void _insert_cell(ID_index rowIndex, const iterator& position); - template - bool _add(const Cell_range& column); - template - bool _multiply_target_and_add(const Field_element& val, const Cell_range& column); - template - bool _multiply_source_and_add(const Cell_range& column, const Field_element& val); + void _delete_entry(iterator& it); + Entry* _insert_entry(const Field_element& value, ID_index rowIndex, const iterator& position); + void _insert_entry(ID_index rowIndex, const iterator& position); + template + bool _add(const Entry_range& column); + template + bool _multiply_target_and_add(const Field_element& val, const Entry_range& column); + template + bool _multiply_source_and_add(const Entry_range& column, const Field_element& val); }; template @@ -259,9 +259,9 @@ inline Intrusive_set_column::Intrusive_set_column(Column_settings Dim_opt(), Chain_opt(), operators_(nullptr), - cellPool_(colSettings == nullptr ? nullptr : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? nullptr : &(colSettings->entryConstructor)) { - if (operators_ == nullptr && cellPool_ == nullptr) return; // to allow default constructor which gives a dummy column + if (operators_ == nullptr && entryPool_ == nullptr) return; // to allow default constructor which gives a dummy column if constexpr (!Master_matrix::Option_list::is_z2) { operators_ = &(colSettings->operators); } @@ -275,19 +275,19 @@ inline Intrusive_set_column::Intrusive_set_column(const Container Dim_opt(nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1), Chain_opt(), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Constructor not available for chain columns, please specify the dimension of the chain."); if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _insert_cell(id, column_.end()); + _insert_entry(id, column_.end()); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _insert_cell(operators_->get_value(p.second), p.first, column_.end()); + _insert_entry(operators_->get_value(p.second), p.first, column_.end()); } } } @@ -308,19 +308,19 @@ inline Intrusive_set_column::Intrusive_set_column(Index columnInd } }()), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Constructor not available for chain columns, please specify the dimension of the chain."); if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _insert_cell(id, column_.end()); + _insert_entry(id, column_.end()); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _insert_cell(operators_->get_value(p.second), p.first, column_.end()); + _insert_entry(operators_->get_value(p.second), p.first, column_.end()); } } } @@ -340,16 +340,16 @@ inline Intrusive_set_column::Intrusive_set_column(const Container } }()), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _insert_cell(id, column_.end()); + _insert_entry(id, column_.end()); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _insert_cell(operators_->get_value(p.second), p.first, column_.end()); + _insert_entry(operators_->get_value(p.second), p.first, column_.end()); } } } @@ -371,16 +371,16 @@ inline Intrusive_set_column::Intrusive_set_column(Index columnInd } }()), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _insert_cell(id, column_.end()); + _insert_entry(id, column_.end()); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _insert_cell(operators_->get_value(p.second), p.first, column_.end()); + _insert_entry(operators_->get_value(p.second), p.first, column_.end()); } } } @@ -392,7 +392,7 @@ inline Intrusive_set_column::Intrusive_set_column(const Intrusive Dim_opt(static_cast(column)), Chain_opt(static_cast(column)), operators_(colSettings == nullptr ? column.operators_ : nullptr), - cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor)) { static_assert(!Master_matrix::Option_list::has_row_access, "Simple copy constructor not available when row access option enabled. Please specify the new column " @@ -402,7 +402,7 @@ inline Intrusive_set_column::Intrusive_set_column(const Intrusive if (colSettings != nullptr) operators_ = &(colSettings->operators); } - column_.clone_from(column.column_, New_cloner(cellPool_), Delete_disposer(this)); + column_.clone_from(column.column_, New_cloner(entryPool_), Delete_disposer(this)); } template @@ -415,17 +415,17 @@ inline Intrusive_set_column::Intrusive_set_column(const Intrusive Dim_opt(static_cast(column)), Chain_opt(static_cast(column)), operators_(colSettings == nullptr ? column.operators_ : nullptr), - cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor)) { if constexpr (!Master_matrix::Option_list::is_z2) { if (colSettings != nullptr) operators_ = &(colSettings->operators); } - for (const Cell& cell : column.column_) { + for (const Entry& entry : column.column_) { if constexpr (Master_matrix::Option_list::is_z2) { - _insert_cell(cell.get_row_index(), column_.end()); + _insert_entry(entry.get_row_index(), column_.end()); } else { - _insert_cell(cell.get_element(), cell.get_row_index(), column_.end()); + _insert_entry(entry.get_element(), entry.get_row_index(), column_.end()); } } } @@ -437,7 +437,7 @@ inline Intrusive_set_column::Intrusive_set_column(Intrusive_set_c Chain_opt(std::move(static_cast(column))), column_(std::move(column.column_)), operators_(std::exchange(column.operators_, nullptr)), - cellPool_(std::exchange(column.cellPool_, nullptr)) + entryPool_(std::exchange(column.entryPool_, nullptr)) {} template @@ -470,7 +470,7 @@ Intrusive_set_column::get_content(int columnLength) const template inline bool Intrusive_set_column::is_non_zero(ID_index rowIndex) const { - return column_.find(Cell(rowIndex)) != column_.end(); + return column_.find(Entry(rowIndex)) != column_.end(); } template @@ -496,31 +496,31 @@ inline void Intrusive_set_column::reorder(const Row_index_map& va if constexpr (Master_matrix::Option_list::has_row_access) { for (auto it = column_.begin(); it != column_.end();) { - Cell* newCell = cellPool_->construct(columnIndex == static_cast(-1) ? RA_opt::columnIndex_ : columnIndex, - valueMap.at(it->get_row_index())); + Entry* newEntry = entryPool_->construct( + columnIndex == static_cast(-1) ? RA_opt::columnIndex_ : columnIndex, valueMap.at(it->get_row_index())); if constexpr (!Master_matrix::Option_list::is_z2) { - newCell->set_element(it->get_element()); + newEntry->set_element(it->get_element()); } - newSet.insert(newSet.end(), *newCell); - _delete_cell(it); // increases it + newSet.insert(newSet.end(), *newEntry); + _delete_entry(it); // increases it if constexpr (Master_matrix::Option_list::has_intrusive_rows) // intrusive list - RA_opt::insert_cell(newCell->get_row_index(), newCell); + RA_opt::insert_entry(newEntry->get_row_index(), newEntry); } - // when row is a set, all cells have to be deleted first, to avoid colliding when inserting + // when row is a set, all entries have to be deleted first, to avoid colliding when inserting if constexpr (!Master_matrix::Option_list::has_intrusive_rows) { // set - for (Cell& cell : newSet) { - RA_opt::insert_cell(cell.get_row_index(), &cell); + for (Entry& entry : newSet) { + RA_opt::insert_entry(entry.get_row_index(), &entry); } } } else { for (auto it = column_.begin(); it != column_.end();) { - Cell* newCell = cellPool_->construct(valueMap.at(it->get_row_index())); + Entry* newEntry = entryPool_->construct(valueMap.at(it->get_row_index())); if constexpr (!Master_matrix::Option_list::is_z2) { - newCell->set_element(it->get_element()); + newEntry->set_element(it->get_element()); } - newSet.insert(newSet.end(), *newCell); - _delete_cell(it); // increases it + newSet.insert(newSet.end(), *newEntry); + _delete_entry(it); // increases it } } @@ -542,9 +542,9 @@ inline void Intrusive_set_column::clear(ID_index rowIndex) static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Method not available for chain columns."); - auto it = column_.find(Cell(rowIndex)); + auto it = column_.find(Entry(rowIndex)); if (it != column_.end()) { - _delete_cell(it); + _delete_entry(it); } } @@ -577,7 +577,7 @@ Intrusive_set_column::get_pivot_value() const return column_.rbegin()->get_element(); } else { if (Chain_opt::get_pivot() == static_cast(-1)) return 0; - auto it = column_.find(Cell(Chain_opt::get_pivot())); + auto it = column_.find(Entry(Chain_opt::get_pivot())); GUDHI_CHECK(it != column_.end(), "Intrusive_set_column::get_pivot_value - Pivot not found only if the column was misused."); return it->get_element(); @@ -640,10 +640,10 @@ inline typename Intrusive_set_column::const_reverse_iterator Intr } template -template -inline Intrusive_set_column& Intrusive_set_column::operator+=(const Cell_range& column) +template +inline Intrusive_set_column& Intrusive_set_column::operator+=(const Entry_range& column) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -696,9 +696,9 @@ inline Intrusive_set_column& Intrusive_set_column: if (val == Field_operators::get_multiplicative_identity()) return *this; - for (Cell& cell : column_) { - operators_->multiply_inplace(cell.get_element(), val); - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_cell(cell); + for (Entry& entry : column_) { + operators_->multiply_inplace(entry.get_element(), val); + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(entry); } } @@ -706,11 +706,11 @@ inline Intrusive_set_column& Intrusive_set_column: } template -template +template inline Intrusive_set_column& Intrusive_set_column::multiply_target_and_add( - const Field_element& val, const Cell_range& column) + const Field_element& val, const Entry_range& column) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -768,11 +768,11 @@ inline Intrusive_set_column& Intrusive_set_column: } template -template +template inline Intrusive_set_column& Intrusive_set_column::multiply_source_and_add( - const Cell_range& column, const Field_element& val) + const Entry_range& column, const Field_element& val) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -833,67 +833,67 @@ inline Intrusive_set_column& Intrusive_set_column: // order is important column_.clear_and_dispose(Delete_disposer(this)); operators_ = other.operators_; - cellPool_ = other.cellPool_; - column_.clone_from(other.column_, New_cloner(cellPool_), Delete_disposer(this)); + entryPool_ = other.entryPool_; + column_.clone_from(other.column_, New_cloner(entryPool_), Delete_disposer(this)); return *this; } template -inline void Intrusive_set_column::_delete_cell(iterator& it) +inline void Intrusive_set_column::_delete_entry(iterator& it) { it = column_.erase_and_dispose(it, Delete_disposer(this)); } template -inline typename Intrusive_set_column::Cell* Intrusive_set_column::_insert_cell( +inline typename Intrusive_set_column::Entry* Intrusive_set_column::_insert_entry( const Field_element& value, ID_index rowIndex, const iterator& position) { if constexpr (Master_matrix::Option_list::has_row_access) { - Cell* newCell = cellPool_->construct(RA_opt::columnIndex_, rowIndex); - newCell->set_element(value); - column_.insert(position, *newCell); - RA_opt::insert_cell(rowIndex, newCell); - return newCell; + Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex); + newEntry->set_element(value); + column_.insert(position, *newEntry); + RA_opt::insert_entry(rowIndex, newEntry); + return newEntry; } else { - Cell* newCell = cellPool_->construct(rowIndex); - newCell->set_element(value); - column_.insert(position, *newCell); - return newCell; + Entry* newEntry = entryPool_->construct(rowIndex); + newEntry->set_element(value); + column_.insert(position, *newEntry); + return newEntry; } } template -inline void Intrusive_set_column::_insert_cell(ID_index rowIndex, const iterator& position) +inline void Intrusive_set_column::_insert_entry(ID_index rowIndex, const iterator& position) { if constexpr (Master_matrix::Option_list::has_row_access) { - Cell* newCell = cellPool_->construct(RA_opt::columnIndex_, rowIndex); - column_.insert(position, *newCell); - RA_opt::insert_cell(rowIndex, newCell); + Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex); + column_.insert(position, *newEntry); + RA_opt::insert_entry(rowIndex, newEntry); } else { - Cell* newCell = cellPool_->construct(rowIndex); - column_.insert(position, *newCell); + Entry* newEntry = entryPool_->construct(rowIndex); + column_.insert(position, *newEntry); } } template -template -inline bool Intrusive_set_column::_add(const Cell_range& column) +template +inline bool Intrusive_set_column::_add(const Entry_range& column) { return _add_to_column(column, *this); } template -template +template inline bool Intrusive_set_column::_multiply_target_and_add(const Field_element& val, - const Cell_range& column) + const Entry_range& column) { return _multiply_target_and_add_to_column(val, column, *this); } template -template -inline bool Intrusive_set_column::_multiply_source_and_add(const Cell_range& column, +template +inline bool Intrusive_set_column::_multiply_source_and_add(const Entry_range& column, const Field_element& val) { return _multiply_source_and_add_to_column(val, column, *this); @@ -908,7 +908,7 @@ inline bool Intrusive_set_column::_multiply_source_and_add(const * @brief Hash method for @ref Gudhi::persistence_matrix::Intrusive_set_column. * * @tparam Master_matrix Template parameter of @ref Gudhi::persistence_matrix::Intrusive_set_column. - * @tparam Cell_constructor Template parameter of @ref Gudhi::persistence_matrix::Intrusive_set_column. + * @tparam Entry_constructor Template parameter of @ref Gudhi::persistence_matrix::Intrusive_set_column. */ template struct std::hash > { diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/list_column.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/list_column.h index f795d87a83..f21827a725 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/list_column.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/list_column.h @@ -26,7 +26,7 @@ #include -#include +#include #include namespace Gudhi { @@ -38,11 +38,11 @@ namespace persistence_matrix { * * @brief Column class following the @ref PersistenceMatrixColumn concept. * - * Column based on a list structure. The cells are always ordered by row index and only non-zero values + * Column based on a list structure. The entries are always ordered by row index and only non-zero values * are stored uniquely in the underlying container. * * @tparam Master_matrix An instantiation of @ref Matrix from which all types and options are deduced. - * @tparam Cell_constructor Factory of @ref Cell classes. + * @tparam Entry_constructor Factory of @ref Entry classes. */ template class List_column : public Master_matrix::Row_access_option, @@ -55,13 +55,13 @@ class List_column : public Master_matrix::Row_access_option, using ID_index = typename Master_matrix::ID_index; using Dimension = typename Master_matrix::Dimension; using Field_element = typename Master_matrix::Element; - using Cell = typename Master_matrix::Matrix_cell; + using Entry = typename Master_matrix::Matrix_entry; using Column_settings = typename Master_matrix::Column_settings; private: using Field_operators = typename Master_matrix::Field_operators; - using Column_support = std::list; - using Cell_constructor = typename Master_matrix::Cell_constructor; + using Column_support = std::list; + using Entry_constructor = typename Master_matrix::Entry_constructor; public: using iterator = boost::indirect_iterator; @@ -116,19 +116,19 @@ class List_column : public Master_matrix::Row_access_option, reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; - template - List_column& operator+=(const Cell_range& column); + template + List_column& operator+=(const Entry_range& column); List_column& operator+=(List_column& column); List_column& operator*=(unsigned int v); // this = v * this + column - template - List_column& multiply_target_and_add(const Field_element& val, const Cell_range& column); + template + List_column& multiply_target_and_add(const Field_element& val, const Entry_range& column); List_column& multiply_target_and_add(const Field_element& val, List_column& column); // this = this + column * v - template - List_column& multiply_source_and_add(const Cell_range& column, const Field_element& val); + template + List_column& multiply_source_and_add(const Entry_range& column, const Field_element& val); List_column& multiply_source_and_add(List_column& column, const Field_element& val); friend bool operator==(const List_column& c1, const List_column& c2) { @@ -177,7 +177,7 @@ class List_column : public Master_matrix::Row_access_option, static_cast(col2)); col1.column_.swap(col2.column_); std::swap(col1.operators_, col2.operators_); - std::swap(col1.cellPool_, col2.cellPool_); + std::swap(col1.entryPool_, col2.entryPool_); } private: @@ -187,47 +187,47 @@ class List_column : public Master_matrix::Row_access_option, Column_support column_; Field_operators* operators_; - Cell_constructor* cellPool_; - - template - friend void _generic_merge_cell_to_column(Column& targetColumn, - Cell_iterator& itSource, - typename Column::Column_support::iterator& itTarget, - F1&& process_target, - F2&& process_source, - F3&& update_target1, - F4&& update_target2, - bool& pivotIsZeroed); - template - friend bool _generic_add_to_column(const Cell_range& source, + Entry_constructor* entryPool_; + + template + friend void _generic_merge_entry_to_column(Column& targetColumn, + Entry_iterator& itSource, + typename Column::Column_support::iterator& itTarget, + F1&& process_target, + F2&& process_source, + F3&& update_target1, + F4&& update_target2, + bool& pivotIsZeroed); + template + friend bool _generic_add_to_column(const Entry_range& source, Column& targetColumn, F1&& process_target, F2&& process_source, F3&& update_target1, F4&& update_target2, F5&& finish_target); - template - friend bool _add_to_column(const Cell_range& source, Column& targetColumn); - template + template + friend bool _add_to_column(const Entry_range& source, Column& targetColumn); + template friend bool _multiply_target_and_add_to_column(const typename Column::Field_element& val, - const Cell_range& source, + const Entry_range& source, Column& targetColumn); - template + template friend bool _multiply_source_and_add_to_column(const typename Column::Field_element& val, - const Cell_range& source, + const Entry_range& source, Column& targetColumn); - void _delete_cell(typename Column_support::iterator& it); - Cell* _insert_cell(const Field_element& value, ID_index rowIndex, const typename Column_support::iterator& position); - void _insert_cell(ID_index rowIndex, const typename Column_support::iterator& position); - void _update_cell(const Field_element& value, ID_index rowIndex, const typename Column_support::iterator& position); - void _update_cell(ID_index rowIndex, const typename Column_support::iterator& position); - template - bool _add(const Cell_range& column); - template - bool _multiply_target_and_add(const Field_element& val, const Cell_range& column); - template - bool _multiply_source_and_add(const Cell_range& column, const Field_element& val); + void _delete_entry(typename Column_support::iterator& it); + Entry* _insert_entry(const Field_element& value, ID_index rowIndex, const typename Column_support::iterator& position); + void _insert_entry(ID_index rowIndex, const typename Column_support::iterator& position); + void _update_entry(const Field_element& value, ID_index rowIndex, const typename Column_support::iterator& position); + void _update_entry(ID_index rowIndex, const typename Column_support::iterator& position); + template + bool _add(const Entry_range& column); + template + bool _multiply_target_and_add(const Field_element& val, const Entry_range& column); + template + bool _multiply_source_and_add(const Entry_range& column, const Field_element& val); }; template @@ -236,9 +236,9 @@ inline List_column::List_column(Column_settings* colSettings) Dim_opt(), Chain_opt(), operators_(nullptr), - cellPool_(colSettings == nullptr ? nullptr : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? nullptr : &(colSettings->entryConstructor)) { - if (operators_ == nullptr && cellPool_ == nullptr) return; // to allow default constructor which gives a dummy column + if (operators_ == nullptr && entryPool_ == nullptr) return; // to allow default constructor which gives a dummy column if constexpr (!Master_matrix::Option_list::is_z2) { operators_ = &(colSettings->operators); } @@ -252,7 +252,7 @@ inline List_column::List_column(const Container& nonZeroRowIndice Chain_opt(), column_(nonZeroRowIndices.size()), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Constructor not available for chain columns, please specify the dimension of the chain."); @@ -260,12 +260,12 @@ inline List_column::List_column(const Container& nonZeroRowIndice auto it = column_.begin(); if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _update_cell(id, it++); + _update_entry(id, it++); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _update_cell(operators_->get_value(p.second), p.first, it++); + _update_entry(operators_->get_value(p.second), p.first, it++); } } } @@ -287,7 +287,7 @@ inline List_column::List_column(Index columnIndex, }()), column_(nonZeroRowIndices.size()), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Constructor not available for chain columns, please specify the dimension of the chain."); @@ -295,12 +295,12 @@ inline List_column::List_column(Index columnIndex, auto it = column_.begin(); if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _update_cell(id, it++); + _update_entry(id, it++); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _update_cell(operators_->get_value(p.second), p.first, it++); + _update_entry(operators_->get_value(p.second), p.first, it++); } } } @@ -321,17 +321,17 @@ inline List_column::List_column(const Container& nonZeroRowIndice }()), column_(nonZeroRowIndices.size()), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { auto it = column_.begin(); if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _update_cell(id, it++); + _update_entry(id, it++); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _update_cell(operators_->get_value(p.second), p.first, it++); + _update_entry(operators_->get_value(p.second), p.first, it++); } } } @@ -354,17 +354,17 @@ inline List_column::List_column(Index columnIndex, }()), column_(nonZeroRowIndices.size()), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { auto it = column_.begin(); if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _update_cell(id, it++); + _update_entry(id, it++); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _update_cell(operators_->get_value(p.second), p.first, it++); + _update_entry(operators_->get_value(p.second), p.first, it++); } } } @@ -376,7 +376,7 @@ inline List_column::List_column(const List_column& column, Column Chain_opt(static_cast(column)), column_(column.column_.size()), operators_(colSettings == nullptr ? column.operators_ : nullptr), - cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor)) { static_assert(!Master_matrix::Option_list::has_row_access, "Simple copy constructor not available when row access option enabled. Please specify the new column " @@ -387,11 +387,11 @@ inline List_column::List_column(const List_column& column, Column } auto it = column_.begin(); - for (const Cell* cell : column.column_) { + for (const Entry* entry : column.column_) { if constexpr (Master_matrix::Option_list::is_z2) { - _update_cell(cell->get_row_index(), it++); + _update_entry(entry->get_row_index(), it++); } else { - _update_cell(cell->get_element(), cell->get_row_index(), it++); + _update_entry(entry->get_element(), entry->get_row_index(), it++); } } } @@ -407,18 +407,18 @@ inline List_column::List_column(const List_column& column, Chain_opt(static_cast(column)), column_(column.column_.size()), operators_(colSettings == nullptr ? column.operators_ : nullptr), - cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor)) { if constexpr (!Master_matrix::Option_list::is_z2) { if (colSettings != nullptr) operators_ = &(colSettings->operators); } auto it = column_.begin(); - for (const Cell* cell : column.column_) { + for (const Entry* entry : column.column_) { if constexpr (Master_matrix::Option_list::is_z2) { - _update_cell(cell->get_row_index(), it++); + _update_entry(entry->get_row_index(), it++); } else { - _update_cell(cell->get_element(), cell->get_row_index(), it++); + _update_entry(entry->get_element(), entry->get_row_index(), it++); } } } @@ -430,14 +430,14 @@ inline List_column::List_column(List_column&& column) noexcept Chain_opt(std::move(static_cast(column))), column_(std::move(column.column_)), operators_(std::exchange(column.operators_, nullptr)), - cellPool_(std::exchange(column.cellPool_, nullptr)) + entryPool_(std::exchange(column.entryPool_, nullptr)) {} template inline List_column::~List_column() { - for (auto* cell : column_) { - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(cell); - cellPool_->destroy(cell); + for (auto* entry : column_) { + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry); + entryPool_->destroy(entry); } } @@ -468,8 +468,8 @@ inline bool List_column::is_non_zero(ID_index rowIndex) const // could be changed to dichotomic search as column is ordered by row index, // but I am not sure if it is really worth it as there is no random access // and the columns should not be that long anyway. - for (const Cell* cell : column_) - if (cell->get_row_index() == rowIndex) return true; + for (const Entry* entry : column_) + if (entry->get_row_index() == rowIndex) return true; return false; } @@ -494,25 +494,25 @@ inline void List_column::reorder(const Row_index_map& valueMap, [ "Method not available for chain columns."); for (auto it = column_.begin(); it != column_.end(); ++it) { - Cell* cell = *it; + Entry* entry = *it; if constexpr (Master_matrix::Option_list::has_row_access) { - RA_opt::unlink(cell); - if (columnIndex != static_cast(-1)) cell->set_column_index(columnIndex); + RA_opt::unlink(entry); + if (columnIndex != static_cast(-1)) entry->set_column_index(columnIndex); } - cell->set_row_index(valueMap.at(cell->get_row_index())); + entry->set_row_index(valueMap.at(entry->get_row_index())); if constexpr (Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access) - RA_opt::insert_cell(cell->get_row_index(), cell); + RA_opt::insert_entry(entry->get_row_index(), entry); } - // all cells have to be deleted first, to avoid problem with insertion when row is a set + // all entries have to be deleted first, to avoid problem with insertion when row is a set if constexpr (!Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access) { for (auto it = column_.begin(); it != column_.end(); ++it) { - Cell* cell = *it; - RA_opt::insert_cell(cell->get_row_index(), cell); + Entry* entry = *it; + RA_opt::insert_entry(entry->get_row_index(), entry); } } - column_.sort([](const Cell* c1, const Cell* c2) { return *c1 < *c2; }); + column_.sort([](const Entry* c1, const Entry* c2) { return *c1 < *c2; }); } template @@ -521,9 +521,9 @@ inline void List_column::clear() static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Method not available for chain columns as a base element should not be empty."); - for (auto* cell : column_) { - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(cell); - cellPool_->destroy(cell); + for (auto* entry : column_) { + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry); + entryPool_->destroy(entry); } column_.clear(); @@ -537,7 +537,7 @@ inline void List_column::clear(ID_index rowIndex) auto it = column_.begin(); while (it != column_.end() && (*it)->get_row_index() != rowIndex) it++; - if (it != column_.end()) _delete_cell(it); + if (it != column_.end()) _delete_entry(it); } template @@ -568,8 +568,8 @@ inline typename List_column::Field_element List_columnget_element(); } else { if (Chain_opt::get_pivot() == static_cast(-1)) return Field_element(); - for (const Cell* cell : column_) { - if (cell->get_row_index() == Chain_opt::get_pivot()) return cell->get_element(); + for (const Entry* entry : column_) { + if (entry->get_row_index() == Chain_opt::get_pivot()) return entry->get_element(); } return Field_element(); // should never happen if chain column is used properly } @@ -625,10 +625,10 @@ inline typename List_column::const_reverse_iterator List_column -template -inline List_column& List_column::operator+=(const Cell_range& column) +template +inline List_column& List_column::operator+=(const Entry_range& column) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -680,9 +680,9 @@ inline List_column& List_column::operator*=(unsign if (val == 1u) return *this; - for (Cell* cell : column_) { - operators_->multiply_inplace(cell->get_element(), val); - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_cell(*cell); + for (Entry* entry : column_) { + operators_->multiply_inplace(entry->get_element(), val); + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(*entry); } } @@ -690,11 +690,11 @@ inline List_column& List_column::operator*=(unsign } template -template +template inline List_column& List_column::multiply_target_and_add(const Field_element& val, - const Cell_range& column) + const Entry_range& column) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -752,11 +752,11 @@ inline List_column& List_column::multiply_target_a } template -template -inline List_column& List_column::multiply_source_and_add(const Cell_range& column, +template +inline List_column& List_column::multiply_source_and_add(const Entry_range& column, const Field_element& val) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -813,8 +813,8 @@ inline List_column& List_column::operator=(const L Dim_opt::operator=(other); Chain_opt::operator=(other); - auto tmpPool = cellPool_; - cellPool_ = other.cellPool_; + auto tmpPool = entryPool_; + entryPool_ = other.entryPool_; while (column_.size() > other.column_.size()) { if (column_.back() != nullptr) { @@ -826,15 +826,15 @@ inline List_column& List_column::operator=(const L column_.resize(other.column_.size(), nullptr); auto it = column_.begin(); - for (const Cell* cell : other.column_) { + for (const Entry* entry : other.column_) { if (*it != nullptr) { if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(*it); tmpPool->destroy(*it); } if constexpr (Master_matrix::Option_list::is_z2) { - _update_cell(cell->get_row_index(), it++); + _update_entry(entry->get_row_index(), it++); } else { - _update_cell(cell->get_element(), cell->get_row_index(), it++); + _update_entry(entry->get_element(), entry->get_row_index(), it++); } } @@ -844,85 +844,85 @@ inline List_column& List_column::operator=(const L } template -inline void List_column::_delete_cell(typename Column_support::iterator& it) +inline void List_column::_delete_entry(typename Column_support::iterator& it) { if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(*it); - cellPool_->destroy(*it); + entryPool_->destroy(*it); it = column_.erase(it); } template -inline typename List_column::Cell* List_column::_insert_cell( +inline typename List_column::Entry* List_column::_insert_entry( const Field_element& value, ID_index rowIndex, const typename Column_support::iterator& position) { if constexpr (Master_matrix::Option_list::has_row_access) { - Cell* newCell = cellPool_->construct(RA_opt::columnIndex_, rowIndex); - newCell->set_element(value); - column_.insert(position, newCell); - RA_opt::insert_cell(rowIndex, newCell); - return newCell; + Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex); + newEntry->set_element(value); + column_.insert(position, newEntry); + RA_opt::insert_entry(rowIndex, newEntry); + return newEntry; } else { - Cell* newCell = cellPool_->construct(rowIndex); - newCell->set_element(value); - column_.insert(position, newCell); - return newCell; + Entry* newEntry = entryPool_->construct(rowIndex); + newEntry->set_element(value); + column_.insert(position, newEntry); + return newEntry; } } template -inline void List_column::_insert_cell(ID_index rowIndex, - const typename Column_support::iterator& position) +inline void List_column::_insert_entry(ID_index rowIndex, + const typename Column_support::iterator& position) { if constexpr (Master_matrix::Option_list::has_row_access) { - Cell* newCell = cellPool_->construct(RA_opt::columnIndex_, rowIndex); - column_.insert(position, newCell); - RA_opt::insert_cell(rowIndex, newCell); + Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex); + column_.insert(position, newEntry); + RA_opt::insert_entry(rowIndex, newEntry); } else { - Cell* newCell = cellPool_->construct(rowIndex); - column_.insert(position, newCell); + Entry* newEntry = entryPool_->construct(rowIndex); + column_.insert(position, newEntry); } } template -inline void List_column::_update_cell(const Field_element& value, - ID_index rowIndex, - const typename Column_support::iterator& position) +inline void List_column::_update_entry(const Field_element& value, + ID_index rowIndex, + const typename Column_support::iterator& position) { if constexpr (Master_matrix::Option_list::has_row_access) { - *position = cellPool_->construct(RA_opt::columnIndex_, rowIndex); + *position = entryPool_->construct(RA_opt::columnIndex_, rowIndex); (*position)->set_element(value); - RA_opt::insert_cell(rowIndex, *position); + RA_opt::insert_entry(rowIndex, *position); } else { - *position = cellPool_->construct(rowIndex); + *position = entryPool_->construct(rowIndex); (*position)->set_element(value); } } template -inline void List_column::_update_cell(ID_index rowIndex, - const typename Column_support::iterator& position) +inline void List_column::_update_entry(ID_index rowIndex, + const typename Column_support::iterator& position) { if constexpr (Master_matrix::Option_list::has_row_access) { - *position = cellPool_->construct(RA_opt::columnIndex_, rowIndex); - RA_opt::insert_cell(rowIndex, *position); + *position = entryPool_->construct(RA_opt::columnIndex_, rowIndex); + RA_opt::insert_entry(rowIndex, *position); } else { - *position = cellPool_->construct(rowIndex); + *position = entryPool_->construct(rowIndex); } } template -template -inline bool List_column::_add(const Cell_range& column) +template +inline bool List_column::_add(const Entry_range& column) { if (column.begin() == column.end()) return false; if (column_.empty()) { // chain should never enter here. column_.resize(column.size()); auto it = column_.begin(); - for (const Cell& cell : column) { + for (const Entry& entry : column) { if constexpr (Master_matrix::Option_list::is_z2) { - _update_cell(cell.get_row_index(), it++); + _update_entry(entry.get_row_index(), it++); } else { - _update_cell(cell.get_element(), cell.get_row_index(), it++); + _update_entry(entry.get_element(), entry.get_row_index(), it++); } } return true; @@ -932,15 +932,15 @@ inline bool List_column::_add(const Cell_range& column) } template -template -inline bool List_column::_multiply_target_and_add(const Field_element& val, const Cell_range& column) +template +inline bool List_column::_multiply_target_and_add(const Field_element& val, const Entry_range& column) { return _multiply_target_and_add_to_column(val, column, *this); } template -template -inline bool List_column::_multiply_source_and_add(const Cell_range& column, const Field_element& val) +template +inline bool List_column::_multiply_source_and_add(const Entry_range& column, const Field_element& val) { return _multiply_source_and_add_to_column(val, column, *this); } @@ -954,7 +954,7 @@ inline bool List_column::_multiply_source_and_add(const Cell_rang * @brief Hash method for @ref Gudhi::persistence_matrix::List_column. * * @tparam Master_matrix Template parameter of @ref Gudhi::persistence_matrix::List_column. - * @tparam Cell_constructor Template parameter of @ref Gudhi::persistence_matrix::List_column. + * @tparam Entry_constructor Template parameter of @ref Gudhi::persistence_matrix::List_column. */ template struct std::hash > { diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/naive_vector_column.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/naive_vector_column.h index 9a7bb6bbc8..e91484b31f 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/naive_vector_column.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/naive_vector_column.h @@ -26,7 +26,7 @@ #include -#include +#include #include namespace Gudhi { @@ -38,11 +38,11 @@ namespace persistence_matrix { * * @brief Column class following the @ref PersistenceMatrixColumn concept. * - * Column based on a vector structure. The cells are always ordered by row index and only non-zero values + * Column based on a vector structure. The entries are always ordered by row index and only non-zero values * are stored uniquely in the underlying container. * * @tparam Master_matrix An instantiation of @ref Matrix from which all types and options are deduced. - * @tparam Cell_constructor Factory of @ref Cell classes. + * @tparam Entry_constructor Factory of @ref Entry classes. */ template class Naive_vector_column : public Master_matrix::Row_access_option, @@ -55,13 +55,13 @@ class Naive_vector_column : public Master_matrix::Row_access_option, using ID_index = typename Master_matrix::ID_index; using Dimension = typename Master_matrix::Dimension; using Field_element = typename Master_matrix::Element; - using Cell = typename Master_matrix::Matrix_cell; + using Entry = typename Master_matrix::Matrix_entry; using Column_settings = typename Master_matrix::Column_settings; private: using Field_operators = typename Master_matrix::Field_operators; - using Column_support = std::vector; - using Cell_constructor = typename Master_matrix::Cell_constructor; + using Column_support = std::vector; + using Entry_constructor = typename Master_matrix::Entry_constructor; public: using iterator = boost::indirect_iterator; @@ -116,19 +116,19 @@ class Naive_vector_column : public Master_matrix::Row_access_option, reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; - template - Naive_vector_column& operator+=(const Cell_range& column); + template + Naive_vector_column& operator+=(const Entry_range& column); Naive_vector_column& operator+=(Naive_vector_column& column); Naive_vector_column& operator*=(unsigned int v); // this = v * this + column - template - Naive_vector_column& multiply_target_and_add(const Field_element& val, const Cell_range& column); + template + Naive_vector_column& multiply_target_and_add(const Field_element& val, const Entry_range& column); Naive_vector_column& multiply_target_and_add(const Field_element& val, Naive_vector_column& column); // this = this + column * v - template - Naive_vector_column& multiply_source_and_add(const Cell_range& column, const Field_element& val); + template + Naive_vector_column& multiply_source_and_add(const Entry_range& column, const Field_element& val); Naive_vector_column& multiply_source_and_add(Naive_vector_column& column, const Field_element& val); friend bool operator==(const Naive_vector_column& c1, const Naive_vector_column& c2) { @@ -177,7 +177,7 @@ class Naive_vector_column : public Master_matrix::Row_access_option, static_cast(col2)); col1.column_.swap(col2.column_); std::swap(col1.operators_, col2.operators_); - std::swap(col1.cellPool_, col2.cellPool_); + std::swap(col1.entryPool_, col2.entryPool_); } private: @@ -187,19 +187,19 @@ class Naive_vector_column : public Master_matrix::Row_access_option, Column_support column_; Field_operators* operators_; - Cell_constructor* cellPool_; - - template - friend void _generic_merge_cell_to_column(Column& targetColumn, - Cell_iterator& itSource, - typename Column::Column_support::iterator& itTarget, - F1&& process_target, - F2&& process_source, - F3&& update_target1, - F4&& update_target2, - bool& pivotIsZeroed); - template - friend bool _generic_add_to_column(const Cell_range& source, + Entry_constructor* entryPool_; + + template + friend void _generic_merge_entry_to_column(Column& targetColumn, + Entry_iterator& itSource, + typename Column::Column_support::iterator& itTarget, + F1&& process_target, + F2&& process_source, + F3&& update_target1, + F4&& update_target2, + bool& pivotIsZeroed); + template + friend bool _generic_add_to_column(const Entry_range& source, Column& targetColumn, F1&& process_target, F2&& process_source, @@ -207,18 +207,18 @@ class Naive_vector_column : public Master_matrix::Row_access_option, F4&& update_target2, F5&& finish_target); - void _delete_cell(Cell* cell); - void _delete_cell(typename Column_support::iterator& it); - Cell* _insert_cell(const Field_element& value, ID_index rowIndex, Column_support& column); - void _insert_cell(ID_index rowIndex, Column_support& column); - void _update_cell(const Field_element& value, ID_index rowIndex, Index position); - void _update_cell(ID_index rowIndex, Index position); - template - bool _add(const Cell_range& column); - template - bool _multiply_target_and_add(const Field_element& val, const Cell_range& column); - template - bool _multiply_source_and_add(const Cell_range& column, const Field_element& val); + void _delete_entry(Entry* entry); + void _delete_entry(typename Column_support::iterator& it); + Entry* _insert_entry(const Field_element& value, ID_index rowIndex, Column_support& column); + void _insert_entry(ID_index rowIndex, Column_support& column); + void _update_entry(const Field_element& value, ID_index rowIndex, Index position); + void _update_entry(ID_index rowIndex, Index position); + template + bool _add(const Entry_range& column); + template + bool _multiply_target_and_add(const Field_element& val, const Entry_range& column); + template + bool _multiply_source_and_add(const Entry_range& column, const Field_element& val); }; template @@ -227,9 +227,9 @@ inline Naive_vector_column::Naive_vector_column(Column_settings* Dim_opt(), Chain_opt(), operators_(nullptr), - cellPool_(colSettings == nullptr ? nullptr : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? nullptr : &(colSettings->entryConstructor)) { - if (operators_ == nullptr && cellPool_ == nullptr) return; // to allow default constructor which gives a dummy column + if (operators_ == nullptr && entryPool_ == nullptr) return; // to allow default constructor which gives a dummy column if constexpr (!Master_matrix::Option_list::is_z2) { operators_ = &(colSettings->operators); } @@ -244,7 +244,7 @@ inline Naive_vector_column::Naive_vector_column(const Container& Chain_opt(), column_(nonZeroRowIndices.size(), nullptr), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Constructor not available for chain columns, please specify the dimension of the chain."); @@ -252,12 +252,12 @@ inline Naive_vector_column::Naive_vector_column(const Container& Index i = 0; if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _update_cell(id, i++); + _update_entry(id, i++); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _update_cell(operators_->get_value(p.second), p.first, i++); + _update_entry(operators_->get_value(p.second), p.first, i++); } } } @@ -279,7 +279,7 @@ inline Naive_vector_column::Naive_vector_column(Index columnIndex }()), column_(nonZeroRowIndices.size(), nullptr), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Constructor not available for chain columns, please specify the dimension of the chain."); @@ -287,12 +287,12 @@ inline Naive_vector_column::Naive_vector_column(Index columnIndex Index i = 0; if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _update_cell(id, i++); + _update_entry(id, i++); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _update_cell(operators_->get_value(p.second), p.first, i++); + _update_entry(operators_->get_value(p.second), p.first, i++); } } } @@ -313,17 +313,17 @@ inline Naive_vector_column::Naive_vector_column(const Container& }()), column_(nonZeroRowIndices.size(), nullptr), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { Index i = 0; if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _update_cell(id, i++); + _update_entry(id, i++); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _update_cell(operators_->get_value(p.second), p.first, i++); + _update_entry(operators_->get_value(p.second), p.first, i++); } } } @@ -346,17 +346,17 @@ inline Naive_vector_column::Naive_vector_column(Index columnIndex }()), column_(nonZeroRowIndices.size(), nullptr), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { Index i = 0; if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _update_cell(id, i++); + _update_entry(id, i++); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _update_cell(operators_->get_value(p.second), p.first, i++); + _update_entry(operators_->get_value(p.second), p.first, i++); } } } @@ -369,7 +369,7 @@ inline Naive_vector_column::Naive_vector_column(const Naive_vecto Chain_opt(static_cast(column)), column_(column.column_.size(), nullptr), operators_(colSettings == nullptr ? column.operators_ : nullptr), - cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor)) { static_assert(!Master_matrix::Option_list::has_row_access, "Simple copy constructor not available when row access option enabled. Please specify the new column " @@ -380,11 +380,11 @@ inline Naive_vector_column::Naive_vector_column(const Naive_vecto } Index i = 0; - for (const Cell* cell : column.column_) { + for (const Entry* entry : column.column_) { if constexpr (Master_matrix::Option_list::is_z2) { - _update_cell(cell->get_row_index(), i++); + _update_entry(entry->get_row_index(), i++); } else { - _update_cell(cell->get_element(), cell->get_row_index(), i++); + _update_entry(entry->get_element(), entry->get_row_index(), i++); } } } @@ -400,18 +400,18 @@ inline Naive_vector_column::Naive_vector_column(const Naive_vecto Chain_opt(static_cast(column)), column_(column.column_.size(), nullptr), operators_(colSettings == nullptr ? column.operators_ : nullptr), - cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor)) { if constexpr (!Master_matrix::Option_list::is_z2) { if (colSettings != nullptr) operators_ = &(colSettings->operators); } Index i = 0; - for (const Cell* cell : column.column_) { + for (const Entry* entry : column.column_) { if constexpr (Master_matrix::Option_list::is_z2) { - _update_cell(cell->get_row_index(), i++); + _update_entry(entry->get_row_index(), i++); } else { - _update_cell(cell->get_element(), cell->get_row_index(), i++); + _update_entry(entry->get_element(), entry->get_row_index(), i++); } } } @@ -423,14 +423,14 @@ inline Naive_vector_column::Naive_vector_column(Naive_vector_colu Chain_opt(std::move(static_cast(column))), column_(std::move(column.column_)), operators_(std::exchange(column.operators_, nullptr)), - cellPool_(std::exchange(column.cellPool_, nullptr)) + entryPool_(std::exchange(column.entryPool_, nullptr)) {} template inline Naive_vector_column::~Naive_vector_column() { - for (auto* cell : column_) { - _delete_cell(cell); + for (auto* entry : column_) { + _delete_entry(entry); } } @@ -458,9 +458,9 @@ Naive_vector_column::get_content(int columnLength) const template inline bool Naive_vector_column::is_non_zero(ID_index rowIndex) const { - Cell cell(rowIndex); - return std::binary_search(column_.begin(), column_.end(), &cell, - [](const Cell* a, const Cell* b) { return a->get_row_index() < b->get_row_index(); }); + Entry entry(rowIndex); + return std::binary_search(column_.begin(), column_.end(), &entry, + [](const Entry* a, const Entry* b) { return a->get_row_index() < b->get_row_index(); }); } template @@ -483,24 +483,24 @@ inline void Naive_vector_column::reorder(const Row_index_map& val static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Method not available for chain columns."); - for (Cell* cell : column_) { + for (Entry* entry : column_) { if constexpr (Master_matrix::Option_list::has_row_access) { - RA_opt::unlink(cell); - if (columnIndex != static_cast(-1)) cell->set_column_index(columnIndex); + RA_opt::unlink(entry); + if (columnIndex != static_cast(-1)) entry->set_column_index(columnIndex); } - cell->set_row_index(valueMap.at(cell->get_row_index())); + entry->set_row_index(valueMap.at(entry->get_row_index())); if constexpr (Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access) - RA_opt::insert_cell(cell->get_row_index(), cell); + RA_opt::insert_entry(entry->get_row_index(), entry); } - // all cells have to be deleted first, to avoid problem with insertion when row is a set + // all entries have to be deleted first, to avoid problem with insertion when row is a set if constexpr (!Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access) { - for (Cell* cell : column_) { - RA_opt::insert_cell(cell->get_row_index(), cell); + for (Entry* entry : column_) { + RA_opt::insert_entry(entry->get_row_index(), entry); } } - std::sort(column_.begin(), column_.end(), [](const Cell* c1, const Cell* c2) { return *c1 < *c2; }); + std::sort(column_.begin(), column_.end(), [](const Entry* c1, const Entry* c2) { return *c1 < *c2; }); } template @@ -509,9 +509,9 @@ inline void Naive_vector_column::clear() static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Method not available for chain columns as a base element should not be empty."); - for (auto* cell : column_) { - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(cell); - cellPool_->destroy(cell); + for (auto* entry : column_) { + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry); + entryPool_->destroy(entry); } column_.clear(); @@ -526,7 +526,7 @@ inline void Naive_vector_column::clear(ID_index rowIndex) auto it = column_.begin(); while (it != column_.end() && (*it)->get_row_index() != rowIndex) ++it; if (it != column_.end()) { - _delete_cell(*it); + _delete_entry(*it); column_.erase(it); } } @@ -558,8 +558,8 @@ inline typename Naive_vector_column::Field_element Naive_vector_c return column_.empty() ? Field_element() : column_.back()->get_element(); } else { if (Chain_opt::get_pivot() == static_cast(-1)) return Field_element(); - for (const Cell* cell : column_) { - if (cell->get_row_index() == Chain_opt::get_pivot()) return cell->get_element(); + for (const Entry* entry : column_) { + if (entry->get_row_index() == Chain_opt::get_pivot()) return entry->get_element(); } return Field_element(); // should never happen if chain column is used properly } @@ -621,10 +621,10 @@ inline typename Naive_vector_column::const_reverse_iterator Naive } template -template -inline Naive_vector_column& Naive_vector_column::operator+=(const Cell_range& column) +template +inline Naive_vector_column& Naive_vector_column::operator+=(const Entry_range& column) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -676,9 +676,9 @@ inline Naive_vector_column& Naive_vector_column::o if (val == Field_operators::get_multiplicative_identity()) return *this; - for (Cell* cell : column_) { - operators_->multiply_inplace(cell->get_element(), val); - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_cell(*cell); + for (Entry* entry : column_) { + operators_->multiply_inplace(entry->get_element(), val); + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(*entry); } } @@ -686,11 +686,11 @@ inline Naive_vector_column& Naive_vector_column::o } template -template +template inline Naive_vector_column& Naive_vector_column::multiply_target_and_add( - const Field_element& val, const Cell_range& column) + const Field_element& val, const Entry_range& column) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -748,11 +748,11 @@ inline Naive_vector_column& Naive_vector_column::m } template -template +template inline Naive_vector_column& Naive_vector_column::multiply_source_and_add( - const Cell_range& column, const Field_element& val) + const Entry_range& column, const Field_element& val) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -810,8 +810,8 @@ inline Naive_vector_column& Naive_vector_column::o Dim_opt::operator=(other); Chain_opt::operator=(other); - auto tmpPool = cellPool_; - cellPool_ = other.cellPool_; + auto tmpPool = entryPool_; + entryPool_ = other.entryPool_; while (column_.size() > other.column_.size()) { if (column_.back() == nullptr) { @@ -823,15 +823,15 @@ inline Naive_vector_column& Naive_vector_column::o column_.resize(other.column_.size(), nullptr); Index i = 0; - for (const Cell* cell : other.column_) { + for (const Entry* entry : other.column_) { if (column_[i] != nullptr) { if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(column_[i]); tmpPool->destroy(column_[i]); } if constexpr (Master_matrix::Option_list::is_z2) { - _update_cell(cell->get_row_index(), i++); + _update_entry(entry->get_row_index(), i++); } else { - _update_cell(cell->get_element(), cell->get_row_index(), i++); + _update_entry(entry->get_element(), entry->get_row_index(), i++); } } @@ -841,90 +841,90 @@ inline Naive_vector_column& Naive_vector_column::o } template -inline void Naive_vector_column::_delete_cell(Cell* cell) +inline void Naive_vector_column::_delete_entry(Entry* entry) { - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(cell); - cellPool_->destroy(cell); + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry); + entryPool_->destroy(entry); } template -inline void Naive_vector_column::_delete_cell(typename Column_support::iterator& it) +inline void Naive_vector_column::_delete_entry(typename Column_support::iterator& it) { - _delete_cell(*it); + _delete_entry(*it); ++it; } template -inline typename Naive_vector_column::Cell* Naive_vector_column::_insert_cell( +inline typename Naive_vector_column::Entry* Naive_vector_column::_insert_entry( const Field_element& value, ID_index rowIndex, Column_support& column) { if constexpr (Master_matrix::Option_list::has_row_access) { - Cell* newCell = cellPool_->construct(RA_opt::columnIndex_, rowIndex); - newCell->set_element(value); - column.push_back(newCell); - RA_opt::insert_cell(rowIndex, newCell); - return newCell; + Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex); + newEntry->set_element(value); + column.push_back(newEntry); + RA_opt::insert_entry(rowIndex, newEntry); + return newEntry; } else { - Cell* newCell = cellPool_->construct(rowIndex); - column.push_back(newCell); - newCell->set_element(value); - return newCell; + Entry* newEntry = entryPool_->construct(rowIndex); + column.push_back(newEntry); + newEntry->set_element(value); + return newEntry; } } template -inline void Naive_vector_column::_insert_cell(ID_index rowIndex, Column_support& column) +inline void Naive_vector_column::_insert_entry(ID_index rowIndex, Column_support& column) { if constexpr (Master_matrix::Option_list::has_row_access) { - Cell* newCell = cellPool_->construct(RA_opt::columnIndex_, rowIndex); - column.push_back(newCell); - RA_opt::insert_cell(rowIndex, newCell); + Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex); + column.push_back(newEntry); + RA_opt::insert_entry(rowIndex, newEntry); } else { - column.push_back(cellPool_->construct(rowIndex)); + column.push_back(entryPool_->construct(rowIndex)); } } template -inline void Naive_vector_column::_update_cell(const Field_element& value, +inline void Naive_vector_column::_update_entry(const Field_element& value, ID_index rowIndex, Index position) { if constexpr (Master_matrix::Option_list::has_row_access) { - Cell* newCell = cellPool_->construct(RA_opt::columnIndex_, rowIndex); - newCell->set_element(value); - column_[position] = newCell; - RA_opt::insert_cell(rowIndex, newCell); + Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex); + newEntry->set_element(value); + column_[position] = newEntry; + RA_opt::insert_entry(rowIndex, newEntry); } else { - column_[position] = cellPool_->construct(rowIndex); + column_[position] = entryPool_->construct(rowIndex); column_[position]->set_element(value); } } template -inline void Naive_vector_column::_update_cell(ID_index rowIndex, Index position) +inline void Naive_vector_column::_update_entry(ID_index rowIndex, Index position) { if constexpr (Master_matrix::Option_list::has_row_access) { - Cell* newCell = cellPool_->construct(RA_opt::columnIndex_, rowIndex); - column_[position] = newCell; - RA_opt::insert_cell(rowIndex, newCell); + Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex); + column_[position] = newEntry; + RA_opt::insert_entry(rowIndex, newEntry); } else { - column_[position] = cellPool_->construct(rowIndex); + column_[position] = entryPool_->construct(rowIndex); } } template -template -inline bool Naive_vector_column::_add(const Cell_range& column) +template +inline bool Naive_vector_column::_add(const Entry_range& column) { if (column.begin() == column.end()) return false; if (column_.empty()) { // chain should never enter here. column_.resize(column.size()); Index i = 0; - for (const Cell& cell : column) { + for (const Entry& entry : column) { if constexpr (Master_matrix::Option_list::is_z2) { - _update_cell(cell.get_row_index(), i++); + _update_entry(entry.get_row_index(), i++); } else { - _update_cell(cell.get_element(), cell.get_row_index(), i++); + _update_entry(entry.get_element(), entry.get_row_index(), i++); } } return true; @@ -936,20 +936,20 @@ inline bool Naive_vector_column::_add(const Cell_range& column) auto pivotIsZeroed = _generic_add_to_column( column, *this, - [&](Cell* cellTarget) { newColumn.push_back(cellTarget); }, - [&](typename Cell_range::const_iterator& itSource, + [&](Entry* entryTarget) { newColumn.push_back(entryTarget); }, + [&](typename Entry_range::const_iterator& itSource, [[maybe_unused]] const typename Column_support::iterator& itTarget) { if constexpr (Master_matrix::Option_list::is_z2) { - _insert_cell(itSource->get_row_index(), newColumn); + _insert_entry(itSource->get_row_index(), newColumn); } else { - _insert_cell(itSource->get_element(), itSource->get_row_index(), newColumn); + _insert_entry(itSource->get_element(), itSource->get_row_index(), newColumn); } }, - [&](Field_element& targetElement, typename Cell_range::const_iterator& itSource) { + [&](Field_element& targetElement, typename Entry_range::const_iterator& itSource) { if constexpr (!Master_matrix::Option_list::is_z2) operators_->add_inplace(targetElement, itSource->get_element()); }, - [&](Cell* cellTarget) { newColumn.push_back(cellTarget); }, + [&](Entry* entryTarget) { newColumn.push_back(entryTarget); }, [&](typename Column_support::iterator& itTarget) { while (itTarget != column_.end()) { newColumn.push_back(*itTarget); @@ -963,9 +963,9 @@ inline bool Naive_vector_column::_add(const Cell_range& column) } template -template +template inline bool Naive_vector_column::_multiply_target_and_add(const Field_element& val, - const Cell_range& column) + const Entry_range& column) { if (val == 0u) { if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) { @@ -978,11 +978,11 @@ inline bool Naive_vector_column::_multiply_target_and_add(const F if (column_.empty()) { // chain should never enter here. column_.resize(column.size()); Index i = 0; - for (const Cell& cell : column) { + for (const Entry& entry : column) { if constexpr (Master_matrix::Option_list::is_z2) { - _update_cell(cell.get_row_index(), i++); + _update_entry(entry.get_row_index(), i++); } else { - _update_cell(cell.get_element(), cell.get_row_index(), i++); + _update_entry(entry.get_element(), entry.get_row_index(), i++); } } return true; @@ -994,22 +994,22 @@ inline bool Naive_vector_column::_multiply_target_and_add(const F auto pivotIsZeroed = _generic_add_to_column( column, *this, - [&](Cell* cellTarget) { - operators_->multiply_inplace(cellTarget->get_element(), val); - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_cell(*cellTarget); - newColumn.push_back(cellTarget); + [&](Entry* entryTarget) { + operators_->multiply_inplace(entryTarget->get_element(), val); + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(*entryTarget); + newColumn.push_back(entryTarget); }, - [&](typename Cell_range::const_iterator& itSource, const typename Column_support::iterator& itTarget) { - _insert_cell(itSource->get_element(), itSource->get_row_index(), newColumn); + [&](typename Entry_range::const_iterator& itSource, const typename Column_support::iterator& itTarget) { + _insert_entry(itSource->get_element(), itSource->get_row_index(), newColumn); }, - [&](Field_element& targetElement, typename Cell_range::const_iterator& itSource) { + [&](Field_element& targetElement, typename Entry_range::const_iterator& itSource) { operators_->multiply_and_add_inplace_front(targetElement, val, itSource->get_element()); }, - [&](Cell* cellTarget) { newColumn.push_back(cellTarget); }, + [&](Entry* entryTarget) { newColumn.push_back(entryTarget); }, [&](typename Column_support::iterator& itTarget) { while (itTarget != column_.end()) { operators_->multiply_inplace((*itTarget)->get_element(), val); - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_cell(**itTarget); + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(**itTarget); newColumn.push_back(*itTarget); itTarget++; } @@ -1021,8 +1021,8 @@ inline bool Naive_vector_column::_multiply_target_and_add(const F } template -template -inline bool Naive_vector_column::_multiply_source_and_add(const Cell_range& column, +template +inline bool Naive_vector_column::_multiply_source_and_add(const Entry_range& column, const Field_element& val) { if (val == 0u || column.begin() == column.end()) { @@ -1035,16 +1035,16 @@ inline bool Naive_vector_column::_multiply_source_and_add(const C auto pivotIsZeroed = _generic_add_to_column( column, *this, - [&](Cell* cellTarget) { newColumn.push_back(cellTarget); }, - [&](typename Cell_range::const_iterator& itSource, const typename Column_support::iterator& itTarget) { - Cell* newCell = _insert_cell(itSource->get_element(), itSource->get_row_index(), newColumn); - operators_->multiply_inplace(newCell->get_element(), val); - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_cell(*newCell); + [&](Entry* entryTarget) { newColumn.push_back(entryTarget); }, + [&](typename Entry_range::const_iterator& itSource, const typename Column_support::iterator& itTarget) { + Entry* newEntry = _insert_entry(itSource->get_element(), itSource->get_row_index(), newColumn); + operators_->multiply_inplace(newEntry->get_element(), val); + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(*newEntry); }, - [&](Field_element& targetElement, typename Cell_range::const_iterator& itSource) { + [&](Field_element& targetElement, typename Entry_range::const_iterator& itSource) { operators_->multiply_and_add_inplace_back(itSource->get_element(), val, targetElement); }, - [&](Cell* cellTarget) { newColumn.push_back(cellTarget); }, + [&](Entry* entryTarget) { newColumn.push_back(entryTarget); }, [&](typename Column_support::iterator& itTarget) { while (itTarget != column_.end()) { newColumn.push_back(*itTarget); @@ -1066,7 +1066,7 @@ inline bool Naive_vector_column::_multiply_source_and_add(const C * @brief Hash method for @ref Gudhi::persistence_matrix::Naive_vector_column. * * @tparam Master_matrix Template parameter of @ref Gudhi::persistence_matrix::Naive_vector_column. - * @tparam Cell_constructor Template parameter of @ref Gudhi::persistence_matrix::Naive_vector_column. + * @tparam Entry_constructor Template parameter of @ref Gudhi::persistence_matrix::Naive_vector_column. */ template struct std::hash > { diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/row_access.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/row_access.h index d170c49d1f..035ad0e12f 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/row_access.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/row_access.h @@ -52,7 +52,7 @@ class Row_access public: using Index = typename Master_matrix::Index; /**< @ref MatIdx index type. */ using ID_index = typename Master_matrix::ID_index; /**< @ref IDIdx index type. */ - using Matrix_cell = typename Master_matrix::Matrix_cell; /**< @ref Cell. */ + using Matrix_entry = typename Master_matrix::Matrix_entry; /**< @ref Entry. */ using Row_container = typename Master_matrix::Row_container; /**< Type of the row container. */ /** @@ -75,28 +75,28 @@ class Row_access Row_access(Row_access&& other) noexcept; /** - * @brief Inserts the given cell at the given row index. + * @brief Inserts the given entry at the given row index. * - * @param rowIndex @ref rowindex "Row index" of the cell. - * @param cell Pointer to the cell to insert. + * @param rowIndex @ref rowindex "Row index" of the entry. + * @param entry Pointer to the entry to insert. */ - void insert_cell(ID_index rowIndex, Matrix_cell* cell); + void insert_entry(ID_index rowIndex, Matrix_entry* entry); /** - * @brief Removes the given cell from its row. + * @brief Removes the given entry from its row. * - * @param cell Pointer to the cell to remove. + * @param entry Pointer to the entry to remove. */ - void unlink(Matrix_cell* cell); + void unlink(Matrix_entry* entry); /** - * @brief If @ref PersistenceMatrixOptions::has_intrusive_rows is false, updates the copy of the cell in its row. + * @brief If @ref PersistenceMatrixOptions::has_intrusive_rows is false, updates the copy of the entry in its row. * Otherwise does nothing. * - * If the rows are intrusive, only a pointer of the cell is stored and therefore any update on the cell (value + * If the rows are intrusive, only a pointer of the entry is stored and therefore any update on the entry (value * or column index) is automatically forwarded. But for non intrusive rows, any update has to be pushed explicitly. * - * @param cell Cell to update. + * @param entry Entry to update. */ - void update_cell(const Matrix_cell& cell); + void update_entry(const Matrix_entry& entry); /** * @brief Returns the @ref MatIdx column index. * @@ -135,7 +135,7 @@ inline Row_access::Row_access(Row_access&& other) noexcept {} template -inline void Row_access::insert_cell(ID_index rowIndex, Matrix_cell* cell) +inline void Row_access::insert_entry(ID_index rowIndex, Matrix_entry* entry) { if (rows_ == nullptr) return; @@ -145,38 +145,38 @@ inline void Row_access::insert_cell(ID_index rowIndex, Matrix_cel // if has_removable_rows should op[] create non existing entry? If not, use try_emplace() if constexpr (Master_matrix::Option_list::has_intrusive_rows) { - rows_->operator[](rowIndex).push_back(*cell); + rows_->operator[](rowIndex).push_back(*entry); } else { - rows_->operator[](rowIndex).insert(*cell); + rows_->operator[](rowIndex).insert(*entry); } } template -inline void Row_access::unlink(Matrix_cell* cell) +inline void Row_access::unlink(Matrix_entry* entry) { if (rows_ == nullptr) return; if constexpr (Master_matrix::Option_list::has_intrusive_rows) { - cell->Base_hook_matrix_row::unlink(); + entry->Base_hook_matrix_row::unlink(); } else { if constexpr (Master_matrix::Option_list::has_removable_rows) { - auto it = rows_->find(cell->get_row_index()); - it->second.erase(*cell); + auto it = rows_->find(entry->get_row_index()); + it->second.erase(*entry); } else { - rows_->operator[](cell->get_row_index()).erase(*cell); + rows_->operator[](entry->get_row_index()).erase(*entry); } } } template -inline void Row_access::update_cell(const Matrix_cell& cell) +inline void Row_access::update_entry(const Matrix_entry& entry) { if constexpr (!Master_matrix::Option_list::has_intrusive_rows) { if (rows_ == nullptr) return; - auto& row = rows_->at(cell.get_row_index()); - auto it = row.find(cell); + auto& row = rows_->at(entry.get_row_index()); + auto it = row.find(entry); it = row.erase(it); - row.insert(it, cell); + row.insert(it, entry); } } diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/set_column.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/set_column.h index d7c84e1277..de7151a75f 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/set_column.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/set_column.h @@ -26,7 +26,7 @@ #include -#include +#include #include namespace Gudhi { @@ -38,11 +38,11 @@ namespace persistence_matrix { * * @brief Column class following the @ref PersistenceMatrixColumn concept. * - * Column based on a set structure. The cells are always ordered by row index and only non-zero values + * Column based on a set structure. The entries are always ordered by row index and only non-zero values * are stored uniquely in the underlying container. * * @tparam Master_matrix An instantiation of @ref Matrix from which all types and options are deduced. - * @tparam Cell_constructor Factory of @ref Cell classes. + * @tparam Entry_constructor Factory of @ref Entry classes. */ template class Set_column : public Master_matrix::Row_access_option, @@ -55,18 +55,18 @@ class Set_column : public Master_matrix::Row_access_option, using ID_index = typename Master_matrix::ID_index; using Dimension = typename Master_matrix::Dimension; using Field_element = typename Master_matrix::Element; - using Cell = typename Master_matrix::Matrix_cell; + using Entry = typename Master_matrix::Matrix_entry; using Column_settings = typename Master_matrix::Column_settings; private: using Field_operators = typename Master_matrix::Field_operators; - struct CellPointerComp { - bool operator()(const Cell* c1, const Cell* c2) const { return *c1 < *c2; } + struct EntryPointerComp { + bool operator()(const Entry* c1, const Entry* c2) const { return *c1 < *c2; } }; - using Column_support = std::set; - using Cell_constructor = typename Master_matrix::Cell_constructor; + using Column_support = std::set; + using Entry_constructor = typename Master_matrix::Entry_constructor; public: using iterator = boost::indirect_iterator; @@ -121,19 +121,19 @@ class Set_column : public Master_matrix::Row_access_option, reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; - template - Set_column& operator+=(const Cell_range& column); + template + Set_column& operator+=(const Entry_range& column); Set_column& operator+=(Set_column& column); Set_column& operator*=(unsigned int v); // this = v * this + column - template - Set_column& multiply_target_and_add(const Field_element& val, const Cell_range& column); + template + Set_column& multiply_target_and_add(const Field_element& val, const Entry_range& column); Set_column& multiply_target_and_add(const Field_element& val, Set_column& column); // this = this + column * v - template - Set_column& multiply_source_and_add(const Cell_range& column, const Field_element& val); + template + Set_column& multiply_source_and_add(const Entry_range& column, const Field_element& val); Set_column& multiply_source_and_add(Set_column& column, const Field_element& val); friend bool operator==(const Set_column& c1, const Set_column& c2) { @@ -182,7 +182,7 @@ class Set_column : public Master_matrix::Row_access_option, static_cast(col2)); col1.column_.swap(col2.column_); std::swap(col1.operators_, col2.operators_); - std::swap(col1.cellPool_, col2.cellPool_); + std::swap(col1.entryPool_, col2.entryPool_); } private: @@ -192,45 +192,45 @@ class Set_column : public Master_matrix::Row_access_option, Column_support column_; Field_operators* operators_; - Cell_constructor* cellPool_; - - template - friend void _generic_merge_cell_to_column(Column& targetColumn, - Cell_iterator& itSource, - typename Column::Column_support::iterator& itTarget, - F1&& process_target, - F2&& process_source, - F3&& update_target1, - F4&& update_target2, - bool& pivotIsZeroed); - template - friend bool _generic_add_to_column(const Cell_range& source, + Entry_constructor* entryPool_; + + template + friend void _generic_merge_entry_to_column(Column& targetColumn, + Entry_iterator& itSource, + typename Column::Column_support::iterator& itTarget, + F1&& process_target, + F2&& process_source, + F3&& update_target1, + F4&& update_target2, + bool& pivotIsZeroed); + template + friend bool _generic_add_to_column(const Entry_range& source, Column& targetColumn, F1&& process_target, F2&& process_source, F3&& update_target1, F4&& update_target2, F5&& finish_target); - template - friend bool _add_to_column(const Cell_range& source, Column& targetColumn); - template + template + friend bool _add_to_column(const Entry_range& source, Column& targetColumn); + template friend bool _multiply_target_and_add_to_column(const typename Column::Field_element& val, - const Cell_range& source, + const Entry_range& source, Column& targetColumn); - template + template friend bool _multiply_source_and_add_to_column(const typename Column::Field_element& val, - const Cell_range& source, + const Entry_range& source, Column& targetColumn); - void _delete_cell(typename Column_support::iterator& it); - Cell* _insert_cell(const Field_element& value, ID_index rowIndex, const typename Column_support::iterator& position); - void _insert_cell(ID_index rowIndex, const typename Column_support::iterator& position); - template - bool _add(const Cell_range& column); - template - bool _multiply_target_and_add(const Field_element& val, const Cell_range& column); - template - bool _multiply_source_and_add(const Cell_range& column, const Field_element& val); + void _delete_entry(typename Column_support::iterator& it); + Entry* _insert_entry(const Field_element& value, ID_index rowIndex, const typename Column_support::iterator& position); + void _insert_entry(ID_index rowIndex, const typename Column_support::iterator& position); + template + bool _add(const Entry_range& column); + template + bool _multiply_target_and_add(const Field_element& val, const Entry_range& column); + template + bool _multiply_source_and_add(const Entry_range& column, const Field_element& val); }; template @@ -239,9 +239,9 @@ inline Set_column::Set_column(Column_settings* colSettings) Dim_opt(), Chain_opt(), operators_(nullptr), - cellPool_(colSettings == nullptr ? nullptr : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? nullptr : &(colSettings->entryConstructor)) { - if (operators_ == nullptr && cellPool_ == nullptr) return; // to allow default constructor which gives a dummy column + if (operators_ == nullptr && entryPool_ == nullptr) return; // to allow default constructor which gives a dummy column if constexpr (!Master_matrix::Option_list::is_z2) { operators_ = &(colSettings->operators); } @@ -254,19 +254,19 @@ inline Set_column::Set_column(const Container& nonZeroRowIndices, Dim_opt(nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1), Chain_opt(), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Constructor not available for chain columns, please specify the dimension of the chain."); if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _insert_cell(id, column_.end()); + _insert_entry(id, column_.end()); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _insert_cell(operators_->get_value(p.second), p.first, column_.end()); + _insert_entry(operators_->get_value(p.second), p.first, column_.end()); } } } @@ -287,19 +287,19 @@ inline Set_column::Set_column(Index columnIndex, } }()), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Constructor not available for chain columns, please specify the dimension of the chain."); if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _insert_cell(id, column_.end()); + _insert_entry(id, column_.end()); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _insert_cell(operators_->get_value(p.second), p.first, column_.end()); + _insert_entry(operators_->get_value(p.second), p.first, column_.end()); } } } @@ -319,16 +319,16 @@ inline Set_column::Set_column(const Container& nonZeroRowIndices, } }()), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _insert_cell(id, column_.end()); + _insert_entry(id, column_.end()); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _insert_cell(operators_->get_value(p.second), p.first, column_.end()); + _insert_entry(operators_->get_value(p.second), p.first, column_.end()); } } } @@ -350,16 +350,16 @@ inline Set_column::Set_column(Index columnIndex, } }()), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _insert_cell(id, column_.end()); + _insert_entry(id, column_.end()); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _insert_cell(operators_->get_value(p.second), p.first, column_.end()); + _insert_entry(operators_->get_value(p.second), p.first, column_.end()); } } } @@ -370,7 +370,7 @@ inline Set_column::Set_column(const Set_column& column, Column_se Dim_opt(static_cast(column)), Chain_opt(static_cast(column)), operators_(colSettings == nullptr ? column.operators_ : nullptr), - cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor)) { static_assert(!Master_matrix::Option_list::has_row_access, "Simple copy constructor not available when row access option enabled. Please specify the new column " @@ -380,11 +380,11 @@ inline Set_column::Set_column(const Set_column& column, Column_se if (colSettings != nullptr) operators_ = &(colSettings->operators); } - for (const Cell* cell : column.column_) { + for (const Entry* entry : column.column_) { if constexpr (Master_matrix::Option_list::is_z2) { - _insert_cell(cell->get_row_index(), column_.end()); + _insert_entry(entry->get_row_index(), column_.end()); } else { - _insert_cell(cell->get_element(), cell->get_row_index(), column_.end()); + _insert_entry(entry->get_element(), entry->get_row_index(), column_.end()); } } } @@ -399,17 +399,17 @@ inline Set_column::Set_column(const Set_column& column, Dim_opt(static_cast(column)), Chain_opt(static_cast(column)), operators_(colSettings == nullptr ? column.operators_ : nullptr), - cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor)) { if constexpr (!Master_matrix::Option_list::is_z2) { if (colSettings != nullptr) operators_ = &(colSettings->operators); } - for (const Cell* cell : column.column_) { + for (const Entry* entry : column.column_) { if constexpr (Master_matrix::Option_list::is_z2) { - _insert_cell(cell->get_row_index(), column_.end()); + _insert_entry(entry->get_row_index(), column_.end()); } else { - _insert_cell(cell->get_element(), cell->get_row_index(), column_.end()); + _insert_entry(entry->get_element(), entry->get_row_index(), column_.end()); } } } @@ -421,15 +421,15 @@ inline Set_column::Set_column(Set_column&& column) noexcept Chain_opt(std::move(static_cast(column))), column_(std::move(column.column_)), operators_(std::exchange(column.operators_, nullptr)), - cellPool_(std::exchange(column.cellPool_, nullptr)) + entryPool_(std::exchange(column.entryPool_, nullptr)) {} template inline Set_column::~Set_column() { - for (auto* cell : column_) { - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(cell); - cellPool_->destroy(cell); + for (auto* entry : column_) { + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry); + entryPool_->destroy(entry); } } @@ -457,8 +457,8 @@ inline std::vector::Field_element> Set_column template inline bool Set_column::is_non_zero(ID_index rowIndex) const { - Cell cell(rowIndex); - return column_.find(&cell) != column_.end(); + Entry entry(rowIndex); + return column_.find(&entry) != column_.end(); } template @@ -482,22 +482,22 @@ inline void Set_column::reorder(const Row_index_map& valueMap, [[ Column_support newSet; - for (Cell* cell : column_) { + for (Entry* entry : column_) { if constexpr (Master_matrix::Option_list::has_row_access) { - RA_opt::unlink(cell); - if (columnIndex != static_cast(-1)) cell->set_column_index(columnIndex); + RA_opt::unlink(entry); + if (columnIndex != static_cast(-1)) entry->set_column_index(columnIndex); } - cell->set_row_index(valueMap.at(cell->get_row_index())); - newSet.insert(cell); + entry->set_row_index(valueMap.at(entry->get_row_index())); + newSet.insert(entry); if constexpr (Master_matrix::Option_list::has_row_access && Master_matrix::Option_list::has_intrusive_rows) // intrusive list - RA_opt::insert_cell(cell->get_row_index(), cell); + RA_opt::insert_entry(entry->get_row_index(), entry); } - // when row is a set, all cells have to be deleted first, to avoid colliding when inserting + // when row is a set, all entries have to be deleted first, to avoid colliding when inserting if constexpr (Master_matrix::Option_list::has_row_access && !Master_matrix::Option_list::has_intrusive_rows) { // set - for (Cell* cell : newSet) { - RA_opt::insert_cell(cell->get_row_index(), cell); + for (Entry* entry : newSet) { + RA_opt::insert_entry(entry->get_row_index(), entry); } } @@ -510,9 +510,9 @@ inline void Set_column::clear() static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Method not available for chain columns as a base element should not be empty."); - for (auto* cell : column_) { - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(cell); - cellPool_->destroy(cell); + for (auto* entry : column_) { + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry); + entryPool_->destroy(entry); } column_.clear(); @@ -524,12 +524,12 @@ inline void Set_column::clear(ID_index rowIndex) static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Method not available for chain columns."); - auto cell = cellPool_->construct(rowIndex); - auto it = column_.find(cell); + auto entry = entryPool_->construct(rowIndex); + auto it = column_.find(entry); if (it != column_.end()) { - _delete_cell(it); + _delete_entry(it); } - cellPool_->destroy(cell); + entryPool_->destroy(entry); } template @@ -560,8 +560,8 @@ inline typename Set_column::Field_element Set_columnget_element(); } else { if (Chain_opt::get_pivot() == static_cast(-1)) return Field_element(); - for (const Cell* cell : column_) { - if (cell->get_row_index() == Chain_opt::get_pivot()) return cell->get_element(); + for (const Entry* entry : column_) { + if (entry->get_row_index() == Chain_opt::get_pivot()) return entry->get_element(); } return Field_element(); // should never happen if chain column is used properly } @@ -617,10 +617,10 @@ inline typename Set_column::const_reverse_iterator Set_column -template -inline Set_column& Set_column::operator+=(const Cell_range& column) +template +inline Set_column& Set_column::operator+=(const Entry_range& column) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -672,9 +672,9 @@ inline Set_column& Set_column::operator*=(unsigned if (val == Field_operators::get_multiplicative_identity()) return *this; - for (Cell* cell : column_) { - operators_->multiply_inplace(cell->get_element(), val); - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_cell(*cell); + for (Entry* entry : column_) { + operators_->multiply_inplace(entry->get_element(), val); + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(*entry); } } @@ -682,11 +682,11 @@ inline Set_column& Set_column::operator*=(unsigned } template -template +template inline Set_column& Set_column::multiply_target_and_add(const Field_element& val, - const Cell_range& column) + const Entry_range& column) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -744,11 +744,11 @@ inline Set_column& Set_column::multiply_target_and } template -template -inline Set_column& Set_column::multiply_source_and_add(const Cell_range& column, +template +inline Set_column& Set_column::multiply_source_and_add(const Entry_range& column, const Field_element& val) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -805,20 +805,20 @@ inline Set_column& Set_column::operator=(const Set Dim_opt::operator=(other); Chain_opt::operator=(other); - for (auto* cell : column_) { - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(cell); - cellPool_->destroy(cell); + for (auto* entry : column_) { + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry); + entryPool_->destroy(entry); } column_.clear(); - cellPool_ = other.cellPool_; + entryPool_ = other.entryPool_; operators_ = other.operators_; - for (const Cell* cell : other.column_) { + for (const Entry* entry : other.column_) { if constexpr (Master_matrix::Option_list::is_z2) { - _insert_cell(cell->get_row_index(), column_.end()); + _insert_entry(entry->get_row_index(), column_.end()); } else { - _insert_cell(cell->get_element(), cell->get_row_index(), column_.end()); + _insert_entry(entry->get_element(), entry->get_row_index(), column_.end()); } } @@ -826,62 +826,62 @@ inline Set_column& Set_column::operator=(const Set } template -inline void Set_column::_delete_cell(typename Column_support::iterator& it) +inline void Set_column::_delete_entry(typename Column_support::iterator& it) { if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(*it); - cellPool_->destroy(*it); + entryPool_->destroy(*it); it = column_.erase(it); } template -inline typename Set_column::Cell* Set_column::_insert_cell( +inline typename Set_column::Entry* Set_column::_insert_entry( const Field_element& value, ID_index rowIndex, const typename Column_support::iterator& position) { if constexpr (Master_matrix::Option_list::has_row_access) { - Cell* newCell = cellPool_->construct(RA_opt::columnIndex_, rowIndex); - newCell->set_element(value); - column_.insert(position, newCell); - RA_opt::insert_cell(rowIndex, newCell); - return newCell; + Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex); + newEntry->set_element(value); + column_.insert(position, newEntry); + RA_opt::insert_entry(rowIndex, newEntry); + return newEntry; } else { - Cell* newCell = cellPool_->construct(rowIndex); - newCell->set_element(value); - column_.insert(position, newCell); - return newCell; + Entry* newEntry = entryPool_->construct(rowIndex); + newEntry->set_element(value); + column_.insert(position, newEntry); + return newEntry; } } template -inline void Set_column::_insert_cell(ID_index rowIndex, +inline void Set_column::_insert_entry(ID_index rowIndex, const typename Column_support::iterator& position) { if constexpr (Master_matrix::Option_list::has_row_access) { - Cell* newCell = cellPool_->construct(RA_opt::columnIndex_, rowIndex); - column_.insert(position, newCell); - RA_opt::insert_cell(rowIndex, newCell); + Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex); + column_.insert(position, newEntry); + RA_opt::insert_entry(rowIndex, newEntry); } else { - Cell* newCell = cellPool_->construct(rowIndex); - column_.insert(position, newCell); + Entry* newEntry = entryPool_->construct(rowIndex); + column_.insert(position, newEntry); } } template -template -inline bool Set_column::_add(const Cell_range& column) +template +inline bool Set_column::_add(const Entry_range& column) { return _add_to_column(column, *this); } template -template -inline bool Set_column::_multiply_target_and_add(const Field_element& val, const Cell_range& column) +template +inline bool Set_column::_multiply_target_and_add(const Field_element& val, const Entry_range& column) { return _multiply_target_and_add_to_column(val, column, *this); } template -template -inline bool Set_column::_multiply_source_and_add(const Cell_range& column, const Field_element& val) +template +inline bool Set_column::_multiply_source_and_add(const Entry_range& column, const Field_element& val) { return _multiply_source_and_add_to_column(val, column, *this); } @@ -895,7 +895,7 @@ inline bool Set_column::_multiply_source_and_add(const Cell_range * @brief Hash method for @ref Gudhi::persistence_matrix::Set_column. * * @tparam Master_matrix Template parameter of @ref Gudhi::persistence_matrix::Set_column. - * @tparam Cell_constructor Template parameter of @ref Gudhi::persistence_matrix::Set_column. + * @tparam Entry_constructor Template parameter of @ref Gudhi::persistence_matrix::Set_column. */ template struct std::hash > { diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/unordered_set_column.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/unordered_set_column.h index 0e4dc12462..4729b004dd 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/unordered_set_column.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/unordered_set_column.h @@ -31,22 +31,22 @@ #include #endif -#include +#include namespace Gudhi { namespace persistence_matrix { // For unordered_set container. Outside of Unordered_set_column because of a msvc bug who can't compile properly // unordered_flat_set if the hash method is nested. -template -struct CellPointerHash +template +struct EntryPointerHash { - size_t operator()(const Cell* c) const { return std::hash()(*c); } + size_t operator()(const Entry* c) const { return std::hash()(*c); } }; -template -struct CellPointerEq +template +struct EntryPointerEq { - bool operator()(const Cell* c1, const Cell* c2) const { return *c1 == *c2; } + bool operator()(const Entry* c1, const Entry* c2) const { return *c1 == *c2; } }; /** @@ -55,12 +55,12 @@ struct CellPointerEq * * @brief Column class following the @ref PersistenceMatrixColumn concept. * - * Column based on an unordered set structure. The cells are not ordered, but only non-zero values - * are stored uniquely in the underlying container. When adding a cell range into it, the given cell range + * Column based on an unordered set structure. The entries are not ordered, but only non-zero values + * are stored uniquely in the underlying container. When adding an entry range into it, the given entry range * also does not need to be ordered (contrary to most other column types). * * @tparam Master_matrix An instantiation of @ref Matrix from which all types and options are deduced. - * @tparam Cell_constructor Factory of @ref Cell classes. + * @tparam Entry_constructor Factory of @ref Entry classes. */ template class Unordered_set_column : public Master_matrix::Row_access_option, @@ -73,21 +73,21 @@ class Unordered_set_column : public Master_matrix::Row_access_option, using ID_index = typename Master_matrix::ID_index; using Dimension = typename Master_matrix::Dimension; using Field_element = typename Master_matrix::Element; - using Cell = typename Master_matrix::Matrix_cell; + using Entry = typename Master_matrix::Matrix_entry; using Column_settings = typename Master_matrix::Column_settings; private: using Field_operators = typename Master_matrix::Field_operators; - using Cell_constructor = typename Master_matrix::Cell_constructor; + using Entry_constructor = typename Master_matrix::Entry_constructor; - struct CellPointerComp { - bool operator()(const Cell* c1, const Cell* c2) const { return *c1 < *c2; } + struct EntryPointerComp { + bool operator()(const Entry* c1, const Entry* c2) const { return *c1 < *c2; } }; #if BOOST_VERSION >= 108100 - using Column_support = boost::unordered_flat_set, CellPointerEq>; + using Column_support = boost::unordered_flat_set, EntryPointerEq>; #else - using Column_support = std::unordered_set, CellPointerEq>; + using Column_support = std::unordered_set, EntryPointerEq>; #endif public: @@ -137,30 +137,30 @@ class Unordered_set_column : public Master_matrix::Row_access_option, iterator end() noexcept; const_iterator end() const noexcept; - template - Unordered_set_column& operator+=(const Cell_range& column); + template + Unordered_set_column& operator+=(const Entry_range& column); Unordered_set_column& operator+=(Unordered_set_column& column); Unordered_set_column& operator*=(unsigned int v); // this = v * this + column - template - Unordered_set_column& multiply_target_and_add(const Field_element& val, const Cell_range& column); + template + Unordered_set_column& multiply_target_and_add(const Field_element& val, const Entry_range& column); Unordered_set_column& multiply_target_and_add(const Field_element& val, Unordered_set_column& column); // this = this + column * v - template - Unordered_set_column& multiply_source_and_add(const Cell_range& column, const Field_element& val); + template + Unordered_set_column& multiply_source_and_add(const Entry_range& column, const Field_element& val); Unordered_set_column& multiply_source_and_add(Unordered_set_column& column, const Field_element& val); friend bool operator==(const Unordered_set_column& c1, const Unordered_set_column& c2) { if (&c1 == &c2) return true; if (c1.column_.size() != c2.column_.size()) return false; - for (Cell* cell : c1.column_) { - auto it = c2.column_.find(cell); + for (Entry* entry : c1.column_) { + auto it = c2.column_.find(entry); if (it == c2.column_.end()) return false; if constexpr (!Master_matrix::Option_list::is_z2) - if ((*it)->get_element() != cell->get_element()) return false; + if ((*it)->get_element() != entry->get_element()) return false; } return true; } @@ -168,7 +168,7 @@ class Unordered_set_column : public Master_matrix::Row_access_option, if (&c1 == &c2) return false; using ID_index = Unordered_set_column::ID_index; - using Cell_rep = + using Entry_rep = typename std::conditional @@ -176,35 +176,35 @@ class Unordered_set_column : public Master_matrix::Row_access_option, auto it1 = c1.column_.begin(); auto it2 = c2.column_.begin(); - std::set cells1, cells2; + std::set entries1, entries2; while (it1 != c1.column_.end() && it2 != c2.column_.end()) { if constexpr (Master_matrix::Option_list::is_z2) { - cells1.insert((*it1)->get_row_index()); - cells2.insert((*it2)->get_row_index()); + entries1.insert((*it1)->get_row_index()); + entries2.insert((*it2)->get_row_index()); } else { - cells1.emplace((*it1)->get_row_index(), (*it1)->get_element()); - cells2.emplace((*it2)->get_row_index(), (*it2)->get_element()); + entries1.emplace((*it1)->get_row_index(), (*it1)->get_element()); + entries2.emplace((*it2)->get_row_index(), (*it2)->get_element()); } ++it1; ++it2; } while (it1 != c1.column_.end()) { if constexpr (Master_matrix::Option_list::is_z2) { - cells1.insert((*it1)->get_row_index()); + entries1.insert((*it1)->get_row_index()); } else { - cells1.emplace((*it1)->get_row_index(), (*it1)->get_element()); + entries1.emplace((*it1)->get_row_index(), (*it1)->get_element()); } ++it1; } while (it2 != c2.column_.end()) { if constexpr (Master_matrix::Option_list::is_z2) { - cells2.insert((*it2)->get_row_index()); + entries2.insert((*it2)->get_row_index()); } else { - cells2.emplace((*it2)->get_row_index(), (*it2)->get_element()); + entries2.emplace((*it2)->get_row_index(), (*it2)->get_element()); } ++it2; } - return cells1 < cells2; + return entries1 < entries2; } // Disabled with row access. @@ -219,7 +219,7 @@ class Unordered_set_column : public Master_matrix::Row_access_option, static_cast(col2)); col1.column_.swap(col2.column_); std::swap(col1.operators_, col2.operators_); - std::swap(col1.cellPool_, col2.cellPool_); + std::swap(col1.entryPool_, col2.entryPool_); } private: @@ -229,19 +229,19 @@ class Unordered_set_column : public Master_matrix::Row_access_option, Column_support column_; Field_operators* operators_; - Cell_constructor* cellPool_; - - void _delete_cell(typename Column_support::iterator& it); - Cell* _insert_cell(const Field_element& value, ID_index rowIndex); - void _insert_cell(ID_index rowIndex); - template - bool _add(const Cell_range& column); - template - bool _multiply_target_and_add(const Field_element& val, const Cell_range& column); - template - bool _multiply_source_and_add(const Cell_range& column, const Field_element& val); - template - bool _generic_add(const Cell_range& source, F1&& process_source, F2&& update_target); + Entry_constructor* entryPool_; + + void _delete_entry(typename Column_support::iterator& it); + Entry* _insert_entry(const Field_element& value, ID_index rowIndex); + void _insert_entry(ID_index rowIndex); + template + bool _add(const Entry_range& column); + template + bool _multiply_target_and_add(const Field_element& val, const Entry_range& column); + template + bool _multiply_source_and_add(const Entry_range& column, const Field_element& val); + template + bool _generic_add(const Entry_range& source, F1&& process_source, F2&& update_target); }; template @@ -250,9 +250,9 @@ inline Unordered_set_column::Unordered_set_column(Column_settings Dim_opt(), Chain_opt(), operators_(nullptr), - cellPool_(colSettings == nullptr ? nullptr : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? nullptr : &(colSettings->entryConstructor)) { - if (operators_ == nullptr && cellPool_ == nullptr) return; // to allow default constructor which gives a dummy column + if (operators_ == nullptr && entryPool_ == nullptr) return; // to allow default constructor which gives a dummy column if constexpr (!Master_matrix::Option_list::is_z2) { operators_ = &(colSettings->operators); } @@ -267,19 +267,19 @@ inline Unordered_set_column::Unordered_set_column(const Container Chain_opt(), column_(nonZeroRowIndices.size()), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Constructor not available for chain columns, please specify the dimension of the chain."); if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _insert_cell(id); + _insert_entry(id); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _insert_cell(operators_->get_value(p.second), p.first); + _insert_entry(operators_->get_value(p.second), p.first); } } } @@ -301,19 +301,19 @@ inline Unordered_set_column::Unordered_set_column(Index columnInd }()), column_(nonZeroRowIndices.size()), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Constructor not available for chain columns, please specify the dimension of the chain."); if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _insert_cell(id); + _insert_entry(id); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _insert_cell(operators_->get_value(p.second), p.first); + _insert_entry(operators_->get_value(p.second), p.first); } } } @@ -334,16 +334,16 @@ inline Unordered_set_column::Unordered_set_column(const Container }()), column_(nonZeroRowIndices.size()), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _insert_cell(id); + _insert_entry(id); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _insert_cell(operators_->get_value(p.second), p.first); + _insert_entry(operators_->get_value(p.second), p.first); } } } @@ -366,16 +366,16 @@ inline Unordered_set_column::Unordered_set_column(Index columnInd }()), column_(nonZeroRowIndices.size()), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _insert_cell(id); + _insert_entry(id); } } else { operators_ = &(colSettings->operators); for (const auto& p : nonZeroRowIndices) { - _insert_cell(operators_->get_value(p.second), p.first); + _insert_entry(operators_->get_value(p.second), p.first); } } } @@ -388,7 +388,7 @@ inline Unordered_set_column::Unordered_set_column(const Unordered Chain_opt(static_cast(column)), column_(column.column_.bucket_count()), operators_(colSettings == nullptr ? column.operators_ : nullptr), - cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor)) { static_assert(!Master_matrix::Option_list::has_row_access, "Simple copy constructor not available when row access option enabled. Please specify the new column " @@ -398,11 +398,11 @@ inline Unordered_set_column::Unordered_set_column(const Unordered if (colSettings != nullptr) operators_ = &(colSettings->operators); } - for (const Cell* cell : column.column_) { + for (const Entry* entry : column.column_) { if constexpr (Master_matrix::Option_list::is_z2) { - _insert_cell(cell->get_row_index()); + _insert_entry(entry->get_row_index()); } else { - _insert_cell(cell->get_element(), cell->get_row_index()); + _insert_entry(entry->get_element(), entry->get_row_index()); } } } @@ -418,17 +418,17 @@ inline Unordered_set_column::Unordered_set_column(const Unordered Chain_opt(static_cast(column)), column_(column.column_.bucket_count()), operators_(colSettings == nullptr ? column.operators_ : nullptr), - cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor)) { if constexpr (!Master_matrix::Option_list::is_z2) { if (colSettings != nullptr) operators_ = &(colSettings->operators); } - for (const Cell* cell : column.column_) { + for (const Entry* entry : column.column_) { if constexpr (Master_matrix::Option_list::is_z2) { - _insert_cell(cell->get_row_index()); + _insert_entry(entry->get_row_index()); } else { - _insert_cell(cell->get_element(), cell->get_row_index()); + _insert_entry(entry->get_element(), entry->get_row_index()); } } } @@ -440,15 +440,15 @@ inline Unordered_set_column::Unordered_set_column(Unordered_set_c Chain_opt(std::move(static_cast(column))), column_(std::move(column.column_)), operators_(std::exchange(column.operators_, nullptr)), - cellPool_(std::exchange(column.cellPool_, nullptr)) + entryPool_(std::exchange(column.entryPool_, nullptr)) {} template inline Unordered_set_column::~Unordered_set_column() { - for (auto* cell : column_) { - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(cell); - cellPool_->destroy(cell); + for (auto* entry : column_) { + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry); + entryPool_->destroy(entry); } } @@ -457,7 +457,7 @@ inline std::vector::Field_element> Unordered_set_column::get_content(int columnLength) const { if (columnLength < 0 && column_.size() > 0) - columnLength = (*std::max_element(column_.begin(), column_.end(), CellPointerComp()))->get_row_index() + 1; + columnLength = (*std::max_element(column_.begin(), column_.end(), EntryPointerComp()))->get_row_index() + 1; else if (columnLength < 0) return std::vector(); @@ -477,8 +477,8 @@ Unordered_set_column::get_content(int columnLength) const template inline bool Unordered_set_column::is_non_zero(ID_index rowIndex) const { - Cell cell(rowIndex); - return column_.find(&cell) != column_.end(); + Entry entry(rowIndex); + return column_.find(&entry) != column_.end(); } template @@ -503,22 +503,22 @@ inline void Unordered_set_column::reorder(const Row_index_map& va Column_support newSet; - for (Cell* cell : column_) { + for (Entry* entry : column_) { if constexpr (Master_matrix::Option_list::has_row_access) { - RA_opt::unlink(cell); - if (columnIndex != static_cast(-1)) cell->set_column_index(columnIndex); + RA_opt::unlink(entry); + if (columnIndex != static_cast(-1)) entry->set_column_index(columnIndex); } - cell->set_row_index(valueMap.at(cell->get_row_index())); - newSet.insert(cell); + entry->set_row_index(valueMap.at(entry->get_row_index())); + newSet.insert(entry); if constexpr (Master_matrix::Option_list::has_row_access && Master_matrix::Option_list::has_intrusive_rows) // intrusive list - RA_opt::insert_cell(cell->get_row_index(), cell); + RA_opt::insert_entry(entry->get_row_index(), entry); } - // when row is a set, all cells have to be deleted first, to avoid colliding when inserting + // when row is a set, all entries have to be deleted first, to avoid colliding when inserting if constexpr (Master_matrix::Option_list::has_row_access && !Master_matrix::Option_list::has_intrusive_rows) { // set - for (Cell* cell : newSet) { - RA_opt::insert_cell(cell->get_row_index(), cell); + for (Entry* entry : newSet) { + RA_opt::insert_entry(entry->get_row_index(), entry); } } @@ -531,9 +531,9 @@ inline void Unordered_set_column::clear() static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Method not available for chain columns as a base element should not be empty."); - for (auto* cell : column_) { - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(cell); - cellPool_->destroy(cell); + for (auto* entry : column_) { + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry); + entryPool_->destroy(entry); } column_.clear(); @@ -545,12 +545,12 @@ inline void Unordered_set_column::clear(ID_index rowIndex) static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Method not available for chain columns."); - auto cell = cellPool_->construct(rowIndex); - auto it = column_.find(cell); + auto entry = entryPool_->construct(rowIndex); + auto it = column_.find(entry); if (it != column_.end()) { - _delete_cell(it); + _delete_entry(it); } - cellPool_->destroy(cell); + entryPool_->destroy(entry); } template @@ -563,7 +563,7 @@ inline typename Unordered_set_column::ID_index Unordered_set_colu if (column_.empty()) return -1; // linear search could be avoided with storing the pivot. But even then, some modifications of the column requires // the max, so not clear how much it is worth it. - return (*std::max_element(column_.begin(), column_.end(), CellPointerComp()))->get_row_index(); + return (*std::max_element(column_.begin(), column_.end(), EntryPointerComp()))->get_row_index(); } else { return Chain_opt::get_pivot(); } @@ -581,11 +581,11 @@ Unordered_set_column::get_pivot_value() const } else { if constexpr (Master_matrix::Option_list::is_of_boundary_type) { if (column_.empty()) return 0; - return (*std::max_element(column_.begin(), column_.end(), CellPointerComp()))->get_element(); + return (*std::max_element(column_.begin(), column_.end(), EntryPointerComp()))->get_element(); } else { if (Chain_opt::get_pivot() == static_cast(-1)) return Field_element(); - for (const Cell* cell : column_) { - if (cell->get_row_index() == Chain_opt::get_pivot()) return cell->get_element(); + for (const Entry* entry : column_) { + if (entry->get_row_index() == Chain_opt::get_pivot()) return entry->get_element(); } return Field_element(); // should never happen if chain column is used properly } @@ -619,10 +619,10 @@ inline typename Unordered_set_column::const_iterator Unordered_se } template -template -inline Unordered_set_column& Unordered_set_column::operator+=(const Cell_range& column) +template +inline Unordered_set_column& Unordered_set_column::operator+=(const Entry_range& column) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -675,9 +675,9 @@ inline Unordered_set_column& Unordered_set_column: if (val == Field_operators::get_multiplicative_identity()) return *this; - for (Cell* cell : column_) { - operators_->multiply_inplace(cell->get_element(), val); - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_cell(*cell); + for (Entry* entry : column_) { + operators_->multiply_inplace(entry->get_element(), val); + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(*entry); } } @@ -685,11 +685,11 @@ inline Unordered_set_column& Unordered_set_column: } template -template +template inline Unordered_set_column& Unordered_set_column::multiply_target_and_add( - const Field_element& val, const Cell_range& column) + const Field_element& val, const Entry_range& column) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -747,11 +747,11 @@ inline Unordered_set_column& Unordered_set_column: } template -template +template inline Unordered_set_column& Unordered_set_column::multiply_source_and_add( - const Cell_range& column, const Field_element& val) + const Entry_range& column, const Field_element& val) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -809,20 +809,20 @@ inline Unordered_set_column& Unordered_set_column: Dim_opt::operator=(other); Chain_opt::operator=(other); - for (auto* cell : column_) { - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(cell); - cellPool_->destroy(cell); + for (auto* entry : column_) { + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry); + entryPool_->destroy(entry); } column_.clear(); operators_ = other.operators_; - cellPool_ = other.cellPool_; + entryPool_ = other.entryPool_; - for (const Cell* cell : other.column_) { + for (const Entry* entry : other.column_) { if constexpr (Master_matrix::Option_list::is_z2) { - _insert_cell(cell->get_row_index()); + _insert_entry(entry->get_row_index()); } else { - _insert_cell(cell->get_element(), cell->get_row_index()); + _insert_entry(entry->get_element(), entry->get_row_index()); } } @@ -830,65 +830,65 @@ inline Unordered_set_column& Unordered_set_column: } template -inline void Unordered_set_column::_delete_cell(typename Column_support::iterator& it) +inline void Unordered_set_column::_delete_entry(typename Column_support::iterator& it) { if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(*it); - cellPool_->destroy(*it); + entryPool_->destroy(*it); auto tmp = it++; // it = column_.erase(it); column_.erase(tmp); } template -inline typename Unordered_set_column::Cell* Unordered_set_column::_insert_cell( +inline typename Unordered_set_column::Entry* Unordered_set_column::_insert_entry( const Field_element& value, ID_index rowIndex) { if constexpr (Master_matrix::Option_list::has_row_access) { - Cell* newCell = cellPool_->construct(RA_opt::columnIndex_, rowIndex); - newCell->set_element(value); - column_.insert(newCell); - RA_opt::insert_cell(rowIndex, newCell); - return newCell; + Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex); + newEntry->set_element(value); + column_.insert(newEntry); + RA_opt::insert_entry(rowIndex, newEntry); + return newEntry; } else { - Cell* newCell = cellPool_->construct(rowIndex); - newCell->set_element(value); - column_.insert(newCell); - return newCell; + Entry* newEntry = entryPool_->construct(rowIndex); + newEntry->set_element(value); + column_.insert(newEntry); + return newEntry; } } template -inline void Unordered_set_column::_insert_cell(ID_index rowIndex) +inline void Unordered_set_column::_insert_entry(ID_index rowIndex) { if constexpr (Master_matrix::Option_list::has_row_access) { - Cell* newCell = cellPool_->construct(RA_opt::columnIndex_, rowIndex); - column_.insert(newCell); - RA_opt::insert_cell(rowIndex, newCell); + Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex); + column_.insert(newEntry); + RA_opt::insert_entry(rowIndex, newEntry); } else { - Cell* newCell = cellPool_->construct(rowIndex); - column_.insert(newCell); + Entry* newEntry = entryPool_->construct(rowIndex); + column_.insert(newEntry); } } template -template -inline bool Unordered_set_column::_add(const Cell_range& column) +template +inline bool Unordered_set_column::_add(const Entry_range& column) { return _generic_add( column, - [&](const Cell& oldCell, Cell* newCell) { - if constexpr (!Master_matrix::Option_list::is_z2) newCell->set_element(oldCell.get_element()); + [&](const Entry& oldEntry, Entry* newEntry) { + if constexpr (!Master_matrix::Option_list::is_z2) newEntry->set_element(oldEntry.get_element()); }, - [&](Cell* targetCell, const Cell& sourceCell) { + [&](Entry* targetEntry, const Entry& sourceEntry) { if constexpr (!Master_matrix::Option_list::is_z2) - operators_->add_inplace(targetCell->get_element(), sourceCell.get_element()); + operators_->add_inplace(targetEntry->get_element(), sourceEntry.get_element()); }); } template -template +template inline bool Unordered_set_column::_multiply_target_and_add(const Field_element& val, - const Cell_range& column) + const Entry_range& column) { if (val == 0u) { if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) { @@ -896,22 +896,22 @@ inline bool Unordered_set_column::_multiply_target_and_add(const // this would not only mess up the base, but also the pivots stored. } else { clear(); - for (const Cell& v : column) { - _insert_cell(v.get_element(), v.get_row_index()); + for (const Entry& v : column) { + _insert_entry(v.get_element(), v.get_row_index()); } return true; } } // because the column is unordered, I don't see a way to do both operations in one go - // without guarantees on the cell range... + // without guarantees on the entry range... operator*=(val); return _add(column); } template -template -inline bool Unordered_set_column::_multiply_source_and_add(const Cell_range& column, +template +inline bool Unordered_set_column::_multiply_source_and_add(const Entry_range& column, const Field_element& val) { if (val == 0u) { @@ -920,50 +920,50 @@ inline bool Unordered_set_column::_multiply_source_and_add(const return _generic_add( column, - [&](const Cell& oldCell, Cell* newCell) { - newCell->set_element(oldCell.get_element()); - operators_->multiply_inplace(newCell->get_element(), val); + [&](const Entry& oldEntry, Entry* newEntry) { + newEntry->set_element(oldEntry.get_element()); + operators_->multiply_inplace(newEntry->get_element(), val); }, - [&](Cell* targetCell, const Cell& sourceCell) { - operators_->multiply_and_add_inplace_back(sourceCell.get_element(), val, targetCell->get_element()); + [&](Entry* targetEntry, const Entry& sourceEntry) { + operators_->multiply_and_add_inplace_back(sourceEntry.get_element(), val, targetEntry->get_element()); }); } template -template -inline bool Unordered_set_column::_generic_add(const Cell_range& source, +template +inline bool Unordered_set_column::_generic_add(const Entry_range& source, F1&& process_source, F2&& update_target) { bool pivotIsZeroed = false; - for (const Cell& cell : source) { - Cell* newCell; + for (const Entry& entry : source) { + Entry* newEntry; if constexpr (Master_matrix::Option_list::has_row_access) { - newCell = cellPool_->construct(RA_opt::columnIndex_, cell.get_row_index()); + newEntry = entryPool_->construct(RA_opt::columnIndex_, entry.get_row_index()); } else { - newCell = cellPool_->construct(cell.get_row_index()); + newEntry = entryPool_->construct(entry.get_row_index()); } - auto res = column_.insert(newCell); + auto res = column_.insert(newEntry); if (res.second) { - process_source(cell, newCell); - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::insert_cell(cell.get_row_index(), newCell); + process_source(entry, newEntry); + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::insert_entry(entry.get_row_index(), newEntry); } else { - cellPool_->destroy(newCell); + entryPool_->destroy(newEntry); if constexpr (Master_matrix::Option_list::is_z2) { if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) { - if (cell.get_row_index() == Chain_opt::get_pivot()) pivotIsZeroed = true; + if (entry.get_row_index() == Chain_opt::get_pivot()) pivotIsZeroed = true; } - _delete_cell(res.first); + _delete_entry(res.first); } else { - update_target(*res.first, cell); + update_target(*res.first, entry); if ((*res.first)->get_element() == Field_operators::get_additive_identity()) { if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) { if ((*res.first)->get_row_index() == Chain_opt::get_pivot()) pivotIsZeroed = true; } - _delete_cell(res.first); + _delete_entry(res.first); } else { - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_cell(**res.first); + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(**res.first); } } } @@ -981,15 +981,15 @@ inline bool Unordered_set_column::_generic_add(const Cell_range& * @brief Hash method for @ref Gudhi::persistence_matrix::Unordered_set_column. * * @tparam Master_matrix Template parameter of @ref Gudhi::persistence_matrix::Unordered_set_column. - * @tparam Cell_constructor Template parameter of @ref Gudhi::persistence_matrix::Unordered_set_column. + * @tparam Entry_constructor Template parameter of @ref Gudhi::persistence_matrix::Unordered_set_column. */ template struct std::hash> { std::size_t operator()(const Gudhi::persistence_matrix::Unordered_set_column& column) const { // can't use Gudhi::persistence_matrix::hash_column because unordered std::size_t seed = 0; - for (const auto& cell : column) { - seed ^= std::hash()(cell.get_row_index() * static_cast(cell.get_element())); + for (const auto& entry : column) { + seed ^= std::hash()(entry.get_row_index() * static_cast(entry.get_element())); } return seed; } diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/vector_column.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/vector_column.h index 135d610bee..8f7d4237bd 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/vector_column.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/vector_column.h @@ -38,13 +38,13 @@ namespace persistence_matrix { * * @brief Column class following the @ref PersistenceMatrixColumn concept. * - * Column based on a vector structure. The cells are always ordered by row index, but cells are removed by + * Column based on a vector structure. The entries are always ordered by row index, but entries are removed by * @ref PersistenceMatrixColumn::clear(PersistenceMatrixOptions::Index rowIndex) "clear(Index)" in a lazy way, * so erased values can still be in the underlying container. - * On the other hand, two cells will never have the same row index. + * On the other hand, two entries will never have the same row index. * * @tparam Master_matrix An instantiation of @ref Matrix from which all types and options are deduced. - * @tparam Cell_constructor Factory of @ref Cell classes. + * @tparam Entry_constructor Factory of @ref Entry classes. */ template class Vector_column : public Master_matrix::Row_access_option, @@ -57,13 +57,13 @@ class Vector_column : public Master_matrix::Row_access_option, using ID_index = typename Master_matrix::ID_index; using Dimension = typename Master_matrix::Dimension; using Field_element = typename Master_matrix::Element; - using Cell = typename Master_matrix::Matrix_cell; + using Entry = typename Master_matrix::Matrix_entry; using Column_settings = typename Master_matrix::Column_settings; private: using Field_operators = typename Master_matrix::Field_operators; - using Column_support = std::vector; - using Cell_constructor = typename Master_matrix::Cell_constructor; + using Column_support = std::vector; + using Entry_constructor = typename Master_matrix::Entry_constructor; public: using iterator = boost::indirect_iterator; @@ -104,7 +104,7 @@ class Vector_column : public Master_matrix::Row_access_option, template void reorder(const Row_index_map& valueMap, [[maybe_unused]] Index columnIndex = -1); void clear(); - // do not clear a cell to 0 if the cell was already 0, otherwise size/is_empty will be wrong. + // do not clear an entry to 0 if the entry was already 0, otherwise size/is_empty will be wrong. void clear(ID_index rowIndex); ID_index get_pivot(); @@ -119,19 +119,19 @@ class Vector_column : public Master_matrix::Row_access_option, reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; - template - Vector_column& operator+=(const Cell_range& column); + template + Vector_column& operator+=(const Entry_range& column); Vector_column& operator+=(Vector_column& column); Vector_column& operator*=(unsigned int v); // this = v * this + column - template - Vector_column& multiply_target_and_add(const Field_element& val, const Cell_range& column); + template + Vector_column& multiply_target_and_add(const Field_element& val, const Entry_range& column); Vector_column& multiply_target_and_add(const Field_element& val, Vector_column& column); // this = this + column * v - template - Vector_column& multiply_source_and_add(const Cell_range& column, const Field_element& val); + template + Vector_column& multiply_source_and_add(const Entry_range& column, const Field_element& val); Vector_column& multiply_source_and_add(Vector_column& column, const Field_element& val); std::size_t compute_hash_value(); @@ -209,7 +209,7 @@ class Vector_column : public Master_matrix::Row_access_option, col1.column_.swap(col2.column_); col1.erasedValues_.swap(col2.erasedValues_); std::swap(col1.operators_, col2.operators_); - std::swap(col1.cellPool_, col2.cellPool_); + std::swap(col1.entryPool_, col2.entryPool_); } private: @@ -221,11 +221,11 @@ class Vector_column : public Master_matrix::Row_access_option, std::unordered_set erasedValues_; // TODO: test other containers? Useless when clear(Index) is never // called, how much is it worth it? Field_operators* operators_; - Cell_constructor* cellPool_; + Entry_constructor* entryPool_; - template - friend void _generic_merge_cell_to_column(Column& targetColumn, - Cell_iterator& itSource, + template + friend void _generic_merge_entry_to_column(Column& targetColumn, + Entry_iterator& itSource, typename Column::Column_support::iterator& itTarget, F1&& process_target, F2&& process_source, @@ -233,20 +233,20 @@ class Vector_column : public Master_matrix::Row_access_option, F4&& update_target2, bool& pivotIsZeroed); - void _delete_cell(Cell* cell); - void _delete_cell(typename Column_support::iterator& it); - Cell* _insert_cell(const Field_element& value, ID_index rowIndex, Column_support& column); - void _insert_cell(ID_index rowIndex, Column_support& column); - void _update_cell(const Field_element& value, ID_index rowIndex, Index position); - void _update_cell(ID_index rowIndex, Index position); - template - bool _add(const Cell_range& column); - template - bool _multiply_target_and_add(const Field_element& val, const Cell_range& column); - template - bool _multiply_source_and_add(const Cell_range& column, const Field_element& val); - template - bool _generic_add(const Cell_range& source, + void _delete_entry(Entry* entry); + void _delete_entry(typename Column_support::iterator& it); + Entry* _insert_entry(const Field_element& value, ID_index rowIndex, Column_support& column); + void _insert_entry(ID_index rowIndex, Column_support& column); + void _update_entry(const Field_element& value, ID_index rowIndex, Index position); + void _update_entry(ID_index rowIndex, Index position); + template + bool _add(const Entry_range& column); + template + bool _multiply_target_and_add(const Field_element& val, const Entry_range& column); + template + bool _multiply_source_and_add(const Entry_range& column, const Field_element& val); + template + bool _generic_add(const Entry_range& source, F1&& process_target, F2&& process_source, F3&& update_target1, @@ -259,9 +259,9 @@ inline Vector_column::Vector_column(Column_settings* colSettings) Dim_opt(), Chain_opt(), operators_(nullptr), - cellPool_(colSettings == nullptr ? nullptr : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? nullptr : &(colSettings->entryConstructor)) { - if (operators_ == nullptr && cellPool_ == nullptr) return; // to allow default constructor which gives a dummy column + if (operators_ == nullptr && entryPool_ == nullptr) return; // to allow default constructor which gives a dummy column if constexpr (!Master_matrix::Option_list::is_z2) { operators_ = &(colSettings->operators); } @@ -275,7 +275,7 @@ inline Vector_column::Vector_column(const Container& nonZeroRowIn Chain_opt(), column_(nonZeroRowIndices.size(), nullptr), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Constructor not available for chain columns, please specify the dimension of the chain."); @@ -287,11 +287,11 @@ inline Vector_column::Vector_column(const Container& nonZeroRowIn Index i = 0; if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _update_cell(id, i++); + _update_entry(id, i++); } } else { for (const auto& p : nonZeroRowIndices) { - _update_cell(operators_->get_value(p.second), p.first, i++); + _update_entry(operators_->get_value(p.second), p.first, i++); } } } @@ -313,7 +313,7 @@ inline Vector_column::Vector_column(Index columnIndex, }()), column_(nonZeroRowIndices.size(), nullptr), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Constructor not available for chain columns, please specify the dimension of the chain."); @@ -325,11 +325,11 @@ inline Vector_column::Vector_column(Index columnIndex, Index i = 0; if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _update_cell(id, i++); + _update_entry(id, i++); } } else { for (const auto& p : nonZeroRowIndices) { - _update_cell(operators_->get_value(p.second), p.first, i++); + _update_entry(operators_->get_value(p.second), p.first, i++); } } } @@ -350,7 +350,7 @@ inline Vector_column::Vector_column(const Container& nonZeroRowIn }()), column_(nonZeroRowIndices.size(), nullptr), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { if constexpr (!Master_matrix::Option_list::is_z2) { operators_ = &(colSettings->operators); @@ -359,11 +359,11 @@ inline Vector_column::Vector_column(const Container& nonZeroRowIn Index i = 0; if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _update_cell(id, i++); + _update_entry(id, i++); } } else { for (const auto& p : nonZeroRowIndices) { - _update_cell(operators_->get_value(p.second), p.first, i++); + _update_entry(operators_->get_value(p.second), p.first, i++); } } } @@ -386,7 +386,7 @@ inline Vector_column::Vector_column(Index columnIndex, }()), column_(nonZeroRowIndices.size(), nullptr), operators_(nullptr), - cellPool_(&(colSettings->cellConstructor)) + entryPool_(&(colSettings->entryConstructor)) { if constexpr (!Master_matrix::Option_list::is_z2) { operators_ = &(colSettings->operators); @@ -395,11 +395,11 @@ inline Vector_column::Vector_column(Index columnIndex, Index i = 0; if constexpr (Master_matrix::Option_list::is_z2) { for (ID_index id : nonZeroRowIndices) { - _update_cell(id, i++); + _update_entry(id, i++); } } else { for (const auto& p : nonZeroRowIndices) { - _update_cell(operators_->get_value(p.second), p.first, i++); + _update_entry(operators_->get_value(p.second), p.first, i++); } } } @@ -412,7 +412,7 @@ inline Vector_column::Vector_column(const Vector_column& column, column_(column.column_.size(), nullptr), erasedValues_(column.erasedValues_), operators_(colSettings == nullptr ? column.operators_ : nullptr), - cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor)) { static_assert(!Master_matrix::Option_list::has_row_access, "Simple copy constructor not available when row access option enabled. Please specify the new column " @@ -423,11 +423,11 @@ inline Vector_column::Vector_column(const Vector_column& column, } Index i = 0; - for (const Cell* cell : column.column_) { + for (const Entry* entry : column.column_) { if constexpr (Master_matrix::Option_list::is_z2) { - _update_cell(cell->get_row_index(), i++); + _update_entry(entry->get_row_index(), i++); } else { - _update_cell(cell->get_element(), cell->get_row_index(), i++); + _update_entry(entry->get_element(), entry->get_row_index(), i++); } } } @@ -444,18 +444,18 @@ inline Vector_column::Vector_column(const Vector_column& column, column_(column.column_.size(), nullptr), erasedValues_(column.erasedValues_), operators_(colSettings == nullptr ? column.operators_ : nullptr), - cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor)) + entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor)) { if constexpr (!Master_matrix::Option_list::is_z2) { if (colSettings != nullptr) operators_ = &(colSettings->operators); } Index i = 0; - for (const Cell* cell : column.column_) { + for (const Entry* entry : column.column_) { if constexpr (Master_matrix::Option_list::is_z2) { - _update_cell(cell->get_row_index(), i++); + _update_entry(entry->get_row_index(), i++); } else { - _update_cell(cell->get_element(), cell->get_row_index(), i++); + _update_entry(entry->get_element(), entry->get_row_index(), i++); } } } @@ -468,14 +468,14 @@ inline Vector_column::Vector_column(Vector_column&& column) noexc column_(std::move(column.column_)), erasedValues_(std::move(column.erasedValues_)), operators_(std::exchange(column.operators_, nullptr)), - cellPool_(std::exchange(column.cellPool_, nullptr)) + entryPool_(std::exchange(column.entryPool_, nullptr)) {} template inline Vector_column::~Vector_column() { - for (auto* cell : column_) { - _delete_cell(cell); + for (auto* entry : column_) { + _delete_entry(entry); } } @@ -509,9 +509,9 @@ inline bool Vector_column::is_non_zero(ID_index rowIndex) const if constexpr (!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type) if (erasedValues_.find(rowIndex) != erasedValues_.end()) return false; - Cell cell(rowIndex); - return std::binary_search(column_.begin(), column_.end(), &cell, - [](const Cell* a, const Cell* b) { return a->get_row_index() < b->get_row_index(); }); + Entry entry(rowIndex); + return std::binary_search(column_.begin(), column_.end(), &entry, + [](const Entry* a, const Entry* b) { return a->get_row_index() < b->get_row_index(); }); } template @@ -544,47 +544,47 @@ inline void Vector_column::reorder(const Row_index_map& valueMap, "Method not available for chain columns."); if (erasedValues_.empty()) { // to avoid useless push_backs. - for (Cell* cell : column_) { + for (Entry* entry : column_) { if constexpr (Master_matrix::Option_list::has_row_access) { - RA_opt::unlink(cell); - if (columnIndex != static_cast(-1)) cell->set_column_index(columnIndex); + RA_opt::unlink(entry); + if (columnIndex != static_cast(-1)) entry->set_column_index(columnIndex); } - cell->set_row_index(valueMap.at(cell->get_row_index())); + entry->set_row_index(valueMap.at(entry->get_row_index())); if constexpr (Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access) - RA_opt::insert_cell(cell->get_row_index(), cell); + RA_opt::insert_entry(entry->get_row_index(), entry); } - // all cells have to be deleted first, to avoid problem with insertion when row is a set + // all entries have to be deleted first, to avoid problem with insertion when row is a set if constexpr (!Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access) { - for (Cell* cell : column_) { - RA_opt::insert_cell(cell->get_row_index(), cell); + for (Entry* entry : column_) { + RA_opt::insert_entry(entry->get_row_index(), entry); } } - std::sort(column_.begin(), column_.end(), [](const Cell* c1, const Cell* c2) { return *c1 < *c2; }); + std::sort(column_.begin(), column_.end(), [](const Entry* c1, const Entry* c2) { return *c1 < *c2; }); } else { Column_support newColumn; - for (Cell* cell : column_) { - if (erasedValues_.find(cell->get_row_index()) == erasedValues_.end()) { + for (Entry* entry : column_) { + if (erasedValues_.find(entry->get_row_index()) == erasedValues_.end()) { if constexpr (Master_matrix::Option_list::has_row_access) { - RA_opt::unlink(cell); - if (columnIndex != static_cast(-1)) cell->set_column_index(columnIndex); + RA_opt::unlink(entry); + if (columnIndex != static_cast(-1)) entry->set_column_index(columnIndex); } - cell->set_row_index(valueMap.at(cell->get_row_index())); - newColumn.push_back(cell); + entry->set_row_index(valueMap.at(entry->get_row_index())); + newColumn.push_back(entry); if constexpr (Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access) - RA_opt::insert_cell(cell->get_row_index(), cell); + RA_opt::insert_entry(entry->get_row_index(), entry); } else { - _delete_cell(cell); + _delete_entry(entry); } } - // all cells have to be deleted first, to avoid problem with insertion when row is a set + // all entries have to be deleted first, to avoid problem with insertion when row is a set if constexpr (!Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access) { - for (Cell* cell : column_) { - RA_opt::insert_cell(cell->get_row_index(), cell); + for (Entry* entry : column_) { + RA_opt::insert_entry(entry->get_row_index(), entry); } } - std::sort(newColumn.begin(), newColumn.end(), [](const Cell* c1, const Cell* c2) { return *c1 < *c2; }); + std::sort(newColumn.begin(), newColumn.end(), [](const Entry* c1, const Entry* c2) { return *c1 < *c2; }); erasedValues_.clear(); column_.swap(newColumn); } @@ -596,9 +596,9 @@ inline void Vector_column::clear() static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type, "Method not available for chain columns as a base element should not be empty."); - for (auto* cell : column_) { - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(cell); - cellPool_->destroy(cell); + for (auto* entry : column_) { + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry); + entryPool_->destroy(entry); } column_.clear(); @@ -627,7 +627,7 @@ inline typename Vector_column::ID_index Vector_columnget_row_index()); while (!column_.empty() && it != erasedValues_.end()) { erasedValues_.erase(it); - _delete_cell(column_.back()); + _delete_entry(column_.back()); column_.pop_back(); if (!column_.empty()) it = erasedValues_.find(column_.back()->get_row_index()); } @@ -655,7 +655,7 @@ inline typename Vector_column::Field_element Vector_columnget_row_index()); while (!column_.empty() && it != erasedValues_.end()) { erasedValues_.erase(it); - _delete_cell(column_.back()); + _delete_entry(column_.back()); column_.pop_back(); if (!column_.empty()) it = erasedValues_.find(column_.back()->get_row_index()); } @@ -664,8 +664,8 @@ inline typename Vector_column::Field_element Vector_columnget_element(); } else { if (Chain_opt::get_pivot() == static_cast(-1)) return Field_element(); - for (const Cell* cell : column_) { - if (cell->get_row_index() == Chain_opt::get_pivot()) return cell->get_element(); + for (const Entry* entry : column_) { + if (entry->get_row_index() == Chain_opt::get_pivot()) return entry->get_element(); } return Field_element(); // should never happen if chain column is used properly } @@ -723,10 +723,10 @@ inline typename Vector_column::const_reverse_iterator Vector_colu } template -template -inline Vector_column& Vector_column::operator+=(const Cell_range& column) +template +inline Vector_column& Vector_column::operator+=(const Entry_range& column) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -778,9 +778,9 @@ inline Vector_column& Vector_column::operator*=(un if (val == Field_operators::get_multiplicative_identity()) return *this; - for (Cell* cell : column_) { - operators_->multiply_inplace(cell->get_element(), val); - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_cell(*cell); + for (Entry* entry : column_) { + operators_->multiply_inplace(entry->get_element(), val); + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(*entry); } } @@ -788,11 +788,11 @@ inline Vector_column& Vector_column::operator*=(un } template -template +template inline Vector_column& Vector_column::multiply_target_and_add(const Field_element& val, - const Cell_range& column) + const Entry_range& column) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -850,11 +850,11 @@ inline Vector_column& Vector_column::multiply_targ } template -template -inline Vector_column& Vector_column::multiply_source_and_add(const Cell_range& column, +template +inline Vector_column& Vector_column::multiply_source_and_add(const Entry_range& column, const Field_element& val) { - static_assert((!Master_matrix::isNonBasic || std::is_same_v), + static_assert((!Master_matrix::isNonBasic || std::is_same_v), "For boundary columns, the range has to be a column of same type to help ensure the validity of the " "base element."); // could be removed, if we give the responsibility to the user. static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type), @@ -911,8 +911,8 @@ inline Vector_column& Vector_column::operator=(con Dim_opt::operator=(other); Chain_opt::operator=(other); - auto tmpPool = cellPool_; - cellPool_ = other.cellPool_; + auto tmpPool = entryPool_; + entryPool_ = other.entryPool_; while (column_.size() > other.column_.size()) { if (column_.back() != nullptr) { @@ -924,15 +924,15 @@ inline Vector_column& Vector_column::operator=(con column_.resize(other.column_.size(), nullptr); Index i = 0; - for (const Cell* cell : other.column_) { + for (const Entry* entry : other.column_) { if (column_[i] != nullptr) { if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(column_[i]); tmpPool->destroy(column_[i]); } if constexpr (Master_matrix::Option_list::is_z2) { - _update_cell(cell->get_row_index(), i++); + _update_entry(entry->get_row_index(), i++); } else { - _update_cell(cell->get_element(), cell->get_row_index(), i++); + _update_entry(entry->get_element(), entry->get_row_index(), i++); } } erasedValues_ = other.erasedValues_; @@ -945,9 +945,9 @@ template inline std::size_t Vector_column::compute_hash_value() { std::size_t seed = 0; - for (Cell* cell : column_) { - if (erasedValues_.find(cell->get_row_index()) == erasedValues_.end()) { - seed ^= std::hash()(cell->get_row_index() * static_cast(cell->get_element())) + + for (Entry* entry : column_) { + if (erasedValues_.find(entry->get_row_index()) == erasedValues_.end()) { + seed ^= std::hash()(entry->get_row_index() * static_cast(entry->get_element())) + 0x9e3779b9 + (seed << 6) + (seed >> 2); } } @@ -955,89 +955,89 @@ inline std::size_t Vector_column::compute_hash_value() } template -inline void Vector_column::_delete_cell(Cell* cell) +inline void Vector_column::_delete_entry(Entry* entry) { - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(cell); - cellPool_->destroy(cell); + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry); + entryPool_->destroy(entry); } template -inline void Vector_column::_delete_cell(typename Column_support::iterator& it) +inline void Vector_column::_delete_entry(typename Column_support::iterator& it) { - _delete_cell(*it); + _delete_entry(*it); ++it; } template -inline typename Vector_column::Cell* Vector_column::_insert_cell( +inline typename Vector_column::Entry* Vector_column::_insert_entry( const Field_element& value, ID_index rowIndex, Column_support& column) { if constexpr (Master_matrix::Option_list::has_row_access) { - Cell* newCell = cellPool_->construct(RA_opt::columnIndex_, rowIndex); - newCell->set_element(value); - column.push_back(newCell); - RA_opt::insert_cell(rowIndex, newCell); - return newCell; + Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex); + newEntry->set_element(value); + column.push_back(newEntry); + RA_opt::insert_entry(rowIndex, newEntry); + return newEntry; } else { - Cell* newCell = cellPool_->construct(rowIndex); - newCell->set_element(value); - column.push_back(newCell); - return newCell; + Entry* newEntry = entryPool_->construct(rowIndex); + newEntry->set_element(value); + column.push_back(newEntry); + return newEntry; } } template -inline void Vector_column::_insert_cell(ID_index rowIndex, Column_support& column) +inline void Vector_column::_insert_entry(ID_index rowIndex, Column_support& column) { if constexpr (Master_matrix::Option_list::has_row_access) { - Cell* newCell = cellPool_->construct(RA_opt::columnIndex_, rowIndex); - column.push_back(newCell); - RA_opt::insert_cell(rowIndex, newCell); + Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex); + column.push_back(newEntry); + RA_opt::insert_entry(rowIndex, newEntry); } else { - Cell* newCell = cellPool_->construct(rowIndex); - column.push_back(newCell); + Entry* newEntry = entryPool_->construct(rowIndex); + column.push_back(newEntry); } } template -inline void Vector_column::_update_cell(const Field_element& value, ID_index rowIndex, Index position) +inline void Vector_column::_update_entry(const Field_element& value, ID_index rowIndex, Index position) { if constexpr (Master_matrix::Option_list::has_row_access) { - Cell* newCell = cellPool_->construct(RA_opt::columnIndex_, rowIndex); - newCell->set_element(value); - column_[position] = newCell; - RA_opt::insert_cell(rowIndex, newCell); + Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex); + newEntry->set_element(value); + column_[position] = newEntry; + RA_opt::insert_entry(rowIndex, newEntry); } else { - column_[position] = cellPool_->construct(rowIndex); + column_[position] = entryPool_->construct(rowIndex); column_[position]->set_element(value); } } template -inline void Vector_column::_update_cell(ID_index rowIndex, Index position) +inline void Vector_column::_update_entry(ID_index rowIndex, Index position) { if constexpr (Master_matrix::Option_list::has_row_access) { - Cell* newCell = cellPool_->construct(RA_opt::columnIndex_, rowIndex); - column_[position] = newCell; - RA_opt::insert_cell(rowIndex, newCell); + Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex); + column_[position] = newEntry; + RA_opt::insert_entry(rowIndex, newEntry); } else { - column_[position] = cellPool_->construct(rowIndex); + column_[position] = entryPool_->construct(rowIndex); } } template -template -inline bool Vector_column::_add(const Cell_range& column) +template +inline bool Vector_column::_add(const Entry_range& column) { if (column.begin() == column.end()) return false; if (column_.empty()) { // chain should never enter here. column_.resize(column.size()); Index i = 0; - for (const Cell& cell : column) { + for (const Entry& entry : column) { if constexpr (Master_matrix::Option_list::is_z2) { - _update_cell(cell.get_row_index(), i++); + _update_entry(entry.get_row_index(), i++); } else { - _update_cell(cell.get_element(), cell.get_row_index(), i++); + _update_entry(entry.get_element(), entry.get_row_index(), i++); } } return true; @@ -1048,20 +1048,20 @@ inline bool Vector_column::_add(const Cell_range& column) auto pivotIsZeroed = _generic_add( column, - [&](Cell* cellTarget) { newColumn.push_back(cellTarget); }, - [&](typename Cell_range::const_iterator& itSource, + [&](Entry* entryTarget) { newColumn.push_back(entryTarget); }, + [&](typename Entry_range::const_iterator& itSource, [[maybe_unused]] const typename Column_support::iterator& itTarget) { if constexpr (Master_matrix::Option_list::is_z2) { - _insert_cell(itSource->get_row_index(), newColumn); + _insert_entry(itSource->get_row_index(), newColumn); } else { - _insert_cell(itSource->get_element(), itSource->get_row_index(), newColumn); + _insert_entry(itSource->get_element(), itSource->get_row_index(), newColumn); } }, - [&](Field_element& targetElement, typename Cell_range::const_iterator& itSource) { + [&](Field_element& targetElement, typename Entry_range::const_iterator& itSource) { if constexpr (!Master_matrix::Option_list::is_z2) operators_->add_inplace(targetElement, itSource->get_element()); }, - [&](Cell* cellTarget) { newColumn.push_back(cellTarget); } + [&](Entry* entryTarget) { newColumn.push_back(entryTarget); } ); column_.swap(newColumn); @@ -1070,8 +1070,8 @@ inline bool Vector_column::_add(const Cell_range& column) } template -template -inline bool Vector_column::_multiply_target_and_add(const Field_element& val, const Cell_range& column) +template +inline bool Vector_column::_multiply_target_and_add(const Field_element& val, const Entry_range& column) { if (val == 0u) { if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) { @@ -1084,14 +1084,14 @@ inline bool Vector_column::_multiply_target_and_add(const Field_e if (column_.empty()) { // chain should never enter here. column_.resize(column.size()); Index i = 0; - for (const Cell& cell : column) { + for (const Entry& entry : column) { if constexpr (Master_matrix::Option_list::is_z2) { - _update_cell(cell.get_row_index(), i++); + _update_entry(entry.get_row_index(), i++); } else { - _update_cell(cell.get_element(), cell.get_row_index(), i++); + _update_entry(entry.get_element(), entry.get_row_index(), i++); } } - if constexpr (std::is_same_v >) erasedValues_ = column.erasedValues_; + if constexpr (std::is_same_v >) erasedValues_ = column.erasedValues_; return true; } @@ -1100,18 +1100,18 @@ inline bool Vector_column::_multiply_target_and_add(const Field_e auto pivotIsZeroed = _generic_add( column, - [&](Cell* cellTarget) { - operators_->multiply_inplace(cellTarget->get_element(), val); - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_cell(*cellTarget); - newColumn.push_back(cellTarget); + [&](Entry* entryTarget) { + operators_->multiply_inplace(entryTarget->get_element(), val); + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(*entryTarget); + newColumn.push_back(entryTarget); }, - [&](typename Cell_range::const_iterator& itSource, const typename Column_support::iterator& itTarget) { - _insert_cell(itSource->get_element(), itSource->get_row_index(), newColumn); + [&](typename Entry_range::const_iterator& itSource, const typename Column_support::iterator& itTarget) { + _insert_entry(itSource->get_element(), itSource->get_row_index(), newColumn); }, - [&](Field_element& targetElement, typename Cell_range::const_iterator& itSource) { + [&](Field_element& targetElement, typename Entry_range::const_iterator& itSource) { operators_->multiply_and_add_inplace_front(targetElement, val, itSource->get_element()); }, - [&](Cell* cellTarget) { newColumn.push_back(cellTarget); } + [&](Entry* entryTarget) { newColumn.push_back(entryTarget); } ); column_.swap(newColumn); @@ -1120,8 +1120,8 @@ inline bool Vector_column::_multiply_target_and_add(const Field_e } template -template -inline bool Vector_column::_multiply_source_and_add(const Cell_range& column, const Field_element& val) +template +inline bool Vector_column::_multiply_source_and_add(const Entry_range& column, const Field_element& val) { if (val == 0u || column.begin() == column.end()) { return false; @@ -1132,16 +1132,16 @@ inline bool Vector_column::_multiply_source_and_add(const Cell_ra auto pivotIsZeroed = _generic_add( column, - [&](Cell* cellTarget) { newColumn.push_back(cellTarget); }, - [&](typename Cell_range::const_iterator& itSource, const typename Column_support::iterator& itTarget) { - Cell* newCell = _insert_cell(itSource->get_element(), itSource->get_row_index(), newColumn); - operators_->multiply_inplace(newCell->get_element(), val); - if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_cell(*newCell); + [&](Entry* entryTarget) { newColumn.push_back(entryTarget); }, + [&](typename Entry_range::const_iterator& itSource, const typename Column_support::iterator& itTarget) { + Entry* newEntry = _insert_entry(itSource->get_element(), itSource->get_row_index(), newColumn); + operators_->multiply_inplace(newEntry->get_element(), val); + if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(*newEntry); }, - [&](Field_element& targetElement, typename Cell_range::const_iterator& itSource) { + [&](Field_element& targetElement, typename Entry_range::const_iterator& itSource) { operators_->multiply_and_add_inplace_back(itSource->get_element(), val, targetElement); }, - [&](Cell* cellTarget) { newColumn.push_back(cellTarget); } + [&](Entry* entryTarget) { newColumn.push_back(entryTarget); } ); column_.swap(newColumn); @@ -1150,8 +1150,8 @@ inline bool Vector_column::_multiply_source_and_add(const Cell_ra } template -template -inline bool Vector_column::_generic_add(const Cell_range& column, +template +inline bool Vector_column::_generic_add(const Entry_range& column, F1&& process_target, F2&& process_source, F3&& update_target1, @@ -1160,13 +1160,13 @@ inline bool Vector_column::_generic_add(const Cell_range& column, auto updateTargetIterator = [&](typename Column_support::iterator& itTarget) { if constexpr (!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type) { while (itTarget != column_.end() && erasedValues_.find((*itTarget)->get_row_index()) != erasedValues_.end()) { - _delete_cell(*itTarget); + _delete_entry(*itTarget); ++itTarget; } } }; - auto updateSourceIterator = [&](typename Cell_range::const_iterator& itSource) { - if constexpr (std::is_same_v > && + auto updateSourceIterator = [&](typename Entry_range::const_iterator& itSource) { + if constexpr (std::is_same_v > && (!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type)) { while (itSource != column.end() && column.erasedValues_.find(itSource->get_row_index()) != column.erasedValues_.end()) @@ -1183,9 +1183,9 @@ inline bool Vector_column::_generic_add(const Cell_range& column, updateSourceIterator(itSource); if (itTarget == column_.end() || itSource == column.end()) break; - _generic_merge_cell_to_column(*this, itSource, itTarget, - process_target, process_source, update_target1, update_target2, - pivotIsZeroed); + _generic_merge_entry_to_column(*this, itSource, itTarget, + process_target, process_source, update_target1, update_target2, + pivotIsZeroed); } while (itSource != column.end()) { @@ -1218,7 +1218,7 @@ inline bool Vector_column::_generic_add(const Cell_range& column, * @brief Hash method for @ref Gudhi::persistence_matrix::Vector_column. * * @tparam Master_matrix Template parameter of @ref Gudhi::persistence_matrix::Vector_column. - * @tparam Cell_constructor Template parameter of @ref Gudhi::persistence_matrix::Vector_column. + * @tparam Entry_constructor Template parameter of @ref Gudhi::persistence_matrix::Vector_column. */ template struct std::hash > { diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/matrix_row_access.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/matrix_row_access.h index cb1f92ba65..925f573f7b 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/matrix_row_access.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/matrix_row_access.h @@ -42,8 +42,8 @@ struct Dummy_matrix_row_access * * @brief Class managing the row access for the inheriting matrix. * - * @tparam Row Either boost::intrusive::list if @ref PersistenceMatrixOptions::has_intrusive_rows - * is true, or std::set otherwise. + * @tparam Row Either boost::intrusive::list if @ref PersistenceMatrixOptions::has_intrusive_rows + * is true, or std::set otherwise. * @tparam Row_container Either std::map if @ref PersistenceMatrixOptions::has_removable_rows is * true, or std::vector otherwise. * @tparam has_removable_rows Value of @ref PersistenceMatrixOptions::has_removable_rows. diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/ru_rep_cycles.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/ru_rep_cycles.h index 330eec4d65..ea77ccb9e8 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/ru_rep_cycles.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/ru_rep_cycles.h @@ -148,8 +148,8 @@ inline void RU_representative_cycles::update_representative_cycle representativeCycles_.clear(); representativeCycles_.resize(c); for (Index i = 0; i < _matrix()->mirrorMatrixU_.get_number_of_columns(); i++) { - for (const auto& cell : _matrix()->mirrorMatrixU_.get_column(i)) { - auto idx = birthToCycle_[cell.get_row_index()]; + for (const auto& entry : _matrix()->mirrorMatrixU_.get_column(i)) { + auto idx = birthToCycle_[entry.get_row_index()]; if (idx != static_cast(-1)) { representativeCycles_[idx].push_back(i); } @@ -161,8 +161,8 @@ inline void RU_representative_cycles::update_representative_cycle for (Index i = 0; i < _matrix()->reducedMatrixR_.get_number_of_columns(); i++) { if (_matrix()->reducedMatrixR_.is_zero_column(i)) { representativeCycles_.push_back(Cycle()); - for (const auto& cell : _matrix()->mirrorMatrixU_.get_column(i)) { - representativeCycles_.back().push_back(cell.get_row_index()); + for (const auto& entry : _matrix()->mirrorMatrixU_.get_column(i)) { + representativeCycles_.back().push_back(entry.get_row_index()); } if constexpr (std::is_same_v || std::is_same_v::vine_swap_with_z_eq_1_case(Pos_index in bool iiIsPositive = _matrix()->reducedMatrixR_.is_zero_column(index + 1); if (iIsPositive && iiIsPositive) { - _matrix()->mirrorMatrixU_.zero_cell(index, _get_row_id_from_position(index + 1)); + _matrix()->mirrorMatrixU_.zero_entry(index, _get_row_id_from_position(index + 1)); return _positive_vine_swap(index); } else if (!iIsPositive && !iiIsPositive) { return _negative_vine_swap(index); @@ -228,14 +228,14 @@ inline bool RU_vine_swap::vine_swap(Pos_index index) _swap_at_index(index); return true; } - if (!_matrix()->mirrorMatrixU_.is_zero_cell(index, _get_row_id_from_position(index + 1))) { - _matrix()->mirrorMatrixU_.zero_cell(index, _get_row_id_from_position(index + 1)); + if (!_matrix()->mirrorMatrixU_.is_zero_entry(index, _get_row_id_from_position(index + 1))) { + _matrix()->mirrorMatrixU_.zero_entry(index, _get_row_id_from_position(index + 1)); } return _positive_vine_swap(index); } else if (!iIsPositive && !iiIsPositive) { if (_matrix()->reducedMatrixR_.get_column_dimension(index) != _matrix()->reducedMatrixR_.get_column_dimension(index + 1) || - _matrix()->mirrorMatrixU_.is_zero_cell(index, _get_row_id_from_position(index + 1))) { + _matrix()->mirrorMatrixU_.is_zero_entry(index, _get_row_id_from_position(index + 1))) { _negative_transpose(index); _swap_at_index(index); return true; @@ -244,7 +244,7 @@ inline bool RU_vine_swap::vine_swap(Pos_index index) } else if (iIsPositive && !iiIsPositive) { if (_matrix()->reducedMatrixR_.get_column_dimension(index) != _matrix()->reducedMatrixR_.get_column_dimension(index + 1) || - _matrix()->mirrorMatrixU_.is_zero_cell(index, _get_row_id_from_position(index + 1))) { + _matrix()->mirrorMatrixU_.is_zero_entry(index, _get_row_id_from_position(index + 1))) { _positive_negative_transpose(index); _swap_at_index(index); return true; @@ -253,7 +253,7 @@ inline bool RU_vine_swap::vine_swap(Pos_index index) } else { if (_matrix()->reducedMatrixR_.get_column_dimension(index) != _matrix()->reducedMatrixR_.get_column_dimension(index + 1) || - _matrix()->mirrorMatrixU_.is_zero_cell(index, _get_row_id_from_position(index + 1))) { + _matrix()->mirrorMatrixU_.is_zero_entry(index, _get_row_id_from_position(index + 1))) { _negative_positive_transpose(index); _swap_at_index(index); return true; @@ -392,7 +392,7 @@ inline bool RU_vine_swap::_positive_vine_swap(Index columnIndex) const Pos_index iiDeath = _get_death(columnIndex + 1); if (iDeath != static_cast(-1) && iiDeath != static_cast(-1) && - !(_matrix()->reducedMatrixR_.is_zero_cell(iiDeath, _get_row_id_from_position(columnIndex)))) { + !(_matrix()->reducedMatrixR_.is_zero_entry(iiDeath, _get_row_id_from_position(columnIndex)))) { if (iDeath < iiDeath) { _swap_at_index(columnIndex); _add_to(iDeath, iiDeath); @@ -408,7 +408,7 @@ inline bool RU_vine_swap::_positive_vine_swap(Index columnIndex) _swap_at_index(columnIndex); if (iDeath != static_cast(-1) || iiDeath == static_cast(-1) || - _matrix()->reducedMatrixR_.is_zero_cell(iiDeath, _get_row_id_from_position(columnIndex + 1))) { + _matrix()->reducedMatrixR_.is_zero_entry(iiDeath, _get_row_id_from_position(columnIndex + 1))) { _positive_transpose(columnIndex); return true; } @@ -437,7 +437,7 @@ inline bool RU_vine_swap::_negative_vine_swap(Index columnIndex) template inline bool RU_vine_swap::_positive_negative_vine_swap(Index columnIndex) { - _matrix()->mirrorMatrixU_.zero_cell(columnIndex, _get_row_id_from_position(columnIndex + 1)); + _matrix()->mirrorMatrixU_.zero_entry(columnIndex, _get_row_id_from_position(columnIndex + 1)); _swap_at_index(columnIndex); _positive_negative_transpose(columnIndex); diff --git a/src/Persistence_matrix/include/gudhi/persistence_matrix_options.h b/src/Persistence_matrix/include/gudhi/persistence_matrix_options.h index 276dad72fa..58f7bc117c 100644 --- a/src/Persistence_matrix/include/gudhi/persistence_matrix_options.h +++ b/src/Persistence_matrix/include/gudhi/persistence_matrix_options.h @@ -28,16 +28,16 @@ namespace persistence_matrix { * @brief List of column types. */ enum class Column_types { - LIST, /**< @ref List_column "": Underlying container is a std::list<@ref Cell*>. */ - SET, /**< @ref Set_column "": Underlying container is a std::set<@ref Cell*>. */ - HEAP, /**< @ref Heap_column "": Underlying container is a std::vector<@ref Cell*> ordered as a heap. + LIST, /**< @ref List_column "": Underlying container is a std::list<@ref Entry*>. */ + SET, /**< @ref Set_column "": Underlying container is a std::set<@ref Entry*>. */ + HEAP, /**< @ref Heap_column "": Underlying container is a std::vector<@ref Entry*> ordered as a heap. Is not compatible with row access and column compression. */ - VECTOR, /**< @ref Vector_column "": Underlying container is a std::vector<@ref Cell*> + VECTOR, /**< @ref Vector_column "": Underlying container is a std::vector<@ref Entry*> with a lazy removal method. */ - NAIVE_VECTOR, /**< @ref Naive_vector_column "": Underlying container is a std::vector<@ref Cell*>. */ - UNORDERED_SET, /**< @ref Unordered_set_column "": Underlying container is a std::unordered_set<@ref Cell*>. */ - INTRUSIVE_LIST, /**< @ref Intrusive_list_column "": Underlying container is a boost::intrusive::list<@ref Cell>. */ - INTRUSIVE_SET /**< @ref Intrusive_set_column "": Underlying container is a boost::intrusive::set<@ref Cell>. */ + NAIVE_VECTOR, /**< @ref Naive_vector_column "": Underlying container is a std::vector<@ref Entry*>. */ + UNORDERED_SET, /**< @ref Unordered_set_column "": Underlying container is a std::unordered_set<@ref Entry*>. */ + INTRUSIVE_LIST, /**< @ref Intrusive_list_column "": Underlying container is a boost::intrusive::list<@ref Entry>. */ + INTRUSIVE_SET /**< @ref Intrusive_set_column "": Underlying container is a boost::intrusive::set<@ref Entry>. */ }; /** diff --git a/src/Persistence_matrix/test/pm_column_tests.h b/src/Persistence_matrix/test/pm_column_tests.h index 29b4bea883..01d8759743 100644 --- a/src/Persistence_matrix/test/pm_column_tests.h +++ b/src/Persistence_matrix/test/pm_column_tests.h @@ -28,11 +28,11 @@ std::vector > get_ordered_column_contents(std::vector::type> > ordCol(matrix.size()); for (unsigned int i = 0; i < matrix.size(); ++i) { Column& col = matrix[i]; - for (auto& cell : col) { + for (auto& entry : col) { if constexpr (is_z2()) { - ordCol[i].insert(cell.get_row_index()); + ordCol[i].insert(entry.get_row_index()); } else { - ordCol[i].insert({cell.get_row_index(), cell.get_element()}); + ordCol[i].insert({entry.get_row_index(), entry.get_element()}); } } } @@ -47,12 +47,12 @@ std::vector > get_ordered_rows(std::vector& matri std::pair >::type> > rows; for (Column& col : matrix) { - for (auto& cell : col) { - if (cell.get_row_index() >= rows.size()) rows.resize(cell.get_row_index() + 1); + for (auto& entry : col) { + if (entry.get_row_index() >= rows.size()) rows.resize(entry.get_row_index() + 1); if constexpr (is_z2()) { - rows[cell.get_row_index()].insert(cell.get_column_index()); + rows[entry.get_row_index()].insert(entry.get_column_index()); } else { - rows[cell.get_row_index()].insert({cell.get_column_index(), cell.get_element()}); + rows[entry.get_row_index()].insert({entry.get_column_index(), entry.get_element()}); } } } @@ -166,11 +166,11 @@ std::vector >::type> > build_rows() { - using cell_type = typename std::conditional(), - unsigned int, - std::pair - >::type; - using Container = std::vector; + using entry_type = typename std::conditional(), + unsigned int, + std::pair + >::type; + using Container = std::vector; std::vector rows(7); if constexpr (is_z2()) { @@ -200,11 +200,11 @@ std::vector >::type> > build_column_values() { - using cell_type = typename std::conditional(), - unsigned int, - std::pair - >::type; - using Container = std::vector; + using entry_type = typename std::conditional(), + unsigned int, + std::pair + >::type; + using Container = std::vector; std::vector columns(6); if constexpr (is_z2()) { @@ -228,11 +228,11 @@ std::vector void column_test_common_constructors() { - using cell_type = typename std::conditional(), - unsigned int, - std::pair - >::type; - using Container = std::vector; + using entry_type = typename std::conditional(), + unsigned int, + std::pair + >::type; + using Container = std::vector; Container cont1, cont2; typename Column::Column_settings settings(5); @@ -278,9 +278,9 @@ void column_test_common_constructors() { BOOST_CHECK_EQUAL(rows.size(), 0); } -template +template void column_test_common_content_access(Column& col, - const std::set& setcont, + const std::set& setcont, const std::vector& veccont) { BOOST_CHECK(get_column_content_via_iterators(col) == setcont); BOOST_CHECK(col.get_content(veccont.size()) == veccont); @@ -519,18 +519,18 @@ void column_test_row_access_constructors(std::vector& matrix, Row_contai for (auto& r : rows) { if constexpr (Column::Master::Option_list::has_removable_rows) { if (!r.second.empty()) { - auto& cell = *r.second.rbegin(); - if (cell.get_row_index() == 0 || cell.get_row_index() == 1 || cell.get_row_index() == 3 || - cell.get_row_index() == 5) { - BOOST_CHECK_EQUAL(cell.get_column_index(), 6); + auto& entry = *r.second.rbegin(); + if (entry.get_row_index() == 0 || entry.get_row_index() == 1 || entry.get_row_index() == 3 || + entry.get_row_index() == 5) { + BOOST_CHECK_EQUAL(entry.get_column_index(), 6); } } } else { if (!r.empty()) { - auto& cell = *r.rbegin(); - if (cell.get_row_index() == 0 || cell.get_row_index() == 1 || cell.get_row_index() == 3 || - cell.get_row_index() == 5) { - BOOST_CHECK_EQUAL(cell.get_column_index(), 6); + auto& entry = *r.rbegin(); + if (entry.get_row_index() == 0 || entry.get_row_index() == 1 || entry.get_row_index() == 3 || + entry.get_row_index() == 5) { + BOOST_CHECK_EQUAL(entry.get_column_index(), 6); } } } @@ -543,18 +543,18 @@ void column_test_row_access_constructors(std::vector& matrix, Row_contai for (auto& r : rows) { if constexpr (Column::Master::Option_list::has_removable_rows) { if (!r.second.empty()) { - auto& cell = *r.second.rbegin(); - if (cell.get_row_index() == 0 || cell.get_row_index() == 1 || cell.get_row_index() == 3 || - cell.get_row_index() == 5) { - BOOST_CHECK_EQUAL(cell.get_column_index(), 6); + auto& entry = *r.second.rbegin(); + if (entry.get_row_index() == 0 || entry.get_row_index() == 1 || entry.get_row_index() == 3 || + entry.get_row_index() == 5) { + BOOST_CHECK_EQUAL(entry.get_column_index(), 6); } } } else { if (!r.empty()) { - auto& cell = *r.rbegin(); - if (cell.get_row_index() == 0 || cell.get_row_index() == 1 || cell.get_row_index() == 3 || - cell.get_row_index() == 5) { - BOOST_CHECK_EQUAL(cell.get_column_index(), 6); + auto& entry = *r.rbegin(); + if (entry.get_row_index() == 0 || entry.get_row_index() == 1 || entry.get_row_index() == 3 || + entry.get_row_index() == 5) { + BOOST_CHECK_EQUAL(entry.get_column_index(), 6); } } } @@ -567,18 +567,18 @@ void column_test_row_access_constructors(std::vector& matrix, Row_contai for (auto& r : rows) { if constexpr (Column::Master::Option_list::has_removable_rows) { if (!r.second.empty()) { - auto& cell = *r.second.rbegin(); - if (cell.get_row_index() == 0 || cell.get_row_index() == 1 || cell.get_row_index() == 3 || - cell.get_row_index() == 5) { - BOOST_CHECK_EQUAL(cell.get_column_index(), 6); + auto& entry = *r.second.rbegin(); + if (entry.get_row_index() == 0 || entry.get_row_index() == 1 || entry.get_row_index() == 3 || + entry.get_row_index() == 5) { + BOOST_CHECK_EQUAL(entry.get_column_index(), 6); } } } else { if (!r.empty()) { - auto& cell = *r.rbegin(); - if (cell.get_row_index() == 0 || cell.get_row_index() == 1 || cell.get_row_index() == 3 || - cell.get_row_index() == 5) { - BOOST_CHECK_EQUAL(cell.get_column_index(), 6); + auto& entry = *r.rbegin(); + if (entry.get_row_index() == 0 || entry.get_row_index() == 1 || entry.get_row_index() == 3 || + entry.get_row_index() == 5) { + BOOST_CHECK_EQUAL(entry.get_column_index(), 6); } } } @@ -587,11 +587,11 @@ void column_test_row_access_constructors(std::vector& matrix, Row_contai template void column_test_base_boundary_constructors() { - using cell_type = typename std::conditional(), - unsigned int, - std::pair - >::type; - using Container = std::vector; + using entry_type = typename std::conditional(), + unsigned int, + std::pair + >::type; + using Container = std::vector; typename Column::Column_settings settings(5); @@ -677,25 +677,25 @@ void column_test_base_boundary_z2_methods() { // assumes that matrix was build with build_column_matrix and was not modified since. template void column_test_base_z5_operators(std::vector& matrix) { - using Cell = typename Column::Cell; - std::set setcont; + using Entry = typename Column::Entry; + std::set setcont; std::vector veccont; - Cell cell(0); - cell.set_element(4); - setcont.insert(cell); - cell = Cell(1); - cell.set_element(2); - setcont.insert(cell); - cell = Cell(2); - cell.set_element(1); - setcont.insert(cell); - cell = Cell(5); - cell.set_element(1); - setcont.insert(cell); - cell = Cell(6); - cell.set_element(1); - setcont.insert(cell); + Entry entry(0); + entry.set_element(4); + setcont.insert(entry); + entry = Entry(1); + entry.set_element(2); + setcont.insert(entry); + entry = Entry(2); + entry.set_element(1); + setcont.insert(entry); + entry = Entry(5); + entry.set_element(1); + setcont.insert(entry); + entry = Entry(6); + entry.set_element(1); + setcont.insert(entry); matrix[0] += setcont; veccont = {0, 4, 1, 3, 0, 0, 1}; @@ -705,21 +705,21 @@ void column_test_base_z5_operators(std::vector& matrix) { } setcont.clear(); - cell = Cell(0); - cell.set_element(1); - setcont.insert(cell); - cell = Cell(1); - cell.set_element(3); - setcont.insert(cell); - cell = Cell(2); - cell.set_element(4); - setcont.insert(cell); - cell = Cell(5); - cell.set_element(4); - setcont.insert(cell); - cell = Cell(6); - cell.set_element(4); - setcont.insert(cell); + entry = Entry(0); + entry.set_element(1); + setcont.insert(entry); + entry = Entry(1); + entry.set_element(3); + setcont.insert(entry); + entry = Entry(2); + entry.set_element(4); + setcont.insert(entry); + entry = Entry(5); + entry.set_element(4); + setcont.insert(entry); + entry = Entry(6); + entry.set_element(4); + setcont.insert(entry); matrix[1] += setcont; veccont = {}; @@ -745,21 +745,21 @@ void column_test_base_z5_operators(std::vector& matrix) { } // this = this + column * v setcont.clear(); - cell = Cell(0); - cell.set_element(3); - setcont.insert(cell); - cell = Cell(2); - cell.set_element(1); - setcont.insert(cell); - cell = Cell(3); - cell.set_element(2); - setcont.insert(cell); - cell = Cell(5); - cell.set_element(2); - setcont.insert(cell); - cell = Cell(6); - cell.set_element(1); - setcont.insert(cell); + entry = Entry(0); + entry.set_element(3); + setcont.insert(entry); + entry = Entry(2); + entry.set_element(1); + setcont.insert(entry); + entry = Entry(3); + entry.set_element(2); + setcont.insert(entry); + entry = Entry(5); + entry.set_element(2); + setcont.insert(entry); + entry = Entry(6); + entry.set_element(1); + setcont.insert(entry); matrix[5].multiply_source_and_add(setcont, 3); veccont = {3, 2, 4, 1, 0, 2, 4}; BOOST_CHECK(matrix[5].get_content(veccont.size()) == veccont); @@ -768,24 +768,24 @@ void column_test_base_z5_operators(std::vector& matrix) { } // this = v * this + column setcont.clear(); - cell = Cell(0); - cell.set_element(3); - setcont.insert(cell); - cell = Cell(1); - cell.set_element(2); - setcont.insert(cell); - cell = Cell(2); - cell.set_element(4); - setcont.insert(cell); - cell = Cell(3); - cell.set_element(1); - setcont.insert(cell); - cell = Cell(5); - cell.set_element(2); - setcont.insert(cell); - cell = Cell(6); - cell.set_element(4); - setcont.insert(cell); + entry = Entry(0); + entry.set_element(3); + setcont.insert(entry); + entry = Entry(1); + entry.set_element(2); + setcont.insert(entry); + entry = Entry(2); + entry.set_element(4); + setcont.insert(entry); + entry = Entry(3); + entry.set_element(1); + setcont.insert(entry); + entry = Entry(5); + entry.set_element(2); + setcont.insert(entry); + entry = Entry(6); + entry.set_element(4); + setcont.insert(entry); matrix[3].multiply_target_and_add(4, setcont); veccont = {3, 2, 4, 1, 0, 2, 4}; BOOST_CHECK(matrix[3].get_content(veccont.size()) == veccont); @@ -797,7 +797,7 @@ void column_test_base_z5_operators(std::vector& matrix) { // assumes that matrix was build with build_column_matrix and was not modified since. template void column_test_base_z2_operators(std::vector& matrix) { - std::set setcont; + std::set setcont; std::vector veccont; setcont = {0, 1, 2, 5, 6}; diff --git a/src/Persistence_matrix/test/pm_column_tests_mastermatrix.h b/src/Persistence_matrix/test/pm_column_tests_mastermatrix.h index 689cbf0420..7a6c711a57 100644 --- a/src/Persistence_matrix/test/pm_column_tests_mastermatrix.h +++ b/src/Persistence_matrix/test/pm_column_tests_mastermatrix.h @@ -21,25 +21,25 @@ #include #include #include -#include +#include #include -#include +#include #include #include -using Gudhi::persistence_matrix::Cell; -using Gudhi::persistence_matrix::Cell_column_index; -using Gudhi::persistence_matrix::Cell_field_element; +using Gudhi::persistence_matrix::Entry; +using Gudhi::persistence_matrix::Entry_column_index; +using Gudhi::persistence_matrix::Entry_field_element; using Gudhi::persistence_matrix::Chain_column_extra_properties; using Gudhi::persistence_matrix::Column_dimension_holder; using Gudhi::persistence_matrix::Column_types; -using Gudhi::persistence_matrix::Dummy_cell_column_index_mixin; -using Gudhi::persistence_matrix::Dummy_cell_field_element_mixin; +using Gudhi::persistence_matrix::Dummy_entry_column_index_mixin; +using Gudhi::persistence_matrix::Dummy_entry_field_element_mixin; using Gudhi::persistence_matrix::Dummy_chain_properties; using Gudhi::persistence_matrix::Dummy_dimension_holder; using Gudhi::persistence_matrix::Dummy_row_access; -using Gudhi::persistence_matrix::New_cell_constructor; -using Gudhi::persistence_matrix::Pool_cell_constructor; +using Gudhi::persistence_matrix::New_entry_constructor; +using Gudhi::persistence_matrix::Pool_entry_constructor; using Gudhi::persistence_matrix::Row_access; using Zp = Gudhi::persistence_fields::Zp_field_operators<>; @@ -85,47 +85,48 @@ struct Column_mini_matrix { >::type >::type; - using Cell_column_index_option = - typename std::conditional, Dummy_cell_column_index_mixin>::type; - using Cell_field_element_option = typename std::conditional - >::type; - using Matrix_cell = Cell >; + using Entry_column_index_option = typename std::conditional, + Dummy_entry_column_index_mixin>::type; + using Entry_field_element_option = typename std::conditional + >::type; + using Matrix_entry = Entry >; - inline static New_cell_constructor defaultCellConstructor; - using Cell_constructor = New_cell_constructor; + inline static New_entry_constructor defaultEntryConstructor; + using Entry_constructor = New_entry_constructor; struct Column_z2_settings { - Column_z2_settings() : cellConstructor() {} - Column_z2_settings([[maybe_unused]] Characteristic characteristic) : cellConstructor() {} + Column_z2_settings() : entryConstructor() {} + Column_z2_settings([[maybe_unused]] Characteristic characteristic) : entryConstructor() {} - Cell_constructor cellConstructor; + Entry_constructor entryConstructor; }; struct Column_zp_settings { - Column_zp_settings() : operators(), cellConstructor() {} - Column_zp_settings(Characteristic characteristic) : operators(characteristic), cellConstructor() {} + Column_zp_settings() : operators(), entryConstructor() {} + Column_zp_settings(Characteristic characteristic) : operators(characteristic), entryConstructor() {} Field_operators operators; - Cell_constructor cellConstructor; + Entry_constructor entryConstructor; }; using Column_settings = typename std::conditional::type; - template - struct RowCellComp { - bool operator()(const Matrix_cell& c1, const Matrix_cell& c2) const { + template + struct RowEntryComp { + bool operator()(const Matrix_entry& c1, const Matrix_entry& c2) const { return c1.get_column_index() < c2.get_column_index(); } }; using Row = typename std::conditional, boost::intrusive::base_hook >, - std::set > + std::set > >::type; using Row_container = typename std::conditional void test_chain_boundary_insertion(Matrix& m1, Matrix& m2) { auto test = [](Matrix& m) { - BOOST_CHECK(m.is_zero_cell(1, 2)); - BOOST_CHECK(!m.is_zero_cell(1, 1)); - BOOST_CHECK(!m.is_zero_cell(3, 3)); + BOOST_CHECK(m.is_zero_entry(1, 2)); + BOOST_CHECK(!m.is_zero_entry(1, 1)); + BOOST_CHECK(!m.is_zero_entry(3, 3)); BOOST_CHECK(!m.is_zero_column(0)); BOOST_CHECK(!m.is_zero_column(1)); BOOST_CHECK(!m.is_zero_column(2)); @@ -549,9 +549,9 @@ void test_chain_boundary_insertion(Matrix& m1, Matrix& m2) { auto boundary1 = orderedBoundaries.back(); orderedBoundaries.pop_back(); - BOOST_CHECK(m2.is_zero_cell(1, 2)); - BOOST_CHECK(!m2.is_zero_cell(1, 1)); - BOOST_CHECK(!m2.is_zero_cell(3, 3)); + BOOST_CHECK(m2.is_zero_entry(1, 2)); + BOOST_CHECK(!m2.is_zero_entry(1, 1)); + BOOST_CHECK(!m2.is_zero_entry(3, 3)); BOOST_CHECK(!m2.is_zero_column(0)); BOOST_CHECK(!m2.is_zero_column(1)); BOOST_CHECK(!m2.is_zero_column(2)); @@ -618,13 +618,13 @@ void test_zeroing() { Matrix m(orderedBoundaries, 5); - BOOST_CHECK(!m.is_zero_cell(3, 1)); + BOOST_CHECK(!m.is_zero_entry(3, 1)); BOOST_CHECK(!m.is_zero_column(3)); - m.zero_cell(3, 1); - BOOST_CHECK(m.is_zero_cell(3, 1)); + m.zero_entry(3, 1); + BOOST_CHECK(m.is_zero_entry(3, 1)); BOOST_CHECK(!m.is_zero_column(3)); m.zero_column(3); - BOOST_CHECK(m.is_zero_cell(3, 1)); + BOOST_CHECK(m.is_zero_entry(3, 1)); BOOST_CHECK(m.is_zero_column(3)); } @@ -669,22 +669,22 @@ void test_ru_u_access() { } if constexpr (Matrix::Option_list::has_vine_update) { - BOOST_CHECK(!m.is_zero_cell(3, 5, false)); + BOOST_CHECK(!m.is_zero_entry(3, 5, false)); BOOST_CHECK(!m.is_zero_column(4, false)); - m.zero_cell(3, 5, false); - BOOST_CHECK(m.is_zero_cell(3, 5, false)); + m.zero_entry(3, 5, false); + BOOST_CHECK(m.is_zero_entry(3, 5, false)); BOOST_CHECK(!m.is_zero_column(4, false)); m.zero_column(4, false); - BOOST_CHECK(m.is_zero_cell(3, 5, false)); + BOOST_CHECK(m.is_zero_entry(3, 5, false)); BOOST_CHECK(m.is_zero_column(4, false)); } else { - BOOST_CHECK(!m.is_zero_cell(5, 3, false)); + BOOST_CHECK(!m.is_zero_entry(5, 3, false)); BOOST_CHECK(!m.is_zero_column(4, false)); - m.zero_cell(5, 3, false); - BOOST_CHECK(m.is_zero_cell(5, 3, false)); + m.zero_entry(5, 3, false); + BOOST_CHECK(m.is_zero_entry(5, 3, false)); BOOST_CHECK(!m.is_zero_column(4, false)); m.zero_column(4, false); - BOOST_CHECK(m.is_zero_cell(5, 3, false)); + BOOST_CHECK(m.is_zero_entry(5, 3, false)); BOOST_CHECK(m.is_zero_column(4, false)); } } @@ -696,8 +696,8 @@ void test_base_z2_row_access() { std::vector > rows; if constexpr (Matrix::Option_list::has_column_compression) { - // if the union find structure changes, the column_index values of de cells could also change. Change the test with - // all possibilities? + // if the union find structure changes, the column_index values of the entries could also change. Change the test + // with all possibilities? rows.push_back({3, 6}); rows.push_back({3, 5}); rows.push_back({5}); @@ -726,8 +726,8 @@ void test_base_z5_row_access() { std::vector > > rows; if constexpr (Matrix::Option_list::has_column_compression) { - // if the union find structure changes, the column_index values of de cells could also change. Change the test with - // all possibilities? + // if the union find structure changes, the column_index values of the entries could also change. Change the test + // with all possibilities? rows.push_back({{3, 1}, {6, 1}}); rows.push_back({{3, 4}, {5, 1}}); rows.push_back({{5, 4}}); @@ -806,11 +806,11 @@ void test_ru_u_row_access() { unsigned int i = 0; for (auto& r : rows) { orderedRows.clear(); - for (const auto& cell : m.get_row(i++, false)) { + for (const auto& entry : m.get_row(i++, false)) { if constexpr (Matrix::Option_list::is_z2) { - orderedRows.insert(cell.get_column_index()); + orderedRows.insert(entry.get_column_index()); } else { - orderedRows.insert({cell.get_column_index(), cell.get_element()}); + orderedRows.insert({entry.get_column_index(), entry.get_element()}); } } test_column_equality(r, orderedRows); @@ -1209,14 +1209,14 @@ void test_chain_operation(Matrix& m) { } template -void test_base_cell_range_operation() { - using Cell = typename Matrix::Matrix_cell; +void test_base_entry_range_operation() { + using Entry = typename Matrix::Matrix_entry; auto columns = build_general_matrix(); Matrix m(columns, 5); - std::vector range; - range = {Cell(0), Cell(1), Cell(4)}; + std::vector range; + range = {Entry(0), Entry(1), Entry(4)}; if constexpr (!Matrix::Option_list::is_z2) { range[0].set_element(1); range[1].set_element(4); @@ -1251,14 +1251,14 @@ void test_base_cell_range_operation() { } template -void test_base_col_comp_cell_range_operation() { - using Cell = typename Matrix::Matrix_cell; +void test_base_col_comp_entry_range_operation() { + using Entry = typename Matrix::Matrix_entry; auto columns = build_general_matrix(); Matrix m(columns, 5); - std::vector range; - range = {Cell(0), Cell(1), Cell(4)}; + std::vector range; + range = {Entry(0), Entry(1), Entry(4)}; if constexpr (!Matrix::Option_list::is_z2) { range[0].set_element(1); range[1].set_element(4); diff --git a/src/Persistence_matrix/test/pm_test_utilities.h b/src/Persistence_matrix/test/pm_test_utilities.h index 8dbb10fa51..dc20ad4bde 100644 --- a/src/Persistence_matrix/test/pm_test_utilities.h +++ b/src/Persistence_matrix/test/pm_test_utilities.h @@ -59,42 +59,44 @@ constexpr bool is_indexed_by_position() { } template -using Cell_representative = typename std::conditional(), unsigned int, - std::pair >::type; +using Entry_representative = typename std::conditional(), + unsigned int, + std::pair + >::type; template -using column_content = std::set >; +using column_content = std::set >; template -using witness_content = std::vector >; +using witness_content = std::vector >; -// for vector, assumes no cell was removed via clear(Index) +// for vector, assumes no entry was removed via clear(Index) template column_content get_column_content_via_iterators(const Column& col) { - column_content cells; + column_content entries; for (const auto& c : col) { if constexpr (is_z2()) { - cells.insert(c.get_row_index()); + entries.insert(c.get_row_index()); } else { - cells.insert({c.get_row_index(), c.get_element()}); + entries.insert({c.get_row_index(), c.get_element()}); } } - return cells; + return entries; } -// assumes no cell was removed via clear(Index) +// assumes no entry was removed via clear(Index) template column_content > get_column_content_via_iterators(const Heap_column& col) { - column_content > cells; + column_content > entries; std::vector::Field_element> cont; Zp operators(5); for (const auto& c : col) { if constexpr (is_z2 >()) { - auto p = cells.insert(c.get_row_index()); + auto p = entries.insert(c.get_row_index()); if (!p.second) { // possible in heap - cells.erase(p.first); + entries.erase(p.first); } } else { if (cont.size() <= c.get_row_index()) cont.resize(c.get_row_index() + 1, 0u); @@ -103,23 +105,23 @@ column_content > get_column_content_via_iterators(const Heap } if constexpr (!is_z2 >()) { for (unsigned int i = 0; i < cont.size(); ++i) { - if (cont[i] != 0u) cells.insert({i, cont[i]}); + if (cont[i] != 0u) entries.insert({i, cont[i]}); } } - return cells; + return entries; } -// for vector, assumes no cell was removed via clear(Index) +// for vector, assumes no entry was removed via clear(Index) // base and base comp cannot call get_row as const so m cannot be const... template column_content get_ordered_row(Matrix& m, unsigned int rowIndex) { column_content orderedRows; - for (const auto& cell : m.get_row(rowIndex)) { + for (const auto& entry : m.get_row(rowIndex)) { if constexpr (is_z2()) { - orderedRows.insert(cell.get_column_index()); + orderedRows.insert(entry.get_column_index()); } else { - orderedRows.insert({cell.get_column_index(), cell.get_element()}); + orderedRows.insert({entry.get_column_index(), entry.get_element()}); } } return orderedRows; diff --git a/src/Persistence_matrix/test/test_persistence_matrix_matrix_z2_base.cpp b/src/Persistence_matrix/test/test_persistence_matrix_matrix_z2_base.cpp index 8d179d204e..a01fbd64b5 100644 --- a/src/Persistence_matrix/test/test_persistence_matrix_matrix_z2_base.cpp +++ b/src/Persistence_matrix/test/test_persistence_matrix_matrix_z2_base.cpp @@ -42,7 +42,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Base_matrix_z2_column_removal, Matrix, removable_c BOOST_AUTO_TEST_CASE_TEMPLATE(Base_matrix_z2_operation, Matrix, full_matrices) { test_base_operation(); - test_base_cell_range_operation(); + test_base_entry_range_operation(); test_const_operation(); } diff --git a/src/Persistence_matrix/test/test_persistence_matrix_matrix_z2_compression.cpp b/src/Persistence_matrix/test/test_persistence_matrix_matrix_z2_compression.cpp index b5f1c31e64..856ef08cf1 100644 --- a/src/Persistence_matrix/test/test_persistence_matrix_matrix_z2_compression.cpp +++ b/src/Persistence_matrix/test/test_persistence_matrix_matrix_z2_compression.cpp @@ -40,6 +40,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Base_column_compression_matrix_z2_row_removal, Mat BOOST_AUTO_TEST_CASE_TEMPLATE(Base_column_compression_matrix_z2_operation, Matrix, full_matrices) { test_base_col_comp_operation(); - test_base_col_comp_cell_range_operation(); + test_base_col_comp_entry_range_operation(); test_base_col_comp_const_operation(); } diff --git a/src/Persistence_matrix/test/test_persistence_matrix_matrix_zp_base.cpp b/src/Persistence_matrix/test/test_persistence_matrix_matrix_zp_base.cpp index 2a5a996d37..d4ded9cff7 100644 --- a/src/Persistence_matrix/test/test_persistence_matrix_matrix_zp_base.cpp +++ b/src/Persistence_matrix/test/test_persistence_matrix_matrix_zp_base.cpp @@ -42,7 +42,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Base_matrix_zp_column_removal, Matrix, removable_c BOOST_AUTO_TEST_CASE_TEMPLATE(Base_matrix_zp_operation, Matrix, full_matrices) { test_base_operation(); - test_base_cell_range_operation(); + test_base_entry_range_operation(); test_const_operation(); } diff --git a/src/Persistence_matrix/test/test_persistence_matrix_matrix_zp_compression.cpp b/src/Persistence_matrix/test/test_persistence_matrix_matrix_zp_compression.cpp index e5c92d0ead..4aa836a00e 100644 --- a/src/Persistence_matrix/test/test_persistence_matrix_matrix_zp_compression.cpp +++ b/src/Persistence_matrix/test/test_persistence_matrix_matrix_zp_compression.cpp @@ -40,6 +40,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(Base_column_compression_matrix_zp_row_removal, Mat BOOST_AUTO_TEST_CASE_TEMPLATE(Base_column_compression_matrix_zp_operation, Matrix, full_matrices) { test_base_col_comp_operation(); - test_base_col_comp_cell_range_operation(); + test_base_col_comp_entry_range_operation(); test_base_col_comp_const_operation(); } From 8d4fe2bb1a7c678cdc2ae09bf16fc17f16a27ae4 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Tue, 24 Sep 2024 10:00:15 +0200 Subject: [PATCH 21/34] feature requires python 3.8 --- .github/next_release.md | 3 ++- src/python/doc/installation.rst | 42 ++++++++++++++++----------------- src/python/setup.py.in | 2 +- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/.github/next_release.md b/.github/next_release.md index abd2ebd1bd..573d8ef940 100644 --- a/.github/next_release.md +++ b/.github/next_release.md @@ -20,6 +20,7 @@ Below is a list of changes: - Installation - CMake ≥ 3.15 is now required (was ≥ 3.8). + - Python ≥ 3.8 is now required (was ≥ 3.5), because of `importlib.metadata`. - Miscellaneous - The [list of bugs that were solved](https://github.com/GUDHI/gudhi-devel/issues?q=label%3A3.11.0+is%3Aclosed) is available on GitHub. @@ -29,7 +30,7 @@ However, there are still GPL dependencies for many modules. We invite you to che We kindly ask users to cite the GUDHI library as appropriately as possible in their papers, and to mention the use of the GUDHI library on the web pages of their projects using GUDHI and provide us with links to these web pages. -We provide [bibtex entries](https://gudhi.inria.fr/doc/latest/_citation.html) for the modules of the User and Reference Manual, as well as for publications directly related to the GUDHI library. +We provide [bibtex entries](https://gudhi.inria.fr/doc/latest/_citation.html) for the modules of the User and Reference Manual, as well as for publications directly related to the GUDHI library. Feel free to [contact us](https://gudhi.inria.fr/contact/) in case you have any questions or remarks. diff --git a/src/python/doc/installation.rst b/src/python/doc/installation.rst index 639a89d652..c1f7bd2c44 100644 --- a/src/python/doc/installation.rst +++ b/src/python/doc/installation.rst @@ -41,7 +41,7 @@ there. The library uses c++17 and requires `Boost `_ :math:`\geq` 1.71.0, `CMake `_ :math:`\geq` 3.15, -Python :math:`\geq` 3.5, `NumPy `_ :math:`\geq` 1.15.0, `Cython `_ +Python :math:`\geq` 3.8, `NumPy `_ :math:`\geq` 1.15.0, `Cython `_ :math:`\geq` 0.27 and `pybind11 `_ to compile the GUDHI Python module. It is a multi-platform library and compiles on Linux, Mac OSX and Visual Studio 2017 or later. @@ -145,10 +145,10 @@ You shall have something like: .. code-block:: none - Pybind11 version 2.8.1 + Pybind11 version 2.8.1 Python version 3.7.12 - Cython version 0.29.25 - Numpy version 1.21.4 + Cython version 0.29.25 + Numpy version 1.21.4 Boost version 1.77.0 + Installed modules are: off_utils;simplex_tree;rips_complex;cubical_complex;periodic_cubical_complex; persistence_graphical_tools;reader_utils;witness_complex;strong_witness_complex; @@ -156,7 +156,7 @@ You shall have something like: euclidean_strong_witness_complex; Here, you can see that the modules that need CGAL are missing, because CGAL is not installed. -:code:`persistence_graphical_tools` is installed, but +:code:`persistence_graphical_tools` is installed, but `its functions `_ will produce an error as matplotlib is not available. Unitary tests cannot be run as pytest is missing. @@ -165,23 +165,23 @@ A complete configuration would be : .. code-block:: none - Pybind11 version 2.8.1 + Pybind11 version 2.8.1 Python version 3.9.7 - Cython version 0.29.24 - Pytest version 6.2.5 - Matplotlib version 3.5.0 - Numpy version 1.21.4 - Scipy version 1.7.3 - Scikit-learn version 1.0.1 - POT version 0.8.0 + Cython version 0.29.24 + Pytest version 6.2.5 + Matplotlib version 3.5.0 + Numpy version 1.21.4 + Scipy version 1.7.3 + Scikit-learn version 1.0.1 + POT version 0.8.0 HNSWlib found PyKeOps version [pyKeOps]: 2.1 - EagerPy version 0.30.0 - TensorFlow version 2.7.0 - Sphinx version 4.3.0 - Sphinx-paramlinks version 0.5.2 - pydata_sphinx_theme version 0.13.1 - NetworkX version 3.0 + EagerPy version 0.30.0 + TensorFlow version 2.7.0 + Sphinx version 4.3.0 + Sphinx-paramlinks version 0.5.2 + pydata_sphinx_theme version 0.13.1 + NetworkX version 3.0 Eigen3 version 3.4.0 Boost version 1.74.0 CGAL version 5.3 @@ -194,7 +194,7 @@ A complete configuration would be : + Installed modules are: bottleneck;off_utils;simplex_tree;rips_complex;cubical_complex;periodic_cubical_complex; persistence_graphical_tools;reader_utils;witness_complex;strong_witness_complex;nerve_gic;subsampling; tangential_complex;alpha_complex;euclidean_witness_complex;euclidean_strong_witness_complex; - + Missing modules are: + + Missing modules are: Documentation @@ -422,7 +422,7 @@ TensorFlow requires `TensorFlow `_. The :doc:`cubical complex `, :doc:`simplex tree ` and :doc:`Rips complex ` modules require `TensorFlow`_ -for incorporating them in neural nets. +for incorporating them in neural nets. `TensorFlow`_ is also used in some automatic differentiation tests. diff --git a/src/python/setup.py.in b/src/python/setup.py.in index 3bc8d0805e..715ecdef77 100644 --- a/src/python/setup.py.in +++ b/src/python/setup.py.in @@ -73,7 +73,7 @@ setup( long_description_content_type='text/x-rst', long_description='@GUDHI_LONG_DESCRIPTION@', ext_modules = ext_modules, - python_requires='>=3.5.0', + python_requires='>=3.8.0', install_requires = ['numpy >= 1.15.0',], package_data={"": ["*.dll"], }, ) From 7b6d033c934ef927bac92e2753d7e904dbdbfa5f Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Tue, 24 Sep 2024 11:53:59 +0200 Subject: [PATCH 22/34] Use importlib.metadata to guess version numbers of dependencies --- .../modules/GUDHI_third_party_libraries.cmake | 30 +++------------ src/python/CMakeLists.txt | 34 ++++++++--------- src/python/doc/installation.rst | 38 ++++++++++--------- 3 files changed, 43 insertions(+), 59 deletions(-) diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index 7c03103cba..18149ebcc2 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -145,8 +145,9 @@ if (WITH_GUDHI_PYTHON) # returns ${PYTHON_MODULE_NAME_UP}_VERSION and ${PYTHON_MODULE_NAME_UP}_FOUND function( find_python_module PYTHON_MODULE_NAME ) string(TOUPPER ${PYTHON_MODULE_NAME} PYTHON_MODULE_NAME_UP) + # Modify tracebacklimit as the exception is quite verbose when module is not found execute_process( - COMMAND ${Python_EXECUTABLE} -c "import ${PYTHON_MODULE_NAME}; print(${PYTHON_MODULE_NAME}.__version__)" + COMMAND ${Python_EXECUTABLE} -c "import sys; sys.tracebacklimit = 0; from importlib.metadata import version; print(version('${PYTHON_MODULE_NAME}'))" RESULT_VARIABLE PYTHON_MODULE_RESULT OUTPUT_VARIABLE PYTHON_MODULE_VERSION ERROR_VARIABLE PYTHON_MODULE_ERROR) @@ -167,25 +168,6 @@ if (WITH_GUDHI_PYTHON) endif() endfunction( find_python_module ) - # For modules that do not define module.__version__ - function( find_python_module_no_version PYTHON_MODULE_NAME ) - string(TOUPPER ${PYTHON_MODULE_NAME} PYTHON_MODULE_NAME_UP) - execute_process( - COMMAND ${Python_EXECUTABLE} -c "import ${PYTHON_MODULE_NAME}" - RESULT_VARIABLE PYTHON_MODULE_RESULT - ERROR_VARIABLE PYTHON_MODULE_ERROR) - if(PYTHON_MODULE_RESULT EQUAL 0) - # Remove carriage return - message ("++ Python module ${PYTHON_MODULE_NAME} found") - set(${PYTHON_MODULE_NAME_UP}_FOUND TRUE PARENT_SCOPE) - else() - message ("PYTHON_MODULE_NAME = ${PYTHON_MODULE_NAME} - - PYTHON_MODULE_RESULT = ${PYTHON_MODULE_RESULT} - - PYTHON_MODULE_ERROR = ${PYTHON_MODULE_ERROR}") - set(${PYTHON_MODULE_NAME_UP}_FOUND FALSE PARENT_SCOPE) - endif() - endfunction( find_python_module_no_version ) - if( TARGET Python::Interpreter ) find_python_module("cython") find_python_module("pytest") @@ -193,17 +175,17 @@ if (WITH_GUDHI_PYTHON) find_python_module("numpy") find_python_module("scipy") find_python_module("sphinx") - find_python_module("sklearn") - find_python_module("ot") + find_python_module("scikit-learn") + find_python_module("POT") find_python_module("pybind11") find_python_module("torch") find_python_module("pykeops") find_python_module("eagerpy") - find_python_module_no_version("hnswlib") + find_python_module("hnswlib") find_python_module("tensorflow") find_python_module("sphinx_paramlinks") find_python_module("pydata_sphinx_theme") - find_python_module_no_version("sphinxcontrib.bibtex") + find_python_module("sphinxcontrib.bibtex") find_python_module("networkx") endif() diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 5b2fad86aa..e68e8f2c64 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -131,19 +131,19 @@ if(SCIPY_FOUND) else() disable_python_documentation("scipy") endif() -if(SKLEARN_FOUND) - add_gudhi_debug_info("Scikit-learn version ${SKLEARN_VERSION}") +if(SCIKIT-LEARN_FOUND) + add_gudhi_debug_info("Scikit-learn version ${SCIKIT-LEARN_VERSION}") else() - disable_python_documentation("sklearn") + disable_python_documentation("scikit-learn") endif() -if(OT_FOUND) - add_gudhi_debug_info("POT version ${OT_VERSION}") +if(POT_FOUND) + add_gudhi_debug_info("POT version ${POT_VERSION}") else() disable_python_documentation("ot") endif() if(HNSWLIB_FOUND) # Does not have a version number... - add_gudhi_debug_info("HNSWlib found") + add_gudhi_debug_info("HNSWlib version ${HNSWLIB_VERSION}") endif() if(TORCH_FOUND) add_gudhi_debug_info("PyTorch version ${TORCH_VERSION}") @@ -176,7 +176,7 @@ else() endif() if(SPHINXCONTRIB.BIBTEX_FOUND) # Does not have a version number... - add_gudhi_debug_info("sphinxcontrib-bibtex found") + add_gudhi_debug_info("sphinxcontrib-bibtex version ${SPHINXCONTRIB.BIBTEX_VERSION}") else() disable_python_documentation("sphinxcontrib-bibtex") endif() @@ -461,7 +461,7 @@ add_test(NAME random_cubical_complex_persistence_example_py_test add_gudhi_py_test(test_cubical_complex) # Datasets are fetched for these tests -if(SKLEARN_FOUND AND WITH_GUDHI_REMOTE_TEST) +if(SCIKIT-LEARN_FOUND AND WITH_GUDHI_REMOTE_TEST) add_gudhi_py_test(test_sklearn_cubical_persistence) add_test(NAME cubical_complex_sklearn_itf_py_test @@ -590,7 +590,7 @@ add_test(NAME rips_complex_from_points_example_py_test add_gudhi_py_test(test_rips_complex) -if(SKLEARN_FOUND) +if(SCIKIT-LEARN_FOUND) # test_sklearn_rips_persistence is using gudhi.datasets.generators if (TARGET CGAL::CGAL AND TARGET Eigen3::Eigen) add_gudhi_py_test(test_sklearn_rips_persistence) @@ -636,7 +636,7 @@ add_gudhi_py_test(test_reader_utils) add_gudhi_py_test(test_off) # Wasserstein -if(OT_FOUND) +if(POT_FOUND) # EagerPy dependency because of enable_autodiff=True if(EAGERPY_FOUND) add_gudhi_py_test(test_wasserstein_distance) @@ -648,7 +648,7 @@ if(OT_FOUND) endif() # Representations -if(SKLEARN_FOUND AND MATPLOTLIB_FOUND AND OT_FOUND AND TARGET CGAL::CGAL) +if(SCIKIT-LEARN_FOUND AND MATPLOTLIB_FOUND AND POT_FOUND AND TARGET CGAL::CGAL) add_gudhi_py_test(test_representations) endif() @@ -658,17 +658,17 @@ if(TENSORFLOW_FOUND) endif() # Perslay -if(TENSORFLOW_FOUND AND SKLEARN_FOUND) +if(TENSORFLOW_FOUND AND SCIKIT-LEARN_FOUND) add_gudhi_py_test(test_perslay) endif() # Betti curves -if(SKLEARN_FOUND AND SCIPY_FOUND) +if(SCIKIT-LEARN_FOUND AND SCIPY_FOUND) add_gudhi_py_test(test_betti_curve_representations) endif() # Representations preprocessing -if(SKLEARN_FOUND) +if(SCIKIT-LEARN_FOUND) add_gudhi_py_test(test_representations_preprocessing) endif() @@ -676,13 +676,13 @@ endif() add_gudhi_py_test(test_time_delay) # DTM -if(SCIPY_FOUND AND SKLEARN_FOUND AND TORCH_FOUND AND HNSWLIB_FOUND AND PYKEOPS_FOUND AND EAGERPY_FOUND) +if(SCIPY_FOUND AND SCIKIT-LEARN_FOUND AND TORCH_FOUND AND HNSWLIB_FOUND AND PYKEOPS_FOUND AND EAGERPY_FOUND) add_gudhi_py_test(test_knn) add_gudhi_py_test(test_dtm) endif() # Tomato -if(SCIPY_FOUND AND SKLEARN_FOUND) +if(SCIPY_FOUND AND SCIKIT-LEARN_FOUND) add_gudhi_py_test(test_tomato) endif() @@ -697,7 +697,7 @@ if(SCIPY_FOUND) endif() # Cover complex -if(SKLEARN_FOUND) +if(SCIKIT-LEARN_FOUND) add_gudhi_py_test(test_cover_complex) endif() diff --git a/src/python/doc/installation.rst b/src/python/doc/installation.rst index c1f7bd2c44..067b733efb 100644 --- a/src/python/doc/installation.rst +++ b/src/python/doc/installation.rst @@ -165,26 +165,28 @@ A complete configuration would be : .. code-block:: none - Pybind11 version 2.8.1 - Python version 3.9.7 - Cython version 0.29.24 - Pytest version 6.2.5 - Matplotlib version 3.5.0 - Numpy version 1.21.4 - Scipy version 1.7.3 - Scikit-learn version 1.0.1 - POT version 0.8.0 - HNSWlib found - PyKeOps version [pyKeOps]: 2.1 + Python version 3.11.9 + Pybind11 version 2.12.0 + Cython version 3.0.10 + Numpy version 1.24.3 + Pytest version 8.2.1 + Matplotlib version 3.9.0 + Scipy version 1.13.1 + Scikit-learn version 1.3.2 + POT version 0.9.4 + HNSWlib version 0.8.0 + PyTorch version 2.3.0 + PyKeOps version 2.2.3 EagerPy version 0.30.0 - TensorFlow version 2.7.0 - Sphinx version 4.3.0 - Sphinx-paramlinks version 0.5.2 - pydata_sphinx_theme version 0.13.1 - NetworkX version 3.0 + TensorFlow version 2.13.1 + Sphinx version 7.3.7 + Sphinx-paramlinks version 0.6.0 + pydata_sphinx_theme version 0.15.2 + sphinxcontrib-bibtex version 2.6.2 + NetworkX version 3.3 Eigen3 version 3.4.0 - Boost version 1.74.0 - CGAL version 5.3 + Boost version 1.84.0 + CGAL header only version 5.6.1 GMP_LIBRARIES = /usr/lib/x86_64-linux-gnu/libgmp.so GMPXX_LIBRARIES = /usr/lib/x86_64-linux-gnu/libgmpxx.so MPFR_LIBRARIES = /usr/lib/x86_64-linux-gnu/libmpfr.so From fdaeb013cdfde476cf9f5bdc391c55062fe818f3 Mon Sep 17 00:00:00 2001 From: hschreiber Date: Tue, 24 Sep 2024 15:27:47 +0200 Subject: [PATCH 23/34] renaming matrix cell as matrix entry --- .../Persistence_matrix/allocators/entry_constructors.h | 6 +++--- .../include/gudhi/Persistence_matrix/columns/entry_types.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/allocators/entry_constructors.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/allocators/entry_constructors.h index 5062a985ec..8485477450 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/allocators/entry_constructors.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/allocators/entry_constructors.h @@ -14,8 +14,8 @@ * @brief Contains different versions of @ref Gudhi::persistence_matrix::Entry factories. */ -#ifndef PM_COLUMN_CELL_CONSTRUCTORS_H -#define PM_COLUMN_CELL_CONSTRUCTORS_H +#ifndef PM_COLUMN_ENTRY_CONSTRUCTORS_H +#define PM_COLUMN_ENTRY_CONSTRUCTORS_H #include //std::swap @@ -136,4 +136,4 @@ struct Pool_entry_constructor } // namespace persistence_matrix } // namespace Gudhi -#endif // PM_COLUMN_CELL_CONSTRUCTORS_H +#endif // PM_COLUMN_ENTRY_CONSTRUCTORS_H diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/entry_types.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/entry_types.h index ca9ad3389f..81083d3d70 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/entry_types.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/columns/entry_types.h @@ -18,8 +18,8 @@ * Also defines the std::hash method for @ref Gudhi::persistence_matrix::Entry. */ -#ifndef PM_MATRIX_CELL_H -#define PM_MATRIX_CELL_H +#ifndef PM_MATRIX_ENTRY_H +#define PM_MATRIX_ENTRY_H #include //std::swap, std::exchange & std::move #include //std::hash @@ -324,4 +324,4 @@ struct std::hash > { } }; -#endif // PM_MATRIX_CELL_H +#endif // PM_MATRIX_ENTRY_H From 848d853159083041511b070b85389ebb8cb217a6 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Wed, 25 Sep 2024 10:03:02 +0200 Subject: [PATCH 24/34] Specific case for PyKeops on Windows --- src/cmake/modules/GUDHI_third_party_libraries.cmake | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index 18149ebcc2..ffed360461 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -179,7 +179,6 @@ if (WITH_GUDHI_PYTHON) find_python_module("POT") find_python_module("pybind11") find_python_module("torch") - find_python_module("pykeops") find_python_module("eagerpy") find_python_module("hnswlib") find_python_module("tensorflow") @@ -189,6 +188,17 @@ if (WITH_GUDHI_PYTHON) find_python_module("networkx") endif() + # Specific case for PyKeops that can be imported on Windows, but fails because it uses fcntl (not available on Windows) + # Also fcntl has no metadata, so find_python_module does not work + # "import fcntl" is about 1 sec. faster than "import pykeops" + execute_process( + COMMAND ${Python_EXECUTABLE} -c "import fcntl" + RESULT_VARIABLE FCNTL_IMPORT_MODULE_RESULT + OUTPUT_VARIABLE FCNTL_IMPORT_MODULE_OUPUT) + if(FCNTL_IMPORT_MODULE_RESULT EQUAL 0) + find_python_module("pykeops") + endif() + if(NOT GUDHI_PYTHON_PATH) message(FATAL_ERROR "ERROR: GUDHI_PYTHON_PATH is not valid.") endif(NOT GUDHI_PYTHON_PATH) From dee13f902aacb50fcf024653600af1cf143a38f5 Mon Sep 17 00:00:00 2001 From: hschreiber Date: Wed, 25 Sep 2024 11:49:41 +0200 Subject: [PATCH 25/34] rename face as cell in persistence matrix --- .../concept/PersistenceMatrixColumn.h | 4 +- .../concept/PersistenceMatrixOptions.h | 8 +- .../doc/Intro_persistence_matrix.h | 4 +- src/Persistence_matrix/include/gudhi/Matrix.h | 148 +++++------ .../Persistence_matrix/Boundary_matrix.h | 46 ++-- .../gudhi/Persistence_matrix/Chain_matrix.h | 140 +++++----- .../Persistence_matrix/Id_to_index_overlay.h | 250 +++++++++--------- .../Position_to_index_overlay.h | 76 +++--- .../gudhi/Persistence_matrix/RU_matrix.h | 70 ++--- .../gudhi/Persistence_matrix/base_pairing.h | 12 +- ... => boundary_cell_position_to_id_mapper.h} | 14 +- .../Persistence_matrix/chain_vine_swap.h | 14 +- .../columns/chain_column_extra_properties.h | 4 +- .../matrix_dimension_holders.h | 16 +- .../gudhi/Persistence_matrix/ru_pairing.h | 12 +- .../gudhi/Persistence_matrix/ru_vine_swap.h | 18 +- src/Persistence_matrix/test/pm_matrix_tests.h | 6 +- 17 files changed, 421 insertions(+), 421 deletions(-) rename src/Persistence_matrix/include/gudhi/Persistence_matrix/{boundary_face_position_to_id_mapper.h => boundary_cell_position_to_id_mapper.h} (74%) diff --git a/src/Persistence_matrix/concept/PersistenceMatrixColumn.h b/src/Persistence_matrix/concept/PersistenceMatrixColumn.h index 6eaf75f7c9..8ae47e2924 100644 --- a/src/Persistence_matrix/concept/PersistenceMatrixColumn.h +++ b/src/Persistence_matrix/concept/PersistenceMatrixColumn.h @@ -86,7 +86,7 @@ class PersistenceMatrixColumn : PersistenceMatrixColumn(Column_settings* colSettings = nullptr); /** * @brief Constructs a column from the given range of @ref Matrix::Entry_representative. If the dimension is stored, - * the face is assumed to be simplicial and its dimension to be `nonZeroRowIndices length - 1` or `0`. + * the cell is assumed to be simplicial and its dimension to be `nonZeroRowIndices length - 1` or `0`. * Otherwise, the dimension should be specified with another constructor. * * @tparam Container Range of @ref Matrix::Entry_representative. Assumed to have a %begin(), %end() and %size() @@ -102,7 +102,7 @@ class PersistenceMatrixColumn : /** * @brief Constructs a column from the given range of @ref Matrix::Entry_representative such that the rows can be * accessed. Each new entry in the column is also inserted in a row using @ref Row_access::insert_entry. - * If the dimension is stored, the face is assumed to be simplicial and its dimension to be + * If the dimension is stored, the cell is assumed to be simplicial and its dimension to be * `nonZeroRowIndices length - 1` or `0`. Otherwise, the dimension should be specified with another constructor. * * @tparam Container Range of @ref Matrix::Entry_representative. Assumed to have a %begin(), %end() and %size() diff --git a/src/Persistence_matrix/concept/PersistenceMatrixOptions.h b/src/Persistence_matrix/concept/PersistenceMatrixOptions.h index b4d72dc82b..9d5cc83540 100644 --- a/src/Persistence_matrix/concept/PersistenceMatrixOptions.h +++ b/src/Persistence_matrix/concept/PersistenceMatrixOptions.h @@ -93,14 +93,14 @@ struct PersistenceMatrixOptions * If set to false, the container is a std::vector. By default, it is recommended to set it to false, but some * methods require it to be true to be enabled: * - @ref Matrix::remove_column(Index) "remove_column(Index)" for @ref basematrix "base matrices", - * - @ref Matrix::remove_maximal_face(Index) "remove_maximal_face(Index)" for @ref chainmatrix "chain matrices", - * - @ref Matrix::remove_maximal_face(Index, const std::vector&) - * "remove_maximal_face(ID_index, const std::vector&)" for @ref chainmatrix "chain matrices", + * - @ref Matrix::remove_maximal_cell(Index) "remove_maximal_cell(Index)" for @ref chainmatrix "chain matrices", + * - @ref Matrix::remove_maximal_cell(Index, const std::vector&) + * "remove_maximal_cell(ID_index, const std::vector&)" for @ref chainmatrix "chain matrices", * - @ref Matrix::remove_last "remove_last()" for @ref chainmatrix "chain matrices" if @ref has_vine_update is true. */ static const bool has_map_column_container; /** - * @brief If set to true, enables the methods @ref Matrix::remove_maximal_face and @ref Matrix::remove_last, + * @brief If set to true, enables the methods @ref Matrix::remove_maximal_cell and @ref Matrix::remove_last, * except for @ref basematrix "base matrices" when @ref has_column_compression is true. */ static const bool has_removable_columns; diff --git a/src/Persistence_matrix/doc/Intro_persistence_matrix.h b/src/Persistence_matrix/doc/Intro_persistence_matrix.h index 77b2657414..1185655b26 100644 --- a/src/Persistence_matrix/doc/Intro_persistence_matrix.h +++ b/src/Persistence_matrix/doc/Intro_persistence_matrix.h @@ -30,12 +30,12 @@ namespace persistence_matrix { * The main functionalities are: * @li column and row access, * @li column addition and scalar multiplication, - * @li removal of maximal faces while maintaining a valid reduced boundary matrix or compatible chain complex base + * @li removal of maximal cells while maintaining a valid reduced boundary matrix or compatible chain complex base * and a valid barcode with respect to the new filtration, * @li computation of persistent homology (but note that if the barcode is your only necessity, using the * @ref persistent_cohomology module is often more performant), * @li computation of representative cycles for the cycle classes, - * @li swapping of two consecutive faces in a filtration (cf. vineyards @cite vineyards) while maintaining a valid + * @li swapping of two consecutive cells in a filtration (cf. vineyards @cite vineyards) while maintaining a valid * reduced boundary matrix or compatible chain complex base and a valid barcode with respect to the new filtration, * * \note Matrix API is in a beta version and may change in incompatible ways in the near future. diff --git a/src/Persistence_matrix/include/gudhi/Matrix.h b/src/Persistence_matrix/include/gudhi/Matrix.h index a403ccaa81..d917bddc80 100644 --- a/src/Persistence_matrix/include/gudhi/Matrix.h +++ b/src/Persistence_matrix/include/gudhi/Matrix.h @@ -109,7 +109,7 @@ namespace persistence_matrix { * always take the same type of index as input (for optimization purposes). So, to avoid confusion, we will name and * define here the different possibilities, such that we can directly refer to it in the descriptions of the methods. * Note that every column and row in a @ref boundarymatrix "boundary" or @ref chainmatrix "chain matrix" is always - * associated to a single simplex/face, so in order to avoid repeating formulations like "of the simplex associated to + * associated to a single simplex/cell, so in order to avoid repeating formulations like "of the simplex associated to * the column" all the time, we will amalgamate both notions together. * * Let @f$ c @f$ be a column. @@ -134,7 +134,7 @@ namespace persistence_matrix { * indexed by its ID, so it correspond to the @ref IDIdx indexing scheme. If the matrix is not a * @ref chainmatrix "chain matrix", @f$ r @f$ will originally also be indexed by the ID, but when a swap occurs, * the rows also swap IDs and the new ID has to be used to access @f$ r @f$. This means that when the default - * @ref IDIdx scheme is used (the faces are numerated in order of appearance in the filtration starting at 0), + * @ref IDIdx scheme is used (the cells are numerated in order of appearance in the filtration starting at 0), * the indexation of the rows correspond to @ref PosIdx. * * @tparam PersistenceMatrixOptions Structure encoding all the options of the matrix. @@ -609,9 +609,9 @@ class Matrix { * (as in the implementation of the Zigzag algorithm @cite zigzag for example.) * * @param birthComparator Method taking two @ref PosIdx indices as parameter and returns true if and only if the first - * face is associated to a bar with strictly smaller birth than the bar associated to the second one. + * cell is associated to a bar with strictly smaller birth than the bar associated to the second one. * @param deathComparator Method taking two @ref PosIdx indices as parameter and returns true if and only if the first - * face is associated to a bar with strictly smaller death than the bar associated to the second one. + * cell is associated to a bar with strictly smaller death than the bar associated to the second one. */ Matrix(const std::function& birthComparator, const std::function& deathComparator); @@ -633,9 +633,9 @@ class Matrix { * method. * @param orderedBoundaries Vector of ordered boundaries in filtration order. Indexed continuously starting at 0. * @param birthComparator Method taking two @ref PosIdx indices as parameter and returns true if and only if the first - * face is associated to a bar with strictly smaller birth than the bar associated to the second one. + * cell is associated to a bar with strictly smaller birth than the bar associated to the second one. * @param deathComparator Method taking two @ref PosIdx indices as parameter and returns true if and only if the first - * face is associated to a bar with strictly smaller death than the bar associated to the second one. + * cell is associated to a bar with strictly smaller death than the bar associated to the second one. * @param characteristic Characteristic of the coefficient field. Has to be specified if * @ref PersistenceMatrixOptions::is_z2 is false. Default value is 11. * Ignored if @ref PersistenceMatrixOptions::is_z2 is true. @@ -660,9 +660,9 @@ class Matrix { * * @param numberOfColumns Number of columns to reserve space for. * @param birthComparator Method taking two @ref PosIdx indices as parameter and returns true if and only if the first - * face is associated to a bar with strictly smaller birth than the bar associated to the second one. + * cell is associated to a bar with strictly smaller birth than the bar associated to the second one. * @param deathComparator Method taking two @ref PosIdx indices as parameter and returns true if and only if the first - * face is associated to a bar with strictly smaller death than the bar associated to the second one. + * cell is associated to a bar with strictly smaller death than the bar associated to the second one. * @param characteristic Characteristic of the coefficient field. If not specified and * @ref PersistenceMatrixOptions::is_z2 is false, the characteristic has to be set later with the use of * @ref set_characteristic before calling for the first time a method needing it. @@ -736,10 +736,10 @@ class Matrix { /** * @brief Inserts at the end of the matrix a new ordered column corresponding to the given boundary. * This means that it is assumed that this method is called on boundaries in the order of the filtration. - * It also assumes that the faces in the given boundary are identified by their relative position in the filtration, + * It also assumes that the cells in the given boundary are identified by their relative position in the filtration, * starting at 0. If it is not the case, use the other - * @ref insert_boundary(ID_index faceIndex, const Boundary_range& boundary, Dimension dim) "insert_boundary" - * instead by indicating the face ID used in the boundaries when the face is inserted. + * @ref insert_boundary(ID_index cellIndex, const Boundary_range& boundary, Dimension dim) "insert_boundary" + * instead by indicating the cell ID used in the boundaries when the cell is inserted. * * Different to the constructor, the boundaries do not have to come from a simplicial complex, but also from * a more general entry complex. This includes cubical complexes or Morse complexes for example. @@ -759,7 +759,7 @@ class Matrix { * * @tparam Boundary_range Range of @ref Entry_representative. Assumed to have a begin(), end() and size() method. * @param boundary Boundary generating the new column. The content should be ordered by ID. - * @param dim Dimension of the face whose boundary is given. If the complex is simplicial, + * @param dim Dimension of the cell whose boundary is given. If the complex is simplicial, * this parameter can be omitted as it can be deduced from the size of the boundary. * @return If it is a @ref chainmatrix "chain matrix", the method returns the @ref MatIdx indices of the unpaired * chains used to reduce the boundary. Otherwise, nothing. @@ -768,26 +768,26 @@ class Matrix { Insertion_return insert_boundary(const Boundary_range& boundary, Dimension dim = -1); /** * @brief Only available for @ref mp_matrices "non-basic matrices". - * It does the same as the other version, but allows the boundary faces to be identified without restrictions + * It does the same as the other version, but allows the boundary cells to be identified without restrictions * except that all IDs have to be strictly increasing in the order of filtration. Note that you should avoid then * to use the other insertion method to avoid overwriting IDs. * - * As a face has to be inserted before one of its cofaces in a valid filtration (recall that it is assumed that - * for @ref mp_matrices "non-basic matrices", the faces are inserted by order of filtration), it is sufficient to - * indicate the ID of the face being inserted. + * As a cell has to be inserted before one of its cofaces in a valid filtration (recall that it is assumed that + * for @ref mp_matrices "non-basic matrices", the cells are inserted by order of filtration), it is sufficient to + * indicate the ID of the cell being inserted. * * @tparam Boundary_range Range of @ref Entry_representative. Assumed to have a begin(), end() and size() method. - * @param faceIndex @ref IDIdx index to use to identify the new face. + * @param cellIndex @ref IDIdx index to use to identify the new cell. * @param boundary Boundary generating the new column. The indices of the boundary have to correspond to the - * @p faceIndex values of precedent calls of the method for the corresponding faces and should be ordered in + * @p cellIndex values of precedent calls of the method for the corresponding cells and should be ordered in * increasing order. - * @param dim Dimension of the face whose boundary is given. If the complex is simplicial, + * @param dim Dimension of the cell whose boundary is given. If the complex is simplicial, * this parameter can be omitted as it can be deduced from the size of the boundary. * @return If it is a @ref chainmatrix "chain matrix", the method returns the @ref MatIdx indices of the unpaired * chains used to reduce the boundary. Otherwise, nothing. */ template - Insertion_return insert_boundary(ID_index faceIndex, const Boundary_range& boundary, Dimension dim = -1); + Insertion_return insert_boundary(ID_index cellIndex, const Boundary_range& boundary, Dimension dim = -1); /** * @brief Returns the column at the given @ref MatIdx index. @@ -895,10 +895,10 @@ class Matrix { * @brief Only available for @ref boundarymatrix "RU" and @ref chainmatrix "chain matrices" and if * @ref PersistenceMatrixOptions::has_removable_columns and @ref PersistenceMatrixOptions::has_vine_update are true. * For @ref chainmatrix "chain matrices", @ref PersistenceMatrixOptions::has_map_column_container and - * @ref PersistenceMatrixOptions::has_column_pairings also need to be true. Assumes that the face is maximal in the + * @ref PersistenceMatrixOptions::has_column_pairings also need to be true. Assumes that the cell is maximal in the * current complex and removes it such that the matrix remains consistent (i.e., RU is still an upper triangular * decomposition of the boundary matrix and chain is still a compatible bases of the chain complex in the sense - * of @cite zigzag). The maximality of the face is not verified. Also updates the barcode if it was computed. + * of @cite zigzag). The maximality of the cell is not verified. Also updates the barcode if it was computed. * * For @ref chainmatrix "chain matrices", using the other version of the method could perform better depending on how * the data is maintained on the side of the user. Then, @ref PersistenceMatrixOptions::has_column_pairings also do @@ -906,56 +906,56 @@ class Matrix { * * See also @ref remove_last and @ref remove_column. * - * @param columnIndex If @ref boundarymatrix "boundary matrix", @ref MatIdx index of the face to remove, otherwise the + * @param columnIndex If @ref boundarymatrix "boundary matrix", @ref MatIdx index of the cell to remove, otherwise the * @ref IDIdx index. */ - void remove_maximal_face(Index columnIndex); + void remove_maximal_cell(Index columnIndex); //TODO: See if it would be better to use something more general than a vector for columnsToSwap, such that // the user do not have to construct the vector from scratch. Like passing iterators instead. But it would be nice, - // to still be able to do (face, {})... + // to still be able to do (cell, {})... /** * @brief Only available for @ref chainmatrix "chain matrices" and if * @ref PersistenceMatrixOptions::has_removable_columns, @ref PersistenceMatrixOptions::has_vine_update and - * @ref PersistenceMatrixOptions::has_map_column_container are true. Assumes that the face is maximal in the current + * @ref PersistenceMatrixOptions::has_map_column_container are true. Assumes that the cell is maximal in the current * complex and removes it such that the matrix remains consistent (i.e., it is still a compatible bases of the chain - * complex in the sense of @cite zigzag). The maximality of the face is not verified. Also updates the barcode if it + * complex in the sense of @cite zigzag). The maximality of the cell is not verified. Also updates the barcode if it * was computed. * - * To maintain the compatibility, vine swaps are done to move the face up to the end of the filtration. Once at the + * To maintain the compatibility, vine swaps are done to move the cell up to the end of the filtration. Once at the * end, the removal is trivial. But for @ref chainmatrix "chain matrices", swaps do not actually swap the position of - * the column every time, so the faces appearing after @p faceIndex in the filtration have to be searched first within - * the matrix. If the user has an easy access to the @ref IDIdx of the faces in the order of filtration, passing them + * the column every time, so the cells appearing after @p cellIndex in the filtration have to be searched first within + * the matrix. If the user has an easy access to the @ref IDIdx of the cells in the order of filtration, passing them * by argument with @p columnsToSwap allows to skip a linear search process. Typically, if the user knows that the - * face he wants to remove is already the last face of the filtration, calling - * @ref remove_maximal_face(ID_index faceIndex, const std::vector& columnsToSwap) - * "remove_maximal_face(faceID, {})" will be faster than @ref remove_last(). + * cell he wants to remove is already the last cell of the filtration, calling + * @ref remove_maximal_cell(ID_index cellIndex, const std::vector& columnsToSwap) + * "remove_maximal_cell(cellID, {})" will be faster than @ref remove_last(). * * See also @ref remove_last. * - * @param faceIndex @ref IDIdx index of the face to remove - * @param columnsToSwap Vector of @ref IDIdx indices of the faces coming after @p faceIndex in the filtration. + * @param cellIndex @ref IDIdx index of the cell to remove + * @param columnsToSwap Vector of @ref IDIdx indices of the cells coming after @p cellIndex in the filtration. */ - void remove_maximal_face(ID_index faceIndex, const std::vector& columnsToSwap); + void remove_maximal_cell(ID_index cellIndex, const std::vector& columnsToSwap); /** - * @brief Removes the last inserted column/face from the matrix. + * @brief Removes the last inserted column/cell from the matrix. * If the matrix is @ref mp_matrices "non basic", @ref PersistenceMatrixOptions::has_removable_columns has to be true * for the method to be available. Additionally, if the matrix is a @ref chainmatrix "chain matrix", either * @ref PersistenceMatrixOptions::has_map_column_container has to be true or * @ref PersistenceMatrixOptions::has_vine_update has to be false. And if the matrix is a * @ref basematrix "base matrix" it should be without column compression. * - * See also @ref remove_maximal_face and @ref remove_column. + * See also @ref remove_maximal_cell and @ref remove_column. * - * For @ref chainmatrix "chain matrices", if @ref PersistenceMatrixOptions::has_vine_update is true, the last face + * For @ref chainmatrix "chain matrices", if @ref PersistenceMatrixOptions::has_vine_update is true, the last cell * does not have to be at the end of the matrix and therefore has to be searched first. In this case, if the user - * already knows the @ref IDIdx of the last face, calling - * @ref remove_maximal_face(ID_index faceIndex, const std::vector& columnsToSwap) - * "remove_maximal_face(faceID, {})" instead allows to skip the search. + * already knows the @ref IDIdx of the last cell, calling + * @ref remove_maximal_cell(ID_index cellIndex, const std::vector& columnsToSwap) + * "remove_maximal_cell(cellID, {})" instead allows to skip the search. */ void remove_last(); /** - * @brief Returns the maximal dimension of a face stored in the matrix. Only available for + * @brief Returns the maximal dimension of a cell stored in the matrix. Only available for * @ref mp_matrices "non-basic matrices" and if @ref PersistenceMatrixOptions::has_matrix_maximal_dimension_access * is true. * @@ -969,10 +969,10 @@ class Matrix { */ Index get_number_of_columns() const; /** - * @brief Returns the dimension of the given face. Only available for @ref mp_matrices "non-basic matrices". + * @brief Returns the dimension of the given cell. Only available for @ref mp_matrices "non-basic matrices". * - * @param columnIndex @ref MatIdx index of the column representing the face. - * @return Dimension of the face. + * @param columnIndex @ref MatIdx index of the column representing the cell. + * @return Dimension of the cell. */ Dimension get_column_dimension(Index columnIndex) const; @@ -1189,10 +1189,10 @@ class Matrix { * indices and that the @ref rowindex "row indices" for a @ref boundarymatrix "RU matrix" correspond to the updated * @ref IDIdx indices which got potentially swapped by a vine swap. * - * @param faceIndex @ref rowindex "Row index" of the pivot. + * @param cellIndex @ref rowindex "Row index" of the pivot. * @return @ref MatIdx index of the column with the given pivot. */ - Index get_column_with_pivot(ID_index faceIndex) const; + Index get_column_with_pivot(ID_index cellIndex) const; /** * @brief Returns the @ref rowindex "row index" of the pivot of the given column. Only available for * @ref mp_matrices "non-basic matrices". @@ -1280,7 +1280,7 @@ class Matrix { * Does the same than @ref vine_swap, but assumes that the swap is non trivial and therefore skips a part of the case * study. * - * @param index @ref PosIdx index of the first face to swap. The second one has to be at `index + 1`. Recall that for + * @param index @ref PosIdx index of the first cell to swap. The second one has to be at `index + 1`. Recall that for * @ref boundarymatrix "boundary matrices", @ref PosIdx == @ref MatIdx. * @return true If the barcode changed from the swap. * @return false Otherwise. @@ -1292,8 +1292,8 @@ class Matrix { * @ref Column_indexation_types::IDENTIFIER. Does the same than @ref vine_swap, but assumes that the swap is * non-trivial and therefore skips a part of the case study. * - * @param columnIndex1 @ref MatIdx index of the first face. - * @param columnIndex2 @ref MatIdx index of the second face. It is assumed that the @ref PosIdx of both only differs + * @param columnIndex1 @ref MatIdx index of the first cell. + * @param columnIndex2 @ref MatIdx index of the second cell. It is assumed that the @ref PosIdx of both only differs * by one. * @return Let \f$ pos1 \f$ be the @ref PosIdx index of @p columnIndex1 and \f$ pos2 \f$ be the @ref PosIdx index of * @p columnIndex2. The method returns the @ref MatIdx of the column which has now, after the swap, the @ref PosIdx @@ -1303,14 +1303,14 @@ class Matrix { /** * @brief Only available if @ref PersistenceMatrixOptions::has_vine_update is true and if it is either a * @ref boundarymatrix "boundary matrix" or @ref PersistenceMatrixOptions::column_indexation_type is set to - * @ref Column_indexation_types::POSITION. Does a vine swap between two faces which are consecutive in the + * @ref Column_indexation_types::POSITION. Does a vine swap between two cells which are consecutive in the * filtration. Roughly, if \f$ F \f$ is the current filtration represented by the matrix, the method modifies the * matrix such that the new state corresponds to a valid state for the filtration \f$ F' \f$ equal to \f$ F \f$ but - * with the two faces at position `index` and `index + 1` swapped. Of course, the two faces should not have a + * with the two cells at position `index` and `index + 1` swapped. Of course, the two cells should not have a * face/coface relation which each other ; \f$ F' \f$ has to be a valid filtration. * See @cite vineyards for more information about vine and vineyards. * - * @param index @ref PosIdx index of the first face to swap. The second one has to be at `index + 1`. Recall that for + * @param index @ref PosIdx index of the first cell to swap. The second one has to be at `index + 1`. Recall that for * @ref boundarymatrix "boundary matrices", @ref PosIdx == @ref MatIdx. * @return true If the barcode changed from the swap. * @return false Otherwise. @@ -1319,15 +1319,15 @@ class Matrix { /** * @brief Only available if @ref PersistenceMatrixOptions::has_vine_update is true and if it is either a * @ref chainmatrix "chain matrix" or @ref PersistenceMatrixOptions::column_indexation_type is set to - * @ref Column_indexation_types::IDENTIFIER. Does a vine swap between two faces which are consecutive in the + * @ref Column_indexation_types::IDENTIFIER. Does a vine swap between two cells which are consecutive in the * filtration. Roughly, if \f$ F \f$ is the current filtration represented by the matrix, the method modifies the * matrix such that the new state corresponds to a valid state for the filtration \f$ F' \f$ equal to \f$ F \f$ but - * with the two given faces at swapped positions. Of course, the two faces should not have a face/coface relation + * with the two given cells at swapped positions. Of course, the two cells should not have a face/coface relation * which each other ; \f$ F' \f$ has to be a valid filtration. * See @cite vineyards for more information about vine and vineyards. * - * @param columnIndex1 @ref MatIdx index of the first face. - * @param columnIndex2 @ref MatIdx index of the second face. It is assumed that the @ref PosIdx of both only differs + * @param columnIndex1 @ref MatIdx index of the first cell. + * @param columnIndex2 @ref MatIdx index of the second cell. It is assumed that the @ref PosIdx of both only differs * by one. * @return Let \f$ pos1 \f$ be the @ref PosIdx index of @p columnIndex1 and \f$ pos2 \f$ be the @ref PosIdx index of * @p columnIndex2. The method returns the @ref MatIdx of the column which has now, after the swap, the @ref PosIdx @@ -1531,7 +1531,7 @@ inline void Matrix::insert_column(const Container& col static_assert( !isNonBasic, - "'insert_column' not available for the chosen options. The input has to be in the form of a face boundary."); + "'insert_column' not available for the chosen options. The input has to be in the form of a cell boundary."); matrix_.insert_column(column); } @@ -1573,7 +1573,7 @@ Matrix::insert_boundary(const Boundary_range& boundary template template inline typename Matrix::Insertion_return -Matrix::insert_boundary(ID_index faceIndex, +Matrix::insert_boundary(ID_index cellIndex, const Boundary_range& boundary, Dimension dim) { @@ -1586,9 +1586,9 @@ Matrix::insert_boundary(ID_index faceIndex, static_assert(isNonBasic, "Only enabled for non-basic matrices."); if constexpr (!PersistenceMatrixOptions::is_of_boundary_type && PersistenceMatrixOptions::column_indexation_type == Column_indexation_types::CONTAINER) - return matrix_.insert_boundary(faceIndex, boundary, dim); + return matrix_.insert_boundary(cellIndex, boundary, dim); else - matrix_.insert_boundary(faceIndex, boundary, dim); + matrix_.insert_boundary(cellIndex, boundary, dim); } template @@ -1673,31 +1673,31 @@ inline void Matrix::erase_empty_row(ID_index rowIndex) } template -inline void Matrix::remove_maximal_face(Index columnIndex) +inline void Matrix::remove_maximal_cell(Index columnIndex) { static_assert(PersistenceMatrixOptions::has_removable_columns, - "'remove_maximal_face(ID_index)' is not available for the chosen options."); + "'remove_maximal_cell(ID_index)' is not available for the chosen options."); static_assert(isNonBasic && PersistenceMatrixOptions::has_vine_update, - "'remove_maximal_face(ID_index)' is not available for the chosen options."); + "'remove_maximal_cell(ID_index)' is not available for the chosen options."); static_assert(PersistenceMatrixOptions::is_of_boundary_type || (PersistenceMatrixOptions::has_map_column_container && PersistenceMatrixOptions::has_column_pairings), - "'remove_maximal_face(ID_index)' is not available for the chosen options."); + "'remove_maximal_cell(ID_index)' is not available for the chosen options."); - matrix_.remove_maximal_face(columnIndex); + matrix_.remove_maximal_cell(columnIndex); } template -inline void Matrix::remove_maximal_face(ID_index faceIndex, +inline void Matrix::remove_maximal_cell(ID_index cellIndex, const std::vector& columnsToSwap) { static_assert(PersistenceMatrixOptions::has_removable_columns, - "'remove_maximal_face(ID_index,const std::vector&)' is not available for the chosen options."); + "'remove_maximal_cell(ID_index,const std::vector&)' is not available for the chosen options."); static_assert(isNonBasic && !PersistenceMatrixOptions::is_of_boundary_type, - "'remove_maximal_face(ID_index,const std::vector&)' is not available for the chosen options."); + "'remove_maximal_cell(ID_index,const std::vector&)' is not available for the chosen options."); static_assert(PersistenceMatrixOptions::has_map_column_container && PersistenceMatrixOptions::has_vine_update, - "'remove_maximal_face(ID_index,const std::vector&)' is not available for the chosen options."); + "'remove_maximal_cell(ID_index,const std::vector&)' is not available for the chosen options."); - matrix_.remove_maximal_face(faceIndex, columnsToSwap); + matrix_.remove_maximal_cell(cellIndex, columnsToSwap); } template @@ -1902,14 +1902,14 @@ inline bool Matrix::is_zero_column(Index columnIndex, template inline typename Matrix::Index Matrix::get_column_with_pivot( - ID_index faceIndex) const + ID_index cellIndex) const { static_assert(isNonBasic && (!PersistenceMatrixOptions::is_of_boundary_type || (PersistenceMatrixOptions::has_vine_update || PersistenceMatrixOptions::can_retrieve_representative_cycles)), "'get_column_with_pivot' is not available for the chosen options."); - return matrix_.get_column_with_pivot(faceIndex); + return matrix_.get_column_with_pivot(cellIndex); } template diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/Boundary_matrix.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/Boundary_matrix.h index 29c6f87d93..93de613c03 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/Boundary_matrix.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/Boundary_matrix.h @@ -32,7 +32,7 @@ namespace persistence_matrix { * * @brief %Matrix structure to store the ordered @ref boundarymatrix "boundary matrix" \f$ R \f$ of a filtered complex * in order to compute its persistent homology. Provides an access to its columns and rows as well as the possibility - * to remove the last faces of the filtration while maintaining a valid barcode. + * to remove the last cells of the filtration while maintaining a valid barcode. * * @tparam Master_matrix An instantiation of @ref Matrix from which all types and options are deduced. */ @@ -120,10 +120,10 @@ class Boundary_matrix : public Master_matrix::Matrix_dimension_option, /** * @brief Inserts at the end of the matrix a new ordered column corresponding to the given boundary. * This means that it is assumed that this method is called on boundaries in the order of the filtration. - * It also assumes that the faces in the given boundary are identified by their relative position in the filtration, + * It also assumes that the cells in the given boundary are identified by their relative position in the filtration, * starting at 0. If it is not the case, use the other - * @ref insert_boundary(ID_index faceIndex, const Boundary_range& boundary, Dimension dim) "insert_boundary" - * instead by indicating the face ID used in the boundaries when the face is inserted. + * @ref insert_boundary(ID_index cellIndex, const Boundary_range& boundary, Dimension dim) "insert_boundary" + * instead by indicating the cell ID used in the boundaries when the cell is inserted. * * Different to the constructor, the boundaries do not have to come from a simplicial complex, but also from * a more general entry complex. This includes cubical complexes or Morse complexes for example. @@ -136,32 +136,32 @@ class Boundary_matrix : public Master_matrix::Matrix_dimension_option, * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() * method. * @param boundary Boundary generating the new column. The content should be ordered by ID. - * @param dim Dimension of the face whose boundary is given. If the complex is simplicial, + * @param dim Dimension of the cell whose boundary is given. If the complex is simplicial, * this parameter can be omitted as it can be deduced from the size of the boundary. * @return The @ref MatIdx index of the inserted boundary. */ template Index insert_boundary(const Boundary_range& boundary, Dimension dim = -1); /** - * @brief It does the same as the other version, but allows the boundary faces to be identified without restrictions + * @brief It does the same as the other version, but allows the boundary cells to be identified without restrictions * except that all IDs have to be strictly increasing in the order of filtration. Note that you should avoid then * to use the other insertion method to avoid overwriting IDs. * - * As a face has to be inserted before one of its cofaces in a valid filtration (recall that it is assumed that - * the faces are inserted by order of filtration), it is sufficient to indicate the ID of the face being inserted. + * As a cell has to be inserted before one of its cofaces in a valid filtration (recall that it is assumed that + * the cells are inserted by order of filtration), it is sufficient to indicate the ID of the cell being inserted. * * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() * method. - * @param faceIndex @ref IDIdx index to use to identify the new face. + * @param cellIndex @ref IDIdx index to use to identify the new cell. * @param boundary Boundary generating the new column. The indices of the boundary have to correspond to the - * @p faceIndex values of precedent calls of the method for the corresponding faces and should be ordered in + * @p cellIndex values of precedent calls of the method for the corresponding cells and should be ordered in * increasing order. - * @param dim Dimension of the face whose boundary is given. If the complex is simplicial, + * @param dim Dimension of the cell whose boundary is given. If the complex is simplicial, * this parameter can be omitted as it can be deduced from the size of the boundary. * @return The @ref MatIdx index of the inserted boundary. */ template - Index insert_boundary(ID_index faceIndex, const Boundary_range& boundary, Dimension dim = -1); + Index insert_boundary(ID_index cellIndex, const Boundary_range& boundary, Dimension dim = -1); /** * @brief Returns the column at the given @ref MatIdx index. * The type of the column depends on the choosen options, see @ref PersistenceMatrixOptions::column_type. @@ -189,9 +189,9 @@ class Boundary_matrix : public Master_matrix::Matrix_dimension_option, Row& get_row(Index rowIndex); /** * @brief Only available if @ref PersistenceMatrixOptions::has_removable_columns is true. - * Removes the last face in the filtration from the matrix and updates the barcode if this one was already computed. + * Removes the last cell in the filtration from the matrix and updates the barcode if this one was already computed. * - * @return The pivot of the removed face. + * @return The pivot of the removed cell. */ Index remove_last(); /** @@ -221,8 +221,8 @@ class Boundary_matrix : public Master_matrix::Matrix_dimension_option, /** * @brief Returns the dimension of the given column. * - * @param columnIndex @ref MatIdx index of the column representing the face. - * @return Dimension of the face. + * @param columnIndex @ref MatIdx index of the column representing the cell. + * @return Dimension of the cell. */ Dimension get_column_dimension(Index columnIndex) const; @@ -469,7 +469,7 @@ inline typename Boundary_matrix::Index Boundary_matrix template inline typename Boundary_matrix::Index Boundary_matrix::insert_boundary( - ID_index faceIndex, const Boundary_range& boundary, Dimension dim) + ID_index cellIndex, const Boundary_range& boundary, Dimension dim) { if (dim == -1) dim = boundary.size() == 0 ? 0 : boundary.size() - 1; @@ -492,12 +492,12 @@ inline typename Boundary_matrix::Index Boundary_matrix::Index Boundary_matrix std::vector insert_boundary(const Boundary_range& boundary, Dimension dim = -1); /** - * @brief It does the same as the other version, but allows the boundary faces to be identified without restrictions + * @brief It does the same as the other version, but allows the boundary cells to be identified without restrictions * except that all IDs have to be strictly increasing in the order of filtration. Note that you should avoid then * to use the other insertion method to avoid overwriting IDs. * - * As a face has to be inserted before one of its cofaces in a valid filtration (recall that it is assumed that - * the faces are inserted by order of filtration), it is sufficient to indicate the ID of the face being inserted. + * As a cell has to be inserted before one of its cofaces in a valid filtration (recall that it is assumed that + * the cells are inserted by order of filtration), it is sufficient to indicate the ID of the cell being inserted. * * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() * method. - * @param faceID @ref IDIdx index to use to identify the new face. + * @param cellID @ref IDIdx index to use to identify the new cell. * @param boundary Boundary generating the new column. The indices of the boundary have to correspond to the - * @p faceID values of precedent calls of the method for the corresponding faces and should be ordered in + * @p cellID values of precedent calls of the method for the corresponding cells and should be ordered in * increasing order. - * @param dim Dimension of the face whose boundary is given. If the complex is simplicial, + * @param dim Dimension of the cell whose boundary is given. If the complex is simplicial, * this parameter can be omitted as it can be deduced from the size of the boundary. * @return The @ref MatIdx index of the inserted boundary. */ template - std::vector insert_boundary(ID_index faceID, + std::vector insert_boundary(ID_index cellID, const Boundary_range& boundary, Dimension dim = -1); /** @@ -290,9 +290,9 @@ class Chain_matrix : public Master_matrix::Matrix_dimension_option, * @brief Only available if @ref PersistenceMatrixOptions::has_removable_columns and * @ref PersistenceMatrixOptions::has_vine_update are true, as well as, * @ref PersistenceMatrixOptions::has_map_column_container and @ref PersistenceMatrixOptions::has_column_pairings. - * Assumes that the face is maximal in the current complex and removes it such that the matrix remains consistent + * Assumes that the cell is maximal in the current complex and removes it such that the matrix remains consistent * (i.e., the matrix is still a compatible bases of the chain complex in the sense of @cite zigzag). - * The maximality of the face is not verified. + * The maximality of the cell is not verified. * Also updates the barcode if it is stored. * * Note that using the other version of the method could perform better depending on how the data is @@ -300,46 +300,46 @@ class Chain_matrix : public Master_matrix::Matrix_dimension_option, * * See also @ref remove_last. * - * @param faceID @ref IDIdx index of the face to remove + * @param cellID @ref IDIdx index of the cell to remove */ - void remove_maximal_face(ID_index faceID); + void remove_maximal_cell(ID_index cellID); /** * @brief Only available if @ref PersistenceMatrixOptions::has_removable_columns, * @ref PersistenceMatrixOptions::has_vine_update and @ref PersistenceMatrixOptions::has_map_column_container * are true. - * Assumes that the face is maximal in the current complex and removes it such that the matrix remains consistent + * Assumes that the cell is maximal in the current complex and removes it such that the matrix remains consistent * (i.e., it is still a compatible bases of the chain complex in the sense of @cite zigzag). - * The maximality of the face is not verified. + * The maximality of the cell is not verified. * Also updates the barcode if it is stored. * - * To maintain the compatibility, vine swaps are done to move the face up to the end of the filtration. Once at + * To maintain the compatibility, vine swaps are done to move the cell up to the end of the filtration. Once at * the end, the removal is trivial. But for @ref chainmatrix "chain matrices", swaps do not actually swap the position - * of the column every time, so the faces appearing after @p faceID in the filtration have to be searched first within - * the matrix. If the user has an easy access to the @ref IDIdx of the faces in the order of filtration, passing them + * of the column every time, so the cells appearing after @p cellID in the filtration have to be searched first within + * the matrix. If the user has an easy access to the @ref IDIdx of the cells in the order of filtration, passing them * by argument with @p columnsToSwap allows to skip a linear search process. Typically, if the user knows that the - * face he wants to remove is already the last face of the filtration, calling - * @ref remove_maximal_face(ID_index faceIndex, const std::vector& columnsToSwap) - * "remove_maximal_face(faceID, {})" will be faster than @ref remove_last(). + * cell he wants to remove is already the last cell of the filtration, calling + * @ref remove_maximal_cell(ID_index cellIndex, const std::vector& columnsToSwap) + * "remove_maximal_cell(cellID, {})" will be faster than @ref remove_last(). * * See also @ref remove_last. * - * @param faceID @ref IDIdx index of the face to remove - * @param columnsToSwap Vector of @ref IDIdx indices of the faces coming after @p faceID in the filtration. + * @param cellID @ref IDIdx index of the cell to remove + * @param columnsToSwap Vector of @ref IDIdx indices of the cells coming after @p cellID in the filtration. */ - void remove_maximal_face(ID_index faceID, const std::vector& columnsToSwap); + void remove_maximal_cell(ID_index cellID, const std::vector& columnsToSwap); /** * @brief Only available if @ref PersistenceMatrixOptions::has_removable_columns is true and, * if @ref PersistenceMatrixOptions::has_map_column_container is true or * @ref PersistenceMatrixOptions::has_vine_update is false. - * Removes the last face in the filtration from the matrix and updates the barcode if it is stored. + * Removes the last cell in the filtration from the matrix and updates the barcode if it is stored. * - * See also @ref remove_maximal_face. + * See also @ref remove_maximal_cell. * - * @warning If @ref PersistenceMatrixOptions::has_vine_update is true, the last face does not have to + * @warning If @ref PersistenceMatrixOptions::has_vine_update is true, the last cell does not have to * be at the end of the matrix container and therefore has to be searched first. In this case, if the user - * already knows the @ref IDIdx of the last face, calling - * @ref remove_maximal_face(ID_index faceIndex, const std::vector& columnsToSwap) - * "remove_maximal_face(faceID, {})" instead allows to skip the search. + * already knows the @ref IDIdx of the last cell, calling + * @ref remove_maximal_cell(ID_index cellIndex, const std::vector& columnsToSwap) + * "remove_maximal_cell(cellID, {})" instead allows to skip the search. */ void remove_last(); @@ -353,8 +353,8 @@ class Chain_matrix : public Master_matrix::Matrix_dimension_option, /** * @brief Returns the dimension of the given column. * - * @param columnIndex @ref MatIdx index of the column representing the face. - * @return Dimension of the face. + * @param columnIndex @ref MatIdx index of the column representing the cell. + * @return Dimension of the cell. */ Dimension get_column_dimension(Index columnIndex) const; @@ -422,10 +422,10 @@ class Chain_matrix : public Master_matrix::Matrix_dimension_option, /** * @brief Returns the column with given @ref rowindex "row index" as pivot. Assumes that the pivot exists. * - * @param faceID @ref rowindex "Row index" of the pivot. + * @param cellID @ref rowindex "Row index" of the pivot. * @return @ref MatIdx index of the column with the given pivot. */ - Index get_column_with_pivot(ID_index faceID) const; + Index get_column_with_pivot(ID_index cellID) const; /** * @brief Returns the @ref rowindex "row index" of the pivot of the given column. * @@ -499,10 +499,10 @@ class Chain_matrix : public Master_matrix::Matrix_dimension_option, Column_settings* colSettings_; /**< Entry factory. */ template - std::vector _reduce_boundary(ID_index faceID, const Boundary_range& boundary, Dimension dim); + std::vector _reduce_boundary(ID_index cellID, const Boundary_range& boundary, Dimension dim); void _reduce_by_G(Tmp_column& column, std::vector& chainsInH, Index currentPivot); void _reduce_by_F(Tmp_column& column, std::vector& chainsInF, Index currentPivot); - void _build_from_H(ID_index faceID, Tmp_column& column, std::vector& chainsInH); + void _build_from_H(ID_index cellID, Tmp_column& column, std::vector& chainsInH); void _update_largest_death_in_F(const std::vector& chainsInF); void _insert_chain(const Tmp_column& column, Dimension dimension); void _insert_chain(const Tmp_column& column, Dimension dimension, Index pair); @@ -681,21 +681,21 @@ inline std::vector Chain_matrix template inline std::vector Chain_matrix::insert_boundary( - ID_index faceID, const Boundary_range& boundary, Dimension dim) + ID_index cellID, const Boundary_range& boundary, Dimension dim) { if constexpr (!Master_matrix::Option_list::has_map_column_container) { - if (pivotToColumnIndex_.size() <= faceID) { - pivotToColumnIndex_.resize(faceID * 2 + 1, -1); + if (pivotToColumnIndex_.size() <= cellID) { + pivotToColumnIndex_.resize(cellID * 2 + 1, -1); } } if constexpr (Master_matrix::Option_list::has_vine_update && Master_matrix::Option_list::has_column_pairings) { if constexpr (Master_matrix::Option_list::has_map_column_container) { - Swap_opt::CP::pivotToPosition_.try_emplace(faceID, _nextPosition()); + Swap_opt::CP::pivotToPosition_.try_emplace(cellID, _nextPosition()); } else { - if (Swap_opt::CP::pivotToPosition_.size() <= faceID) + if (Swap_opt::CP::pivotToPosition_.size() <= cellID) Swap_opt::CP::pivotToPosition_.resize(pivotToColumnIndex_.size(), -1); - Swap_opt::CP::pivotToPosition_[faceID] = _nextPosition(); + Swap_opt::CP::pivotToPosition_[cellID] = _nextPosition(); } } @@ -703,7 +703,7 @@ inline std::vector Chain_matrix(-1) ? (boundary.size() == 0 ? 0 : boundary.size() - 1) : dim); } - return _reduce_boundary(faceID, boundary, dim); + return _reduce_boundary(cellID, boundary, dim); } template @@ -728,22 +728,22 @@ inline const typename Chain_matrix::Column& Chain_matrix -inline void Chain_matrix::remove_maximal_face(ID_index faceID) +inline void Chain_matrix::remove_maximal_cell(ID_index cellID) { static_assert(Master_matrix::Option_list::has_removable_columns, - "'remove_maximal_face' is not implemented for the chosen options."); + "'remove_maximal_cell' is not implemented for the chosen options."); static_assert(Master_matrix::Option_list::has_map_column_container && Master_matrix::Option_list::has_vine_update && Master_matrix::Option_list::has_column_pairings, - "'remove_maximal_face' is not implemented for the chosen options."); + "'remove_maximal_cell' is not implemented for the chosen options."); // TODO: find simple test to verify that col at columnIndex is maximal even without row access. const auto& pivotToPosition = Swap_opt::CP::pivotToPosition_; - auto it = pivotToPosition.find(faceID); - if (it == pivotToPosition.end()) return; // face does not exists. TODO: put an assert instead? + auto it = pivotToPosition.find(cellID); + if (it == pivotToPosition.end()) return; // cell does not exists. TODO: put an assert instead? Pos_index startPos = it->second; - Index startIndex = pivotToColumnIndex_.at(faceID); + Index startIndex = pivotToColumnIndex_.at(cellID); if (startPos != _nextPosition() - 1) { std::vector colToSwap; @@ -765,17 +765,17 @@ inline void Chain_matrix::remove_maximal_face(ID_index faceID) } template -inline void Chain_matrix::remove_maximal_face(ID_index faceID, +inline void Chain_matrix::remove_maximal_cell(ID_index cellID, const std::vector& columnsToSwap) { static_assert(Master_matrix::Option_list::has_removable_columns, - "'remove_maximal_face' is not implemented for the chosen options."); + "'remove_maximal_cell' is not implemented for the chosen options."); static_assert(Master_matrix::Option_list::has_map_column_container && Master_matrix::Option_list::has_vine_update, - "'remove_maximal_face' is not implemented for the chosen options."); + "'remove_maximal_cell' is not implemented for the chosen options."); // TODO: find simple test to verify that col at columnIndex is maximal even without row access. - Index startIndex = pivotToColumnIndex_.at(faceID); + Index startIndex = pivotToColumnIndex_.at(cellID); for (ID_index i : columnsToSwap) { startIndex = Swap_opt::vine_swap(startIndex, pivotToColumnIndex_.at(i)); @@ -797,7 +797,7 @@ inline void Chain_matrix::remove_last() if constexpr (Master_matrix::Option_list::has_vine_update) { // careful: linear because of the search of the last index. It is better to keep track of the @ref IDIdx index // of the last column while performing swaps (or the @ref MatIdx with the return values of `vine_swap` + get_pivot) - // and then call `remove_maximal_face` with it and an empty `columnsToSwap`. + // and then call `remove_maximal_cell` with it and an empty `columnsToSwap`. ID_index pivot = 0; Index colIndex = 0; @@ -869,12 +869,12 @@ inline bool Chain_matrix::is_zero_column(Index columnIndex) template inline typename Chain_matrix::Index Chain_matrix::get_column_with_pivot( - ID_index faceID) const + ID_index cellID) const { if constexpr (Master_matrix::Option_list::has_map_column_container) { - return pivotToColumnIndex_.at(faceID); + return pivotToColumnIndex_.at(cellID); } else { - return pivotToColumnIndex_[faceID]; + return pivotToColumnIndex_[cellID]; } } @@ -959,7 +959,7 @@ inline void Chain_matrix::print() const template template inline std::vector Chain_matrix::_reduce_boundary( - ID_index faceID, const Boundary_range& boundary, Dimension dim) + ID_index cellID, const Boundary_range& boundary, Dimension dim) { Tmp_column column(boundary.begin(), boundary.end()); if (dim == static_cast(-1)) dim = boundary.begin() == boundary.end() ? 0 : boundary.size() - 1; @@ -975,9 +975,9 @@ inline std::vector Chain_matrix Chain_matrix Chain_matrix::_reduce_by_F(Tmp_column& column, } template -inline void Chain_matrix::_build_from_H(ID_index faceID, +inline void Chain_matrix::_build_from_H(ID_index cellID, Tmp_column& column, std::vector& chainsInH) { if constexpr (Master_matrix::Option_list::is_z2) { - column.insert(faceID); + column.insert(cellID); for (Index idx_h : chainsInH) { _add_to(get_column(idx_h), column, 1u); } } else { - column.emplace(faceID, 1); + column.emplace(cellID, 1); for (std::pair& idx_h : chainsInH) { _add_to(get_column(idx_h.first), column, idx_h.second); } diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/Id_to_index_overlay.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/Id_to_index_overlay.h index 91b09f2659..be885d182a 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/Id_to_index_overlay.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/Id_to_index_overlay.h @@ -220,10 +220,10 @@ class Id_to_index_overlay /** * @brief Inserts at the end of the matrix a new ordered column corresponding to the given boundary. * This means that it is assumed that this method is called on boundaries in the order of the filtration. - * It also assumes that the faces in the given boundary are identified by their relative position in the filtration, + * It also assumes that the cells in the given boundary are identified by their relative position in the filtration, * starting at 0. If it is not the case, use the other * @ref insert_boundary(ID_index, const Boundary_range&, Dimension) "insert_boundary" instead by indicating the - * face ID used in the boundaries when the face is inserted. + * cell ID used in the boundaries when the cell is inserted. * * Different to the constructor, the boundaries do not have to come from a simplicial complex, but also from * a more general entry complex. This includes cubical complexes or Morse complexes for example. @@ -241,39 +241,39 @@ class Id_to_index_overlay * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() * method. * @param boundary Boundary generating the new column. The content should be ordered by ID. - * @param dim Dimension of the face whose boundary is given. If the complex is simplicial, + * @param dim Dimension of the cell whose boundary is given. If the complex is simplicial, * this parameter can be omitted as it can be deduced from the size of the boundary. */ template void insert_boundary(const Boundary_range& boundary, Dimension dim = -1); /** - * @brief It does the same as the other version, but allows the boundary faces to be identified without restrictions + * @brief It does the same as the other version, but allows the boundary cells to be identified without restrictions * except that all IDs have to be strictly increasing in the order of filtration. Note that you should avoid then * to use the other insertion method to avoid overwriting IDs. * - * As a face has to be inserted before one of its cofaces in a valid filtration (recall that it is assumed that - * the faces are inserted by order of filtration), it is sufficient to indicate the ID of the face being inserted. + * As a cell has to be inserted before one of its cofaces in a valid filtration (recall that it is assumed that + * the cells are inserted by order of filtration), it is sufficient to indicate the ID of the cell being inserted. * * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() * method. - * @param faceIndex @ref IDIdx index to use to identify the new face. + * @param cellIndex @ref IDIdx index to use to identify the new cell. * @param boundary Boundary generating the new column. The indices of the boundary have to correspond to the - * @p faceIndex values of precedent calls of the method for the corresponding faces and should be ordered in + * @p cellIndex values of precedent calls of the method for the corresponding cells and should be ordered in * increasing order. - * @param dim Dimension of the face whose boundary is given. If the complex is simplicial, + * @param dim Dimension of the cell whose boundary is given. If the complex is simplicial, * this parameter can be omitted as it can be deduced from the size of the boundary. */ template - void insert_boundary(ID_index faceIndex, const Boundary_range& boundary, Dimension dim = -1); + void insert_boundary(ID_index cellIndex, const Boundary_range& boundary, Dimension dim = -1); /** * @brief Returns the column at the given @ref IDIdx index. * For @ref boundarymatrix "RU matrices", the returned column is from \f$ R \f$. * The type of the column depends on the choosen options, see @ref PersistenceMatrixOptions::column_type. * - * @param faceID @ref IDIdx index of the column to return. + * @param cellID @ref IDIdx index of the column to return. * @return Reference to the column. */ - Column& get_column(ID_index faceID); + Column& get_column(ID_index cellID); /** * @brief Only available if @ref PersistenceMatrixOptions::has_row_access is true. * Returns the row at the given @ref rowindex "row index". @@ -319,10 +319,10 @@ class Id_to_index_overlay * @ref PersistenceMatrixOptions::has_removable_columns and @ref PersistenceMatrixOptions::has_vine_update are true. * For @ref chainmatrix "chain matrices", @ref PersistenceMatrixOptions::has_map_column_container and * @ref PersistenceMatrixOptions::has_column_pairings also need to be true. - * Assumes that the face is maximal in the current complex and removes it such that the matrix remains consistent + * Assumes that the cell is maximal in the current complex and removes it such that the matrix remains consistent * (i.e., RU is still an upper triangular decomposition of the @ref boundarymatrix "boundary matrix" and chain is * still a compatible bases of the chain complex in the sense of @cite zigzag). - * The maximality of the face is not verified. + * The maximality of the cell is not verified. * Also updates the barcode if it was computed. * * For @ref chainmatrix "chain matrices", using the other version of the method could perform better depending on @@ -331,51 +331,51 @@ class Id_to_index_overlay * * See also @ref remove_last. * - * @param faceID @ref IDIdx index of the face to remove. + * @param cellID @ref IDIdx index of the cell to remove. */ - void remove_maximal_face(ID_index faceID); + void remove_maximal_cell(ID_index cellID); /** * @brief Only available for @ref chainmatrix "chain matrices" and if * @ref PersistenceMatrixOptions::has_removable_columns, @ref PersistenceMatrixOptions::has_vine_update * and @ref PersistenceMatrixOptions::has_map_column_container are true. - * Assumes that the face is maximal in the current complex and removes it such that the matrix remains consistent + * Assumes that the cell is maximal in the current complex and removes it such that the matrix remains consistent * (i.e., it is still a compatible bases of the chain complex in the sense of @cite zigzag). - * The maximality of the face is not verified. + * The maximality of the cell is not verified. * Also updates the barcode if it was computed. * - * To maintain the compatibility, vine swaps are done to move the face up to the end of the filtration. Once at + * To maintain the compatibility, vine swaps are done to move the cell up to the end of the filtration. Once at * the end, the removal is trivial. But for @ref chainmatrix "chain matrices", swaps do not actually swap the position - * of the column every time, so the faces appearing after @p faceIndex in the filtration have to be searched first - * within the matrix. If the user has an easy access to the @ref IDIdx of the faces in the order of filtration, + * of the column every time, so the cells appearing after @p cellIndex in the filtration have to be searched first + * within the matrix. If the user has an easy access to the @ref IDIdx of the cells in the order of filtration, * passing them by argument with @p columnsToSwap allows to skip a linear search process. Typically, if the user knows - * that the face he wants to remove is already the last face of the filtration, calling - * @ref remove_maximal_face(ID_index, const std::vector&) "remove_maximal_face(faceID, {})" + * that the cell he wants to remove is already the last cell of the filtration, calling + * @ref remove_maximal_cell(ID_index, const std::vector&) "remove_maximal_cell(cellID, {})" * will be faster than @ref remove_last(). * * See also @ref remove_last. * - * @param faceID @ref IDIdx index of the face to remove. - * @param columnsToSwap Vector of @ref IDIdx indices of the faces coming after @p faceID in the filtration. + * @param cellID @ref IDIdx index of the cell to remove. + * @param columnsToSwap Vector of @ref IDIdx indices of the cells coming after @p cellID in the filtration. */ - void remove_maximal_face(ID_index faceID, const std::vector& columnsToSwap); + void remove_maximal_cell(ID_index cellID, const std::vector& columnsToSwap); /** * @brief Only available if @ref PersistenceMatrixOptions::has_removable_columns is true. Additionally, if the * matrix is a @ref chainmatrix "chain matrix", either @ref PersistenceMatrixOptions::has_map_column_container has to * be true or @ref PersistenceMatrixOptions::has_vine_update has to be false. - * Removes the last face in the filtration from the matrix and updates the barcode if it is stored. + * Removes the last cell in the filtration from the matrix and updates the barcode if it is stored. * - * See also @ref remove_maximal_face. + * See also @ref remove_maximal_cell. * - * For @ref chainmatrix "chain matrices", if @ref PersistenceMatrixOptions::has_vine_update is true, the last face + * For @ref chainmatrix "chain matrices", if @ref PersistenceMatrixOptions::has_vine_update is true, the last cell * does not have to be at the end of the matrix and therefore has to be searched first. In this case, if the user - * already knows the @ref IDIdx of the last face, calling - * @ref remove_maximal_face(ID_index, const std::vector&) "remove_maximal_face(faceID, {})" + * already knows the @ref IDIdx of the last cell, calling + * @ref remove_maximal_cell(ID_index, const std::vector&) "remove_maximal_cell(cellID, {})" * instead allows to skip the search. */ void remove_last(); /** - * @brief Returns the maximal dimension of a face stored in the matrix. Only available + * @brief Returns the maximal dimension of a cell stored in the matrix. Only available * if @ref PersistenceMatrixOptions::has_matrix_maximal_dimension_access is true. * * @return The maximal dimension. @@ -388,24 +388,24 @@ class Id_to_index_overlay */ Index get_number_of_columns() const; /** - * @brief Returns the dimension of the given face. Only available for @ref mp_matrices "non-basic matrices". + * @brief Returns the dimension of the given cell. Only available for @ref mp_matrices "non-basic matrices". * - * @param faceID @ref IDIdx index of the face. - * @return Dimension of the face. + * @param cellID @ref IDIdx index of the cell. + * @return Dimension of the cell. */ - Dimension get_column_dimension(ID_index faceID) const; + Dimension get_column_dimension(ID_index cellID) const; /** - * @brief Adds column corresponding to @p sourceFaceID onto the column corresponding to @p targetFaceID. + * @brief Adds column corresponding to @p sourceCellID onto the column corresponding to @p targetCellID. * * @warning They will be no verification to ensure that the addition makes sense for the validity of the matrix. * For example, a right-to-left addition could corrupt the computation of the barcode if done blindly. * So should be used with care. * - * @param sourceFaceID @ref IDIdx index of the source column. - * @param targetFaceID @ref IDIdx index of the target column. + * @param sourceCellID @ref IDIdx index of the source column. + * @param targetCellID @ref IDIdx index of the target column. */ - void add_to(ID_index sourceFaceID, ID_index targetFaceID); + void add_to(ID_index sourceCellID, ID_index targetCellID); /** * @brief Multiplies the target column with the coefficient and then adds the source column to it. * That is: `targetColumn = (targetColumn * coefficient) + sourceColumn`. @@ -414,11 +414,11 @@ class Id_to_index_overlay * For example, a right-to-left addition could corrupt the computation of the barcode if done blindly. * So should be used with care. * - * @param sourceFaceID @ref IDIdx index of the source column. + * @param sourceCellID @ref IDIdx index of the source column. * @param coefficient Value to multiply. - * @param targetFaceID @ref IDIdx index of the target column. + * @param targetCellID @ref IDIdx index of the target column. */ - void multiply_target_and_add_to(ID_index sourceFaceID, const Field_element& coefficient, ID_index targetFaceID); + void multiply_target_and_add_to(ID_index sourceCellID, const Field_element& coefficient, ID_index targetCellID); /** * @brief Multiplies the source column with the coefficient before adding it to the target column. * That is: `targetColumn += (coefficient * sourceColumn)`. The source column will **not** be modified. @@ -428,10 +428,10 @@ class Id_to_index_overlay * So should be used with care. * * @param coefficient Value to multiply. - * @param sourceFaceID @ref IDIdx index of the source column. - * @param targetFaceID @ref IDIdx index of the target column. + * @param sourceCellID @ref IDIdx index of the source column. + * @param targetCellID @ref IDIdx index of the target column. */ - void multiply_source_and_add_to(const Field_element& coefficient, ID_index sourceFaceID, ID_index targetFaceID); + void multiply_source_and_add_to(const Field_element& coefficient, ID_index sourceCellID, ID_index targetCellID); /** * @brief Zeroes the entry at the given coordinates. Not available for @ref chainmatrix "chain matrices". @@ -440,10 +440,10 @@ class Id_to_index_overlay * * For @ref boundarymatrix "RU matrices", zeros only the entry in \f$ R \f$. * - * @param faceID @ref IDIdx index of the face corresponding to the column of the entry. + * @param cellID @ref IDIdx index of the cell corresponding to the column of the entry. * @param rowIndex @ref rowindex "Row index" of the row of the entry. */ - void zero_entry(ID_index faceID, ID_index rowIndex); + void zero_entry(ID_index cellID, ID_index rowIndex); /** * @brief Zeroes the column at the given index. Not available for @ref chainmatrix "chain matrices". * In general, should be used with care to not destroy the validity @@ -451,20 +451,20 @@ class Id_to_index_overlay * * For @ref boundarymatrix "RU matrices", zeros only the column in \f$ R \f$. * - * @param faceID @ref IDIdx index of the face corresponding to the column. + * @param cellID @ref IDIdx index of the cell corresponding to the column. */ - void zero_column(ID_index faceID); + void zero_column(ID_index cellID); /** * @brief Indicates if the entry at given coordinates has value zero. * * For @ref boundarymatrix "RU matrices", looks into \f$ R \f$. * - * @param faceID @ref IDIdx index of the face corresponding to the column of the entry. + * @param cellID @ref IDIdx index of the cell corresponding to the column of the entry. * @param rowIndex @ref rowindex "Row index" of the row of the entry. * @return true If the entry has value zero. * @return false Otherwise. */ - bool is_zero_entry(ID_index faceID, ID_index rowIndex) const; + bool is_zero_entry(ID_index cellID, ID_index rowIndex) const; /** * @brief Indicates if the column at given index has value zero. * @@ -473,11 +473,11 @@ class Id_to_index_overlay * Note that for @ref chainmatrix "chain matrices", this method should always return false, as a valid * @ref chainmatrix "chain matrix" never has empty columns. * - * @param faceID @ref IDIdx index of the face corresponding to the column. + * @param cellID @ref IDIdx index of the cell corresponding to the column. * @return true If the column has value zero. * @return false Otherwise. */ - bool is_zero_column(ID_index faceID); + bool is_zero_column(ID_index cellID); /** * @brief Returns the @ref IDIdx index of the column which has the given @ref rowindex "row index" as pivot. @@ -487,17 +487,17 @@ class Id_to_index_overlay * the row indices for a @ref boundarymatrix "RU matrix" correspond to the updated @ref IDIdx indices which got * potentially swapped by a vine swap. * - * @param faceIndex @ref rowindex "Row index" of the pivot. + * @param cellIndex @ref rowindex "Row index" of the pivot. * @return @ref IDIdx index of the column with the given pivot. */ - ID_index get_column_with_pivot(ID_index faceIndex) const; + ID_index get_column_with_pivot(ID_index cellIndex) const; /** * @brief Returns the @ref rowindex "row index" of the pivot of the given column. * - * @param faceID @ref IDIdx index of the face corresponding to the column. + * @param cellID @ref IDIdx index of the cell corresponding to the column. * @return The @ref rowindex "row index" of the pivot. */ - ID_index get_pivot(ID_index faceID); + ID_index get_pivot(ID_index cellID); /** * @brief Resets the matrix to an empty matrix. @@ -549,10 +549,10 @@ class Id_to_index_overlay * Swaps the two given columns. Note that it really just swaps two columns and do not updates * anything else, nor performs additions to maintain some properties on the matrix. * - * @param faceID1 First column @ref IDIdx index to swap. - * @param faceID2 Second column @ref IDIdx index to swap. + * @param cellID1 First column @ref IDIdx index to swap. + * @param cellID2 Second column @ref IDIdx index to swap. */ - void swap_columns(ID_index faceID1, ID_index faceID2); + void swap_columns(ID_index cellID1, ID_index cellID2); /** * @brief Only available for simple @ref boundarymatrix "boundary matrices" (only storing R) * and if @ref PersistenceMatrixOptions::has_column_and_row_swaps is true. @@ -568,29 +568,29 @@ class Id_to_index_overlay * Does the same than @ref vine_swap, but assumes that the swap is non trivial and * therefore skips a part of the case study. * - * @param faceID1 @ref IDIdx index of the first face. - * @param faceID2 @ref IDIdx index of the second face. It is assumed that the @ref PosIdx of both only differs by one. + * @param cellID1 @ref IDIdx index of the first cell. + * @param cellID2 @ref IDIdx index of the second cell. It is assumed that the @ref PosIdx of both only differs by one. * @return Let \f$ pos1 \f$ be the @ref PosIdx index of @p columnIndex1 and \f$ pos2 \f$ be the @ref PosIdx index of * @p columnIndex2. The method returns the @ref MatIdx of the column which has now, after the swap, the @ref PosIdx * \f$ max(pos1, pos2) \f$. */ - ID_index vine_swap_with_z_eq_1_case(ID_index faceID1, ID_index faceID2); + ID_index vine_swap_with_z_eq_1_case(ID_index cellID1, ID_index cellID2); /** * @brief Only available if @ref PersistenceMatrixOptions::has_vine_update is true. - * Does a vine swap between two faces which are consecutive in the filtration. Roughly, if \f$ F \f$ is + * Does a vine swap between two cells which are consecutive in the filtration. Roughly, if \f$ F \f$ is * the current filtration represented by the matrix, the method modifies the matrix such that the new state - * corresponds to a valid state for the filtration \f$ F' \f$ equal to \f$ F \f$ but with the two given faces - * at swapped positions. Of course, the two faces should not have a face/coface relation which each other ; + * corresponds to a valid state for the filtration \f$ F' \f$ equal to \f$ F \f$ but with the two given cells + * at swapped positions. Of course, the two cells should not have a face/coface relation which each other ; * \f$ F' \f$ has to be a valid filtration. * See @cite vineyards for more information about vine and vineyards. * - * @param faceID1 @ref IDIdx index of the first face. - * @param faceID2 @ref IDIdx index of the second face. It is assumed that the @ref PosIdx of both only differs by one. + * @param cellID1 @ref IDIdx index of the first cell. + * @param cellID2 @ref IDIdx index of the second cell. It is assumed that the @ref PosIdx of both only differs by one. * @return Let \f$ pos1 \f$ be the @ref PosIdx index of @p columnIndex1 and \f$ pos2 \f$ be the @ref PosIdx index of * @p columnIndex2. The method returns the @ref MatIdx of the column which has now, after the swap, the @ref PosIdx * \f$ max(pos1, pos2) \f$. */ - ID_index vine_swap(ID_index faceID1, ID_index faceID2); + ID_index vine_swap(ID_index cellID1, ID_index cellID2); /** * @brief Only available if @ref PersistenceMatrixOptions::can_retrieve_representative_cycles is true. Pre-computes @@ -752,26 +752,26 @@ inline void Id_to_index_overlay::insert_bounda template template -inline void Id_to_index_overlay::insert_boundary(ID_index faceIndex, +inline void Id_to_index_overlay::insert_boundary(ID_index cellIndex, const Boundary_range& boundary, Dimension dim) { if constexpr (Master_matrix::Option_list::has_map_column_container) { - GUDHI_CHECK(idToIndex_->find(faceIndex) == idToIndex_->end(), + GUDHI_CHECK(idToIndex_->find(cellIndex) == idToIndex_->end(), std::invalid_argument("Id_to_index_overlay::insert_boundary - Index for simplex already chosen!")); } else { - GUDHI_CHECK((idToIndex_->size() <= faceIndex || _id_to_index(faceIndex) == static_cast(-1)), + GUDHI_CHECK((idToIndex_->size() <= cellIndex || _id_to_index(cellIndex) == static_cast(-1)), std::invalid_argument("Id_to_index_overlay::insert_boundary - Index for simplex already chosen!")); } - matrix_.insert_boundary(faceIndex, boundary, dim); + matrix_.insert_boundary(cellIndex, boundary, dim); if constexpr (Master_matrix::Option_list::is_of_boundary_type) { if constexpr (Master_matrix::Option_list::has_map_column_container) { - idToIndex_->emplace(faceIndex, nextIndex_); + idToIndex_->emplace(cellIndex, nextIndex_); } else { - if (idToIndex_->size() <= faceIndex) { - idToIndex_->resize(faceIndex + 1, -1); + if (idToIndex_->size() <= cellIndex) { + idToIndex_->resize(cellIndex + 1, -1); } - _id_to_index(faceIndex) = nextIndex_; + _id_to_index(cellIndex) = nextIndex_; } ++nextIndex_; } @@ -779,9 +779,9 @@ inline void Id_to_index_overlay::insert_bounda template inline typename Id_to_index_overlay::Column& -Id_to_index_overlay::get_column(ID_index faceID) +Id_to_index_overlay::get_column(ID_index cellID) { - return matrix_.get_column(_id_to_index(faceID)); + return matrix_.get_column(_id_to_index(cellID)); } template @@ -798,7 +798,7 @@ inline void Id_to_index_overlay::erase_empty_r } template -inline void Id_to_index_overlay::remove_maximal_face(ID_index faceID) +inline void Id_to_index_overlay::remove_maximal_cell(ID_index cellID) { if constexpr (Master_matrix::Option_list::is_of_boundary_type) { std::vector indexToID(nextIndex_); @@ -812,34 +812,34 @@ inline void Id_to_index_overlay::remove_maxima } } --nextIndex_; - for (Index curr = _id_to_index(faceID); curr < nextIndex_; ++curr) { + for (Index curr = _id_to_index(cellID); curr < nextIndex_; ++curr) { matrix_.vine_swap(curr); std::swap(idToIndex_->at(indexToID[curr]), idToIndex_->at(indexToID[curr + 1])); } matrix_.remove_last(); - GUDHI_CHECK(_id_to_index(faceID) == nextIndex_, - std::logic_error("Id_to_index_overlay::remove_maximal_face - Indexation problem.")); + GUDHI_CHECK(_id_to_index(cellID) == nextIndex_, + std::logic_error("Id_to_index_overlay::remove_maximal_cell - Indexation problem.")); if constexpr (Master_matrix::Option_list::has_map_column_container) { - idToIndex_->erase(faceID); + idToIndex_->erase(cellID); } else { - _id_to_index(faceID) = -1; + _id_to_index(cellID) = -1; } } else { - matrix_.remove_maximal_face(faceID); + matrix_.remove_maximal_cell(cellID); } } template -inline void Id_to_index_overlay::remove_maximal_face( - ID_index faceID, const std::vector& columnsToSwap) +inline void Id_to_index_overlay::remove_maximal_cell( + ID_index cellID, const std::vector& columnsToSwap) { static_assert(!Master_matrix::Option_list::is_of_boundary_type, - "'remove_maximal_face(ID_index,const std::vector&)' is not available for the chosen options."); + "'remove_maximal_cell(ID_index,const std::vector&)' is not available for the chosen options."); std::vector translatedIndices; std::transform(columnsToSwap.cbegin(), columnsToSwap.cend(), std::back_inserter(translatedIndices), [&](ID_index id) { return _id_to_index(id); }); - matrix_.remove_maximal_face(faceID, translatedIndices); + matrix_.remove_maximal_cell(cellID, translatedIndices); } template @@ -881,54 +881,54 @@ Id_to_index_overlay::get_number_of_columns() c template inline typename Id_to_index_overlay::Dimension -Id_to_index_overlay::get_column_dimension(ID_index faceID) const +Id_to_index_overlay::get_column_dimension(ID_index cellID) const { - return matrix_.get_column_dimension(_id_to_index(faceID)); + return matrix_.get_column_dimension(_id_to_index(cellID)); } template -inline void Id_to_index_overlay::add_to(ID_index sourceFaceID, ID_index targetFaceID) +inline void Id_to_index_overlay::add_to(ID_index sourceCellID, ID_index targetCellID) { - return matrix_.add_to(_id_to_index(sourceFaceID), _id_to_index(targetFaceID)); + return matrix_.add_to(_id_to_index(sourceCellID), _id_to_index(targetCellID)); } template inline void Id_to_index_overlay::multiply_target_and_add_to( - ID_index sourceFaceID, const Field_element& coefficient, ID_index targetFaceID) + ID_index sourceCellID, const Field_element& coefficient, ID_index targetCellID) { - return matrix_.multiply_target_and_add_to(_id_to_index(sourceFaceID), coefficient, _id_to_index(targetFaceID)); + return matrix_.multiply_target_and_add_to(_id_to_index(sourceCellID), coefficient, _id_to_index(targetCellID)); } template inline void Id_to_index_overlay::multiply_source_and_add_to( - const Field_element& coefficient, ID_index sourceFaceID, ID_index targetFaceID) + const Field_element& coefficient, ID_index sourceCellID, ID_index targetCellID) { - return matrix_.multiply_source_and_add_to(coefficient, _id_to_index(sourceFaceID), _id_to_index(targetFaceID)); + return matrix_.multiply_source_and_add_to(coefficient, _id_to_index(sourceCellID), _id_to_index(targetCellID)); } template -inline void Id_to_index_overlay::zero_entry(ID_index faceID, ID_index rowIndex) +inline void Id_to_index_overlay::zero_entry(ID_index cellID, ID_index rowIndex) { - return matrix_.zero_entry(_id_to_index(faceID), rowIndex); + return matrix_.zero_entry(_id_to_index(cellID), rowIndex); } template -inline void Id_to_index_overlay::zero_column(ID_index faceID) +inline void Id_to_index_overlay::zero_column(ID_index cellID) { - return matrix_.zero_column(_id_to_index(faceID)); + return matrix_.zero_column(_id_to_index(cellID)); } template -inline bool Id_to_index_overlay::is_zero_entry(ID_index faceID, +inline bool Id_to_index_overlay::is_zero_entry(ID_index cellID, ID_index rowIndex) const { - return matrix_.is_zero_entry(_id_to_index(faceID), rowIndex); + return matrix_.is_zero_entry(_id_to_index(cellID), rowIndex); } template -inline bool Id_to_index_overlay::is_zero_column(ID_index faceID) +inline bool Id_to_index_overlay::is_zero_column(ID_index cellID) { - return matrix_.is_zero_column(_id_to_index(faceID)); + return matrix_.is_zero_column(_id_to_index(cellID)); } template @@ -947,12 +947,12 @@ Id_to_index_overlay::get_column_with_pivot(ID_ template inline typename Id_to_index_overlay::ID_index -Id_to_index_overlay::get_pivot(ID_index faceID) +Id_to_index_overlay::get_pivot(ID_index cellID) { if constexpr (Master_matrix::Option_list::is_of_boundary_type) { - return matrix_.get_pivot(_id_to_index(faceID)); + return matrix_.get_pivot(_id_to_index(cellID)); } else { - return faceID; + return cellID; } } @@ -1004,10 +1004,10 @@ Id_to_index_overlay::get_representative_cycle( } template -inline void Id_to_index_overlay::swap_columns(ID_index faceID1, ID_index faceID2) +inline void Id_to_index_overlay::swap_columns(ID_index cellID1, ID_index cellID2) { - matrix_.swap_columns(_id_to_index(faceID1), _id_to_index(faceID2)); - std::swap(idToIndex_->at(faceID1), idToIndex_->at(faceID2)); + matrix_.swap_columns(_id_to_index(cellID1), _id_to_index(cellID2)); + std::swap(idToIndex_->at(cellID1), idToIndex_->at(cellID2)); } template @@ -1018,10 +1018,10 @@ inline void Id_to_index_overlay::swap_rows(Ind template inline typename Id_to_index_overlay::ID_index -Id_to_index_overlay::vine_swap_with_z_eq_1_case(ID_index faceID1, ID_index faceID2) +Id_to_index_overlay::vine_swap_with_z_eq_1_case(ID_index cellID1, ID_index cellID2) { - Index first = _id_to_index(faceID1); - Index second = _id_to_index(faceID2); + Index first = _id_to_index(cellID1); + Index second = _id_to_index(cellID2); if (first > second) std::swap(first, second); if constexpr (Master_matrix::Option_list::is_of_boundary_type) { @@ -1031,12 +1031,12 @@ Id_to_index_overlay::vine_swap_with_z_eq_1_cas bool change = matrix_.vine_swap_with_z_eq_1_case(first); - std::swap(idToIndex_->at(faceID1), idToIndex_->at(faceID2)); + std::swap(idToIndex_->at(cellID1), idToIndex_->at(cellID2)); if (change) { - return faceID1; + return cellID1; } - return faceID2; + return cellID2; } else { return matrix_.vine_swap_with_z_eq_1_case(first, second); } @@ -1044,10 +1044,10 @@ Id_to_index_overlay::vine_swap_with_z_eq_1_cas template inline typename Id_to_index_overlay::ID_index -Id_to_index_overlay::vine_swap(ID_index faceID1, ID_index faceID2) +Id_to_index_overlay::vine_swap(ID_index cellID1, ID_index cellID2) { - Index first = _id_to_index(faceID1); - Index second = _id_to_index(faceID2); + Index first = _id_to_index(cellID1); + Index second = _id_to_index(cellID2); if (first > second) std::swap(first, second); if constexpr (Master_matrix::Option_list::is_of_boundary_type) { @@ -1056,12 +1056,12 @@ Id_to_index_overlay::vine_swap(ID_index faceID bool change = matrix_.vine_swap(first); - std::swap(idToIndex_->at(faceID1), idToIndex_->at(faceID2)); + std::swap(idToIndex_->at(cellID1), idToIndex_->at(cellID2)); if (change) { - return faceID1; + return cellID1; } - return faceID2; + return cellID2; } else { return matrix_.vine_swap(first, second); } diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/Position_to_index_overlay.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/Position_to_index_overlay.h index 56cd2c2d27..4a19488230 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/Position_to_index_overlay.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/Position_to_index_overlay.h @@ -216,10 +216,10 @@ class Position_to_index_overlay /** * @brief Inserts at the end of the matrix a new ordered column corresponding to the given boundary. * This means that it is assumed that this method is called on boundaries in the order of the filtration. - * It also assumes that the faces in the given boundary are identified by their relative position in the filtration, + * It also assumes that the cells in the given boundary are identified by their relative position in the filtration, * starting at 0. If it is not the case, use the other * @ref insert_boundary(ID_index, const Boundary_range&, Dimension) "insert_boundary" instead by indicating the - * face ID used in the boundaries when the face is inserted. + * cell ID used in the boundaries when the cell is inserted. * * Different to the constructor, the boundaries do not have to come from a simplicial complex, but also from * a more general entry complex. This includes cubical complexes or Morse complexes for example. @@ -230,30 +230,30 @@ class Position_to_index_overlay * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() * method. * @param boundary Boundary generating the new column. The content should be ordered by ID. - * @param dim Dimension of the face whose boundary is given. If the complex is simplicial, + * @param dim Dimension of the cell whose boundary is given. If the complex is simplicial, * this parameter can be omitted as it can be deduced from the size of the boundary. */ template void insert_boundary(const Boundary_range& boundary, Dimension dim = -1); /** - * @brief It does the same as the other version, but allows the boundary faces to be identified without restrictions + * @brief It does the same as the other version, but allows the boundary cells to be identified without restrictions * except that all IDs have to be strictly increasing in the order of filtration. Note that you should avoid then * to use the other insertion method to avoid overwriting IDs. * - * As a face has to be inserted before one of its cofaces in a valid filtration (recall that it is assumed that - * the faces are inserted by order of filtration), it is sufficient to indicate the ID of the face being inserted. + * As a cell has to be inserted before one of its cofaces in a valid filtration (recall that it is assumed that + * the cells are inserted by order of filtration), it is sufficient to indicate the ID of the cell being inserted. * * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() * method. - * @param faceIndex @ref IDIdx index to use to identify the new face. + * @param cellIndex @ref IDIdx index to use to identify the new cell. * @param boundary Boundary generating the new column. The indices of the boundary have to correspond to the - * @p faceID values of precedent calls of the method for the corresponding faces and should be ordered in + * @p cellID values of precedent calls of the method for the corresponding cells and should be ordered in * increasing order. - * @param dim Dimension of the face whose boundary is given. If the complex is simplicial, + * @param dim Dimension of the cell whose boundary is given. If the complex is simplicial, * this parameter can be omitted as it can be deduced from the size of the boundary. */ template - void insert_boundary(ID_index faceIndex, const Boundary_range& boundary, Dimension dim = -1); + void insert_boundary(ID_index cellIndex, const Boundary_range& boundary, Dimension dim = -1); /** * @brief Returns the column at the given @ref PosIdx index. * The type of the column depends on the choosen options, see @ref PersistenceMatrixOptions::column_type. @@ -307,28 +307,28 @@ class Position_to_index_overlay * @brief Only available if @ref PersistenceMatrixOptions::has_removable_columns, * @ref PersistenceMatrixOptions::has_vine_update and @ref PersistenceMatrixOptions::has_map_column_container * are true. - * Assumes that the face is maximal in the current complex and removes it such that the matrix remains consistent + * Assumes that the cell is maximal in the current complex and removes it such that the matrix remains consistent * (i.e., the matrix is still a compatible bases of the chain complex in the sense of @cite zigzag). - * The maximality of the face is not verified. + * The maximality of the cell is not verified. * Also updates the barcode if it was computed. * * See also @ref remove_last. * - * @param position @ref PosIdx index of the face to remove. + * @param position @ref PosIdx index of the cell to remove. */ - void remove_maximal_face(Pos_index position); + void remove_maximal_cell(Pos_index position); /** * @brief Only available if @ref PersistenceMatrixOptions::has_removable_columns is true and, * if @ref PersistenceMatrixOptions::has_map_column_container is true or * @ref PersistenceMatrixOptions::has_vine_update is false. - * Removes the last face in the filtration from the matrix and updates the barcode if it is stored. + * Removes the last cell in the filtration from the matrix and updates the barcode if it is stored. * - * See also @ref remove_maximal_face. + * See also @ref remove_maximal_cell. */ void remove_last(); /** - * @brief Returns the maximal dimension of a face stored in the matrix. Only available + * @brief Returns the maximal dimension of a cell stored in the matrix. Only available * if @ref PersistenceMatrixOptions::has_matrix_maximal_dimension_access is true. * * @return The maximal dimension. @@ -341,10 +341,10 @@ class Position_to_index_overlay */ Index get_number_of_columns() const; /** - * @brief Returns the dimension of the given face. + * @brief Returns the dimension of the given cell. * - * @param position @ref PosIdx index of the face. - * @return Dimension of the face. + * @param position @ref PosIdx index of the cell. + * @return Dimension of the cell. */ Dimension get_column_dimension(Pos_index position) const; @@ -393,7 +393,7 @@ class Position_to_index_overlay /** * @brief Indicates if the entry at given coordinates has value zero. * - * @param position @ref PosIdx index of the face corresponding to the column of the entry. + * @param position @ref PosIdx index of the cell corresponding to the column of the entry. * @param rowIndex @ref rowindex "Row index" of the row of the entry. * @return true If the entry has value zero. * @return false Otherwise. @@ -405,7 +405,7 @@ class Position_to_index_overlay * Note that this method should always return false, as a valid @ref chainmatrix "chain matrix" never has * empty columns. * - * @param position @ref PosIdx index of the face corresponding to the column. + * @param position @ref PosIdx index of the cell corresponding to the column. * @return true If the column has value zero. * @return false Otherwise. */ @@ -415,14 +415,14 @@ class Position_to_index_overlay * @brief Returns the @ref PosIdx index of the column which has the given @ref rowindex "row index" as pivot. * Assumes that the pivot exists. * - * @param faceIndex @ref rowindex "Row index" of the pivot. + * @param cellIndex @ref rowindex "Row index" of the pivot. * @return @ref PosIdx index of the column with the given pivot. */ - Pos_index get_column_with_pivot(ID_index faceIndex) const; // assumes that pivot exists + Pos_index get_column_with_pivot(ID_index cellIndex) const; // assumes that pivot exists /** * @brief Returns the @ref rowindex "row index" of the pivot of the given column. * - * @param position @ref PosIdx index of the face corresponding to the column. + * @param position @ref PosIdx index of the cell corresponding to the column. * @return The @ref rowindex "row index" of the pivot. */ ID_index get_pivot(Pos_index position); @@ -500,21 +500,21 @@ class Position_to_index_overlay * Does the same than @ref vine_swap, but assumes that the swap is non trivial and * therefore skips a part of the case study. * - * @param position @ref PosIdx index of the first face to swap. The second one has to be at `position + 1`. + * @param position @ref PosIdx index of the first cell to swap. The second one has to be at `position + 1`. * @return true If the barcode changed from the swap. * @return false Otherwise. */ bool vine_swap_with_z_eq_1_case(Pos_index position); /** * @brief Only available if @ref PersistenceMatrixOptions::has_vine_update is true. - * Does a vine swap between two faces which are consecutive in the filtration. Roughly, if \f$ F \f$ is the current + * Does a vine swap between two cells which are consecutive in the filtration. Roughly, if \f$ F \f$ is the current * filtration represented by the matrix, the method modifies the matrix such that the new state corresponds to - * a valid state for the filtration \f$ F' \f$ equal to \f$ F \f$ but with the two faces at position `position` - * and `position + 1` swapped. Of course, the two faces should not have a face/coface relation which each other ; + * a valid state for the filtration \f$ F' \f$ equal to \f$ F \f$ but with the two cells at position `position` + * and `position + 1` swapped. Of course, the two cells should not have a face/coface relation which each other ; * \f$ F' \f$ has to be a valid filtration. * See @cite vineyards for more information about vine and vineyards. * - * @param position @ref PosIdx index of the first face to swap. The second one has to be at `position + 1`. + * @param position @ref PosIdx index of the first cell to swap. The second one has to be at `position + 1`. * @return true If the barcode changed from the swap. * @return false Otherwise. */ @@ -629,7 +629,7 @@ inline void Position_to_index_overlay::insert_ template template -inline void Position_to_index_overlay::insert_boundary(ID_index faceIndex, +inline void Position_to_index_overlay::insert_boundary(ID_index cellIndex, const Boundary_range& boundary, Dimension dim) { @@ -639,7 +639,7 @@ inline void Position_to_index_overlay::insert_ positionToIndex_[nextPosition_++] = nextIndex_++; - matrix_.insert_boundary(faceIndex, boundary, dim); + matrix_.insert_boundary(cellIndex, boundary, dim); } template @@ -677,7 +677,7 @@ inline void Position_to_index_overlay::erase_e } template -inline void Position_to_index_overlay::remove_maximal_face(Pos_index position) +inline void Position_to_index_overlay::remove_maximal_cell(Pos_index position) { --nextPosition_; @@ -693,7 +693,7 @@ inline void Position_to_index_overlay::remove_ columnsToSwap.back() = positionToIndex_[nextPosition_]; } - matrix_.remove_maximal_face(pivot, columnsToSwap); + matrix_.remove_maximal_cell(pivot, columnsToSwap); } template @@ -702,9 +702,9 @@ inline void Position_to_index_overlay::remove_ --nextPosition_; if constexpr (Master_matrix::Option_list::has_vine_update) { std::vector columnsToSwap; - matrix_.remove_maximal_face(matrix_.get_pivot(positionToIndex_[nextPosition_]), columnsToSwap); + matrix_.remove_maximal_cell(matrix_.get_pivot(positionToIndex_[nextPosition_]), columnsToSwap); } else { - matrix_.remove_last(); // linear with vine updates, so it is better to use remove_maximal_face + matrix_.remove_last(); // linear with vine updates, so it is better to use remove_maximal_cell } } @@ -769,9 +769,9 @@ inline bool Position_to_index_overlay::is_zero template inline typename Position_to_index_overlay::Pos_index -Position_to_index_overlay::get_column_with_pivot(ID_index faceIndex) const +Position_to_index_overlay::get_column_with_pivot(ID_index cellIndex) const { - Index id = matrix_.get_column_with_pivot(faceIndex); + Index id = matrix_.get_column_with_pivot(cellIndex); Pos_index i = 0; while (positionToIndex_[i] != id) ++i; return i; diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/RU_matrix.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/RU_matrix.h index f738404e42..7c3661a8a9 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/RU_matrix.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/RU_matrix.h @@ -30,7 +30,7 @@ namespace persistence_matrix { * * @brief %Matrix structure to store the ordered @ref boundarymatrix "boundary matrix" \f$ R \cdot U \f$ of a filtered * complex in order to compute its persistent homology, as well as representative cycles. - * Supports vineyards (see @cite vineyards) and the removal of maximal faces while maintaining + * Supports vineyards (see @cite vineyards) and the removal of maximal cells while maintaining * a valid barcode. Provides an access to its columns and rows. * * @tparam Master_matrix An instantiation of @ref Matrix from which all types and options are deduced. @@ -115,10 +115,10 @@ class RU_matrix : public Master_matrix::RU_pairing_option, /** * @brief Inserts at the end of the matrix a new ordered column corresponding to the given boundary. * This means that it is assumed that this method is called on boundaries in the order of the filtration. - * It also assumes that the faces in the given boundary are identified by their relative position in the filtration, + * It also assumes that the cells in the given boundary are identified by their relative position in the filtration, * starting at 0. If it is not the case, use the other * @ref insert_boundary(ID_index, const Boundary_range&, Dimension) "insert_boundary" instead by indicating the - * face ID used in the boundaries when the face is inserted. + * cell ID used in the boundaries when the cell is inserted. * * Different to the constructor, the boundaries do not have to come from a simplicial complex, but also from * a more general entry complex. This includes cubical complexes or Morse complexes for example. @@ -128,30 +128,30 @@ class RU_matrix : public Master_matrix::RU_pairing_option, * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() * method. * @param boundary Boundary generating the new column. The content should be ordered by ID. - * @param dim Dimension of the face whose boundary is given. If the complex is simplicial, + * @param dim Dimension of the cell whose boundary is given. If the complex is simplicial, * this parameter can be omitted as it can be deduced from the size of the boundary. */ template void insert_boundary(const Boundary_range& boundary, Dimension dim = -1); /** - * @brief It does the same as the other version, but allows the boundary faces to be identified without restrictions + * @brief It does the same as the other version, but allows the boundary cells to be identified without restrictions * except that all IDs have to be strictly increasing in the order of filtration. Note that you should avoid then * to use the other insertion method to avoid overwriting IDs. * - * As a face has to be inserted before one of its cofaces in a valid filtration (recall that it is assumed that - * the faces are inserted by order of filtration), it is sufficient to indicate the ID of the face being inserted. + * As a cell has to be inserted before one of its cofaces in a valid filtration (recall that it is assumed that + * the cells are inserted by order of filtration), it is sufficient to indicate the ID of the cell being inserted. * * @tparam Boundary_range Range of @ref Matrix::Entry_representative. Assumed to have a begin(), end() and size() * method. - * @param faceIndex @ref IDIdx index to use to identify the new face. + * @param cellIndex @ref IDIdx index to use to identify the new cell. * @param boundary Boundary generating the new column. The indices of the boundary have to correspond to the - * @p faceIndex values of precedent calls of the method for the corresponding faces and should be ordered in + * @p cellIndex values of precedent calls of the method for the corresponding cells and should be ordered in * increasing order. - * @param dim Dimension of the face whose boundary is given. If the complex is simplicial, + * @param dim Dimension of the cell whose boundary is given. If the complex is simplicial, * this parameter can be omitted as it can be deduced from the size of the boundary. */ template - void insert_boundary(ID_index faceIndex, const Boundary_range& boundary, Dimension dim = -1); + void insert_boundary(ID_index cellIndex, const Boundary_range& boundary, Dimension dim = -1); /** * @brief Returns the column at the given @ref MatIdx index in \f$ R \f$ if @p inR is true and * in \f$ U \f$ if @p inR is false. @@ -203,26 +203,26 @@ class RU_matrix : public Master_matrix::RU_pairing_option, /** * @brief Only available if @ref PersistenceMatrixOptions::has_removable_columns and * @ref PersistenceMatrixOptions::has_vine_update are true. - * Assumes that the face is maximal in the current complex and removes it such that the matrix remains consistent + * Assumes that the cell is maximal in the current complex and removes it such that the matrix remains consistent * (i.e., RU is still an upper triangular decomposition of the @ref boundarymatrix "boundary matrix"). - * The maximality of the face is not verified. + * The maximality of the cell is not verified. * Also updates the barcode if it is stored. * * See also @ref remove_last. * - * @param columnIndex @ref MatIdx index of the face to remove. + * @param columnIndex @ref MatIdx index of the cell to remove. */ - void remove_maximal_face(Index columnIndex); + void remove_maximal_cell(Index columnIndex); /** * @brief Only available if @ref PersistenceMatrixOptions::has_removable_columns is true. - * Removes the last face in the filtration from the matrix and updates the barcode if it is stored. + * Removes the last cell in the filtration from the matrix and updates the barcode if it is stored. * - * See also @ref remove_maximal_face. + * See also @ref remove_maximal_cell. */ void remove_last(); /** - * @brief Returns the maximal dimension of a face stored in the matrix. + * @brief Returns the maximal dimension of a cell stored in the matrix. * Only available if @ref PersistenceMatrixOptions::has_matrix_maximal_dimension_access is true. * * @return The maximal dimension. @@ -237,8 +237,8 @@ class RU_matrix : public Master_matrix::RU_pairing_option, /** * @brief Returns the dimension of the given column. * - * @param columnIndex @ref MatIdx index of the column representing the face. - * @return Dimension of the face. + * @param columnIndex @ref MatIdx index of the column representing the cell. + * @return Dimension of the cell. */ Dimension get_column_dimension(Index columnIndex) const; @@ -331,10 +331,10 @@ class RU_matrix : public Master_matrix::RU_pairing_option, * @brief Returns the @ref MatIdx index of the column which has the given @ref rowindex "row index" as pivot in * \f$ R \f$. Assumes that the pivot exists. * - * @param faceIndex @ref rowindex "Row index" of the pivot. + * @param cellIndex @ref rowindex "Row index" of the pivot. * @return @ref MatIdx index of the column in \f$ R \f$ with the given pivot. */ - Index get_column_with_pivot(Index faceIndex) const; + Index get_column_with_pivot(Index cellIndex) const; /** * @brief Returns the @ref rowindex "row index" of the pivot of the given column in \f$ R \f$. * @@ -522,28 +522,28 @@ inline void RU_matrix::insert_boundary(const Boundary_range& boun template template -inline void RU_matrix::insert_boundary(ID_index faceIndex, +inline void RU_matrix::insert_boundary(ID_index cellIndex, const Boundary_range& boundary, Dimension dim) { // maps for possible shifting between column content and position indices used for birth events if constexpr (Master_matrix::Option_list::has_column_pairings && !Master_matrix::Option_list::has_vine_update) { - if (faceIndex != nextEventIndex_) { - Pair_opt::idToPosition_.emplace(faceIndex, nextEventIndex_); + if (cellIndex != nextEventIndex_) { + Pair_opt::idToPosition_.emplace(cellIndex, nextEventIndex_); if constexpr (Master_matrix::Option_list::has_removable_columns) { - Pair_opt::PIDM::map_.emplace(nextEventIndex_, faceIndex); + Pair_opt::PIDM::map_.emplace(nextEventIndex_, cellIndex); } } } if constexpr (Master_matrix::Option_list::has_vine_update) { - if (faceIndex != nextEventIndex_) { - Swap_opt::_positionToRowIdx().emplace(nextEventIndex_, faceIndex); + if (cellIndex != nextEventIndex_) { + Swap_opt::_positionToRowIdx().emplace(nextEventIndex_, cellIndex); if (Master_matrix::Option_list::has_column_pairings) { - Swap_opt::template RU_pairing::idToPosition_.emplace(faceIndex, nextEventIndex_); + Swap_opt::template RU_pairing::idToPosition_.emplace(cellIndex, nextEventIndex_); } } } - _insert_boundary(reducedMatrixR_.insert_boundary(faceIndex, boundary, dim)); + _insert_boundary(reducedMatrixR_.insert_boundary(cellIndex, boundary, dim)); } template @@ -573,10 +573,10 @@ inline void RU_matrix::erase_empty_row(Index rowIndex) } template -inline void RU_matrix::remove_maximal_face(Index columnIndex) +inline void RU_matrix::remove_maximal_cell(Index columnIndex) { static_assert(Master_matrix::Option_list::has_removable_columns && Master_matrix::Option_list::has_vine_update, - "'remove_maximal_face' is not implemented for the chosen options."); + "'remove_maximal_cell' is not implemented for the chosen options."); // TODO: is there an easy test to verify maximality even without row access? @@ -699,12 +699,12 @@ inline bool RU_matrix::is_zero_column(Index columnIndex, bool inR } template -inline typename RU_matrix::Index RU_matrix::get_column_with_pivot(Index faceIndex) const +inline typename RU_matrix::Index RU_matrix::get_column_with_pivot(Index cellIndex) const { if constexpr (Master_matrix::Option_list::has_map_column_container) { - return pivotToColumnIndex_.at(faceIndex); + return pivotToColumnIndex_.at(cellIndex); } else { - return pivotToColumnIndex_[faceIndex]; + return pivotToColumnIndex_[cellIndex]; } } diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/base_pairing.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/base_pairing.h index ac883fff38..8ce95ce743 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/base_pairing.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/base_pairing.h @@ -23,7 +23,7 @@ #include #include -#include "boundary_face_position_to_id_mapper.h" +#include "boundary_cell_position_to_id_mapper.h" namespace Gudhi { namespace persistence_matrix { @@ -50,7 +50,7 @@ struct Dummy_base_pairing { template class Base_pairing : public std::conditional< Master_matrix::Option_list::has_removable_columns, - Face_position_to_ID_mapper, + Cell_position_to_ID_mapper, Dummy_pos_mapper >::type { @@ -82,8 +82,8 @@ class Base_pairing : public std::conditional< */ friend void swap(Base_pairing& pairing1, Base_pairing& pairing2) { if constexpr (Master_matrix::Option_list::has_removable_columns) { - swap(static_cast&>(pairing1), - static_cast&>(pairing2)); + swap(static_cast&>(pairing1), + static_cast&>(pairing2)); } pairing1.barcode_.swap(pairing2.barcode_); pairing1.deathToBar_.swap(pairing2.deathToBar_); @@ -98,14 +98,14 @@ class Base_pairing : public std::conditional< using Base_matrix = typename Master_matrix::Master_boundary_matrix; //PIDM = Position to ID Map using PIDM = typename std::conditional, + Cell_position_to_ID_mapper, Dummy_pos_mapper >::type; Barcode barcode_; /**< Bar container. */ Dictionary deathToBar_; /**< Map from death index to bar index. */ /** - * @brief Map from face ID to face position. Only stores a pair if ID != position. + * @brief Map from cell ID to cell position. Only stores a pair if ID != position. */ std::unordered_map idToPosition_; //TODO: test other map types bool isReduced_; /**< True if `_reduce()` was called. */ diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/boundary_face_position_to_id_mapper.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/boundary_cell_position_to_id_mapper.h similarity index 74% rename from src/Persistence_matrix/include/gudhi/Persistence_matrix/boundary_face_position_to_id_mapper.h rename to src/Persistence_matrix/include/gudhi/Persistence_matrix/boundary_cell_position_to_id_mapper.h index 5464804196..1b85b07c82 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/boundary_face_position_to_id_mapper.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/boundary_cell_position_to_id_mapper.h @@ -9,10 +9,10 @@ */ /** - * @file base_pairing.h + * @file boundary_cell_position_to_id_mapper.h * @author Hannah Schreiber - * @brief Contains the @ref Gudhi::persistence_matrix::Base_pairing class and - * @ref Gudhi::persistence_matrix::Dummy_base_pairing structure. + * @brief Contains the @ref Gudhi::persistence_matrix::Cell_position_to_ID_mapper class and + * @ref Gudhi::persistence_matrix::Dummy_pos_mapper structure. */ #ifndef PM_ID_POS_MAPPER_H @@ -28,7 +28,7 @@ namespace persistence_matrix { * @ingroup persistence_matrix * * @brief Empty structure. - * Inherited instead of @ref Face_position_to_ID_mapper. + * Inherited instead of @ref Cell_position_to_ID_mapper. */ struct Dummy_pos_mapper { friend void swap([[maybe_unused]] Dummy_pos_mapper& d1, [[maybe_unused]] Dummy_pos_mapper& d2) {} @@ -38,18 +38,18 @@ struct Dummy_pos_mapper { * @private * @ingroup persistence_matrix * - * @brief Map from face position to face ID. Only stores a pair if ID != position and has_removable_column is true. + * @brief Map from cell position to cell ID. Only stores a pair if ID != position and has_removable_column is true. * * @tparam ID_index @ref IDIdx index type * @tparam Pos_index @ref PosIdx index type */ template -struct Face_position_to_ID_mapper { +struct Cell_position_to_ID_mapper { using Index_map = std::unordered_map; //TODO: test other map types Index_map map_; - friend void swap(Face_position_to_ID_mapper& mapper1, Face_position_to_ID_mapper& mapper2) { + friend void swap(Cell_position_to_ID_mapper& mapper1, Cell_position_to_ID_mapper& mapper2) { mapper1.map_.swap(mapper2.map_); } }; diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/chain_vine_swap.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/chain_vine_swap.h index 887f89cb2c..3168b54031 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/chain_vine_swap.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/chain_vine_swap.h @@ -281,23 +281,23 @@ class Chain_vine_swap : public std::conditional dimensions_; /**< Number of faces by dimension. */ - Dimension maxDim_; /**< Current maximal dimension. */ + std::vector dimensions_; /**< Number of cells by dimension. */ + Dimension maxDim_; /**< Current maximal dimension. */ void update_up(unsigned int dimension) { if (dimensions_.size() <= dimension) dimensions_.resize(dimension + 1, 0); diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/ru_pairing.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/ru_pairing.h index f44e518e78..e6afe9fc89 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/ru_pairing.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/ru_pairing.h @@ -20,7 +20,7 @@ #include -#include "boundary_face_position_to_id_mapper.h" +#include "boundary_cell_position_to_id_mapper.h" namespace Gudhi { namespace persistence_matrix { @@ -48,7 +48,7 @@ struct Dummy_ru_pairing template class RU_pairing : public std::conditional< Master_matrix::Option_list::has_removable_columns, - Face_position_to_ID_mapper, + Cell_position_to_ID_mapper, Dummy_pos_mapper >::type { @@ -57,9 +57,9 @@ class RU_pairing : public std::conditional< using ID_index = typename Master_matrix::ID_index; //PIDM = Position to ID Map using PIDM = typename std::conditional, - Dummy_pos_mapper - >::type; + Cell_position_to_ID_mapper, + Dummy_pos_mapper + >::type; public: using Barcode = typename Master_matrix::Barcode; /**< Barcode type. */ @@ -93,7 +93,7 @@ class RU_pairing : public std::conditional< Barcode barcode_; /**< Bar container. */ Dictionary indexToBar_; /**< Map from @ref MatIdx index to bar index. */ /** - * @brief Map from face ID to face position. Only stores a pair if ID != position. + * @brief Map from cell ID to cell position. Only stores a pair if ID != position. */ std::unordered_map idToPosition_; //TODO: test other map types diff --git a/src/Persistence_matrix/include/gudhi/Persistence_matrix/ru_vine_swap.h b/src/Persistence_matrix/include/gudhi/Persistence_matrix/ru_vine_swap.h index 64561c8683..00c76749f7 100644 --- a/src/Persistence_matrix/include/gudhi/Persistence_matrix/ru_vine_swap.h +++ b/src/Persistence_matrix/include/gudhi/Persistence_matrix/ru_vine_swap.h @@ -25,7 +25,7 @@ #include //std::invalid_argument #include "ru_pairing.h" -#include "boundary_face_position_to_id_mapper.h" +#include "boundary_cell_position_to_id_mapper.h" namespace Gudhi { namespace persistence_matrix { @@ -68,7 +68,7 @@ class RU_vine_swap : public std::conditional >::type { @@ -98,20 +98,20 @@ class RU_vine_swap : public std::conditional&>(swap1), static_cast&>(swap2)); } if (!Master_matrix::Option_list::has_column_pairings || !Master_matrix::Option_list::has_removable_columns) { - swap(static_cast&>(swap1), - static_cast&>(swap2)); + swap(static_cast&>(swap1), + static_cast&>(swap2)); } } @@ -144,7 +144,7 @@ class RU_vine_swap : public std::conditional + Cell_position_to_ID_mapper >::type; constexpr auto& _positionToRowIdx(); diff --git a/src/Persistence_matrix/test/pm_matrix_tests.h b/src/Persistence_matrix/test/pm_matrix_tests.h index c6785b9b92..dd20612656 100644 --- a/src/Persistence_matrix/test/pm_matrix_tests.h +++ b/src/Persistence_matrix/test/pm_matrix_tests.h @@ -902,7 +902,7 @@ void test_ru_maximal_simplex_removal() { } if constexpr (Matrix::Option_list::has_vine_update) { - m.remove_maximal_face(6); + m.remove_maximal_cell(6); } else { m.remove_last(); } @@ -927,7 +927,7 @@ void test_chain_maximal_simplex_removal(Matrix& m) { if constexpr (Matrix::Option_list::has_vine_update && Matrix::Option_list::has_map_column_container && Matrix::Option_list::has_column_pairings) { - m.remove_maximal_face(6); + m.remove_maximal_cell(6); } else { m.remove_last(); } @@ -957,7 +957,7 @@ void test_maximal_dimension(Matrix& m) { if constexpr (Matrix::Option_list::has_vine_update && (Matrix::Option_list::is_of_boundary_type || (Matrix::Option_list::has_map_column_container && Matrix::Option_list::has_column_pairings))) { - m.remove_maximal_face(7); + m.remove_maximal_cell(7); BOOST_CHECK_EQUAL(m.get_max_dimension(), 3); } } From b4694d930d810c26c5aa5234dc059ce2f771595f Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Thu, 26 Sep 2024 15:59:43 +0200 Subject: [PATCH 26/34] code review: just test if windows for pykeops --- .../modules/GUDHI_third_party_libraries.cmake | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index ffed360461..a72d106bb2 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -186,18 +186,12 @@ if (WITH_GUDHI_PYTHON) find_python_module("pydata_sphinx_theme") find_python_module("sphinxcontrib.bibtex") find_python_module("networkx") + # Specific case for PyKeops that can be imported on Windows, but fails because it uses fcntl (not available on Windows) + if (NOT WIN32) + find_python_module("pykeops") + endif() endif() - # Specific case for PyKeops that can be imported on Windows, but fails because it uses fcntl (not available on Windows) - # Also fcntl has no metadata, so find_python_module does not work - # "import fcntl" is about 1 sec. faster than "import pykeops" - execute_process( - COMMAND ${Python_EXECUTABLE} -c "import fcntl" - RESULT_VARIABLE FCNTL_IMPORT_MODULE_RESULT - OUTPUT_VARIABLE FCNTL_IMPORT_MODULE_OUPUT) - if(FCNTL_IMPORT_MODULE_RESULT EQUAL 0) - find_python_module("pykeops") - endif() if(NOT GUDHI_PYTHON_PATH) message(FATAL_ERROR "ERROR: GUDHI_PYTHON_PATH is not valid.") From 9df2c0460d5ca9b646fa228fb3b228aeed8d967a Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Thu, 26 Sep 2024 16:47:29 +0200 Subject: [PATCH 27/34] try sphinx_autodoc_typehints --- src/python/doc/conf.py | 5 ++- src/python/gudhi/sklearn/rips_persistence.py | 42 ++++++++++---------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/python/doc/conf.py b/src/python/doc/conf.py index 76c8e15ece..6adf827328 100755 --- a/src/python/doc/conf.py +++ b/src/python/doc/conf.py @@ -8,18 +8,21 @@ sys.path.insert(0, os.path.abspath(".")) extensions = [ + "sphinx.ext.napoleon", + # let napoleon be the first extension, cf. https://github.com/tox-dev/sphinx-autodoc-typehints/issues/15 "matplotlib.sphinxext.plot_directive", "sphinx.ext.autodoc", + "sphinx_autodoc_typehints", "sphinx.ext.doctest", "sphinx.ext.mathjax", "sphinx.ext.ifconfig", "sphinx.ext.viewcode", - "sphinx.ext.napoleon", "sphinxcontrib.bibtex", "sphinx_paramlinks", ] autodoc_class_signature = "separated" +autodoc_typehints = "description" bibtex_bibfiles = ["../../biblio/bibliography.bib"] diff --git a/src/python/gudhi/sklearn/rips_persistence.py b/src/python/gudhi/sklearn/rips_persistence.py index 68f0646e14..b5c643fb1f 100644 --- a/src/python/gudhi/sklearn/rips_persistence.py +++ b/src/python/gudhi/sklearn/rips_persistence.py @@ -52,25 +52,25 @@ def __init__( homology_coeff_field: int = 11, n_jobs: Optional[int] = None, ): - """ - Constructor for the RipsPersistence class. - - Parameters: - homology_dimensions (int or list of int): The returned persistence diagrams dimension(s). - Short circuit the use of :class:`~gudhi.representations.preprocessing.DimensionSelector` when only one - dimension matters (in other words, when `homology_dimensions` is an int). - threshold (float): Rips maximal edge length value. Default is +Inf. Ignored if input_type is 'distance coo_matrix'. - input_type (str): Can be 'point cloud' when inputs are point clouds, 'full distance matrix', - 'lower distance matrix' when inputs are lower triangular distance matrix (can be full square, - but the upper part will not be considered), or 'distance coo_matrix' for a distance matrix in SciPy's - sparse format, which should contain each edge at most once (avoid the symmetric) and no diagonal entry. - Default is 'point cloud'. - num_collapses (int|str): Specify the number of iterations of :func:`~gudhi.flag_filtration.edge_collapse.reduce_graph` - (edge collapse) to perform on the graph. Default value is 'auto'. - homology_coeff_field (int): The homology coefficient field. Must be a prime number. Default value is 11. - n_jobs (Optional[int]): Number of jobs to run in parallel. `None` (default value) means `n_jobs = 1` unless in a - joblib.parallel_backend context. `-1` means using all processors. cf. - https://joblib.readthedocs.io/en/latest/generated/joblib.Parallel.html for more details. + """Constructor for the RipsPersistence class. + + :param homology_dimensions: The returned persistence diagrams dimension(s). + Short circuit the use of :class:`~gudhi.representations.preprocessing.DimensionSelector` when only one + dimension matters (in other words, when `homology_dimensions` is an int). + :param threshold: Rips maximal edge length value. Default is +Inf. Ignored if input_type is + 'distance coo_matrix'. + :param input_type: Can be 'point cloud' when inputs are point clouds, 'full distance matrix', + 'lower distance matrix' when inputs are lower triangular distance matrix (can be full square, + but the upper part will not be considered), or 'distance coo_matrix' for a distance matrix in SciPy's + sparse format, which should contain each edge at most once (avoid the symmetric) and no diagonal entry. + Default is 'point cloud'. + :param num_collapses: Specify the number of iterations of + :func:`~gudhi.flag_filtration.edge_collapse.reduce_graph` (edge collapse) to perform on the graph. + Default value is 'auto'. + :param homology_coeff_field: The homology coefficient field. Must be a prime number. Default value is 11. + :param n_jobs: Number of jobs to run in parallel. `None` (default value) means `n_jobs = 1` unless in a + joblib.parallel_backend context. `-1` means using all processors. cf. + https://joblib.readthedocs.io/en/latest/generated/joblib.Parallel.html for more details. """ self.homology_dimensions = homology_dimensions self.threshold = threshold @@ -165,7 +165,7 @@ def __transform(self, inp): dgm = _sparse(inp.row, inp.col, inp.data, inp.shape[0], max_dimension=max_dimension, max_edge_length=threshold, homology_coeff_field=self.homology_coeff_field) else: raise ValueError("Only 'point cloud', 'lower distance matrix', 'full distance matrix' and 'distance coo_matrix' are valid input_type") # move to __init__? - + # dgm stops at n-2 return [dgm[dim] if dim < len(dgm) else np.empty((0,2)) for dim in self.dim_list_] @@ -177,7 +177,7 @@ def transform(self, X, Y=None): :return: Persistence diagrams in the format: - - If `homology_dimensions` was set to `n`: `[array( Hn(X[0]) ), array( Hn(X[1]) ), ...]` + - If `homology_dimensions` was set to `n`: `[array( Hn(X[0]) ), array( Hn(X[1]) ), ...]` - If `homology_dimensions` was set to `[i, j]`: `[[array( Hi(X[0]) ), array( Hj(X[0]) )], [array( Hi(X[1]) ), array( Hj(X[1]) )], ...]` :rtype: list of numpy ndarray of shape (,2) or list of list of numpy ndarray of shape (,2) From 9fbea63b0db06a40a80d5be379bbfda24677985a Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Thu, 26 Sep 2024 16:51:05 +0200 Subject: [PATCH 28/34] [skip ci] code review: Rework comment. Remove comments that were no more relevant. --- src/cmake/modules/GUDHI_third_party_libraries.cmake | 2 +- src/python/CMakeLists.txt | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index a72d106bb2..6527d0be3c 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -186,7 +186,7 @@ if (WITH_GUDHI_PYTHON) find_python_module("pydata_sphinx_theme") find_python_module("sphinxcontrib.bibtex") find_python_module("networkx") - # Specific case for PyKeops that can be imported on Windows, but fails because it uses fcntl (not available on Windows) + # Specific case for PyKeops on Windows where import fails because it uses fcntl (not available on Windows) if (NOT WIN32) find_python_module("pykeops") endif() diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index e68e8f2c64..3198461820 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -142,7 +142,6 @@ else() disable_python_documentation("ot") endif() if(HNSWLIB_FOUND) - # Does not have a version number... add_gudhi_debug_info("HNSWlib version ${HNSWLIB_VERSION}") endif() if(TORCH_FOUND) @@ -175,7 +174,6 @@ else() disable_python_documentation("pydata_sphinx_theme") endif() if(SPHINXCONTRIB.BIBTEX_FOUND) - # Does not have a version number... add_gudhi_debug_info("sphinxcontrib-bibtex version ${SPHINXCONTRIB.BIBTEX_VERSION}") else() disable_python_documentation("sphinxcontrib-bibtex") From f8ecddfac18aa7e6ab3bde0e72cec29a269c3876 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Thu, 26 Sep 2024 22:35:52 +0200 Subject: [PATCH 29/34] make sphinx-autodoc-typehints work as required (cmake, ci, doc) --- .circleci/config.yml | 20 ++++++++----------- .../modules/GUDHI_third_party_libraries.cmake | 1 + src/python/CMakeLists.txt | 5 +++++ src/python/doc/conf.py | 2 +- src/python/doc/installation.rst | 2 ++ 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6559558c32..1dbd459a57 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,12 +1,11 @@ version: 2.0 jobs: - -### With all third parties + ### With all third parties examples: docker: # cf. https://github.com/GUDHI/gudhi-deploy/blob/main/Dockerfile_for_circleci_image - - image: gudhi/ci_for_gudhi:2024.06.02 + - image: gudhi/ci_for_gudhi:2024.09.01 steps: - checkout - run: @@ -25,7 +24,7 @@ jobs: tests: docker: - - image: gudhi/ci_for_gudhi:2024.06.02 + - image: gudhi/ci_for_gudhi:2024.09.01 steps: - checkout - run: @@ -44,7 +43,7 @@ jobs: debug_tests: docker: - - image: gudhi/ci_for_gudhi:2024.06.02 + - image: gudhi/ci_for_gudhi:2024.09.01 steps: - checkout - run: @@ -63,7 +62,7 @@ jobs: utils: docker: - - image: gudhi/ci_for_gudhi:2024.06.02 + - image: gudhi/ci_for_gudhi:2024.09.01 steps: - checkout - run: @@ -82,7 +81,7 @@ jobs: python: docker: - - image: gudhi/ci_for_gudhi:2024.06.02 + - image: gudhi/ci_for_gudhi:2024.09.01 resource_class: large # Delaunay complex requires about 5 Gb of RAM to compile steps: - checkout @@ -94,7 +93,6 @@ jobs: - run: name: Build and test python module. Generates and tests the python documentation command: | - pip3 install pydata-sphinx-theme mkdir build cd build cmake -DWITH_GUDHI_THIRD_PARTY=OFF -DUSER_VERSION_DIR=version .. @@ -167,8 +165,7 @@ jobs: latexmk -pdf -interaction=nonstopmode test_biblio.tex latexmk -pdf -interaction=nonstopmode test_gudhi_citation.tex - -### With all third parties, except CGAL and Eigen + ### With all third parties, except CGAL and Eigen examples_without_cgal_eigen: docker: @@ -248,8 +245,7 @@ jobs: python3 setup.py build_ext --inplace ctest --output-on-failure - -### With all third parties, except CGAL + ### With all third parties, except CGAL examples_without_cgal: docker: diff --git a/src/cmake/modules/GUDHI_third_party_libraries.cmake b/src/cmake/modules/GUDHI_third_party_libraries.cmake index 6527d0be3c..250401ff3a 100644 --- a/src/cmake/modules/GUDHI_third_party_libraries.cmake +++ b/src/cmake/modules/GUDHI_third_party_libraries.cmake @@ -185,6 +185,7 @@ if (WITH_GUDHI_PYTHON) find_python_module("sphinx_paramlinks") find_python_module("pydata_sphinx_theme") find_python_module("sphinxcontrib.bibtex") + find_python_module("sphinx-autodoc-typehints") find_python_module("networkx") # Specific case for PyKeops on Windows where import fails because it uses fcntl (not available on Windows) if (NOT WIN32) diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt index 3198461820..4be5ce9602 100644 --- a/src/python/CMakeLists.txt +++ b/src/python/CMakeLists.txt @@ -178,6 +178,11 @@ if(SPHINXCONTRIB.BIBTEX_FOUND) else() disable_python_documentation("sphinxcontrib-bibtex") endif() +if(SPHINX-AUTODOC-TYPEHINTS_FOUND) + add_gudhi_debug_info("sphinx-autodoc-typehints version ${SPHINX-AUTODOC-TYPEHINTS_VERSION}") +else() + disable_python_documentation("sphinx-autodoc-typehints") +endif() if(NETWORKX_FOUND) add_gudhi_debug_info("NetworkX version ${NETWORKX_VERSION}") endif() diff --git a/src/python/doc/conf.py b/src/python/doc/conf.py index 6adf827328..a974c7aee4 100755 --- a/src/python/doc/conf.py +++ b/src/python/doc/conf.py @@ -22,7 +22,7 @@ ] autodoc_class_signature = "separated" -autodoc_typehints = "description" +autodoc_typehints = "none" bibtex_bibfiles = ["../../biblio/bibliography.bib"] diff --git a/src/python/doc/installation.rst b/src/python/doc/installation.rst index 067b733efb..d3aff7e706 100644 --- a/src/python/doc/installation.rst +++ b/src/python/doc/installation.rst @@ -183,6 +183,7 @@ A complete configuration would be : Sphinx-paramlinks version 0.6.0 pydata_sphinx_theme version 0.15.2 sphinxcontrib-bibtex version 2.6.2 + sphinx-autodoc-typehints version 2.4.4 NetworkX version 3.3 Eigen3 version 3.4.0 Boost version 1.84.0 @@ -204,6 +205,7 @@ Documentation To build the documentation, `sphinx-doc `_, `sphinxcontrib-bibtex `_, +`sphinx-autodoc-typehints `_, `sphinxcontrib-paramlinks `_ and `pydata-sphinx-theme `_ :math:`\geq` 0.8.0 are required. As the documentation is auto-tested, `CGAL`_, `Eigen`_, From 52aa6022583a68c781ce925a904d7870c5206c62 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Fri, 27 Sep 2024 12:33:06 +0200 Subject: [PATCH 30/34] code review: switch to google style --- src/python/gudhi/sklearn/rips_persistence.py | 35 ++++++++++---------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/python/gudhi/sklearn/rips_persistence.py b/src/python/gudhi/sklearn/rips_persistence.py index b5c643fb1f..ff6bbecba6 100644 --- a/src/python/gudhi/sklearn/rips_persistence.py +++ b/src/python/gudhi/sklearn/rips_persistence.py @@ -54,23 +54,24 @@ def __init__( ): """Constructor for the RipsPersistence class. - :param homology_dimensions: The returned persistence diagrams dimension(s). - Short circuit the use of :class:`~gudhi.representations.preprocessing.DimensionSelector` when only one - dimension matters (in other words, when `homology_dimensions` is an int). - :param threshold: Rips maximal edge length value. Default is +Inf. Ignored if input_type is - 'distance coo_matrix'. - :param input_type: Can be 'point cloud' when inputs are point clouds, 'full distance matrix', - 'lower distance matrix' when inputs are lower triangular distance matrix (can be full square, - but the upper part will not be considered), or 'distance coo_matrix' for a distance matrix in SciPy's - sparse format, which should contain each edge at most once (avoid the symmetric) and no diagonal entry. - Default is 'point cloud'. - :param num_collapses: Specify the number of iterations of - :func:`~gudhi.flag_filtration.edge_collapse.reduce_graph` (edge collapse) to perform on the graph. - Default value is 'auto'. - :param homology_coeff_field: The homology coefficient field. Must be a prime number. Default value is 11. - :param n_jobs: Number of jobs to run in parallel. `None` (default value) means `n_jobs = 1` unless in a - joblib.parallel_backend context. `-1` means using all processors. cf. - https://joblib.readthedocs.io/en/latest/generated/joblib.Parallel.html for more details. + Parameters: + homology_dimensions: The returned persistence diagrams dimension(s). + Short circuit the use of :class:`~gudhi.representations.preprocessing.DimensionSelector` when only one + dimension matters (in other words, when `homology_dimensions` is an int). + threshold: Rips maximal edge length value. Default is +Inf. Ignored if input_type is + 'distance coo_matrix'. + input_type: Can be 'point cloud' when inputs are point clouds, 'full distance matrix', + 'lower distance matrix' when inputs are lower triangular distance matrix (can be full square, + but the upper part will not be considered), or 'distance coo_matrix' for a distance matrix in SciPy's + sparse format, which should contain each edge at most once (avoid the symmetric) and no diagonal entry. + Default is 'point cloud'. + num_collapses: Specify the number of iterations of + :func:`~gudhi.flag_filtration.edge_collapse.reduce_graph` (edge collapse) to perform on the graph. + Default value is 'auto'. + homology_coeff_field: The homology coefficient field. Must be a prime number. Default value is 11. + n_jobs: Number of jobs to run in parallel. `None` (default value) means `n_jobs = 1` unless in a + joblib.parallel_backend context. `-1` means using all processors. cf. + https://joblib.readthedocs.io/en/latest/generated/joblib.Parallel.html for more details. """ self.homology_dimensions = homology_dimensions self.threshold = threshold From 20c7761a60a3e5ddf48f8aaaad898d773223f415 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Mon, 30 Sep 2024 09:42:15 +0200 Subject: [PATCH 31/34] code review: optimize some options --- src/python/doc/conf.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/python/doc/conf.py b/src/python/doc/conf.py index a974c7aee4..5738d04eab 100755 --- a/src/python/doc/conf.py +++ b/src/python/doc/conf.py @@ -22,7 +22,10 @@ ] autodoc_class_signature = "separated" +# cf. https://github.com/tox-dev/sphinx-autodoc-typehints#options autodoc_typehints = "none" +napoleon_use_rtype = True +always_use_bars_union = True bibtex_bibfiles = ["../../biblio/bibliography.bib"] From 418247a2dcac31243624bf54758da286f54b1336 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Wed, 2 Oct 2024 09:12:40 +0200 Subject: [PATCH 32/34] include mpl list that is used in this test --- src/Alpha_complex/test/Incremental_delaunay_test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Alpha_complex/test/Incremental_delaunay_test.cpp b/src/Alpha_complex/test/Incremental_delaunay_test.cpp index 8609fb3f34..4c697ea2f0 100644 --- a/src/Alpha_complex/test/Incremental_delaunay_test.cpp +++ b/src/Alpha_complex/test/Incremental_delaunay_test.cpp @@ -12,6 +12,7 @@ #define BOOST_TEST_MODULE "incremental_delaunay" #include #include +#include #include #include From 00b82d18113bf58bb1fccec18270a97273e260d9 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Fri, 4 Oct 2024 13:40:56 +0200 Subject: [PATCH 33/34] Fix strange bug on windows, where '#define far' is performed in windows.h and makes the compilation fails sometimes --- .../include/gudhi/choose_n_farthest_points.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Subsampling/include/gudhi/choose_n_farthest_points.h b/src/Subsampling/include/gudhi/choose_n_farthest_points.h index eaf91e676d..f270e2049e 100644 --- a/src/Subsampling/include/gudhi/choose_n_farthest_points.h +++ b/src/Subsampling/include/gudhi/choose_n_farthest_points.h @@ -168,7 +168,7 @@ using radius_priority_ds = boost::heap::mutable_, boost::heap::constant_time_size>; template struct Landmark_info { - std::size_t far; FT radius; + std::size_t far_idx; FT radius; // The points that are closer to this landmark than to other landmarks std::vector> voronoi; // For a landmark A, the list of landmarks B such that picking a Voronoi @@ -251,7 +251,7 @@ void choose_n_farthest_points_metric(Distance dist_, } } landmarks[i].radius = r; - landmarks[i].far = jmax; + landmarks[i].far_idx = jmax; }; auto update_radius = [&](std::size_t i) { @@ -280,7 +280,7 @@ void choose_n_farthest_points_metric(Distance dist_, for (std::size_t current_number_of_landmarks = 1; current_number_of_landmarks != final_size; current_number_of_landmarks++) { std::size_t l_parent = radius_priority.top(); auto& parent_info = landmarks[l_parent]; - std::size_t l = parent_info.far; + std::size_t l = parent_info.far_idx; FT radius = parent_info.radius; auto& info = landmarks[l]; *output_it++ = input_pts[l]; @@ -309,8 +309,8 @@ void choose_n_farthest_points_metric(Distance dist_, if (it != ngb_info.voronoi.end()) { // modified, always true for ngb==l_parent ngb_info.voronoi.erase(it, ngb_info.voronoi.end()); modified_neighbors.push_back(ngb); - // We only need to recompute the radius if far was removed, which we can test here with - // if (dist(l, ngb_info.far) < ngb_info.radius) + // We only need to recompute the radius if far_idx was removed, which we can test here with + // if (dist(l, ngb_info.far_idx) < ngb_info.radius) // to avoid a costly test for each w in the loop above, but it does not seem to help. update_radius(ngb); // if (ngb_info.voronoi.empty()) radius_priority.erase(ngb_info.position_in_queue); From 7fb35b8a511e27407188399a075262d70ffb0fe8 Mon Sep 17 00:00:00 2001 From: Vincent Rouvreau Date: Fri, 4 Oct 2024 15:02:48 +0200 Subject: [PATCH 34/34] code review: Rename as farthest --- .../include/gudhi/choose_n_farthest_points.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Subsampling/include/gudhi/choose_n_farthest_points.h b/src/Subsampling/include/gudhi/choose_n_farthest_points.h index f270e2049e..8925c4669c 100644 --- a/src/Subsampling/include/gudhi/choose_n_farthest_points.h +++ b/src/Subsampling/include/gudhi/choose_n_farthest_points.h @@ -168,7 +168,7 @@ using radius_priority_ds = boost::heap::mutable_, boost::heap::constant_time_size>; template struct Landmark_info { - std::size_t far_idx; FT radius; + std::size_t farthest; FT radius; // The points that are closer to this landmark than to other landmarks std::vector> voronoi; // For a landmark A, the list of landmarks B such that picking a Voronoi @@ -251,7 +251,7 @@ void choose_n_farthest_points_metric(Distance dist_, } } landmarks[i].radius = r; - landmarks[i].far_idx = jmax; + landmarks[i].farthest = jmax; }; auto update_radius = [&](std::size_t i) { @@ -280,7 +280,7 @@ void choose_n_farthest_points_metric(Distance dist_, for (std::size_t current_number_of_landmarks = 1; current_number_of_landmarks != final_size; current_number_of_landmarks++) { std::size_t l_parent = radius_priority.top(); auto& parent_info = landmarks[l_parent]; - std::size_t l = parent_info.far_idx; + std::size_t l = parent_info.farthest; FT radius = parent_info.radius; auto& info = landmarks[l]; *output_it++ = input_pts[l]; @@ -309,8 +309,8 @@ void choose_n_farthest_points_metric(Distance dist_, if (it != ngb_info.voronoi.end()) { // modified, always true for ngb==l_parent ngb_info.voronoi.erase(it, ngb_info.voronoi.end()); modified_neighbors.push_back(ngb); - // We only need to recompute the radius if far_idx was removed, which we can test here with - // if (dist(l, ngb_info.far_idx) < ngb_info.radius) + // We only need to recompute the radius if farthest was removed, which we can test here with + // if (dist(l, ngb_info.farthest) < ngb_info.radius) // to avoid a costly test for each w in the loop above, but it does not seem to help. update_radius(ngb); // if (ngb_info.voronoi.empty()) radius_priority.erase(ngb_info.position_in_queue);