58 namespace fs = std::filesystem;
72 const string & content,
78 cerr <<
" could not open " << label <<
" file: " << path <<
'\n';
85 cerr <<
" error writing " << label <<
" to: " << path <<
'\n';
91 cerr <<
" error closing " << label <<
" file: " << path <<
'\n';
93 cout <<
" certificate " << label <<
" written to: " << path <<
'\n';
108 cout <<
" external validator command:\n";
109 cout <<
" ruby scripts/planarity_certificate_validator.rb"
112 cout <<
" optional Gephi adapter command:\n";
113 cout <<
" ruby scripts/planarity_certificate_validator.rb"
116 <<
" --gephi-cmd \"gephi --headless --import {input}\"" <<
'\n';
117 cout <<
" optional Gephi catalog template command:\n";
118 cout <<
" ruby scripts/planarity_certificate_validator.rb"
120 <<
" --gephi --require-gephi"
121 <<
" --gephi-template portable.python-file-exists" <<
'\n';
122 cout <<
" optional render profile catalog command:\n";
123 cout <<
" ruby scripts/planarity_certificate_validator.rb"
124 <<
" --list-gephi-render-profiles --json" <<
'\n';
127 (
output_dir /
"aleph_planarity_renders").
string();
129 (
output_dir /
"aleph_planarity_ci_report.json").
string();
131 (
output_dir /
"aleph_planarity_ci_render_report.json").
string();
133 (
output_dir /
"aleph_planarity_visual_renders").
string();
135 (
output_dir /
"aleph_planarity_visual_diff_report.json").
string();
137 (
output_dir /
"gephi_nightly_comparison.json").
string();
139 (
output_dir /
"gephi_nightly_alert.md").
string();
141 cout <<
" optional render validation command:\n";
142 cout <<
" ruby scripts/planarity_certificate_validator.rb"
144 <<
" --render-gephi --require-render"
145 <<
" --render-profile portable.python-render-svg"
146 <<
" --render-output-dir " <<
render_dir <<
'\n';
147 cout <<
" optional CI batch command:\n";
148 cout <<
" ruby scripts/planarity_certificate_ci_batch.rb"
151 <<
" --gephi --require-gephi"
152 <<
" --gephi-template portable.python-file-exists"
153 <<
" --report " <<
ci_report <<
" --print-summary"
155 cout <<
" optional CI batch render command:\n";
156 cout <<
" ruby scripts/planarity_certificate_ci_batch.rb"
158 <<
" --render-gephi --require-render"
159 <<
" --render-profile portable.python-render-svg"
162 <<
" --print-summary" <<
'\n';
163 cout <<
" optional visual golden diff command:\n";
164 cout <<
" ruby scripts/planarity_certificate_ci_visual_diff.rb"
166 <<
" --profile portable.python-render-svg"
167 <<
" --profile portable.python-render-pdf"
170 <<
" --print-summary" <<
'\n';
171 cout <<
" optional nightly real-Gephi workflow:\n";
172 cout <<
" .github/workflows/planarity_gephi_nightly.yml"
173 <<
" (workflow_dispatch / weekly schedule; multi-tag matrix)"
175 cout <<
" optional nightly regression notify command:\n";
176 cout <<
" ruby scripts/planarity_gephi_regression_notify.rb"
179 <<
" --repository lrleon/Aleph-w"
180 <<
" --run-url https://github.com/lrleon/Aleph-w/actions/runs/123"
181 <<
" --webhook-env ALEPH_PLANARITY_ALERT_WEBHOOK --print-summary"
203 cout << title <<
'\n';
204 cout <<
" planar: " << (
r.is_planar ?
"yes" :
"no") <<
'\n';
205 cout <<
" input nodes/arcs: " <<
r.num_nodes <<
"/" <<
r.num_input_arcs <<
'\n';
206 cout <<
" simplified nodes/edges: "
207 <<
r.simplified_num_nodes <<
"/" <<
r.simplified_num_edges <<
'\n';
208 cout <<
" ignored loops: " <<
r.ignored_loops <<
'\n';
209 cout <<
" ignored parallel arcs: " <<
r.ignored_parallel_arcs <<
'\n';
210 if (
r.failed_euler_bound)
211 cout <<
" rejected by Euler bound before LR test\n";
213 cout <<
" embedding available: "
214 << (
r.has_combinatorial_embedding ?
"yes" :
"no") <<
'\n';
215 if (
r.embedding_search_truncated)
216 cout <<
" embedding search truncated by options\n";
217 if (
r.has_combinatorial_embedding)
219 cout <<
" embedding faces: " <<
r.embedding_num_faces <<
'\n';
220 cout <<
" embedding mode: "
221 << (
r.embedding_is_lr_linear ?
"LR-linear" :
"fallback-exact")
225 cout <<
" non-planar certificate available: "
226 << (
r.has_nonplanar_certificate ?
"yes" :
"no") <<
'\n';
227 if (
r.certificate_search_truncated)
228 cout <<
" certificate search truncated by options\n";
229 if (
r.has_nonplanar_certificate)
231 cout <<
" certificate type: "
233 cout <<
" witness edges: "
234 <<
r.certificate_obstruction_edges.size() <<
'\n';
235 if (
r.certificate_obstruction_edges.size() > 0)
236 cout <<
" first witness edge input-arc multiplicity: "
237 <<
r.certificate_obstruction_edges[0].input_arcs.size() <<
'\n';
238 if (
r.certificate_type == Planarity_Certificate_Type::K5_Subdivision
239 or r.certificate_type == Planarity_Certificate_Type::K33_Subdivision)
241 cout <<
" branch nodes: " <<
r.certificate_branch_nodes.size() <<
'\n';
242 cout <<
" witness paths: " <<
r.certificate_paths.size() <<
'\n';
243 if (
r.certificate_paths.size() > 0)
244 cout <<
" first witness path edges: "
245 <<
r.certificate_paths[0].edges.size() <<
'\n';
265 cout <<
" geometric drawing available: "
271 cout <<
" drawing validated no-crossings: "
276 for (
size_t i = 0; i <
show; ++i)
279 cout <<
" node[" << i <<
"] @" << p.x <<
", " << p.y <<
'\n';
303 const char *
env_out_dir = std::getenv(
"PLANARITY_OUT_DIR");
314 cout <<
"warning: could not ensure output directory exists: "
319 opts.compute_nonplanar_certificate =
true;
323 cout <<
"Planarity test on Aleph graphs\n";
324 cout <<
"=============================\n\n";
325 cout <<
"Certificate output directory: " <<
output_dir.string() <<
"\n\n";
346 if (
r.has_combinatorial_embedding)
350 cout <<
" dual graph nodes/arcs (local faces): "
351 <<
dual.get_num_nodes() <<
"/" <<
dual.get_num_arcs() <<
"\n\n";
359 cout <<
" dual metadata skipped (strict LR did not build embedding)\n\n";
383 print_result(
"Planar dense sample (strict LR embedding)",
r);
385 if (
r.has_combinatorial_embedding)
388 cout <<
" dual metadata local/global faces: "
389 <<
md.num_faces_local <<
"/" <<
md.num_faces_global <<
"\n\n";
397 cout <<
" dual metadata skipped (embedding unavailable)\n\n";
418 if (
r.has_nonplanar_certificate)
427 (
output_dir /
"planarity_k33_certificate.json").
string();
429 (
output_dir /
"planarity_k33_certificate.dot").
string();
431 (
output_dir /
"planarity_k33_certificate.graphml").
string();
433 (
output_dir /
"planarity_k33_certificate.gexf").
string();
440 cout <<
" certificate JSON bytes: " << json.size() <<
'\n';
441 cout <<
" certificate DOT bytes: " << dot.size() <<
'\n';
442 cout <<
" certificate GraphML bytes: " <<
graphml.size() <<
'\n';
443 cout <<
" certificate GEXF bytes: " <<
gexf.size() <<
'\n';
444 cout <<
" certificate structural validation: "
445 << (
vr.is_valid ?
"valid" :
"invalid") <<
'\n';
451 cout <<
" null branch nodes: " <<
vr.null_branch_nodes <<
'\n';
452 cout <<
" path/edge shape mismatches: "
453 <<
vr.path_node_edge_length_mismatch <<
'\n';
454 cout <<
" path edges not in obstruction: "
455 <<
vr.path_edge_not_in_obstruction <<
'\n';
463 auto * s = g.insert_node(
"S");
464 auto * t = g.insert_node(
"T");
465 auto * x = g.insert_node(
"X");
469 g.insert_arc(s, t, 1);
470 g.insert_arc(t, x, 1);
471 g.insert_arc(x, s, 1);
473 g.insert_arc(s, s, 1);
474 g.insert_arc(t, t, 1);
476 g.insert_arc(s, t, 1);
477 g.insert_arc(t, s, 1);
Planarity testing on Aleph graphs.
Generic directed graph (digraph) wrapper template.
Graph implemented with double-linked adjacency lists.
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
std::string nonplanar_certificate_to_gexf(const Planarity_Test_Result< GT > &result, Node_Label node_label=Node_Label(), const NonPlanar_Certificate_Export_Options &options=NonPlanar_Certificate_Export_Options())
Export non-planar certificate as GEXF.
Planar_Geometric_Drawing< GT > planar_geometric_drawing(const Planarity_Test_Result< GT > &result, const Planar_Geometric_Drawing_Options &options=Planar_Geometric_Drawing_Options())
Build embedding-aware 2D node coordinates from a planar result.
Planarity_Test_Result< GT > planarity_test(const GT &g, SA sa=SA(), const Planarity_Test_Options &options=Planarity_Test_Options())
Execute planarity test on an Aleph graph.
Planar_Dual_Metadata< GT > planar_dual_metadata(const Planarity_Test_Result< GT > &result)
Build face and dual-edge metadata from a planar embedding result.
std::string nonplanar_certificate_to_dot(const Planarity_Test_Result< GT > &result, Node_Label node_label=Node_Label(), const NonPlanar_Certificate_Export_Options &options=NonPlanar_Certificate_Export_Options())
Export non-planar certificate as GraphViz DOT.
std::string nonplanar_certificate_to_graphml(const Planarity_Test_Result< GT > &result, Node_Label node_label=Node_Label(), const NonPlanar_Certificate_Export_Options &options=NonPlanar_Certificate_Export_Options())
Export non-planar certificate as GraphML.
std::string nonplanar_certificate_to_json(const Planarity_Test_Result< GT > &result, Node_Label node_label=Node_Label(), const NonPlanar_Certificate_Export_Options &options=NonPlanar_Certificate_Export_Options())
Export non-planar certificate as JSON.
NonPlanar_Certificate_Validation< GT > validate_nonplanar_certificate(const Planarity_Test_Result< GT > &result)
Validate structural consistency of a non-planar certificate.
void print_result(const string &label, const Multipoly &poly)
Main namespace for Aleph-w library functions.
and
Check uniqueness with explicit hash + equality functors.
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
std::string to_string(const time_t t, const std::string &format)
Format a time_t value into a string using format.
Arc of graph implemented with double-linked adjacency lists.
Embedding-aware geometric drawing result.
bool drawing_validated_no_crossings
Array< Node_Position > node_positions
size_t relaxation_iterations
Configuration for planarity test optional outputs.
bool embedding_allow_bruteforce_fallback
Allow exact embedding fallback if LR-constructive embedding fails validation.
bool compute_embedding
If true and graph is planar, tries to compute combinatorial embedding.
Result of planarity testing.
Generic graph and digraph implementations.