synkit 1.6.5__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (636) hide show
  1. synkit/CRN/Benchmark/__init__.py +53 -0
  2. synkit/CRN/Benchmark/crosschecks.py +13 -0
  3. synkit/CRN/Benchmark/kegg.py +12 -0
  4. synkit/CRN/Benchmark/networks.py +13 -0
  5. synkit/CRN/Benchmark/scaling.py +13 -0
  6. synkit/CRN/Benchmark/validate.py +13 -0
  7. synkit/CRN/Construct/__init__.py +16 -0
  8. synkit/CRN/Construct/abstract.py +668 -0
  9. synkit/CRN/Construct/arity.py +36 -0
  10. synkit/CRN/Construct/builder.py +619 -0
  11. synkit/CRN/Construct/derivation.py +63 -0
  12. synkit/CRN/Construct/flattener.py +100 -0
  13. synkit/CRN/Construct/keys.py +14 -0
  14. synkit/CRN/Construct/mixtures.py +117 -0
  15. synkit/CRN/Construct/rdkit_worker.py +69 -0
  16. synkit/CRN/Construct/smiles.py +99 -0
  17. synkit/CRN/Construct/state.py +31 -0
  18. synkit/CRN/Construct/strategy.py +75 -0
  19. synkit/CRN/Construct/worker.py +42 -0
  20. synkit/CRN/IO/__init__.py +36 -0
  21. synkit/CRN/IO/sbml.py +925 -0
  22. synkit/CRN/Pathway/__init__.py +72 -0
  23. synkit/CRN/Pathway/_adapter.py +333 -0
  24. synkit/CRN/Pathway/pathfinder.py +500 -0
  25. synkit/CRN/Pathway/reachability.py +796 -0
  26. synkit/CRN/Pathway/realizability.py +1322 -0
  27. synkit/CRN/Petrinet/__init__.py +93 -0
  28. synkit/CRN/Petrinet/analyzer.py +486 -0
  29. synkit/CRN/Petrinet/minimal_semiflows.py +436 -0
  30. synkit/CRN/Petrinet/net.py +1041 -0
  31. synkit/CRN/Petrinet/persistence.py +97 -0
  32. synkit/CRN/Petrinet/semiflows.py +483 -0
  33. synkit/CRN/Petrinet/siphon_search.py +402 -0
  34. synkit/CRN/Petrinet/structure.py +286 -0
  35. synkit/CRN/Props/__init__.py +130 -0
  36. synkit/CRN/Props/_rank.py +29 -0
  37. synkit/CRN/Props/deficiency.py +953 -0
  38. synkit/CRN/Props/dynamics.py +832 -0
  39. synkit/CRN/Props/helper.py +151 -0
  40. synkit/CRN/Props/stoich.py +751 -0
  41. synkit/CRN/Props/thermo.py +584 -0
  42. synkit/CRN/Query/__init__.py +66 -0
  43. synkit/CRN/Query/cache.py +41 -0
  44. synkit/CRN/Query/kegg_api.py +99 -0
  45. synkit/CRN/Query/kegg_extract.py +714 -0
  46. synkit/CRN/Query/kegg_impute.py +707 -0
  47. synkit/CRN/Query/kegg_parse.py +480 -0
  48. synkit/CRN/Query/to_syncrn.py +290 -0
  49. synkit/CRN/README.md +234 -0
  50. synkit/CRN/Structure/__init__.py +12 -0
  51. synkit/CRN/Structure/_graph_io.py +713 -0
  52. synkit/CRN/Structure/_matrices.py +88 -0
  53. synkit/CRN/Structure/_parse.py +544 -0
  54. synkit/CRN/Structure/reaction.py +237 -0
  55. synkit/CRN/Structure/rule.py +55 -0
  56. synkit/CRN/Structure/species.py +46 -0
  57. synkit/CRN/Structure/syncrn.py +929 -0
  58. synkit/CRN/Symmetry/__init__.py +20 -0
  59. synkit/CRN/Symmetry/_common.py +1059 -0
  60. synkit/CRN/Symmetry/_ir.py +940 -0
  61. synkit/CRN/Symmetry/automorphism.py +472 -0
  62. synkit/CRN/Symmetry/canon.py +441 -0
  63. synkit/CRN/Symmetry/isomorphism.py +412 -0
  64. synkit/CRN/Symmetry/symmetry.py +61 -0
  65. synkit/CRN/Symmetry/wl_canon.py +967 -0
  66. synkit/CRN/Visualize/__init__.py +11 -0
  67. synkit/CRN/Visualize/labels.py +113 -0
  68. synkit/CRN/Visualize/layout.py +708 -0
  69. synkit/CRN/Visualize/palette.py +292 -0
  70. synkit/CRN/Visualize/validation.py +122 -0
  71. synkit/CRN/Visualize/vis.py +1152 -0
  72. synkit/CRN/__init__.py +233 -0
  73. synkit/CRN/_build.py +50 -0
  74. synkit/CRN/_native_build.py +175 -0
  75. synkit/CRN/analysis.py +629 -0
  76. synkit/CRN/backend.py +74 -0
  77. synkit/CRN/cpp/CMakeLists.txt +58 -0
  78. synkit/CRN/cpp/algebra.cpp +46 -0
  79. synkit/CRN/cpp/closure.cpp +29 -0
  80. synkit/CRN/cpp/exact.h +55 -0
  81. synkit/CRN/cpp/pathway.cpp +46 -0
  82. synkit/CRN/cpp/semiflows.cpp +209 -0
  83. synkit/CRN/cpp/structural.cpp +240 -0
  84. synkit/CRN/cpp/symmetry.cpp +45 -0
  85. synkit/CRN/cpp/write_manifest.cmake +28 -0
  86. synkit/CRN/kinds.py +137 -0
  87. synkit/CRN/lib/synkit_crn.dll +0 -0
  88. synkit/CRN/lib/synkit_crn.json +33 -0
  89. synkit/CRN/native.py +388 -0
  90. synkit/CRN/native_analysis.py +459 -0
  91. synkit/Chem/Cluster/__init__.py +0 -0
  92. synkit/Chem/Cluster/butina.py +140 -0
  93. synkit/Chem/Fingerprint/__init__.py +0 -0
  94. synkit/Chem/Fingerprint/fp_calculator.py +155 -0
  95. synkit/Chem/Fingerprint/smiles_featurizer.py +258 -0
  96. synkit/Chem/Fingerprint/transformation_fp.py +139 -0
  97. synkit/Chem/Mapper/README.rst +43 -0
  98. synkit/Chem/Mapper/__init__.py +255 -0
  99. synkit/Chem/Mapper/_compat.py +130 -0
  100. synkit/Chem/Mapper/adapters/__init__.py +1 -0
  101. synkit/Chem/Mapper/adapters/prediction.py +126 -0
  102. synkit/Chem/Mapper/adapters/template.py +412 -0
  103. synkit/Chem/Mapper/chem/__init__.py +52 -0
  104. synkit/Chem/Mapper/chem/aam.py +673 -0
  105. synkit/Chem/Mapper/chem/blind.py +160 -0
  106. synkit/Chem/Mapper/chem/its.py +309 -0
  107. synkit/Chem/Mapper/chem/smiles.py +564 -0
  108. synkit/Chem/Mapper/graph/__init__.py +66 -0
  109. synkit/Chem/Mapper/graph/automorphism.py +395 -0
  110. synkit/Chem/Mapper/graph/blockcut.py +98 -0
  111. synkit/Chem/Mapper/graph/labeled_graph.py +104 -0
  112. synkit/Chem/Mapper/graph/refine.py +176 -0
  113. synkit/Chem/Mapper/graph/synkit_adapter.py +110 -0
  114. synkit/Chem/Mapper/io/__init__.py +13 -0
  115. synkit/Chem/Mapper/io/idxmapstr.py +82 -0
  116. synkit/Chem/Mapper/mapper.py +685 -0
  117. synkit/Chem/Mapper/reaction_search.py +554 -0
  118. synkit/Chem/Mapper/reporting/__init__.py +1 -0
  119. synkit/Chem/Mapper/reporting/alternatives.py +451 -0
  120. synkit/Chem/Mapper/reporting/analysis.py +681 -0
  121. synkit/Chem/Mapper/reporting/native_analysis.py +485 -0
  122. synkit/Chem/Mapper/reporting/spectrum.py +642 -0
  123. synkit/Chem/Mapper/solvers/__init__.py +1 -0
  124. synkit/Chem/Mapper/solvers/exact/__init__.py +141 -0
  125. synkit/Chem/Mapper/solvers/exact/assignment/__init__.py +1 -0
  126. synkit/Chem/Mapper/solvers/exact/assignment/assignment_certificate.py +113 -0
  127. synkit/Chem/Mapper/solvers/exact/assignment/assignment_domains.py +162 -0
  128. synkit/Chem/Mapper/solvers/exact/assignment/assignment_verification.py +58 -0
  129. synkit/Chem/Mapper/solvers/exact/assignment/incremental_assignment.py +247 -0
  130. synkit/Chem/Mapper/solvers/exact/certificate.py +128 -0
  131. synkit/Chem/Mapper/solvers/exact/core.py +183 -0
  132. synkit/Chem/Mapper/solvers/exact/distance_search/__init__.py +1 -0
  133. synkit/Chem/Mapper/solvers/exact/distance_search/bounds.py +319 -0
  134. synkit/Chem/Mapper/solvers/exact/distance_search/exhaustive.py +179 -0
  135. synkit/Chem/Mapper/solvers/exact/distance_search/inputs.py +283 -0
  136. synkit/Chem/Mapper/solvers/exact/distance_search/records.py +242 -0
  137. synkit/Chem/Mapper/solvers/exact/distance_search/search.py +1025 -0
  138. synkit/Chem/Mapper/solvers/exact/distance_search/verify.py +378 -0
  139. synkit/Chem/Mapper/solvers/exact/edit_support.py +375 -0
  140. synkit/Chem/Mapper/solvers/exact/hybrid.py +224 -0
  141. synkit/Chem/Mapper/solvers/exact/hydrogen.py +264 -0
  142. synkit/Chem/Mapper/solvers/exact/kernel_solvers/__init__.py +1 -0
  143. synkit/Chem/Mapper/solvers/exact/kernel_solvers/branching.py +499 -0
  144. synkit/Chem/Mapper/solvers/exact/kernel_solvers/enumerate.py +1050 -0
  145. synkit/Chem/Mapper/solvers/exact/kernel_solvers/enumeration_result.py +30 -0
  146. synkit/Chem/Mapper/solvers/exact/kernel_solvers/kernel.py +256 -0
  147. synkit/Chem/Mapper/solvers/exact/kernel_solvers/milp.py +194 -0
  148. synkit/Chem/Mapper/solvers/exact/native/__init__.py +1 -0
  149. synkit/Chem/Mapper/solvers/exact/native/build.py +154 -0
  150. synkit/Chem/Mapper/solvers/exact/native/candidates.py +593 -0
  151. synkit/Chem/Mapper/solvers/exact/native/canonical.py +396 -0
  152. synkit/Chem/Mapper/solvers/exact/native/disk_frontier.py +415 -0
  153. synkit/Chem/Mapper/solvers/exact/native/frontier.py +390 -0
  154. synkit/Chem/Mapper/solvers/exact/native/hydrogen_quotient.py +213 -0
  155. synkit/Chem/Mapper/solvers/exact/native/its.py +528 -0
  156. synkit/Chem/Mapper/solvers/exact/native/native_distance.cpp +2803 -0
  157. synkit/Chem/Mapper/solvers/exact/native/orbit_aggregation.py +328 -0
  158. synkit/Chem/Mapper/solvers/exact/native/parallel.py +205 -0
  159. synkit/Chem/Mapper/solvers/exact/native/pmcd.py +203 -0
  160. synkit/Chem/Mapper/solvers/exact/native/runtime.py +40 -0
  161. synkit/Chem/Mapper/solvers/exact/native/search.py +294 -0
  162. synkit/Chem/Mapper/solvers/exact/native/separator.py +224 -0
  163. synkit/Chem/Mapper/solvers/exact/native_build.py +12 -0
  164. synkit/Chem/Mapper/solvers/exact/pabs/__init__.py +1 -0
  165. synkit/Chem/Mapper/solvers/exact/pabs/cost_lattice.py +43 -0
  166. synkit/Chem/Mapper/solvers/exact/pabs/factor_spectrum.py +110 -0
  167. synkit/Chem/Mapper/solvers/exact/pabs/multi_shell.py +368 -0
  168. synkit/Chem/Mapper/solvers/exact/pabs/propagation.py +679 -0
  169. synkit/Chem/Mapper/solvers/exact/pabs/propagation_bounds.py +436 -0
  170. synkit/Chem/Mapper/solvers/exact/pabs/propagation_limits.py +13 -0
  171. synkit/Chem/Mapper/solvers/exact/pabs/propagation_search.py +856 -0
  172. synkit/Chem/Mapper/solvers/exact/pabs/propagation_symmetry.py +66 -0
  173. synkit/Chem/Mapper/solvers/exact/pabs/residual_typed_bonds.py +136 -0
  174. synkit/Chem/Mapper/solvers/exact/pabs/reward_frontier.py +201 -0
  175. synkit/Chem/Mapper/solvers/exact/pabs/separator_bound.py +258 -0
  176. synkit/Chem/Mapper/solvers/exact/pabs/separator_spectrum.py +308 -0
  177. synkit/Chem/Mapper/solvers/exact/pabs/sparse_reward_bound.py +207 -0
  178. synkit/Chem/Mapper/solvers/exact/pabs/suffix_spectrum.py +299 -0
  179. synkit/Chem/Mapper/solvers/exact/search.py +55 -0
  180. synkit/Chem/Mapper/solvers/exact/seeds/__init__.py +1 -0
  181. synkit/Chem/Mapper/solvers/exact/seeds/seed.py +104 -0
  182. synkit/Chem/Mapper/solvers/exact/seeds/seed_fragments.py +148 -0
  183. synkit/Chem/Mapper/solvers/exact/seeds/seed_relaxation.py +181 -0
  184. synkit/Chem/Mapper/solvers/exact/symmetry.py +223 -0
  185. synkit/Chem/Mapper/solvers/native/__init__.py +4 -0
  186. synkit/Chem/Mapper/solvers/native/assignment.py +99 -0
  187. synkit/Chem/Mapper/solvers/native/astar.py +22 -0
  188. synkit/Chem/Mapper/solvers/native/build.py +385 -0
  189. synkit/Chem/Mapper/solvers/native/classification.py +641 -0
  190. synkit/Chem/Mapper/solvers/native/core.py +378 -0
  191. synkit/Chem/Mapper/solvers/native/cpp/CMakeLists.txt +120 -0
  192. synkit/Chem/Mapper/solvers/native/cpp/examples/map_reaction.cpp +29 -0
  193. synkit/Chem/Mapper/solvers/native/cpp/examples/slap_graph.cpp +63 -0
  194. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/assignment/assignment.h +18 -0
  195. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/astar/astar.h +18 -0
  196. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/astar/bound.h +33 -0
  197. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/core/pmcd_witness.h +16 -0
  198. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/core/runtime.h +130 -0
  199. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/hydrogen/hydrogen.h +73 -0
  200. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/mapper.h +175 -0
  201. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/mces/mces.h +9 -0
  202. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/pabs/seed.h +34 -0
  203. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/reaction/reaction.h +30 -0
  204. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/sepdp/sepdp.h +21 -0
  205. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/slap.h +72 -0
  206. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/solvers/solvers.h +16 -0
  207. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/symmetry/classification.h +140 -0
  208. synkit/Chem/Mapper/solvers/native/cpp/include/synkit_mapper/symmetry/cpabs.h +33 -0
  209. synkit/Chem/Mapper/solvers/native/cpp/src/assignment/abb.cpp +302 -0
  210. synkit/Chem/Mapper/solvers/native/cpp/src/astar/CMakeLists.txt +12 -0
  211. synkit/Chem/Mapper/solvers/native/cpp/src/astar/README.md +47 -0
  212. synkit/Chem/Mapper/solvers/native/cpp/src/astar/astar.cpp +228 -0
  213. synkit/Chem/Mapper/solvers/native/cpp/src/astar/astar_graph.cpp +37 -0
  214. synkit/Chem/Mapper/solvers/native/cpp/src/astar/bound.cpp +212 -0
  215. synkit/Chem/Mapper/solvers/native/cpp/src/core/dispatch.cpp +272 -0
  216. synkit/Chem/Mapper/solvers/native/cpp/src/core/pmcd_witness.cpp +36 -0
  217. synkit/Chem/Mapper/solvers/native/cpp/src/hydrogen/hydrogen.cpp +380 -0
  218. synkit/Chem/Mapper/solvers/native/cpp/src/mces/README.md +57 -0
  219. synkit/Chem/Mapper/solvers/native/cpp/src/mces/mces.cpp +287 -0
  220. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/bridge.cpp +334 -0
  221. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/chemical_floor.inc +181 -0
  222. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/endpoint_symmetry.inc +104 -0
  223. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/exact_helpers.h +20 -0
  224. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_assignment_certificate.h +165 -0
  225. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_certificate.h +125 -0
  226. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_model.h +365 -0
  227. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_provider.inc +319 -0
  228. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_rounding.inc +170 -0
  229. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/lp_test_hooks.h +342 -0
  230. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/objective_reduction.inc +137 -0
  231. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/overlap_dual.inc +351 -0
  232. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/profile_seed.inc +214 -0
  233. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/seed_heuristics.inc +640 -0
  234. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/sparse_embedding.cpp +430 -0
  235. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/sparse_root_lp.h +176 -0
  236. synkit/Chem/Mapper/solvers/native/cpp/src/pabs/test_hooks.inc +262 -0
  237. synkit/Chem/Mapper/solvers/native/cpp/src/reaction/reaction.cpp +611 -0
  238. synkit/Chem/Mapper/solvers/native/cpp/src/sepdp/README.md +61 -0
  239. synkit/Chem/Mapper/solvers/native/cpp/src/sepdp/sepdp.cpp +253 -0
  240. synkit/Chem/Mapper/solvers/native/cpp/src/slap.cpp +810 -0
  241. synkit/Chem/Mapper/solvers/native/cpp/src/solvers/formulation.h +138 -0
  242. synkit/Chem/Mapper/solvers/native/cpp/src/solvers/maxsat.cpp +526 -0
  243. synkit/Chem/Mapper/solvers/native/cpp/src/solvers/ortools.cpp +475 -0
  244. synkit/Chem/Mapper/solvers/native/cpp/src/solvers/seed.h +80 -0
  245. synkit/Chem/Mapper/solvers/native/cpp/src/solvers/weighted_cnf.h +256 -0
  246. synkit/Chem/Mapper/solvers/native/cpp/src/supporting/README.md +43 -0
  247. synkit/Chem/Mapper/solvers/native/cpp/src/supporting/dfs.cpp +123 -0
  248. synkit/Chem/Mapper/solvers/native/cpp/src/supporting/edit_support.cpp +224 -0
  249. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/classification.cpp +553 -0
  250. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/classification_pipeline.cpp +124 -0
  251. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/classification_stream.h +13 -0
  252. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/cpabs.cpp +455 -0
  253. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/edge_deck.cpp +743 -0
  254. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/COPYRIGHT +44 -0
  255. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/LICENSE-2.0.txt +202 -0
  256. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naugraph.c +732 -0
  257. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naurng.c +94 -0
  258. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naurng.h +49 -0
  259. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nausparse.c +1771 -0
  260. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nausparse.h +133 -0
  261. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nautil.c +750 -0
  262. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/naututil.h +355 -0
  263. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nauty.c +1256 -0
  264. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/nauty.h +1544 -0
  265. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/schreier.c +1131 -0
  266. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/schreier.h +70 -0
  267. synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/sorttemplates.c +580 -0
  268. synkit/Chem/Mapper/solvers/native/hydrogen.py +711 -0
  269. synkit/Chem/Mapper/solvers/native/implicit.py +506 -0
  270. synkit/Chem/Mapper/solvers/native/implicit_certificate.py +187 -0
  271. synkit/Chem/Mapper/solvers/native/implicit_preparation.py +309 -0
  272. synkit/Chem/Mapper/solvers/native/lib/synkit_mapper.dll +0 -0
  273. synkit/Chem/Mapper/solvers/native/mces.py +16 -0
  274. synkit/Chem/Mapper/solvers/native/reaction.py +179 -0
  275. synkit/Chem/Mapper/solvers/native/reaction_build.py +277 -0
  276. synkit/Chem/Mapper/solvers/native/reaction_text.py +26 -0
  277. synkit/Chem/Mapper/solvers/native/runtime.py +242 -0
  278. synkit/Chem/Mapper/solvers/native/sepdp.py +47 -0
  279. synkit/Chem/Mapper/solvers/native/slap.py +266 -0
  280. synkit/Chem/Mapper/solvers/native/solvers.py +67 -0
  281. synkit/Chem/Mapper/solvers/native/stereo.py +86 -0
  282. synkit/Chem/Mapper/solvers/native/supporting.py +34 -0
  283. synkit/Chem/Mapper/solvers/native/symmetry.py +91 -0
  284. synkit/Chem/Mapper/solvers/slap/__init__.py +29 -0
  285. synkit/Chem/Mapper/solvers/slap/lap.py +174 -0
  286. synkit/Chem/Mapper/solvers/slap/sequential.py +696 -0
  287. synkit/Chem/Mapper/validation/__init__.py +1 -0
  288. synkit/Chem/Mapper/validation/aam_validator.py +442 -0
  289. synkit/Chem/Mapper/validation/annotations.py +274 -0
  290. synkit/Chem/Mapper/validation/bonds.py +124 -0
  291. synkit/Chem/Mapper/validation/cohorts.py +72 -0
  292. synkit/Chem/Mapper/validation/identifiability.py +150 -0
  293. synkit/Chem/Mapper/validation/numerical_scope.py +36 -0
  294. synkit/Chem/Mapper/validation/orbits.py +137 -0
  295. synkit/Chem/Molecule/__init__.py +0 -0
  296. synkit/Chem/Molecule/_chirality_loci.py +165 -0
  297. synkit/Chem/Molecule/_chirality_types.py +231 -0
  298. synkit/Chem/Molecule/_helical_loci.py +167 -0
  299. synkit/Chem/Molecule/_stereo_axis_evidence.py +202 -0
  300. synkit/Chem/Molecule/_stereo_element_detection.py +193 -0
  301. synkit/Chem/Molecule/_stereo_orientation_constraints.py +511 -0
  302. synkit/Chem/Molecule/_tetrahedral_carriers.py +63 -0
  303. synkit/Chem/Molecule/atom_features.py +379 -0
  304. synkit/Chem/Molecule/chirality.py +1041 -0
  305. synkit/Chem/Molecule/cip_assignment.py +569 -0
  306. synkit/Chem/Molecule/cip_ranking.py +843 -0
  307. synkit/Chem/Molecule/coordinate_stereo.py +503 -0
  308. synkit/Chem/Molecule/derived_stereo_naming.py +165 -0
  309. synkit/Chem/Molecule/descriptors.py +452 -0
  310. synkit/Chem/Molecule/formula.py +249 -0
  311. synkit/Chem/Molecule/global_stereo.py +175 -0
  312. synkit/Chem/Molecule/graph_annotator.py +300 -0
  313. synkit/Chem/Molecule/standardize.py +817 -0
  314. synkit/Chem/Molecule/stereo_evidence.py +179 -0
  315. synkit/Chem/Molecule/stereo_perception.py +1032 -0
  316. synkit/Chem/Molecule/valence.py +123 -0
  317. synkit/Chem/Reaction/Mapper/__init__.py +44 -0
  318. synkit/Chem/Reaction/__init__.py +20 -0
  319. synkit/Chem/Reaction/aam_validator.py +5 -0
  320. synkit/Chem/Reaction/balance_check.py +138 -0
  321. synkit/Chem/Reaction/canon_rsmi.py +249 -0
  322. synkit/Chem/Reaction/cleaning.py +58 -0
  323. synkit/Chem/Reaction/deionize.py +199 -0
  324. synkit/Chem/Reaction/explicit_h_audit.py +232 -0
  325. synkit/Chem/Reaction/fix_aam.py +64 -0
  326. synkit/Chem/Reaction/neutralize.py +207 -0
  327. synkit/Chem/Reaction/radical_wildcard.py +224 -0
  328. synkit/Chem/Reaction/standardize.py +203 -0
  329. synkit/Chem/Reaction/tautomerize.py +205 -0
  330. synkit/Chem/__init__.py +1 -0
  331. synkit/Chem/utils.py +315 -0
  332. synkit/Data/__init__.py +0 -0
  333. synkit/Data/aldol.json.gz +1 -0
  334. synkit/Data/gen_partial_aam.py +147 -0
  335. synkit/Data/paracetamol.json.gz +1 -0
  336. synkit/Graph/Canon/__init__.py +16 -0
  337. synkit/Graph/Canon/_native/__init__.py +13 -0
  338. synkit/Graph/Canon/_native/build.py +93 -0
  339. synkit/Graph/Canon/_native/lib/synkit_canon.dll +0 -0
  340. synkit/Graph/Canon/_native/prepare.py +49 -0
  341. synkit/Graph/Canon/_native/runtime.py +140 -0
  342. synkit/Graph/Canon/_native/search.py +137 -0
  343. synkit/Graph/Canon/canon_algs.py +228 -0
  344. synkit/Graph/Canon/canon_graph.py +531 -0
  345. synkit/Graph/Canon/cpp/CMakeLists.txt +42 -0
  346. synkit/Graph/Canon/cpp/README.md +123 -0
  347. synkit/Graph/Canon/cpp/examples/canonical_graph.cpp +16 -0
  348. synkit/Graph/Canon/cpp/include/synkit_canon/canon.h +85 -0
  349. synkit/Graph/Canon/cpp/src/canonical.cpp +391 -0
  350. synkit/Graph/Canon/cpp/src/symmetry.h +83 -0
  351. synkit/Graph/Canon/cpp/tests/symmetry.cpp +93 -0
  352. synkit/Graph/Canon/exact.py +1020 -0
  353. synkit/Graph/Canon/exact_refinement.py +368 -0
  354. synkit/Graph/Canon/nauty.py +143 -0
  355. synkit/Graph/Context/__init__.py +0 -0
  356. synkit/Graph/Context/hier_context.py +244 -0
  357. synkit/Graph/Context/radius_expand.py +252 -0
  358. synkit/Graph/FG/__init__.py +19 -0
  359. synkit/Graph/FG/api.py +39 -0
  360. synkit/Graph/FG/audit.py +155 -0
  361. synkit/Graph/FG/catalog.py +919 -0
  362. synkit/Graph/FG/detector.py +288 -0
  363. synkit/Graph/FG/model.py +97 -0
  364. synkit/Graph/FG/recognizers.py +274 -0
  365. synkit/Graph/FG/ring_system.py +154 -0
  366. synkit/Graph/Feature/Descriptors/topology.py +857 -0
  367. synkit/Graph/Feature/Fingerprint/__init__.py +0 -0
  368. synkit/Graph/Feature/Fingerprint/wl_rxn_fps.py +222 -0
  369. synkit/Graph/Feature/__init__.py +5 -0
  370. synkit/Graph/Feature/graph_descriptors.py +323 -0
  371. synkit/Graph/Feature/graph_fps.py +96 -0
  372. synkit/Graph/Feature/graph_signature.py +239 -0
  373. synkit/Graph/Feature/hash_fps.py +133 -0
  374. synkit/Graph/Feature/morgan_fps.py +88 -0
  375. synkit/Graph/Feature/path_fps.py +81 -0
  376. synkit/Graph/Feature/wl_hash.py +134 -0
  377. synkit/Graph/Fusion/__init__.py +85 -0
  378. synkit/Graph/Fusion/candidate.py +559 -0
  379. synkit/Graph/Fusion/constructor.py +877 -0
  380. synkit/Graph/Fusion/identity.py +184 -0
  381. synkit/Graph/Fusion/interface.py +700 -0
  382. synkit/Graph/Fusion/search.py +241 -0
  383. synkit/Graph/Hyrogen/__init__.py +6 -0
  384. synkit/Graph/Hyrogen/_misc.py +591 -0
  385. synkit/Graph/Hyrogen/hcomplete.py +995 -0
  386. synkit/Graph/Hyrogen/hcomplete_legacy.py +368 -0
  387. synkit/Graph/Hyrogen/hcompletion_algorithms.py +713 -0
  388. synkit/Graph/Hyrogen/hextend.py +570 -0
  389. synkit/Graph/Hyrogen/hextend_legacy.py +215 -0
  390. synkit/Graph/ITS/__init__.py +4 -0
  391. synkit/Graph/ITS/its_builder.py +120 -0
  392. synkit/Graph/ITS/its_construction.py +719 -0
  393. synkit/Graph/ITS/its_decompose.py +572 -0
  394. synkit/Graph/ITS/its_destruction.py +331 -0
  395. synkit/Graph/ITS/its_expand.py +1251 -0
  396. synkit/Graph/ITS/its_relabel.py +187 -0
  397. synkit/Graph/ITS/its_reverter.py +356 -0
  398. synkit/Graph/ITS/normalize_aam.py +145 -0
  399. synkit/Graph/ITS/partial_its.py +238 -0
  400. synkit/Graph/ITS/rc_extractor.py +656 -0
  401. synkit/Graph/ITS/stereo.py +74 -0
  402. synkit/Graph/MTG/__init__.py +107 -0
  403. synkit/Graph/MTG/gluing.py +451 -0
  404. synkit/Graph/MTG/history.py +928 -0
  405. synkit/Graph/MTG/inventory.py +118 -0
  406. synkit/Graph/MTG/local.py +447 -0
  407. synkit/Graph/MTG/mcs_matcher.py +246 -0
  408. synkit/Graph/MTG/mtg.py +611 -0
  409. synkit/Graph/MTG/mtg_explore.py +74 -0
  410. synkit/Graph/MTG/observation.py +209 -0
  411. synkit/Graph/MTG/process.py +577 -0
  412. synkit/Graph/MTG/queries.py +66 -0
  413. synkit/Graph/MTG/realization.py +95 -0
  414. synkit/Graph/MTG/series_parallel.py +107 -0
  415. synkit/Graph/MTG/utils.py +424 -0
  416. synkit/Graph/Matcher/__init__.py +10 -0
  417. synkit/Graph/Matcher/approx_mcs.py +1264 -0
  418. synkit/Graph/Matcher/auto_est.py +736 -0
  419. synkit/Graph/Matcher/automorphism.py +314 -0
  420. synkit/Graph/Matcher/batch_cluster.py +224 -0
  421. synkit/Graph/Matcher/dedup_matches.py +247 -0
  422. synkit/Graph/Matcher/graph_cluster.py +191 -0
  423. synkit/Graph/Matcher/graph_matcher.py +312 -0
  424. synkit/Graph/Matcher/graph_morphism.py +421 -0
  425. synkit/Graph/Matcher/mcs_matcher.py +804 -0
  426. synkit/Graph/Matcher/multi_turbo_iso.py +186 -0
  427. synkit/Graph/Matcher/orbit.py +284 -0
  428. synkit/Graph/Matcher/partial_matcher.py +694 -0
  429. synkit/Graph/Matcher/sing.py +544 -0
  430. synkit/Graph/Matcher/subgraph_matcher.py +812 -0
  431. synkit/Graph/Matcher/turbo_iso.py +272 -0
  432. synkit/Graph/Matcher/wl_sel.py +537 -0
  433. synkit/Graph/Mech/__init__.py +26 -0
  434. synkit/Graph/Mech/conversion.py +1466 -0
  435. synkit/Graph/Mech/conversion_debug.py +237 -0
  436. synkit/Graph/Mech/electron_accounting.py +200 -0
  437. synkit/Graph/Mech/lwg_editor.py +406 -0
  438. synkit/Graph/Mech/lwg_ops.py +313 -0
  439. synkit/Graph/Morphism/__init__.py +99 -0
  440. synkit/Graph/Morphism/constraints.py +460 -0
  441. synkit/Graph/Morphism/llg.py +999 -0
  442. synkit/Graph/Morphism/morphism.py +349 -0
  443. synkit/Graph/Morphism/stereo.py +258 -0
  444. synkit/Graph/Morphism/stereo_morphism.py +383 -0
  445. synkit/Graph/Morphism/stereo_morphism_helpers.py +957 -0
  446. synkit/Graph/Morphism/stereo_morphism_types.py +117 -0
  447. synkit/Graph/Stereo/__init__.py +376 -0
  448. synkit/Graph/Stereo/_descriptor_core.py +207 -0
  449. synkit/Graph/Stereo/_descriptor_serialization.py +138 -0
  450. synkit/Graph/Stereo/canonical.py +648 -0
  451. synkit/Graph/Stereo/changes.py +964 -0
  452. synkit/Graph/Stereo/composition.py +391 -0
  453. synkit/Graph/Stereo/configured.py +946 -0
  454. synkit/Graph/Stereo/couplings.py +245 -0
  455. synkit/Graph/Stereo/descriptors.py +1030 -0
  456. synkit/Graph/Stereo/enumeration.py +597 -0
  457. synkit/Graph/Stereo/extended_descriptors.py +406 -0
  458. synkit/Graph/Stereo/global_configured.py +152 -0
  459. synkit/Graph/Stereo/global_stereo.py +304 -0
  460. synkit/Graph/Stereo/identity.py +648 -0
  461. synkit/Graph/Stereo/interchange.py +496 -0
  462. synkit/Graph/Stereo/legacy.py +460 -0
  463. synkit/Graph/Stereo/matching.py +899 -0
  464. synkit/Graph/Stereo/native.py +154 -0
  465. synkit/Graph/Stereo/orbits.py +668 -0
  466. synkit/Graph/Stereo/outcomes.py +99 -0
  467. synkit/Graph/Stereo/pairwise.py +350 -0
  468. synkit/Graph/Stereo/rdkit_adapter.py +662 -0
  469. synkit/Graph/Stereo/rdkit_identity.py +118 -0
  470. synkit/Graph/Stereo/rdkit_resonance.py +140 -0
  471. synkit/Graph/Stereo/reaction_interchange.py +266 -0
  472. synkit/Graph/Stereo/semantics.py +296 -0
  473. synkit/Graph/Stereo/supports.py +257 -0
  474. synkit/Graph/Stereo/wire.py +339 -0
  475. synkit/Graph/Wildcard/__init__.py +0 -0
  476. synkit/Graph/Wildcard/fuse_graph.py +156 -0
  477. synkit/Graph/Wildcard/graph_wc.py +303 -0
  478. synkit/Graph/Wildcard/its_merge.py +857 -0
  479. synkit/Graph/Wildcard/radwc.py +114 -0
  480. synkit/Graph/Wildcard/wc_matcher.py +576 -0
  481. synkit/Graph/Wildcard/wildcard.py +225 -0
  482. synkit/Graph/__init__.py +17 -0
  483. synkit/Graph/canon_graph.py +14 -0
  484. synkit/Graph/syn_graph.py +199 -0
  485. synkit/Graph/utils.py +324 -0
  486. synkit/IO/__init__.py +4 -0
  487. synkit/IO/chem_converter.py +1059 -0
  488. synkit/IO/combinatorial/__init__.py +8 -0
  489. synkit/IO/combinatorial/gml_to_graph.py +223 -0
  490. synkit/IO/combinatorial/graph_to_gml.py +280 -0
  491. synkit/IO/combinatorial/graph_to_smarts.py +186 -0
  492. synkit/IO/combinatorial/smarts_expander.py +147 -0
  493. synkit/IO/combinatorial/smarts_generalizer.py +133 -0
  494. synkit/IO/combinatorial/smarts_to_graph.py +179 -0
  495. synkit/IO/conversion.py +42 -0
  496. synkit/IO/data_io.py +269 -0
  497. synkit/IO/data_process.py +143 -0
  498. synkit/IO/debug.py +73 -0
  499. synkit/IO/gml_to_nx.py +150 -0
  500. synkit/IO/graph_to_mol.py +199 -0
  501. synkit/IO/mol_to_graph.py +1105 -0
  502. synkit/IO/mol_to_graph_chemistry.py +545 -0
  503. synkit/IO/nx_to_gml.py +209 -0
  504. synkit/IO/smiles_to_id.py +123 -0
  505. synkit/Mechanism/__init__.py +151 -0
  506. synkit/Mechanism/adapters.py +136 -0
  507. synkit/Mechanism/audit.py +323 -0
  508. synkit/Mechanism/benchmark.py +638 -0
  509. synkit/Mechanism/compatibility.py +13 -0
  510. synkit/Mechanism/drawing.py +85 -0
  511. synkit/Mechanism/electron_models.py +725 -0
  512. synkit/Mechanism/equivalence.py +521 -0
  513. synkit/Mechanism/evidence.py +262 -0
  514. synkit/Mechanism/interchange.py +141 -0
  515. synkit/Mechanism/model.py +918 -0
  516. synkit/Mechanism/neighbor_stereo.py +312 -0
  517. synkit/Mechanism/radical_data.py +740 -0
  518. synkit/Mechanism/replay.py +986 -0
  519. synkit/Mechanism/schema.py +264 -0
  520. synkit/Mechanism/stereo_state.py +416 -0
  521. synkit/Mechanism/symbols.py +91 -0
  522. synkit/Rule/Apply/__init__.py +35 -0
  523. synkit/Rule/Apply/conditions.py +45 -0
  524. synkit/Rule/Apply/dpo.py +998 -0
  525. synkit/Rule/Apply/rule_matcher.py +218 -0
  526. synkit/Rule/Apply/validation.py +354 -0
  527. synkit/Rule/Compose/__init__.py +106 -0
  528. synkit/Rule/Compose/_identity.py +43 -0
  529. synkit/Rule/Compose/composition.py +976 -0
  530. synkit/Rule/Compose/laws.py +439 -0
  531. synkit/Rule/Compose/search.py +771 -0
  532. synkit/Rule/Compose/synrule.py +170 -0
  533. synkit/Rule/Modify/__init__.py +0 -0
  534. synkit/Rule/Modify/implict_rule.py +56 -0
  535. synkit/Rule/Modify/longest_path.py +92 -0
  536. synkit/Rule/Modify/molecule_rule.py +115 -0
  537. synkit/Rule/Modify/prune_templates.py +78 -0
  538. synkit/Rule/Modify/rule_utils.py +194 -0
  539. synkit/Rule/Modify/strip_rule.py +97 -0
  540. synkit/Rule/__init__.py +28 -0
  541. synkit/Rule/generic_stereo.py +884 -0
  542. synkit/Rule/stereo_identity.py +271 -0
  543. synkit/Rule/syn_rule.py +1090 -0
  544. synkit/Synthesis/MSR/__init__.py +0 -0
  545. synkit/Synthesis/MSR/path_finder.py +239 -0
  546. synkit/Synthesis/Metrics/__init__.py +0 -0
  547. synkit/Synthesis/Metrics/_base.py +52 -0
  548. synkit/Synthesis/Metrics/_plot.py +129 -0
  549. synkit/Synthesis/Metrics/_ranking.py +179 -0
  550. synkit/Synthesis/RBL/__init__.py +80 -0
  551. synkit/Synthesis/RBL/engine.py +1249 -0
  552. synkit/Synthesis/RBL/matching.py +652 -0
  553. synkit/Synthesis/RBL/overlap.py +336 -0
  554. synkit/Synthesis/RBL/pipeline.py +376 -0
  555. synkit/Synthesis/RBL/policy.py +139 -0
  556. synkit/Synthesis/RBL/proof.py +370 -0
  557. synkit/Synthesis/RBL/reaction.py +506 -0
  558. synkit/Synthesis/RBL/state.py +169 -0
  559. synkit/Synthesis/RBL/validation.py +1060 -0
  560. synkit/Synthesis/Reactor/__init__.py +60 -0
  561. synkit/Synthesis/Reactor/core/__init__.py +1 -0
  562. synkit/Synthesis/Reactor/core/engine.py +967 -0
  563. synkit/Synthesis/Reactor/core/product.py +621 -0
  564. synkit/Synthesis/Reactor/core/rewrite.py +561 -0
  565. synkit/Synthesis/Reactor/core/strategy.py +44 -0
  566. synkit/Synthesis/Reactor/matching/__init__.py +1 -0
  567. synkit/Synthesis/Reactor/matching/mixin.py +920 -0
  568. synkit/Synthesis/Reactor/matching/policy.py +345 -0
  569. synkit/Synthesis/Reactor/matching/symmetry.py +309 -0
  570. synkit/Synthesis/Reactor/output/__init__.py +1 -0
  571. synkit/Synthesis/Reactor/output/deduplication.py +703 -0
  572. synkit/Synthesis/Reactor/output/policy.py +16 -0
  573. synkit/Synthesis/Reactor/output/serialization.py +485 -0
  574. synkit/Synthesis/Reactor/output/structural.py +893 -0
  575. synkit/Synthesis/Reactor/stereo/__init__.py +1 -0
  576. synkit/Synthesis/Reactor/stereo/assignment.py +35 -0
  577. synkit/Synthesis/Reactor/stereo/mixin.py +780 -0
  578. synkit/Synthesis/Reactor/variants/__init__.py +1 -0
  579. synkit/Synthesis/Reactor/variants/imbalanced.py +180 -0
  580. synkit/Synthesis/Reactor/variants/partial.py +84 -0
  581. synkit/Synthesis/Reactor/workflow/__init__.py +1 -0
  582. synkit/Synthesis/Reactor/workflow/batch.py +550 -0
  583. synkit/Synthesis/Reactor/workflow/benchmark.py +143 -0
  584. synkit/Synthesis/Reactor/workflow/postprocess.py +267 -0
  585. synkit/Synthesis/Reactor/workflow/rule_filter.py +210 -0
  586. synkit/Synthesis/__init__.py +0 -0
  587. synkit/Synthesis/reactor_utils.py +316 -0
  588. synkit/Utils/__init__.py +0 -0
  589. synkit/Utils/utils.py +172 -0
  590. synkit/Vis/__init__.py +91 -0
  591. synkit/Vis/crn/__init__.py +40 -0
  592. synkit/Vis/epd/__init__.py +20 -0
  593. synkit/Vis/epd/arrows.py +425 -0
  594. synkit/Vis/epd/chem.py +197 -0
  595. synkit/Vis/epd/constants.py +83 -0
  596. synkit/Vis/epd/layout.py +283 -0
  597. synkit/Vis/epd/mapping.py +51 -0
  598. synkit/Vis/epd/models.py +136 -0
  599. synkit/Vis/epd/render.py +543 -0
  600. synkit/Vis/epd/utils.py +108 -0
  601. synkit/Vis/epd/visualizer.py +811 -0
  602. synkit/Vis/graph_visualizer.py +375 -0
  603. synkit/Vis/its/__init__.py +19 -0
  604. synkit/Vis/its/drawer.py +615 -0
  605. synkit/Vis/its_drawer.py +35 -0
  606. synkit/Vis/molecule/__init__.py +31 -0
  607. synkit/Vis/molecule/drawer.py +563 -0
  608. synkit/Vis/molecule/reaction.py +285 -0
  609. synkit/Vis/molecule_drawer.py +33 -0
  610. synkit/Vis/mtg/__init__.py +17 -0
  611. synkit/Vis/mtg/drawer.py +769 -0
  612. synkit/Vis/mtg_drawer.py +34 -0
  613. synkit/Vis/pdf_writer.py +146 -0
  614. synkit/Vis/reaction/__init__.py +19 -0
  615. synkit/Vis/reaction/rule.py +141 -0
  616. synkit/Vis/reaction/rxn.py +532 -0
  617. synkit/Vis/reaction_drawer.py +41 -0
  618. synkit/Vis/space/__init__.py +17 -0
  619. synkit/Vis/space/chemical.py +80 -0
  620. synkit/Vis/space/embedding.py +87 -0
  621. synkit/Vis/vis_synedu/Vis/__init__.py +7 -0
  622. synkit/Vis/vis_synedu/Vis/dpo.py +862 -0
  623. synkit/Vis/vis_synedu/rxn_vis.py +377 -0
  624. synkit/Vis/vis_synedu/vis.py +501 -0
  625. synkit/Vis/visual_drawer.py +215 -0
  626. synkit/Vis/visual_model.py +520 -0
  627. synkit/__init__.py +3 -0
  628. synkit/_native.py +91 -0
  629. synkit/examples.py +50 -0
  630. synkit/version.py +23 -0
  631. synkit-1.6.5.dist-info/METADATA +156 -0
  632. synkit-1.6.5.dist-info/RECORD +636 -0
  633. synkit-1.6.5.dist-info/WHEEL +4 -0
  634. synkit-1.6.5.dist-info/licenses/LICENSE +21 -0
  635. synkit-1.6.5.dist-info/licenses/synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/COPYRIGHT +44 -0
  636. synkit-1.6.5.dist-info/licenses/synkit/Chem/Mapper/solvers/native/cpp/src/symmetry/vendor/nauty/LICENSE-2.0.txt +202 -0
@@ -0,0 +1,1771 @@
1
+ /*****************************************************************************
2
+ * *
3
+ * Sparse-graph-specific auxiliary source file for version 2.9 of nauty. *
4
+ * *
5
+ * Subject to waivers and disclaimers in the file COPYRIGHT. *
6
+ * *
7
+ * CHANGE HISTORY *
8
+ * 26-Oct-04 : initial creation *
9
+ * 23-Nov-06 : dispatch uses targetcell_sg, not bestcell_sg *
10
+ * 8-Dec-06 : add adjacencies_sg() *
11
+ * 10-Nov-09 : remove types shortish and permutation *
12
+ * 14-Nov-09 : added copy_sg() *
13
+ * 11-May-10 : use sorttemplates.c for sorting procedures *
14
+ * 19-May-10 : add two *_tr procedures for traces. *
15
+ * 21-May-10 : fixes for nde,v fields becoming size_t *
16
+ * 23-May-10 : add sparsenauty() *
17
+ * 15-Jan-12 : add TLS_ATTR attributes *
18
+ * 17-Dec-15 : extend sortlists_sg() to sort weights *
19
+ * : add weights to copy_sg() and updatecan_sg() *
20
+ * 11-Mar-16 : add cleanup_sg(). This can be used in the cleanup *
21
+ * field of the dispatch vector to sort the lists of the *
22
+ * canonical graph, but isn't there by default. *
23
+ * 15-Oct-19 : fix static declaration of snwork[] *
24
+ * 6-Apr-21 : increase work space in sparsenauty() *
25
+ * 16-Nov-22 : fix an error in the Traces utility comparelab_tr() *
26
+ * *
27
+ *****************************************************************************/
28
+
29
+ #define TMP
30
+
31
+ /* #define ONE_WORD_SETS not sure about this! See notes.txt. */
32
+ #include "nausparse.h"
33
+
34
+ /* macros for hash-codes: */
35
+ #define MASH(l,i) ((((l) ^ 065435) + (i)) & 077777)
36
+ /* : expression whose long value depends only on long l and int/long i.
37
+ Anything goes, preferably non-commutative. */
38
+
39
+ #define CLEANUP(l) ((int)((l) % 077777))
40
+ /* : expression whose value depends on long l and is less than 077777
41
+ when converted to int then short. Anything goes. */
42
+
43
+ #if MAXM==1
44
+ #define M 1
45
+ #else
46
+ #define M m
47
+ #endif
48
+
49
+ #define ACCUM(x,y) x = (((x) + (y)) & 077777)
50
+
51
+ static const int fuzz1[] = {037541,061532,005257,026416};
52
+ static const int fuzz2[] = {006532,070236,035523,062437};
53
+
54
+ #define FUZZ1(x) ((x) ^ fuzz1[(x)&3])
55
+ #define FUZZ2(x) ((x) ^ fuzz2[(x)&3])
56
+
57
+ /* aproto: header new_nauty_protos.h */
58
+
59
+ dispatchvec dispatch_sparse =
60
+ {isautom_sg,testcanlab_sg,updatecan_sg,refine_sg,refine_sg,cheapautom_sg,
61
+ targetcell_sg,nausparse_freedyn,nausparse_check,init_sg,NULL};
62
+
63
+ #if !MAXN
64
+ DYNALLSTAT(short,vmark1,vmark1_sz);
65
+ DYNALLSTAT(short,vmark2,vmark2_sz);
66
+ DYNALLSTAT(int,work1,work1_sz);
67
+ DYNALLSTAT(int,work2,work2_sz);
68
+ DYNALLSTAT(int,work3,work3_sz);
69
+ DYNALLSTAT(int,work4,work4_sz);
70
+ DYNALLSTAT(set,snwork,snwork_sz);
71
+ #else
72
+ static TLS_ATTR short vmark1[MAXN];
73
+ static TLS_ATTR short vmark2[MAXN];
74
+ static TLS_ATTR int work1[MAXN];
75
+ static TLS_ATTR int work2[MAXN];
76
+ static TLS_ATTR int work3[MAXN];
77
+ static TLS_ATTR int work4[MAXN];
78
+ static TLS_ATTR set snwork[2*500*MAXM];
79
+ #endif
80
+
81
+ static TLS_ATTR short vmark1_val = 32000;
82
+ #define MARK1(i) vmark1[i] = vmark1_val
83
+ #define UNMARK1(i) vmark1[i] = 0
84
+ #define ISMARKED1(i) (vmark1[i] == vmark1_val)
85
+ #define ISNOTMARKED1(i) (vmark1[i] != vmark1_val)
86
+
87
+ static TLS_ATTR short vmark2_val = 32000;
88
+ #define MARK2(i) vmark2[i] = vmark2_val
89
+ #define UNMARK2(i) vmark2[i] = 0
90
+ #define ISMARKED2(i) (vmark2[i] == vmark2_val)
91
+ #define ISNOTMARKED2(i) (vmark2[i] != vmark2_val)
92
+
93
+ #if !MAXN
94
+ #define RESETMARKS1 {if (vmark1_val++ >= 32000) \
95
+ {size_t ij; for (ij=0;ij<vmark1_sz;++ij) vmark1[ij]=0; vmark1_val=1;}}
96
+ #define PREPAREMARKS1(nn) preparemarks1(nn)
97
+ #define RESETMARKS2 {if (vmark2_val++ >= 32000) \
98
+ {size_t ij; for (ij=0;ij<vmark2_sz;++ij) vmark2[ij]=0; vmark2_val=1;}}
99
+ #define PREPAREMARKS2(nn) preparemarks2(nn)
100
+ #else
101
+ #define RESETMARKS1 {if (vmark1_val++ >= 32000) \
102
+ {size_t ij; for (ij=0;ij<MAXN;++ij) vmark1[ij]=0; vmark1_val=1;}}
103
+ #define PREPAREMARKS1(nn)
104
+ #define RESETMARKS2 {if (vmark2_val++ >= 32000) \
105
+ {size_t ij; for (ij=0;ij<MAXN;++ij) vmark2[ij]=0; vmark2_val=1;}}
106
+ #define PREPAREMARKS2(nn)
107
+ #endif
108
+
109
+ /*****************************************************************************
110
+ * *
111
+ * preparemarks1(N) and preparemarks2(N) *
112
+ * make vmarks array large enough to mark 0..N-1 and such that *
113
+ * the next RESETMARKS command will work correctly *
114
+ * *
115
+ *****************************************************************************/
116
+
117
+ #if !MAXN
118
+ static void
119
+ preparemarks1(size_t nn)
120
+ {
121
+ size_t oldsize;
122
+ short *oldpos;
123
+
124
+ oldsize = vmark1_sz;
125
+ oldpos = vmark1;
126
+ DYNALLOC1(short,vmark1,vmark1_sz,nn,"preparemarks");
127
+ if (vmark1_sz != oldsize || vmark1 != oldpos) vmark1_val = 32000;
128
+ }
129
+ #endif
130
+
131
+ #if !MAXN
132
+ static void
133
+ preparemarks2(size_t nn)
134
+ {
135
+ size_t oldsize;
136
+ short *oldpos;
137
+
138
+ oldsize = vmark2_sz;
139
+ oldpos = vmark2;
140
+ DYNALLOC1(short,vmark2,vmark2_sz,nn,"preparemarks");
141
+ if (vmark2_sz != oldsize || vmark2 != oldpos) vmark2_val = 32000;
142
+ }
143
+ #endif
144
+
145
+ /*****************************************************************************
146
+ * *
147
+ * isautom_sg(g,perm,digraph,m,n) = TRUE iff perm is an automorphism of g *
148
+ * (i.e., g^perm = g). Symmetry is assumed unless digraph = TRUE. *
149
+ * *
150
+ *****************************************************************************/
151
+
152
+ boolean
153
+ isautom_sg(graph *g, int *p, boolean digraph, int m, int n)
154
+ {
155
+ int *d,*e;
156
+ size_t *v;
157
+ int i,pi,di;
158
+ size_t vi,vpi,j;
159
+
160
+ SG_VDE(g,v,d,e);
161
+
162
+ PREPAREMARKS1(n);
163
+
164
+ for (i = 0; i < n; ++i)
165
+ if (p[i] != i || digraph)
166
+ {
167
+ pi = p[i];
168
+ di = d[i];
169
+ if (d[pi] != di) return FALSE;
170
+
171
+ vi = v[i];
172
+ vpi = v[pi];
173
+ RESETMARKS1;
174
+ for (j = 0; j < di; ++j) MARK1(p[e[vi+j]]);
175
+ for (j = 0; j < di; ++j) if (ISNOTMARKED1(e[vpi+j])) return FALSE;
176
+ }
177
+
178
+ return TRUE;
179
+ }
180
+
181
+ /*****************************************************************************
182
+ * *
183
+ * aresame_sg(g1,g2) = TRUE iff g1 and g2 are identical as labelled digraphs *
184
+ * *
185
+ *****************************************************************************/
186
+
187
+ boolean
188
+ aresame_sg(sparsegraph *g1, sparsegraph *g2)
189
+ {
190
+ int *d1,*e1;
191
+ int *d2,*e2;
192
+ int n,i,di;
193
+ size_t vi,*v1,*v2,j;
194
+
195
+ n = g1->nv;
196
+ if (g2->nv != n || g2->nde != g1->nde) return FALSE;
197
+
198
+ SG_VDE(g1,v1,d1,e1);
199
+ SG_VDE(g2,v2,d2,e2);
200
+
201
+ PREPAREMARKS1(n);
202
+
203
+ for (i = 0; i < n; ++i)
204
+ {
205
+ di = d1[i];
206
+ if (d2[i] != di) return FALSE;
207
+
208
+ vi = v1[i];
209
+ RESETMARKS1;
210
+ for (j = 0; j < di; ++j) MARK1(e1[vi+j]);
211
+ vi = v2[i];
212
+ for (j = 0; j < di; ++j) if (ISNOTMARKED1(e2[vi+j])) return FALSE;
213
+ }
214
+
215
+ return TRUE;
216
+ }
217
+
218
+ /*****************************************************************************
219
+ * *
220
+ * testcanlab_sg(g,canong,lab,samerows,m,n) compares g^lab to canong, *
221
+ * using an ordering which is immaterial since it's only used here. The *
222
+ * value returned is -1,0,1 if g^lab <,=,> canong. *samerows is set to *
223
+ * the number of rows (0..n) of canong which are the same as those of g^lab. *
224
+ * *
225
+ *****************************************************************************/
226
+
227
+ int
228
+ testcanlab_sg(graph *g, graph *canong, int *lab, int *samerows, int m, int n)
229
+ {
230
+ int *d,*e;
231
+ int *cd,*ce;
232
+ int i,k,di,dli;
233
+ size_t j,vi,vli,*v,*cv;
234
+ int mina;
235
+
236
+ SG_VDE(g,v,d,e);
237
+ SG_VDE(canong,cv,cd,ce);
238
+
239
+ #if !MAXN
240
+ DYNALLOC1(int,work1,work1_sz,n,"testcanlab_sg");
241
+ #endif
242
+ #define INVLAB work1
243
+
244
+ PREPAREMARKS1(n);
245
+
246
+ for (i = 0; i < n; ++i) INVLAB[lab[i]] = i;
247
+
248
+ for (i = 0; i < n; ++i)
249
+ {
250
+ /* compare g[lab[i]]^INVLAB to canong[i] */
251
+ vi = cv[i];
252
+ di = cd[i];
253
+ vli = v[lab[i]];
254
+ dli = d[lab[i]];
255
+
256
+ if (di != dli)
257
+ {
258
+ *samerows = i;
259
+ if (di < dli) return -1;
260
+ return 1;
261
+ }
262
+
263
+ RESETMARKS1;
264
+ mina = n;
265
+ for (j = 0; j < di; ++j) MARK1(ce[vi+j]);
266
+ for (j = 0; j < di; ++j)
267
+ {
268
+ k = INVLAB[e[vli+j]];
269
+ if (ISMARKED1(k)) UNMARK1(k);
270
+ else if (k < mina) mina = k;
271
+ }
272
+ if (mina != n)
273
+ {
274
+ *samerows = i;
275
+ for (j = 0; j < di; ++j)
276
+ {
277
+ k = ce[vi+j];
278
+ if (ISMARKED1(k) && k < mina) return -1;
279
+ }
280
+ return 1;
281
+ }
282
+ }
283
+
284
+ *samerows = n;
285
+ return 0;
286
+ }
287
+
288
+ /*****************************************************************************
289
+ * *
290
+ * updatecan_sg(g,canong,lab,samerows,m,n) sets canong = g^lab, assuming *
291
+ * the first samerows vertices of canong are ok already. Also assumes *
292
+ * contiguity and ample space in canong. *
293
+ * *
294
+ *****************************************************************************/
295
+
296
+ void
297
+ updatecan_sg(graph *g, graph *canong, int *lab, int samerows, int m, int n)
298
+ {
299
+ int *d,*e;
300
+ int *cd,*ce;
301
+ int i,dli;
302
+ size_t *v,*cv,vli,j,k;
303
+ sg_weight *wt,*cwt;
304
+
305
+ SWG_VDE(g,v,d,e,wt);
306
+ SWG_VDE(canong,cv,cd,ce,cwt);
307
+
308
+ #if !MAXN
309
+ DYNALLOC1(int,work1,work1_sz,n,"testcanlab_sg");
310
+ #endif
311
+ #define INVLAB work1
312
+
313
+ ((sparsegraph*)canong)->nv = n;
314
+ ((sparsegraph*)canong)->nde = ((sparsegraph*)g)->nde;
315
+
316
+ for (i = 0; i < n; ++i) INVLAB[lab[i]] = i;
317
+
318
+ if (samerows == 0) k = 0;
319
+ else k = cv[samerows-1]+cd[samerows-1];
320
+
321
+ for (i = samerows; i < n; ++i)
322
+ {
323
+ cv[i] = k;
324
+ cd[i] = dli = d[lab[i]];
325
+ vli = v[lab[i]];
326
+ if (wt)
327
+ {
328
+ for (j = 0; j < dli; ++j)
329
+ {
330
+ ce[k] = INVLAB[e[vli+j]];
331
+ cwt[k] = wt[vli+j];
332
+ ++k;
333
+ }
334
+ }
335
+ else
336
+ for (j = 0; j < dli; ++j) ce[k++] = INVLAB[e[vli+j]];
337
+ }
338
+ }
339
+
340
+ /*****************************************************************************
341
+ * *
342
+ * comparelab_tr(g,lab1,invlab1,lab2,invlab2,cls,col) compares *
343
+ * g^lab1 to g^lab2 and returns -1,0,1 according to the comparison. *
344
+ * invlab1[] and invlab2[] are assumed to hold inverses of lab1,lab2. *
345
+ * *
346
+ *****************************************************************************/
347
+
348
+ int
349
+ comparelab_tr(sparsegraph *g,
350
+ int *lab1, int *invlab1, int *lab2, int *invlab2, int *cls, int *col)
351
+ {
352
+ int d1,*e1,d2,*e2;
353
+ int i,j,k,n,c,end;
354
+ int mina;
355
+
356
+ n = g->nv;
357
+
358
+ #if !MAXN
359
+ DYNALLOC1(int,work1,work1_sz,n,"comparelab_tr");
360
+ #endif
361
+ #define NGHCOUNTS work1
362
+
363
+ memset(NGHCOUNTS,0,n*sizeof(int));
364
+ for (c=0; c<n; c+=cls[c])
365
+ {
366
+ if (cls[c] == 1)
367
+ {
368
+ end = c+cls[c];
369
+ for (i = c; i < end; ++i)
370
+ {
371
+ e1 = g->e + g->v[lab1[i]];
372
+ d1 = g->d[lab1[i]];
373
+ e2 = g->e + g->v[lab2[i]];
374
+ d2 = g->d[lab2[i]];
375
+ if (d1 < d2) return -1;
376
+ else if (d1 > d2) return 1;
377
+
378
+ mina = n;
379
+ for (j = 0; j < d1; ++j) {
380
+ (NGHCOUNTS[col[invlab1[e1[j]]]])++;
381
+ }
382
+ for (j = 0; j < d1; ++j)
383
+ {
384
+ k = col[invlab2[e2[j]]];
385
+ if (NGHCOUNTS[k]) {
386
+ (NGHCOUNTS[k])--;
387
+ }
388
+ else {
389
+ if (k < mina) mina = k;
390
+ }
391
+ }
392
+ if (mina != n)
393
+ {
394
+ for (j = 0; j < d1; ++j)
395
+ {
396
+ k = col[invlab1[e1[j]]];
397
+ if (NGHCOUNTS[k] && k < mina) return -1;
398
+ }
399
+ return 1;
400
+ }
401
+ }
402
+ }
403
+ }
404
+
405
+ return 0;
406
+ }
407
+
408
+ /*****************************************************************************
409
+ * *
410
+ * testcanlab_tr(g,canong,lab,invlab,samerows) compares g^lab to canong, *
411
+ * using an ordering which is immaterial since it's only used here. The *
412
+ * value returned is -1,0,1 if g^lab <,=,> canong. *samerows is set to *
413
+ * the number of rows (0..n) of canong which are the same as those of g^lab. *
414
+ * invlab[] is assumed to hold the inverse of lab[] *
415
+ * *
416
+ *****************************************************************************/
417
+
418
+ int
419
+ testcanlab_tr(sparsegraph *g, sparsegraph *canong,
420
+ int *lab, int *invlab, int *samerows)
421
+ {
422
+ int *d,*e;
423
+ int *cd,*ce;
424
+ int i,di,dli;
425
+ int k,n;
426
+ size_t *v,*cv,vi,vli,j;
427
+ int mina;
428
+
429
+ SG_VDE(g,v,d,e);
430
+ SG_VDE(canong,cv,cd,ce);
431
+ n = g->nv;
432
+
433
+ PREPAREMARKS1(n);
434
+
435
+ for (i = 0; i < n; ++i)
436
+ {
437
+ /* compare g[lab[i]]^invlab to canong[i] */
438
+ vi = cv[i];
439
+ di = cd[i];
440
+ vli = v[lab[i]];
441
+ dli = d[lab[i]];
442
+
443
+ if (di != dli)
444
+ {
445
+ *samerows = i;
446
+ if (di < dli) return -1;
447
+ return 1;
448
+ }
449
+
450
+ RESETMARKS1;
451
+ mina = n;
452
+ for (j = 0; j < di; ++j) MARK1(ce[vi+j]);
453
+
454
+ for (j = 0; j < di; ++j)
455
+ {
456
+ k = invlab[e[vli+j]];
457
+ if (ISMARKED1(k)) UNMARK1(k);
458
+ else if (k < mina) mina = k;
459
+ }
460
+ if (mina != n)
461
+ {
462
+ *samerows = i;
463
+ for (j = 0; j < di; ++j)
464
+ {
465
+ k = ce[vi+j];
466
+ if (ISMARKED1(k) && k < mina) return -1;
467
+ }
468
+ return 1;
469
+ }
470
+ }
471
+
472
+ *samerows = n;
473
+ return 0;
474
+ }
475
+
476
+ /*****************************************************************************
477
+ * *
478
+ * updatecan_tr(g,canong,lab,invlab,samerows) sets canong = g^lab, *
479
+ * assuming the first samerows vertices of canong are ok already. *
480
+ * Also assumes contiguity and ample space in canong. *
481
+ * Assumes invlab[] holds the inverse of lab[] *
482
+ * *
483
+ *****************************************************************************/
484
+
485
+ void
486
+ updatecan_tr(sparsegraph *g, sparsegraph *canong,
487
+ int *lab, int *invlab, int samerows)
488
+ {
489
+ int *d,*e;
490
+ int *cd,*ce;
491
+ int i,dli,n;
492
+ size_t *v,*cv,vli,j,k;
493
+
494
+ SG_VDE(g,v,d,e);
495
+ SG_VDE(canong,cv,cd,ce);
496
+ n = g->nv;
497
+
498
+ PREPAREMARKS1(n);
499
+
500
+ canong->nv = n;
501
+ canong->nde = g->nde;
502
+
503
+ if (samerows == 0) k = 0;
504
+ else k = cv[samerows-1]+cd[samerows-1];
505
+
506
+ for (i = samerows; i < n; ++i)
507
+ {
508
+ cv[i] = k;
509
+ cd[i] = dli = d[lab[i]];
510
+ vli = v[lab[i]];
511
+ for (j = 0; j < dli; ++j) ce[k++] = invlab[e[vli+j]];
512
+ }
513
+ }
514
+
515
+ #define SORT_OF_SORT 3
516
+ #define SORT_NAME sortindirect
517
+ #define SORT_TYPE1 int
518
+ #define SORT_TYPE2 int
519
+ #include "sorttemplates.c"
520
+
521
+ #define SORT_OF_SORT 1
522
+ #define SORT_NAME sortints
523
+ #define SORT_TYPE1 int
524
+ #include "sorttemplates.c"
525
+
526
+ #define SORT_OF_SORT 2
527
+ #define SORT_NAME sortweights
528
+ #define SORT_TYPE1 int
529
+ #define SORT_TYPE2 sg_weight
530
+ #include "sorttemplates.c"
531
+
532
+ /*****************************************************************************
533
+ * *
534
+ * init_sg(graph *gin, graph **gout, graph *hin, graph **hout, *
535
+ * int *lab, int *ptn, set *active, optionblk *options, *
536
+ * int *status, int m, int n) *
537
+ * Initialise routine for dispatch vector. This one just makes sure *
538
+ * that *hin has enough space and sets fields for n=0. *
539
+ * *
540
+ *****************************************************************************/
541
+
542
+ void
543
+ init_sg(graph *gin, graph **gout, graph *hin, graph **hout, int *lab,
544
+ int *ptn, set *active, struct optionstruct *options, int *status,
545
+ int m, int n)
546
+ {
547
+ sparsegraph *sg,*sh;
548
+
549
+ if (options->getcanon)
550
+ {
551
+ sg = (sparsegraph*)gin;
552
+ sh = (sparsegraph*)hin;
553
+ SG_ALLOC(*sh,sg->nv,sg->nde,"init_sg");
554
+ sh->nv = sg->nv;
555
+ sh->nde = sg->nde;
556
+ }
557
+ *status = 0;
558
+ }
559
+
560
+ /*****************************************************************************
561
+ * *
562
+ * cleanup_sg(graph *gin, graph **gout, graph *hin, graph **hout, *
563
+ * int *lab, int *ptn, optionblk *options, *
564
+ * statsblk *stats, int m, int n) *
565
+ * Cleanup routine for dispatch vector. This one sorts the adjacency *
566
+ * lists for the canonical labelling. *
567
+ * *
568
+ *****************************************************************************/
569
+
570
+ void
571
+ cleanup_sg(graph *gin, graph **gout, graph *hin, graph **hout, int *lab,
572
+ int *ptn, optionblk *options, statsblk *stats, int m, int n)
573
+ {
574
+ sparsegraph *sh;
575
+
576
+ if (options->getcanon
577
+ && (stats->errstatus == 0 || stats->errstatus == NAUABORTED))
578
+ {
579
+ sh = (sparsegraph*)hin;
580
+ sortlists_sg(sh);
581
+ }
582
+ }
583
+
584
+ /*****************************************************************************
585
+ * *
586
+ * distvals(sparsegraph *sg, int v0, int *dist, int n) sets dist[i] *
587
+ * to the distance from v0 to i, for each i, or to n if there is no such *
588
+ * distance. work4[] is used as a queue. *
589
+ * *
590
+ *****************************************************************************/
591
+
592
+ void
593
+ distvals(sparsegraph *g, int v0, int *dist, int n)
594
+ {
595
+ int *d,*e;
596
+ int i,head,tail;
597
+ int di,k;
598
+ size_t *v,vi,j;
599
+
600
+ SG_VDE(g,v,d,e);
601
+ #if !MAXN
602
+ DYNALLOC1(int,work4,work4_sz,n,"distvals");
603
+ #endif
604
+ #define QUEUE work4
605
+
606
+ for (i = 0; i < n; ++i) dist[i] = n;
607
+
608
+ QUEUE[0] = v0;
609
+ dist[v0] = 0;
610
+
611
+ head = 0;
612
+ tail = 1;
613
+ while (tail < n && head < tail)
614
+ {
615
+ i = QUEUE[head++];
616
+ vi = v[i];
617
+ di = d[i];
618
+ for (j = 0; j < di; ++j)
619
+ {
620
+ k = e[vi+j];
621
+ if (dist[k] == n)
622
+ {
623
+ dist[k] = dist[i] + 1;
624
+ QUEUE[tail++] = k;
625
+ }
626
+ }
627
+ }
628
+ }
629
+
630
+ /*****************************************************************************
631
+ * *
632
+ * refine_sg(g,lab,ptn,level,numcells,count,active,code,m,n) performs a *
633
+ * refinement operation on the partition at the specified level of the *
634
+ * partition nest (lab,ptn). *numcells is assumed to contain the number of *
635
+ * cells on input, and is updated. The initial set of active cells (alpha *
636
+ * in the paper) is specified in the set active. Precisely, x is in active *
637
+ * iff the cell starting at index x in lab is active. *
638
+ * The resulting partition is equitable if active is correct (see the paper *
639
+ * and the Guide). *
640
+ * *code is set to a value which depends on the fine detail of the *
641
+ * algorithm, but which is independent of the labelling of the graph. *
642
+ * count is used for work space. *
643
+ * *
644
+ *****************************************************************************/
645
+
646
+ void
647
+ refine_sg(graph *g, int *lab, int *ptn, int level, int *numcells,
648
+ int *count, set *active, int *code, int m, int n)
649
+ {
650
+ int i,j,k,l,v1,v2,v3,isplit;
651
+ int w1,w2,w3;
652
+ long longcode;
653
+ int *d,*e;
654
+ int size,bigsize,bigpos;
655
+ int nactive,hitcells;
656
+ int lj,di,splitv;
657
+ boolean trivsplit;
658
+ size_t *v,vi,ii;
659
+
660
+ SG_VDE(g,v,d,e);
661
+
662
+ #if !MAXN
663
+ DYNALLOC1(int,work1,work1_sz,n,"refine_sg");
664
+ DYNALLOC1(int,work2,work2_sz,n,"refine_sg");
665
+ DYNALLOC1(int,work3,work3_sz,n,"refine_sg");
666
+ DYNALLOC1(int,work4,work4_sz,n,"refine_sg");
667
+ #endif
668
+ #define CELLSTART work1
669
+ #define ACTIVE work2
670
+ #define HITS work3
671
+ #define HITCELL work4
672
+
673
+ PREPAREMARKS1(n);
674
+ PREPAREMARKS2(n);
675
+
676
+ longcode = *numcells;
677
+
678
+ /* Set ACTIVE[0..nactive-1] = queue of active cell starts */
679
+
680
+ nactive = 0;
681
+ for (i = -1; (i = nextelement(active,m,i)) >= 0;)
682
+ ACTIVE[nactive++] = i;
683
+
684
+ if (nactive == 0)
685
+ {
686
+ *code = CLEANUP(longcode);
687
+ return;
688
+ }
689
+
690
+ /* Set CELLSTART[i] = starting point in lab[] of nontrivial cell
691
+ containing i, or n if i is a singleton */
692
+
693
+ for (i = 0; i < n; )
694
+ {
695
+ /* Just here, i is a cell starting position */
696
+ if (ptn[i] <= level)
697
+ {
698
+ CELLSTART[lab[i]] = n;
699
+ ++i;
700
+ }
701
+ else
702
+ {
703
+ j = i;
704
+ do
705
+ {
706
+ CELLSTART[lab[i]] = j;
707
+ } while (ptn[i++] > level);
708
+ }
709
+ }
710
+
711
+ if (level <= 2 && nactive == 1 && ptn[ACTIVE[0]] <= level
712
+ && *numcells <= n/8)
713
+ {
714
+ isplit = ACTIVE[--nactive];
715
+ DELELEMENT(active,isplit);
716
+
717
+ distvals((sparsegraph*)g,lab[isplit],HITS,n);
718
+
719
+ for (v1 = 0; v1 < n; )
720
+ {
721
+ if (ptn[v1] <= level)
722
+ {
723
+ ++v1;
724
+ continue;
725
+ }
726
+
727
+ longcode = MASH(longcode,v1);
728
+ w1 = HITS[lab[v1]];
729
+
730
+ v2 = v1+1;
731
+ while (ptn[v2-1] > level && HITS[lab[v2]] == w1) ++v2;
732
+
733
+ if (ptn[v2-1] <= level)
734
+ {
735
+ v1 = v2;
736
+ continue;
737
+ }
738
+
739
+ w2 = NAUTY_INFINITY;
740
+ v3 = j = v2;
741
+
742
+ do
743
+ {
744
+ lj = lab[j];
745
+ w3 = HITS[lj];
746
+ if (w3 == w1)
747
+ {
748
+ lab[j] = lab[v3];
749
+ lab[v3] = lab[v2];
750
+ lab[v2] = lj;
751
+ ++v2;
752
+ ++v3;
753
+ }
754
+ else if (w3 == w2)
755
+ {
756
+ lab[j] = lab[v3];
757
+ lab[v3] = lj;
758
+ ++v3;
759
+ }
760
+ else if (w3 < w1)
761
+ {
762
+ lab[j] = lab[v2];
763
+ lab[v2] = lab[v1];
764
+ lab[v1] = lj;
765
+ v3 = v2 + 1;
766
+ v2 = v1 + 1;
767
+ w2 = w1;
768
+ w1 = w3;
769
+ }
770
+ else if (w3 < w2)
771
+ {
772
+ lab[j] = lab[v2];
773
+ lab[v2] = lj;
774
+ v3 = v2 + 1;
775
+ w2 = w3;
776
+ }
777
+ } while (ptn[j++] > level);
778
+
779
+ longcode = MASH(longcode,w2);
780
+ longcode = MASH(longcode,v2);
781
+ if (j != v2) /* At least two fragments
782
+ * v1..v2-1 = w1; v2..v3-1 = w2 */
783
+ {
784
+ if (v2 == v1+1)
785
+ CELLSTART[lab[v1]] = n;
786
+
787
+ if (v3 == v2+1)
788
+ CELLSTART[lab[v2]] = n;
789
+ else
790
+ for (k = v2; k < v3; ++k)
791
+ CELLSTART[lab[k]] = v2;
792
+ ++*numcells;
793
+ ptn[v2-1] = level;
794
+
795
+ if (j == v3)
796
+ {
797
+ /* Two fragments only */
798
+ if (v2-v1 <= v3-v2 && !ISELEMENT(active,v1))
799
+ {
800
+ ADDELEMENT(active,v1);
801
+ ACTIVE[nactive++] = v1;
802
+ }
803
+ else
804
+ {
805
+ ADDELEMENT(active,v2);
806
+ ACTIVE[nactive++] = v2;
807
+ }
808
+ }
809
+ else
810
+ {
811
+ /* Extra fragments: v3..j-1 > w2 */
812
+ sortindirect(lab+v3,HITS,j-v3);
813
+ ACTIVE[nactive++] = v2;
814
+ ADDELEMENT(active,v2);
815
+ if (v2-v1 >= v3-v2)
816
+ {
817
+ bigpos = -1;
818
+ bigsize = v2-v1;
819
+ }
820
+ else
821
+ {
822
+ bigpos = nactive-1;
823
+ bigsize = v3-v2;
824
+ }
825
+ for (k = v3-1; k < j-1;)
826
+ {
827
+ ptn[k] = level;
828
+ longcode = MASH(longcode,k);
829
+ ++*numcells;
830
+ l = k+1;
831
+ ADDELEMENT(active,l);
832
+ ACTIVE[nactive++] = l;
833
+ w3 = HITS[lab[l]];
834
+ for (k = l; k < j-1
835
+ && HITS[lab[k+1]] == w3; ++k)
836
+ CELLSTART[lab[k+1]] = l;
837
+ size = k-l+1;
838
+ if (size == 1)
839
+ CELLSTART[lab[l]] = n;
840
+ else
841
+ {
842
+ CELLSTART[lab[l]] = l;
843
+ if (size > bigsize)
844
+ {
845
+ bigsize = size;
846
+ bigpos = nactive-1;
847
+ }
848
+ }
849
+ }
850
+
851
+ if (bigpos >= 0 && !ISELEMENT(active,v1))
852
+ {
853
+ longcode = MASH(longcode,bigpos);
854
+ DELELEMENT(active,ACTIVE[bigpos]);
855
+ ADDELEMENT(active,v1);
856
+ ACTIVE[bigpos] = v1;
857
+ }
858
+ }
859
+ }
860
+ v1 = j;
861
+ }
862
+ }
863
+
864
+ /* Iterate until complete */
865
+ while (nactive > 0 && *numcells < n)
866
+ {
867
+ for (i = 0; i < nactive && i < 10; ++i)
868
+ if (ptn[ACTIVE[i]] <= level) break;
869
+
870
+ if (i < nactive && i < 10)
871
+ {
872
+ trivsplit = TRUE;
873
+ isplit = ACTIVE[i];
874
+ ACTIVE[i] = ACTIVE[--nactive];
875
+ }
876
+ else
877
+ {
878
+ isplit = ACTIVE[--nactive];
879
+ trivsplit = ptn[isplit] <= level;
880
+ }
881
+
882
+ DELELEMENT(active,isplit);
883
+ longcode = MASH(longcode,isplit);
884
+
885
+ if (trivsplit)
886
+ {
887
+ RESETMARKS1;
888
+ RESETMARKS2;
889
+ hitcells = 0;
890
+ splitv = lab[isplit];
891
+ vi = v[splitv];
892
+ di = d[splitv];
893
+ for (ii = 0; ii < di; ++ii)
894
+ {
895
+ j = e[vi+ii];
896
+ MARK2(j);
897
+ k = CELLSTART[j];
898
+ if (k != n && ISNOTMARKED1(k))
899
+ {
900
+ MARK1(k);
901
+ HITCELL[hitcells++] = k;
902
+ }
903
+ }
904
+
905
+ if (hitcells > 1) sortints(HITCELL,hitcells);
906
+ longcode = MASH(longcode,hitcells);
907
+
908
+ /* divide cells according to which vertices are hit */
909
+
910
+ for (i = 0; i < hitcells; ++i)
911
+ {
912
+ j = v1 = v2 = HITCELL[i];
913
+ longcode = MASH(longcode,v2);
914
+ k = 0;
915
+ do
916
+ {
917
+ lj = lab[j];
918
+ if (ISMARKED2(lj))
919
+ HITS[k++] = lj;
920
+ else
921
+ lab[v2++] = lj;
922
+ } while (ptn[j++] > level);
923
+
924
+ longcode = MASH(longcode,k);
925
+ v3 = v2;
926
+ while (--k >= 0)
927
+ {
928
+ j = HITS[k];
929
+ CELLSTART[j] = v2;
930
+ lab[v3++] = j;
931
+ }
932
+
933
+ if (v2 != v3 && v2 != v1)
934
+ {
935
+ ++*numcells;
936
+ if (v2 == v1+1) CELLSTART[lab[v1]] = n;
937
+ if (v3 == v2+1) CELLSTART[lab[v2]] = n;
938
+ ptn[v2-1] = level;
939
+ longcode = MASH(longcode,v2);
940
+ if (v2-v1 <= v3-v2 && !ISELEMENT(active,v1))
941
+ {
942
+ ADDELEMENT(active,v1);
943
+ ACTIVE[nactive++] = v1;
944
+ }
945
+ else
946
+ {
947
+ ADDELEMENT(active,v2);
948
+ ACTIVE[nactive++] = v2;
949
+ }
950
+ }
951
+ }
952
+ }
953
+ else /* non-trivial splitting */
954
+ {
955
+ /* isplit is the start of the splitting cell.
956
+ Set HITS[i] = hits of i for i in non-trivial cells,
957
+ HITCELL[0..hitcells-1] = starts of hit non-trivial cells */
958
+
959
+ RESETMARKS1;
960
+ hitcells = 0;
961
+ do
962
+ {
963
+ vi = v[lab[isplit]];
964
+ di = d[lab[isplit]];
965
+ for (ii = 0; ii < di; ++ii)
966
+ {
967
+ j = e[vi+ii];
968
+ k = CELLSTART[j];
969
+ if (k != n)
970
+ {
971
+ if (ISNOTMARKED1(k))
972
+ {
973
+ MARK1(k);
974
+ HITCELL[hitcells++] = k;
975
+ do
976
+ {
977
+ HITS[lab[k]] = 0;
978
+ } while (ptn[k++] > level);
979
+ }
980
+ ++HITS[j];
981
+ }
982
+ }
983
+ } while (ptn[isplit++] > level);
984
+
985
+ if (hitcells > 1) sortints(HITCELL,hitcells);
986
+
987
+ /* divide cells according to hit counts */
988
+
989
+ longcode = MASH(longcode,hitcells);
990
+ for (i = 0; i < hitcells; ++i)
991
+ {
992
+ v1 = HITCELL[i];
993
+ w1 = HITS[lab[v1]];
994
+ longcode = MASH(longcode,v1);
995
+
996
+ v2 = v1+1;
997
+ while (ptn[v2-1] > level && HITS[lab[v2]] == w1) ++v2;
998
+
999
+ if (ptn[v2-1] <= level) continue;
1000
+ w2 = NAUTY_INFINITY;
1001
+ v3 = j = v2;
1002
+
1003
+ do
1004
+ {
1005
+ lj = lab[j];
1006
+ w3 = HITS[lj];
1007
+ if (w3 == w1)
1008
+ {
1009
+ lab[j] = lab[v3];
1010
+ lab[v3] = lab[v2];
1011
+ lab[v2] = lj;
1012
+ ++v2;
1013
+ ++v3;
1014
+ }
1015
+ else if (w3 == w2)
1016
+ {
1017
+ lab[j] = lab[v3];
1018
+ lab[v3] = lj;
1019
+ ++v3;
1020
+ }
1021
+ else if (w3 < w1)
1022
+ {
1023
+ lab[j] = lab[v2];
1024
+ lab[v2] = lab[v1];
1025
+ lab[v1] = lj;
1026
+ v3 = v2 + 1;
1027
+ v2 = v1 + 1;
1028
+ w2 = w1;
1029
+ w1 = w3;
1030
+ }
1031
+ else if (w3 < w2)
1032
+ {
1033
+ lab[j] = lab[v2];
1034
+ lab[v2] = lj;
1035
+ v3 = v2 + 1;
1036
+ w2 = w3;
1037
+ }
1038
+ } while (ptn[j++] > level);
1039
+
1040
+ longcode = MASH(longcode,w1);
1041
+ longcode = MASH(longcode,v2);
1042
+ if (j != v2) /* At least two fragments
1043
+ * v1..v2-1 = w1; v2..v3-1 = w2 */
1044
+ {
1045
+ if (v2 == v1+1)
1046
+ CELLSTART[lab[v1]] = n;
1047
+
1048
+ if (v3 == v2+1)
1049
+ CELLSTART[lab[v2]] = n;
1050
+ else
1051
+ for (k = v2; k < v3; ++k)
1052
+ CELLSTART[lab[k]] = v2;
1053
+ ++*numcells;
1054
+ ptn[v2-1] = level;
1055
+
1056
+ if (j == v3)
1057
+ {
1058
+ /* Two fragments only */
1059
+ if (v2-v1 <= v3-v2 && !ISELEMENT(active,v1))
1060
+ {
1061
+ ADDELEMENT(active,v1);
1062
+ ACTIVE[nactive++] = v1;
1063
+ }
1064
+ else
1065
+ {
1066
+ ADDELEMENT(active,v2);
1067
+ ACTIVE[nactive++] = v2;
1068
+ }
1069
+ }
1070
+ else
1071
+ {
1072
+ /* Extra fragments: v3..j-1 > w2 */
1073
+ longcode = MASH(longcode,v3);
1074
+ sortindirect(lab+v3,HITS,j-v3);
1075
+ ACTIVE[nactive++] = v2;
1076
+ ADDELEMENT(active,v2);
1077
+ if (v2-v1 >= v3-v2)
1078
+ {
1079
+ bigpos = -1;
1080
+ bigsize = v2-v1;
1081
+ }
1082
+ else
1083
+ {
1084
+ bigpos = nactive-1;
1085
+ bigsize = v3-v2;
1086
+ longcode = MASH(longcode,bigsize);
1087
+ }
1088
+ for (k = v3-1; k < j-1;)
1089
+ {
1090
+ ptn[k] = level;
1091
+ ++*numcells;
1092
+ l = k+1;
1093
+ ADDELEMENT(active,l);
1094
+ ACTIVE[nactive++] = l;
1095
+ w3 = HITS[lab[l]];
1096
+ longcode = MASH(longcode,w3);
1097
+ for (k = l; k < j-1
1098
+ && HITS[lab[k+1]] == w3; ++k)
1099
+ CELLSTART[lab[k+1]] = l;
1100
+ size = k-l+1;
1101
+ if (size == 1)
1102
+ CELLSTART[lab[l]] = n;
1103
+ else
1104
+ {
1105
+ CELLSTART[lab[l]] = l;
1106
+ if (size > bigsize)
1107
+ {
1108
+ bigsize = size;
1109
+ bigpos = nactive-1;
1110
+ }
1111
+ }
1112
+ }
1113
+
1114
+ if (bigpos >= 0 && !ISELEMENT(active,v1))
1115
+ {
1116
+ DELELEMENT(active,ACTIVE[bigpos]);
1117
+ ADDELEMENT(active,v1);
1118
+ ACTIVE[bigpos] = v1;
1119
+ }
1120
+ }
1121
+ }
1122
+ }
1123
+ }
1124
+ }
1125
+
1126
+ longcode = MASH(longcode,*numcells);
1127
+ *code = CLEANUP(longcode);
1128
+ }
1129
+
1130
+ /*****************************************************************************
1131
+ * *
1132
+ * cheapautom_sg(ptn,level,digraph,n) returns TRUE if the partition at the *
1133
+ * specified level in the partition nest (lab,ptn) {lab is not needed here} *
1134
+ * satisfies a simple sufficient condition for its cells to be the orbits of *
1135
+ * some subgroup of the automorphism group. Otherwise it returns FALSE. *
1136
+ * It always returns FALSE if digraph!=FALSE. *
1137
+ * *
1138
+ * nauty assumes that this function will always return TRUE for any *
1139
+ * partition finer than one for which it returns TRUE. *
1140
+ * *
1141
+ *****************************************************************************/
1142
+
1143
+ boolean
1144
+ cheapautom_sg(int *ptn, int level, boolean digraph, int n)
1145
+ {
1146
+ int i,k,nnt;
1147
+
1148
+ if (digraph) return FALSE;
1149
+
1150
+ k = n;
1151
+ nnt = 0;
1152
+ for (i = 0; i < n; ++i)
1153
+ {
1154
+ --k;
1155
+ if (ptn[i] > level)
1156
+ {
1157
+ ++nnt;
1158
+ while (ptn[++i] > level) {}
1159
+ }
1160
+ }
1161
+
1162
+ return (k <= nnt + 1 || k <= 4);
1163
+ }
1164
+
1165
+ /*****************************************************************************
1166
+ * *
1167
+ * bestcell_sg(g,lab,ptn,level,tc_level,m,n) returns the index in lab of *
1168
+ * the start of the "best non-singleton cell" for fixing. If there is no *
1169
+ * non-singleton cell it returns n. *
1170
+ * This implementation finds the first cell which is non-trivially joined *
1171
+ * to the greatest number of other cells, assuming equitability. *
1172
+ * This is not good for digraphs! *
1173
+ * *
1174
+ *****************************************************************************/
1175
+
1176
+ static int
1177
+ bestcell_sg(graph *g, int *lab, int *ptn, int level,
1178
+ int tc_level, int m, int n)
1179
+ {
1180
+ int nnt;
1181
+ int *d,*e;
1182
+ int i,k,di;
1183
+ int *work1b;
1184
+ int maxcnt;
1185
+ size_t *v,vi,j;
1186
+
1187
+ SG_VDE(g,v,d,e);
1188
+
1189
+ #if !MAXN
1190
+ DYNALLOC1(int,work1,work1_sz,n,"bestcell_sg");
1191
+ DYNALLOC1(int,work2,work2_sz,n,"bestcell_sg");
1192
+ DYNALLOC1(int,work3,work3_sz,n,"bestcell_sg");
1193
+ DYNALLOC1(int,work4,work4_sz,n,"bestcell_sg");
1194
+ #endif
1195
+ work1b = work1 + (n/2);
1196
+ #define START work1
1197
+ #define SIZE work1b
1198
+ #define NNTCELL work2
1199
+ #define HITS work3
1200
+ #define COUNT work4
1201
+
1202
+ /* find non-singleton cells: put starts in START[0..nnt-1],
1203
+ sizes in SIZE[0..nnt-1].
1204
+ Also NNTCELL[i] = n if {i} is a singelton, else index of
1205
+ nontriv cell containing i. */
1206
+
1207
+ i = nnt = 0;
1208
+
1209
+ while (i < n)
1210
+ {
1211
+ if (ptn[i] > level)
1212
+ {
1213
+ START[nnt] = i;
1214
+ j = i;
1215
+ do
1216
+ NNTCELL[lab[j]] = nnt;
1217
+ while (ptn[j++] > level);
1218
+ SIZE[nnt] = j-i;
1219
+ ++nnt;
1220
+ i = j;
1221
+ }
1222
+ else
1223
+ {
1224
+ NNTCELL[lab[i]] = n;
1225
+ ++i;
1226
+ }
1227
+ }
1228
+
1229
+ if (nnt == 0) return n;
1230
+
1231
+ /* set COUNT[i] to # non-trivial neighbours of n.s. cell i */
1232
+
1233
+ for (i = 0; i < nnt; ++i) HITS[i] = COUNT[i] = 0;
1234
+
1235
+ for (i = 0; i < nnt; ++i)
1236
+ {
1237
+ vi = v[lab[START[i]]];
1238
+ di = d[lab[START[i]]];
1239
+
1240
+ for (j = 0; j < di; ++j)
1241
+ {
1242
+ k = NNTCELL[e[vi+j]];
1243
+ if (k != n) ++HITS[k];
1244
+ }
1245
+ for (j = 0; j < di; ++j)
1246
+ {
1247
+ k = NNTCELL[e[vi+j]];
1248
+ if (k != n)
1249
+ {
1250
+ if (HITS[k] > 0 && HITS[k] < SIZE[k]) ++COUNT[i];
1251
+ HITS[k] = 0;
1252
+ }
1253
+ }
1254
+ }
1255
+
1256
+ /* find first greatest bucket value */
1257
+
1258
+ j = 0;
1259
+ maxcnt = COUNT[0];
1260
+ for (i = 1; i < nnt; ++i)
1261
+ if (COUNT[i] > maxcnt)
1262
+ {
1263
+ j = i;
1264
+ maxcnt = COUNT[i];
1265
+ }
1266
+
1267
+ return (int)START[j];
1268
+ }
1269
+ /*****************************************************************************
1270
+ * *
1271
+ * targetcell_sg(g,lab,ptn,level,tc_level,digraph,hint,m,n) returns the *
1272
+ * index in lab of the next cell to split. *
1273
+ * hint is a suggestion for the answer, which is obeyed if it is valid. *
1274
+ * Otherwise we use bestcell() up to tc_level and the first non-trivial *
1275
+ * cell after that. *
1276
+ * *
1277
+ *****************************************************************************/
1278
+
1279
+ int
1280
+ targetcell_sg(graph *g, int *lab, int *ptn, int level, int tc_level,
1281
+ boolean digraph, int hint, int m, int n)
1282
+ {
1283
+ int i;
1284
+
1285
+ if (hint >= 0 && ptn[hint] > level &&
1286
+ (hint == 0 || ptn[hint-1] <= level))
1287
+ return hint;
1288
+ else if (level <= tc_level)
1289
+ return bestcell_sg(g,lab,ptn,level,tc_level,m,n);
1290
+ else
1291
+ {
1292
+ for (i = 0; i < n && ptn[i] <= level; ++i) {}
1293
+ return (i == n ? 0 : i);
1294
+ }
1295
+ }
1296
+
1297
+ /*****************************************************************************
1298
+ * *
1299
+ * sortlists_sg(g) sorts the adjacency lists into numerical order *
1300
+ * *
1301
+ *****************************************************************************/
1302
+
1303
+ void
1304
+ sortlists_sg(sparsegraph *g)
1305
+ {
1306
+ int *d,*e;
1307
+ int n,i;
1308
+ size_t *v;
1309
+ sg_weight *wt;
1310
+
1311
+ SWG_VDE(g,v,d,e,wt);
1312
+ n = g->nv;
1313
+
1314
+ if (wt)
1315
+ {
1316
+ for (i = 0; i < n; ++i)
1317
+ if (d[i] > 1) sortweights(e+v[i],wt+v[i],d[i]);
1318
+ }
1319
+ else
1320
+ {
1321
+ for (i = 0; i < n; ++i)
1322
+ if (d[i] > 1) sortints(e+v[i],d[i]);
1323
+ }
1324
+ }
1325
+
1326
+ /*****************************************************************************
1327
+ * *
1328
+ * put_sg(f,sg,digraph,linelength) writes the sparse graph to file f using *
1329
+ * at most linelength characters per line. If digraph then all directed *
1330
+ * edges are written; else one v-w for w>=v is written. *
1331
+ * *
1332
+ *****************************************************************************/
1333
+
1334
+ void
1335
+ put_sg(FILE *f, sparsegraph *sg, boolean digraph, int linelength)
1336
+ {
1337
+ int *d,*e;
1338
+ int n,di;
1339
+ int i,curlen,slen;
1340
+ size_t *v,vi,j;
1341
+ char s[12];
1342
+
1343
+ SG_VDE(sg,v,d,e);
1344
+ n = sg->nv;
1345
+
1346
+ for (i = 0; i < n; ++i)
1347
+ {
1348
+ vi = v[i];
1349
+ di = d[i];
1350
+ if (di == 0) continue;
1351
+ slen = itos(i+labelorg,s);
1352
+ putstring(f,s);
1353
+ putstring(f," :");
1354
+ curlen = slen + 2;
1355
+
1356
+ for (j = 0; j < di; ++j)
1357
+ {
1358
+ if (!digraph && e[vi+j] < i) continue;
1359
+ slen = itos(e[vi+j]+labelorg,s);
1360
+ if (linelength && curlen + slen + 1 >= linelength)
1361
+ {
1362
+ putstring(f,"\n ");
1363
+ curlen = 2;
1364
+ }
1365
+ PUTC(' ',f);
1366
+ putstring(f,s);
1367
+ curlen += slen + 1;
1368
+ }
1369
+ PUTC('\n',f);
1370
+ }
1371
+ }
1372
+
1373
+ /*****************************************************************************
1374
+ * *
1375
+ * sg_to_nauty(sg,g,reqm,&m) creates a nauty-format graph from a sparse *
1376
+ * graph. reqm is the required m value (computed from n if reqm=0), and *
1377
+ * m is the actual value used. g is dynamically generated if NULL is given. *
1378
+ * A pointer to g is returned. *
1379
+ * *
1380
+ *****************************************************************************/
1381
+
1382
+ graph*
1383
+ sg_to_nauty(sparsegraph *sg, graph *g, int reqm, int *pm)
1384
+ {
1385
+ int *d,*e;
1386
+ int m,n,i,di;
1387
+ size_t *v,vi,j;
1388
+ set *gi;
1389
+
1390
+ SG_VDE(sg,v,d,e);
1391
+ n = sg->nv;
1392
+ if (reqm != 0 && reqm*WORDSIZE < n)
1393
+ {
1394
+ fprintf(ERRFILE,"sg_to_nauty: reqm is impossible\n");
1395
+ exit(1);
1396
+ }
1397
+
1398
+ if (reqm != 0) m = reqm;
1399
+ else m = (n+WORDSIZE-1)/WORDSIZE;
1400
+
1401
+ *pm = m;
1402
+
1403
+ if (g == NULL)
1404
+ {
1405
+ if ((g = (graph*)ALLOCS(n,m*sizeof(graph))) == NULL)
1406
+ {
1407
+ fprintf(ERRFILE,"sg_to_nauty: malloc failed\n");
1408
+ exit(1);
1409
+ }
1410
+ }
1411
+
1412
+ for (i = 0, gi = g; i < n; ++i, gi += m)
1413
+ {
1414
+ vi = v[i];
1415
+ di = d[i];
1416
+ EMPTYSET(gi,m);
1417
+ for (j = 0; j < di; ++j) ADDELEMENT(gi,e[vi+j]);
1418
+ }
1419
+
1420
+ return g;
1421
+ }
1422
+
1423
+ /*****************************************************************************
1424
+ * *
1425
+ * copy_sg(sg1,sg2) makes a copy of sg1 into sg2. *
1426
+ * If sg2 is not NULL, it is assumed that the vlen,dlen,elen fields are *
1427
+ * correct and v,d,e are dynamically allocated (or NULL); they are *
1428
+ * reallocated if necessary. If sg2==NULL, a new structure is allocated. *
1429
+ * A pointer to the copy is returned. *
1430
+ * The new graph e component is the same, no compression is done. *
1431
+ * *
1432
+ *****************************************************************************/
1433
+
1434
+ sparsegraph*
1435
+ copy_sg(sparsegraph *sg1, sparsegraph *sg2)
1436
+ {
1437
+ int *d1,*e1,*d2,*e2;
1438
+ int i,n;
1439
+ size_t *v1,*v2,k;
1440
+ sg_weight *wt1,*wt2;
1441
+
1442
+ if (!sg2)
1443
+ {
1444
+ if ((sg2 = (sparsegraph*)ALLOCS(1,sizeof(sparsegraph))) == NULL)
1445
+ {
1446
+ fprintf(ERRFILE,"copy_sg: malloc failed\n");
1447
+ exit(1);
1448
+ }
1449
+ SG_INIT(*sg2);
1450
+ }
1451
+
1452
+ SWG_VDE(sg1,v1,d1,e1,wt1);
1453
+
1454
+ n = sg1->nv;
1455
+
1456
+ k = 0;
1457
+ for (i = 0; i < n; ++i)
1458
+ if (v1[i]+d1[i]>k) k = v1[i] + d1[i];
1459
+
1460
+ if (wt1)
1461
+ SWG_ALLOC(*sg2,n,k,"copy_sg malloc");
1462
+ else
1463
+ {
1464
+ SG_ALLOC(*sg2,n,k,"copy_sg malloc");
1465
+ DYNFREE(sg2->w,sg2->wlen);
1466
+ }
1467
+ SWG_VDE(sg2,v2,d2,e2,wt2);
1468
+
1469
+ sg2->nv = n;
1470
+ sg2->nde = sg1->nde;
1471
+ memcpy(v2,v1,n*sizeof(size_t));
1472
+ memcpy(d2,d1,n*sizeof(int));
1473
+ memcpy(e2,e1,k*sizeof(int));
1474
+ if (wt1) memcpy(wt2,wt1,k*sizeof(sg_weight));
1475
+
1476
+ return sg2;
1477
+ }
1478
+
1479
+ /*****************************************************************************
1480
+ * *
1481
+ * nauty_to_sg(g,sg,m,n) creates a sparse graph from a nauty format graph *
1482
+ * If sg is not NULL, it is assumed that the vlen,dlen,elen fields are *
1483
+ * correct and v,d,e are dynamically allocated (or NULL); they are *
1484
+ * reallocated if necessary. If sg==NULL, a new structure is allocated. *
1485
+ * A pointer to the sparse graph is returned. *
1486
+ * *
1487
+ *****************************************************************************/
1488
+
1489
+ sparsegraph*
1490
+ nauty_to_sg(graph *g, sparsegraph *sg, int m, int n)
1491
+ {
1492
+ int *d,*e;
1493
+ int i,k;
1494
+ set *gi;
1495
+ size_t j,*v,nde;
1496
+
1497
+ if (!sg)
1498
+ {
1499
+ if ((sg = (sparsegraph*)ALLOCS(1,sizeof(sparsegraph))) == NULL)
1500
+ {
1501
+ fprintf(ERRFILE,"nauty_to_sg: malloc failed\n");
1502
+ exit(1);
1503
+ }
1504
+ SG_INIT(*sg);
1505
+ }
1506
+
1507
+ SETSIZE(nde,g,(size_t)m*(size_t)n);
1508
+
1509
+ sg->nv = n;
1510
+ sg->nde = nde;
1511
+
1512
+ SG_ALLOC(*sg,n,nde,"nauty_to_sg");
1513
+
1514
+ SG_VDE(sg,v,d,e);
1515
+
1516
+ j = 0;
1517
+ for (i = 0, gi = g; i < n; ++i, gi += m)
1518
+ {
1519
+ v[i] = j;
1520
+ for (k = -1; (k = nextelement(gi,m,k)) >= 0; )
1521
+ e[j++] = k;
1522
+ d[i] = j - v[i];
1523
+ }
1524
+
1525
+ return sg;
1526
+ }
1527
+
1528
+ /*****************************************************************************
1529
+ * *
1530
+ * distances_sg() assigns to each vertex v a value depending on the number *
1531
+ * of vertices at each distance from v, and what cells they lie in. *
1532
+ * If we find any cell which is split in this manner, we don't try any *
1533
+ * further cells. *
1534
+ * *
1535
+ *****************************************************************************/
1536
+
1537
+ void
1538
+ distances_sg(graph *g, int *lab, int *ptn, int level, int numcells, int tvpos,
1539
+ int *invar, int invararg, boolean digraph, int m, int n)
1540
+ {
1541
+ int *d,*e;
1542
+ int i,k,dlim,wt;
1543
+ int di;
1544
+ int cell1,cell2,iv,liv,kcode;
1545
+ int head,tail;
1546
+ long longcode;
1547
+ size_t *v,vi,j;
1548
+ boolean success;
1549
+
1550
+ SG_VDE(g,v,d,e);
1551
+
1552
+ #if !MAXN
1553
+ DYNALLOC1(int,work1,work1_sz,n,"distances_sg");
1554
+ DYNALLOC1(int,work4,work4_sz,n,"distances_sg");
1555
+ DYNALLOC1(int,work3,work3_sz,n,"distances_sg");
1556
+ #endif
1557
+ #define CELLCODE work1
1558
+ #define QUEUE work4
1559
+ #define DIST work3
1560
+
1561
+ for (i = n; --i >= 0;) invar[i] = 0;
1562
+
1563
+ wt = 1;
1564
+ for (i = 0; i < n; ++i)
1565
+ {
1566
+ CELLCODE[lab[i]] = FUZZ1(wt);
1567
+ if (ptn[i] <= level) ++wt;
1568
+ }
1569
+
1570
+ if (invararg > n || invararg == 0) dlim = n;
1571
+ else dlim = invararg+1;
1572
+
1573
+ success = FALSE;
1574
+ for (cell1 = 0; cell1 < n; cell1 = cell2 + 1)
1575
+ {
1576
+ for (cell2 = cell1; ptn[cell2] > level; ++cell2) {}
1577
+ if (cell2 == cell1) continue;
1578
+
1579
+ for (iv = cell1; iv <= cell2; ++iv)
1580
+ {
1581
+ liv = lab[iv];
1582
+ QUEUE[0] = liv;
1583
+ DIST[liv] = 0;
1584
+ RESETMARKS1;
1585
+ MARK1(liv);
1586
+ longcode = 0;
1587
+ head = 0;
1588
+ tail = 1;
1589
+
1590
+ while (tail < n && head < tail)
1591
+ {
1592
+ i = QUEUE[head++];
1593
+ if (DIST[i] >= dlim) break;
1594
+ vi = v[i];
1595
+ di = d[i];
1596
+
1597
+ for (j = 0; j < di; ++j)
1598
+ {
1599
+ k = e[vi+j];
1600
+ if (ISNOTMARKED1(k))
1601
+ {
1602
+ MARK1(k);
1603
+ DIST[k] = DIST[i] + 1;
1604
+ kcode = DIST[k]+CELLCODE[k];
1605
+ ACCUM(longcode,FUZZ1(kcode));
1606
+ QUEUE[tail++] = k;
1607
+ }
1608
+ }
1609
+ }
1610
+ invar[liv] = CLEANUP(longcode);
1611
+ if (invar[liv] != invar[lab[cell1]]) success = TRUE;
1612
+ }
1613
+ if (success) break;
1614
+ }
1615
+ }
1616
+
1617
+ /*****************************************************************************
1618
+ * *
1619
+ * adjacencies_sg() assigns to each vertex v a code depending on which cells *
1620
+ * it is joined to and from, and how many times. It is intended to provide *
1621
+ * better partitioning that the normal refinement routine for digraphs. *
1622
+ * It will not help with undirected graphs in nauty at all. *
1623
+ * *
1624
+ *****************************************************************************/
1625
+
1626
+ void
1627
+ adjacencies_sg(graph *g, int *lab, int *ptn, int level, int numcells,
1628
+ int tvpos, int *invar, int invararg, boolean digraph,
1629
+ int m, int n)
1630
+ {
1631
+ int *d,*e;
1632
+ int vwt,wwt;
1633
+ int *ei,di,i;
1634
+ size_t *v,j;
1635
+
1636
+ SG_VDE(g,v,d,e);
1637
+
1638
+ #if !MAXN
1639
+ DYNALLOC1(int,work2,work2_sz,n,"adjacencies_sg");
1640
+ #endif
1641
+
1642
+ vwt = 1;
1643
+ for (i = 0; i < n; ++i)
1644
+ {
1645
+ work2[lab[i]] = vwt;
1646
+ if (ptn[i] <= level) ++vwt;
1647
+ invar[i] = 0;
1648
+ }
1649
+
1650
+ for (i = 0; i < n; ++i)
1651
+ {
1652
+ vwt = FUZZ1(work2[i]);
1653
+ wwt = 0;
1654
+ di = d[i];
1655
+ ei = e + v[i];
1656
+ for (j = 0; j < di; ++j)
1657
+ {
1658
+ ACCUM(wwt,FUZZ2(work2[ei[j]]));
1659
+ ACCUM(invar[ei[j]],vwt);
1660
+ }
1661
+ ACCUM(invar[i],wwt);
1662
+ }
1663
+ }
1664
+
1665
+ /*****************************************************************************
1666
+ * *
1667
+ * sparsenauty(g,lab,ptn,orbits,&options,&stats,h) *
1668
+ * is a slightly simplified interface to nauty(). It allocates enough *
1669
+ * workspace for 500 automorphisms and checks that the sparsegraph dispatch *
1670
+ * vector is in use. *
1671
+ * *
1672
+ *****************************************************************************/
1673
+
1674
+ void
1675
+ sparsenauty(sparsegraph *sg, int *lab, int *ptn, int *orbits,
1676
+ optionblk *options, statsblk *stats, sparsegraph *h)
1677
+ {
1678
+ int m,n;
1679
+ boolean digraph;
1680
+ int i,*d,*e,*ei,*eilim;
1681
+ size_t *v;
1682
+
1683
+ if (options->dispatch != &dispatch_sparse)
1684
+ {
1685
+ fprintf(ERRFILE,"Error: sparsenauty() needs standard options block\n");
1686
+ exit(1);
1687
+ }
1688
+
1689
+ n = sg->nv;
1690
+ m = SETWORDSNEEDED(n);
1691
+
1692
+ digraph = options->digraph;
1693
+ if (!digraph)
1694
+ {
1695
+ SG_VDE(sg,v,d,e);
1696
+ for (i = 0; i < n; ++i)
1697
+ {
1698
+ eilim = e + (v[i] + d[i]);
1699
+ for (ei = e+v[i]; ei < eilim; ++ei) if (*ei == i) break;
1700
+ if (ei < eilim) break;
1701
+ }
1702
+ if (i < n) options->digraph = TRUE;
1703
+ }
1704
+
1705
+ #if !MAXN
1706
+ /* Don't increase 2*500*m in the following without also increasing
1707
+ the static decalaration of snwork[] above. */
1708
+ DYNALLOC1(set,snwork,snwork_sz,2*500*m,"densenauty malloc");
1709
+ #endif
1710
+
1711
+ nauty((graph*)sg,lab,ptn,NULL,orbits,options,stats,
1712
+ snwork,2*500*m,m,n,(graph*)h);
1713
+ options->digraph = digraph;
1714
+ }
1715
+
1716
+ /*****************************************************************************
1717
+ * *
1718
+ * nausparse_check() checks that this file is compiled compatibly with the *
1719
+ * given parameters. If not, call exit(1). *
1720
+ * *
1721
+ *****************************************************************************/
1722
+
1723
+ void
1724
+ nausparse_check(int wordsize, int m, int n, int version)
1725
+ {
1726
+ if (wordsize != WORDSIZE)
1727
+ {
1728
+ fprintf(ERRFILE,"Error: WORDSIZE mismatch in nausparse.c\n");
1729
+ exit(1);
1730
+ }
1731
+
1732
+ #if MAXN
1733
+ if (m > MAXM)
1734
+ {
1735
+ fprintf(ERRFILE,"Error: MAXM inadequate in nausparse.c\n");
1736
+ exit(1);
1737
+ }
1738
+
1739
+ if (n > MAXN)
1740
+ {
1741
+ fprintf(ERRFILE,"Error: MAXN inadequate in nausparse.c\n");
1742
+ exit(1);
1743
+ }
1744
+ #endif
1745
+
1746
+ if (version < NAUTYREQUIRED)
1747
+ {
1748
+ fprintf(ERRFILE,"Error: nausparse.c version mismatch\n");
1749
+ exit(1);
1750
+ }
1751
+ }
1752
+
1753
+ /*****************************************************************************
1754
+ * *
1755
+ * nausparse_freedyn() - free the dynamic memory in this module *
1756
+ * *
1757
+ *****************************************************************************/
1758
+
1759
+ void
1760
+ nausparse_freedyn(void)
1761
+ {
1762
+ #if !MAXN
1763
+ DYNFREE(vmark1,vmark1_sz);
1764
+ DYNFREE(vmark2,vmark2_sz);
1765
+ DYNFREE(work1,work1_sz);
1766
+ DYNFREE(work2,work2_sz);
1767
+ DYNFREE(work3,work3_sz);
1768
+ DYNFREE(work4,work4_sz);
1769
+ DYNFREE(snwork,snwork_sz);
1770
+ #endif
1771
+ }