https://hal.archives-ouvertes.fr/hal-02398953
Raw File
Tip revision: c33910a29d53f4e137c225b21a8d59e43327cbf9 authored by Software Heritage on 08 December 2019, 12:26:32 UTC
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;
} 
back to top