https://hal.archives-ouvertes.fr/hal-02398953
Tip revision: c33910a29d53f4e137c225b21a8d59e43327cbf9 authored by Software Heritage on 08 December 2019, 12:26:32 UTC
hal: Deposit 351 in collection hal
hal: Deposit 351 in collection hal
Tip revision: c33910a
sgraph.cpp
#include "sgraph.h"
#include <cmath>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
sgraph::sgraph(){
};
sgraph::sgraph(vector<vector<int> > orig_list){
/*
* This moves the elements in the list around, in order to construct the spanning tree along the way...
* WE WILL NEED TO KEEP TRACK OF THIS PERMUTATION!!
*/
// cout << "Constructing graph, I will reorder edges in order to construct a spanning tree" << endl;
vector<vector<int> > list;
for (unsigned u=0; u<orig_list.size(); u++) {
vector<int> te;
for (unsigned v=0; v<orig_list[u].size(); v++) {
te.push_back(orig_list[u][v]);
}
list.push_back(te);
}
vector<int> orig_order;
for (unsigned u=0; u<list.size(); u++) {
orig_order.push_back(u);
}
bool foundfirst = false;
int count = 0;
while (!foundfirst && count<list.size()) {
foundfirst = list[0][0]!=list[0][1];
if (!foundfirst) {
vector<int> yo;
yo.push_back(list[0][0]);
yo.push_back(list[0][1]);
list.erase(list.begin());
list.push_back(yo);
int z = orig_order[0];
orig_order.push_back(z);
orig_order.erase(orig_order.begin());
count++;
}
}
if (!foundfirst) {
cout << "All edges have the same endpoint, just take all edges (but one) to get generators!" << endl;
}
else {
initGraph(list[0]);
list.erase(list.begin());
int z = orig_order[0];
orig_order.erase(orig_order.begin());
new_order.push_back(z);
while (list.size()>0) {
if (!addEdge(list[0])) {
vector<int> yo;
yo.push_back(list[0][0]);
yo.push_back(list[0][1]);
list.erase(list.begin());
list.push_back(yo);
int z = orig_order[0];
orig_order.push_back(z);
orig_order.erase(orig_order.begin());
}
else {
list.erase(list.begin());
int z = orig_order[0];
new_order.push_back(z);
orig_order.erase(orig_order.begin());
}
}
}
// cout << "New order of edges: ";
for (unsigned u=0; u<new_order.size(); u++) {
new_order[u]++;
// cout << new_order[u] << "," ;
}
// cout << endl;
// cout << "Done creating graph" << endl;
// cout << endl;
}
void sgraph::initGraph(vector<int> pair) {
if (edges.size()>0) {
cerr << "You cannot init this graph, it already has at least one edge!" << endl;
exit(1);
}
else {
if (pair.size()!=2) {
cerr << "Edges must have TWO vertices!" << endl;
exit(1);
}
else {
vector<int> fakeedge;
fakeedge.push_back(-1);
fakeedge.push_back(-1);
edges.push_back(fakeedge); // included just for numbering purposes, so we can encode reverse of edge #k by -k.
edges.push_back(pair);
spanningtree.push_back(1);
if (pair[0]==pair[1]) {
cerr << "Please init graph with an embedded edge (I need different endpoints)" << endl;
exit(1);
}
else {
vertices.push_back(pair[0]);
vertices.push_back(pair[1]);
}
}
}
}
bool sgraph::addEdge(vector<int> pair) {
if (find(vertices.begin(),vertices.end(),pair[0])==vertices.end()) {
if (find(vertices.begin(),vertices.end(),pair[1])==vertices.end()) {
// cout << "Disconnected edge.." << endl;
return false;
}
else {
spanningtree.push_back(edges.size());
edges.push_back(pair);
vertices.push_back(pair[0]);
return true;
}
}
else {
if (find(vertices.begin(),vertices.end(),pair[1])==vertices.end()) {
spanningtree.push_back(edges.size());
edges.push_back(pair);
vertices.push_back(pair[1]);
return true;
}
else {
generators.push_back(edges.size());
edges.push_back(pair);
return true;
}
}
}
bool sgraph::extendpath(int goal, vector<int> &path) {
vector<int> list;
unsigned lp = path.size();
int u = path[lp-1];
int su;
if (u>0) {
su = u;
}
else {
su = -u;
}
bool done = false;
int k=0;
while (!done && k<spanningtree.size()) {
int sk = spanningtree[k];
if (u>0) {
if (edges[sk][0]==edges[su][1] && edges[sk][1]!=edges[su][0]) {
if (edges[sk][1]==goal) {
path.push_back(sk);
// cout << "Got there!" << endl;
return true;
}
else {
list.push_back(sk);
}
}
else {
if (edges[sk][1]==edges[su][1] && edges[sk][0]!=edges[su][0]) {
if (edges[sk][0]==goal) {
path.push_back(-sk);
// cout << "Got there!" << endl;
return true;
}
else {
list.push_back(-sk);
}
}
}
}
else {
if (edges[sk][0]==edges[su][0] && edges[sk][1]!=edges[su][1]) {
if (edges[sk][1]==goal) {
path.push_back(sk);
// cout << "Got there!" << endl;
return true;
}
else {
list.push_back(sk);
}
}
else {
if (edges[sk][1]==edges[su][0] && edges[sk][0]!=edges[su][1]) {
if (edges[sk][0]==goal) {
path.push_back(-sk);
// cout << "Got there!" << endl;
return true;
}
else {
list.push_back(-sk);
}
}
}
}
k++;
}
// cout << "list.size(): " << list.size() << endl;
if (list.size()>0) {
int kk=0;
path.push_back(list[kk]);
done = extendpath(goal,path);
while (!done && kk<list.size()-1) {
kk++;
path[path.size()-1] = list[kk];
done = extendpath(goal,path);
}
}
return done;
}
vector<int> sgraph::findpath(int j, int k) {
// cout << "Constructing a path in the spanning tree from vertex #" << j << " to #" << k << endl;
if (j==k) {
// cout << "No path to find in spanning tree, the endpoints are the same!" << endl;
vector<int> res;
return res;
}
else {
bool done = false;
unsigned u=0;
vector<int> init_path;
while (!done && u<spanningtree.size()) {
init_path.clear();
init_path.push_back(-6); // just insert something so it has size 1
int su = spanningtree[u];
bool gotone = false;
if (edges[su][0]==j) {
gotone = true;
init_path[0] = su;
if (edges[su][1]==k) {
done = true;
}
}
else {
if (edges[su][1]==j) {
gotone = true;
init_path[0] = -su;
if (edges[su][0]==k) {
done = true;
}
}
}
if (gotone && !done) {
done = extendpath(k,init_path);
}
u++;
}
if (done) {
// cout << "Found a path: ";
/* for (unsigned kk=0; kk<init_path.size(); kk++) {
cout << init_path[kk] << ",";
}
cout << endl;*/
return init_path;
}
}
}
void sgraph::fundamental_group(int basept, vector<vector<int> > &gens, vector<vector<bool> > &orientation) {
// cout << "Generators of fund group (in original ordering)" << endl;
for (unsigned u=0; u<generators.size(); u++) {
int su = generators[u];
vector<int> te = findpath(basept,edges[su][0]);
int tesize = te.size();
te.push_back(su);
if (edges[su][0]!=edges[su][1]) {
vector<int> te2 = findpath(edges[su][1],basept);
for (unsigned v=0; v<te2.size(); v++) {
te.push_back(te2[v]);
}
}
else {// use opposite of t1
for (int v=tesize-1; v>-1; v--) {
te.push_back(-te[v]);
}
}
// cout << "Base pt: " << basept << endl;
/* cout << "u=" << u << ", te=" ;
for (unsigned h=0; h<te.size(); h++) {
cout << te[h] << ",";
}
cout << endl;*/
vector<int> tee;
vector<bool> tee_orientation;
for (unsigned l=0; l<te.size(); l++) {
int zo = te[l];
if (zo>0) {
tee_orientation.push_back(true);
}
else {
// cout << "-";
zo = -zo;
tee_orientation.push_back(false);
}
tee.push_back((new_order[zo-1]-1)); // bizarre formula!! (this comes from phantom edge in graph, but I'm not sure about this)
// cout << (new_order[zo-1]-1) << ",";
/* bool fd = false;
int uu = -1;
while (!fd && uu!=new_order.size()-1) {
uu++;
fd = new_order[uu]==zo;
}
if (fd) {
tee.push_back(uu);
}
else {
cerr << "Trouble inverting permutation" << endl;
}
cout << uu << ",";*/
}
// cout << endl;
gens.push_back(tee);
orientation.push_back(tee_orientation);
}
}
void sgraph::export_fg_with_relations(int basept, string tag, vector<vector<int> > rels, vector<vector<bool> > orients) {
ofstream file;
string filename = "sphere/spherePres"+tag+".g";
cout << "Will write the presentation of the pi_1 of the boundary of the polytope in GAP style in the file: " << filename << endl;
file.open(filename.c_str());
file << "F:=FreeGroup(";
for (unsigned u=0; u<generators.size()-1; u++) {
file << "\"x" << (u+1) << "\",";
}
file << "\"x" << generators.size() << "\");" << endl;
file << "G:=F/[";
for (unsigned u=0; u<rels.size(); u++) {
int count = 0;
int rl = rels[u].size();
for (unsigned v=0; v<rl; v++) {
int oldnb = rels[u][v]+1;
bool fd = false;
int w = -1;
while (!fd && w!=new_order.size()-1) {
w++;
fd = oldnb==new_order[w];
}
if (fd) {
bool isgen = false;
int z = -1;
while (!isgen && z!=generators.size()-1) {
z++;
isgen = (w+1)==generators[z];
}
if (isgen) {
if (count>0) {
file << "*";
}
count++;
file << "F." << (z+1);
if (orients[u][v]) {
file << "^-1";
}
}
}
else {
cerr << "Trouble identifying relation" << endl;
exit(1);
}
}
if (count >0 && u<rels.size()-1) {
file << "," << endl;
}
}
file << "];" << endl;
file.close();
}
ostream & operator<<(ostream &out, const sgraph &g) {
cout << "Vertices: ";
for (unsigned k=0; k<g.vertices.size(); k++) {
cout << g.vertices[k] << ",";
}
cout << endl;
cout << "Spanning tree: ";
for (unsigned k=0; k<g.spanningtree.size(); k++) {
cout << g.spanningtree[k] << ",";
}
cout << endl;
cout << "Generators: ";
for (unsigned k=0; k<g.generators.size(); k++) {
cout << g.generators[k] << ",";
}
cout << endl;
cout << "Edges: " << endl;
for (unsigned k=1; k<g.edges.size(); k++) {
out << g.edges[k][0] << "->" << g.edges[k][1] << endl;
}
return out;
}