cpp-pd-code-simplify-interface 0.1.0__py3-none-any.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.
@@ -0,0 +1,21 @@
1
+ from .main import (
2
+ PdCodeSimplifyInterfaceError,
3
+ compile_simplifier,
4
+ get_simplifier_executable,
5
+ get_simplifier_library,
6
+ normalize_pd_code,
7
+ normalize_pd_codes,
8
+ simplify,
9
+ simplify_many,
10
+ )
11
+
12
+ __all__ = [
13
+ "PdCodeSimplifyInterfaceError",
14
+ "compile_simplifier",
15
+ "get_simplifier_executable",
16
+ "get_simplifier_library",
17
+ "normalize_pd_code",
18
+ "normalize_pd_codes",
19
+ "simplify",
20
+ "simplify_many",
21
+ ]
@@ -0,0 +1,4 @@
1
+ from .main import main
2
+
3
+ if __name__ == "__main__":
4
+ raise SystemExit(main())
@@ -0,0 +1,145 @@
1
+ #pragma once
2
+
3
+ #include <array>
4
+ #include <cstddef>
5
+ #include <iosfwd>
6
+ #include <string>
7
+ #include <vector>
8
+
9
+ #if defined(_WIN32) && (defined(PDCODE_SIMPLIFY_SHARED) || defined(PDCODE_SIMPLIFY_BUILD_SHARED))
10
+ #if defined(PDCODE_SIMPLIFY_BUILD_SHARED)
11
+ #define PDCODE_SIMPLIFY_API __declspec(dllexport)
12
+ #else
13
+ #define PDCODE_SIMPLIFY_API __declspec(dllimport)
14
+ #endif
15
+ #elif defined(PDCODE_SIMPLIFY_BUILD_SHARED) && defined(__GNUC__)
16
+ #define PDCODE_SIMPLIFY_API __attribute__((visibility("default")))
17
+ #else
18
+ #define PDCODE_SIMPLIFY_API
19
+ #endif
20
+
21
+ namespace pdcode_simplify {
22
+
23
+ struct Endpoint {
24
+ int crossing = -1;
25
+ int strand = -1;
26
+
27
+ friend bool operator==(const Endpoint& lhs, const Endpoint& rhs) {
28
+ return lhs.crossing == rhs.crossing && lhs.strand == rhs.strand;
29
+ }
30
+
31
+ friend bool operator!=(const Endpoint& lhs, const Endpoint& rhs) {
32
+ return !(lhs == rhs);
33
+ }
34
+ };
35
+
36
+ using Crossing = std::array<int, 4>;
37
+ using PDCode = std::vector<Crossing>;
38
+
39
+ enum class Direction {
40
+ Left,
41
+ Right
42
+ };
43
+
44
+ struct GreenCrossing {
45
+ int from_face = -1;
46
+ int to_face = -1;
47
+ std::string strand_level;
48
+ };
49
+
50
+ struct SimplifierOptions {
51
+ int max_paths = 100;
52
+ };
53
+
54
+ struct LinkComponentSummary {
55
+ std::vector<int> crossing_indices;
56
+ };
57
+
58
+ struct ComponentAnalysis {
59
+ std::vector<LinkComponentSummary> components;
60
+ std::size_t crossingless_components = 0;
61
+
62
+ std::size_t components_with_crossings() const {
63
+ return components.size();
64
+ }
65
+
66
+ std::size_t total_components() const {
67
+ return components.size() + crossingless_components;
68
+ }
69
+ };
70
+
71
+ struct RandomInflationOptions {
72
+ int moves = 16;
73
+ unsigned int seed = 1;
74
+ int type_ii_percentage = 50;
75
+ };
76
+
77
+ struct RandomInflationResult {
78
+ PDCode code;
79
+ unsigned int seed = 1;
80
+ int type_i_moves = 0;
81
+ int type_ii_moves = 0;
82
+ };
83
+
84
+ struct ReidemeisterSimplificationResult {
85
+ PDCode code;
86
+ std::size_t crossingless_components = 0;
87
+ int type_i_moves = 0;
88
+ int type_ii_moves = 0;
89
+ };
90
+
91
+ struct PDSimplificationResult {
92
+ PDCode code;
93
+ std::size_t crossingless_components = 0;
94
+ int reidemeister_i_moves = 0;
95
+ int nugatory_crossing_moves = 0;
96
+ };
97
+
98
+ struct SimplificationResult {
99
+ bool found = false;
100
+ Direction direction = Direction::Left;
101
+ std::vector<Endpoint> red_path;
102
+ std::vector<int> green_path;
103
+ std::vector<GreenCrossing> green_crossings;
104
+ std::size_t tested_red_paths = 0;
105
+ std::size_t tested_green_paths = 0;
106
+ };
107
+
108
+ PDCODE_SIMPLIFY_API PDCode parse_pd_code(const std::string& text);
109
+ PDCODE_SIMPLIFY_API std::string format_pd_code(const PDCode& code);
110
+ PDCODE_SIMPLIFY_API std::string format_endpoint(const Endpoint& endpoint);
111
+ PDCODE_SIMPLIFY_API std::string format_direction(Direction direction);
112
+
113
+ PDCODE_SIMPLIFY_API ComponentAnalysis analyze_components(
114
+ const PDCode& code,
115
+ std::size_t known_crossingless_components = 0);
116
+
117
+ PDCODE_SIMPLIFY_API ComponentAnalysis analyze_components_after_removing_crossings(
118
+ const PDCode& code,
119
+ const std::vector<int>& removed_crossings,
120
+ std::size_t known_crossingless_components = 0);
121
+
122
+ PDCODE_SIMPLIFY_API std::size_t count_crossingless_components_after_removing_crossings(
123
+ const PDCode& code,
124
+ const std::vector<int>& removed_crossings,
125
+ std::size_t known_crossingless_components = 0);
126
+
127
+ PDCODE_SIMPLIFY_API RandomInflationResult randomly_increase_crossings(
128
+ const PDCode& code,
129
+ const RandomInflationOptions& options = RandomInflationOptions{});
130
+
131
+ PDCODE_SIMPLIFY_API ReidemeisterSimplificationResult simplify_reidemeister_i_ii(
132
+ const PDCode& code,
133
+ std::size_t known_crossingless_components = 0);
134
+
135
+ PDCODE_SIMPLIFY_API PDSimplificationResult simplify_pd_code(
136
+ const PDCode& code,
137
+ std::size_t known_crossingless_components = 0);
138
+
139
+ PDCODE_SIMPLIFY_API SimplificationResult find_simplification(
140
+ const PDCode& code,
141
+ const SimplifierOptions& options = SimplifierOptions{});
142
+
143
+ PDCODE_SIMPLIFY_API std::ostream& operator<<(std::ostream& out, const Endpoint& endpoint);
144
+
145
+ } // namespace pdcode_simplify
@@ -0,0 +1,195 @@
1
+ #include "pdcode_simplify/pdcode_simplify.hpp"
2
+
3
+ #include <cstdlib>
4
+ #include <cstring>
5
+ #include <exception>
6
+ #include <sstream>
7
+ #include <string>
8
+ #include <vector>
9
+
10
+ namespace {
11
+
12
+ bool denotes_crossingless_unknot(const std::string& text) {
13
+ std::string compact;
14
+ for (char c : text) {
15
+ if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
16
+ compact.push_back(c);
17
+ }
18
+ }
19
+ return compact == "PD[]" || compact == "[]";
20
+ }
21
+
22
+ std::string json_escape(const std::string& text) {
23
+ std::ostringstream escaped;
24
+ for (char c : text) {
25
+ switch (c) {
26
+ case '\\':
27
+ escaped << "\\\\";
28
+ break;
29
+ case '"':
30
+ escaped << "\\\"";
31
+ break;
32
+ case '\n':
33
+ escaped << "\\n";
34
+ break;
35
+ case '\r':
36
+ escaped << "\\r";
37
+ break;
38
+ case '\t':
39
+ escaped << "\\t";
40
+ break;
41
+ default:
42
+ escaped << c;
43
+ break;
44
+ }
45
+ }
46
+ return escaped.str();
47
+ }
48
+
49
+ void append_component_counts(
50
+ std::ostringstream& out,
51
+ const pdcode_simplify::ComponentAnalysis& analysis) {
52
+ out << "\"components_with_crossings\":" << analysis.components_with_crossings()
53
+ << ",\"crossingless_components\":" << analysis.crossingless_components
54
+ << ",\"total_components\":" << analysis.total_components();
55
+ }
56
+
57
+ std::string result_to_json(
58
+ const pdcode_simplify::SimplificationResult& result,
59
+ const pdcode_simplify::ComponentAnalysis& input_components,
60
+ const pdcode_simplify::ComponentAnalysis* after_removal_components,
61
+ const pdcode_simplify::PDSimplificationResult& pd_simplification,
62
+ const pdcode_simplify::ComponentAnalysis& search_components) {
63
+ std::ostringstream out;
64
+ out << "{";
65
+ out << "\"simplification_found\":" << (result.found ? "true" : "false") << ",";
66
+ out << "\"input_components\":{";
67
+ append_component_counts(out, input_components);
68
+ out << "},";
69
+ if (after_removal_components != nullptr) {
70
+ out << "\"after_removal_components\":{";
71
+ append_component_counts(out, *after_removal_components);
72
+ out << "},";
73
+ }
74
+ out << "\"pd_simplification\":{"
75
+ << "\"enabled\":true,"
76
+ << "\"reidemeister_i_moves\":" << pd_simplification.reidemeister_i_moves << ","
77
+ << "\"nugatory_crossing_moves\":" << pd_simplification.nugatory_crossing_moves << ","
78
+ << "\"output_crossings\":" << pd_simplification.code.size()
79
+ << "},";
80
+ out << "\"search_components\":{";
81
+ append_component_counts(out, search_components);
82
+ out << "},";
83
+ out << "\"tested_red_paths\":" << result.tested_red_paths << ",";
84
+ out << "\"tested_green_paths\":" << result.tested_green_paths;
85
+ if (result.found) {
86
+ out << ",";
87
+ out << "\"direction\":\"" << pdcode_simplify::format_direction(result.direction) << "\",";
88
+ out << "\"red_path\":[";
89
+ for (std::size_t i = 0; i < result.red_path.size(); ++i) {
90
+ if (i != 0) {
91
+ out << ",";
92
+ }
93
+ out << "{\"crossing\":" << result.red_path[i].crossing
94
+ << ",\"strand\":" << result.red_path[i].strand << "}";
95
+ }
96
+ out << "],";
97
+ out << "\"green_path\":[";
98
+ for (std::size_t i = 0; i < result.green_path.size(); ++i) {
99
+ if (i != 0) {
100
+ out << ",";
101
+ }
102
+ out << result.green_path[i];
103
+ }
104
+ out << "],";
105
+ out << "\"green_crossings\":[";
106
+ for (std::size_t i = 0; i < result.green_crossings.size(); ++i) {
107
+ if (i != 0) {
108
+ out << ",";
109
+ }
110
+ const auto& crossing = result.green_crossings[i];
111
+ out << "{\"from_face\":" << crossing.from_face
112
+ << ",\"to_face\":" << crossing.to_face
113
+ << ",\"strand_level\":\"" << json_escape(crossing.strand_level) << "\"}";
114
+ }
115
+ out << "]";
116
+ }
117
+ out << "}";
118
+ return out.str();
119
+ }
120
+
121
+ char* copy_string(const std::string& text) {
122
+ char* result = static_cast<char*>(std::malloc(text.size() + 1));
123
+ if (result == nullptr) {
124
+ return nullptr;
125
+ }
126
+ std::memcpy(result, text.c_str(), text.size() + 1);
127
+ return result;
128
+ }
129
+
130
+ } // namespace
131
+
132
+ extern "C" {
133
+
134
+ #if defined(_WIN32)
135
+ __declspec(dllexport)
136
+ #endif
137
+ char* pdcode_simplify_run_json(
138
+ const char* pd_text,
139
+ int max_paths,
140
+ unsigned long long known_crossingless_components,
141
+ const int* removed_crossings,
142
+ unsigned long long removed_crossing_count) {
143
+ try {
144
+ if (pd_text == nullptr) {
145
+ return copy_string("{\"error\":\"pd_text must not be null\"}");
146
+ }
147
+
148
+ const std::string text(pd_text);
149
+ pdcode_simplify::SimplifierOptions options;
150
+ options.max_paths = max_paths;
151
+
152
+ const pdcode_simplify::PDCode code = pdcode_simplify::parse_pd_code(text);
153
+ std::size_t crossingless = static_cast<std::size_t>(known_crossingless_components);
154
+ if (denotes_crossingless_unknot(text)) {
155
+ ++crossingless;
156
+ }
157
+
158
+ const auto input_components = pdcode_simplify::analyze_components(code, crossingless);
159
+ pdcode_simplify::ComponentAnalysis after_removal_components;
160
+ const bool has_removal = removed_crossings != nullptr && removed_crossing_count > 0;
161
+ if (has_removal) {
162
+ std::vector<int> removed(
163
+ removed_crossings,
164
+ removed_crossings + static_cast<std::size_t>(removed_crossing_count));
165
+ after_removal_components =
166
+ pdcode_simplify::analyze_components_after_removing_crossings(
167
+ code, removed, crossingless);
168
+ }
169
+
170
+ const auto pd_simplification = pdcode_simplify::simplify_pd_code(code, crossingless);
171
+ const auto search_components = pdcode_simplify::analyze_components(
172
+ pd_simplification.code,
173
+ pd_simplification.crossingless_components);
174
+ const auto result = pdcode_simplify::find_simplification(pd_simplification.code, options);
175
+ return copy_string(result_to_json(
176
+ result,
177
+ input_components,
178
+ has_removal ? &after_removal_components : nullptr,
179
+ pd_simplification,
180
+ search_components));
181
+ } catch (const std::exception& error) {
182
+ return copy_string(std::string("{\"error\":\"") + json_escape(error.what()) + "\"}");
183
+ } catch (...) {
184
+ return copy_string("{\"error\":\"unknown C++ exception\"}");
185
+ }
186
+ }
187
+
188
+ #if defined(_WIN32)
189
+ __declspec(dllexport)
190
+ #endif
191
+ void pdcode_simplify_free_string(char* text) {
192
+ std::free(text);
193
+ }
194
+
195
+ } // extern "C"