// TO_DO проверить, что 2n плюсов и минусов
// TO_DO чекер змейки
// TO_DO везде оператор равно
// TO_DO delete
// TO_DO assert число ребер и вершин
// TO_DO Нужно ли менять номера ребер???????
// ???? Равно true, если ребро a переходит в ребро b сверху над переходом из c в d
// Зачем   void dfs(int vertex, int previous_edge);
// Изложить формально getUntangleSequence()



#include <string>
#include <map>
#include <set>
#include <vector>
#define MAX_vertex_num 7
#define MAXcomponent_number 100
typedef pair<int, int> point;

// Полиномы, используемые в формуле для полинома Джонса
// p=1
polynom<int> one; 
// p = q^2
polynom<int> q_in_plus_2;
// p = q^(-2)
polynom<int> q_in_minus_2;
// p = q
polynom<int> q_in_plus_1;
// p = q^(-1)
polynom<int> q_in_minus_1;
// p = q - q^(-1)
polynom<int> q_in_plus_1_minus_q_in_minus_1;
// p = q + q^(-1)
polynom<int> q_in_plus_1_plus_q_in_minus_1;

// Нужно для определения типа перекрестка
int vector_product(int x1, int y1, int x2, int y2)
{
  return x1 * y2 - x2 * y1;
}

ostream& operator<<(ostream& o, point p)
{
  return o << "(" << p.first << "," << p.second << ")";
}

// Вершина графа плоской диаграммы зацепления
// В вершине всегда два входящих ребра a и c и два выходящих - b и d
// В вершине ребро a переходит в ребро b, ребро c в ребро d
// Ребра a и d лежат слева, ребра с и b - справа (важно)
class link_vertex
{
public:
  point p; // Координаты точки
  int a, b, c, d; // Номера ребер
  int is_above; // Здесь над - это плюс, прочитанный из файла
  int is_plus; // Этот плюс - тот, который из полинома Джонса
  link_vertex() { a = b = c = d = -1; is_above = -1; is_plus = -1;}
};

ostream& operator<<(ostream& o, link_vertex lv)
{
  return o << "p=" << lv.p << " is_above=" << lv.is_above << " is_plus=" << lv.is_plus
  	<< " a=" << lv.a << " b=" << lv.b << " c=" << lv.c << " d=" << lv.d;
}

// Ребро графа плоской диаграммы зацепления
class link_edge
{
public:
  int component_number; // Номер компоненты зацепления, к которой относится ребро
  point first_point; // Точка, которая идет в ребре сразу за точкой, в которой вершина, из которой ребро - нужна для определения типа перекрестка
  pair<int, int> pa; // Состоит из номеров вершин ребра
  link_edge() {}
  link_edge(int _component_number, point _first_point, pair<int, int> _pa)
  	: component_number(_component_number), first_point(_first_point), pa(_pa) {}
};

ostream& operator<<(ostream& o, link_edge le)
{
  return o << "componenta=" << le.component_number << " first point=" << le.first_point 
  	<< " (u,v)=(" << le.pa.first << "," << le.pa.second << ")\n";
}

// Граф плоской диаграммы зацепления (тень зацепления и все переходы)
class link_graph
{
public:
  // Вершины зацепления
  map<int, link_vertex> vertices;
  // Ребра графа зацепления
  map<int, link_edge> edges;
  // Число компонент зацепления (Не обязательная нужна переменная, его можно вычислить)
  int component_number;
  link_graph() {}
  link_graph(map<int, link_vertex> _vertices, map<int, link_edge> _edges, int _component_number)
  	: vertices(_vertices), edges(_edges), component_number(_component_number) { }
  void print_vertices(ostream& o);
  void print_edges(ostream& o);
  // Возвращает распутывающую последовательность - номера вершин, 
  //в которых нужно поменять знак, чтобы зацепление стало тривиальным (Это и есть решение) 
  list<int> getUntangleSequence();
  // Возвращает такое же зацепление, только в нем в перекрестке с номером num поменяли над и под
  link_graph get_L_wih_another_sign_on_this_place(int num);
  // Возвращает последовательность зацеплений, соответствующую распутывающей последовательности l
  // Первый член последовательности - тривиальное зацепление
  // Зацепление i отличается от зацепления i+1 только видом ровно одного перекрестка
  // Последний член последовательности - исходное зацепление
  list<link_graph> getLinkUntangleSequence(list<int> l);
  // Возвращает истину, если перекресток зацепления с номером num является положительным
  bool is_L_plus(int num);
  // 
  void dfs(int vertex, int previous_edge);
  // Дополнительные функции для получения L_0
  void change_vertices(int num);
  void delete_edge(int num);
  void change_edges(link_vertex lv);
  void change_components(link_vertex lv);
  // Начиная с ребра с номером edge_num идем по пути из ребер, делая каждому из встречающихся ребер номер компоненты равным component_num
  // или Начиная с ребра с номером edge_num идем по пути из ребер, добавляя их в список
  void make_component(int edge_num, int component_num, list<pair<int, link_edge> >* p_list = NULL);
  //
  link_graph get_L_0(int num);
  //
  polynom<int> getJonesPolynomOfTrivialLink();
  //
  polynom<int> getJonesPolynom(bool debug = false);
};

void link_graph::print_vertices(ostream& o)
{
  o << "vertex_number=" << vertices.size() << "\n";
  for(map<int, link_vertex>::iterator vit = vertices.begin(); vit != vertices.end(); vit++)
    o << "vertex " << (*vit).first << ": " << (*vit).second << "\n";
}

void link_graph::print_edges(ostream& o)
{
  o << "edge_number=" << edges.size() << "\n";
  for(map<int, link_edge>::iterator eit = edges.begin(); eit != edges.end(); eit++)
    o << "edge " << (*eit).first << ": " << (*eit).second << "\n";
}

ostream& operator<<(ostream& o, link_graph lg)
{
  o << "component_number=" << lg.component_number << "\n";
  lg.print_vertices(o);
  lg.print_edges(o);
  list<int> li = lg.getUntangleSequence();
//  cout << "Graph untangle sequence: ";
//  for(list<int>::iterator lit = li.begin(); lit != li.end(); lit++)
//    cout << *lit << " ";
//  cout << "\n";
  return o;
}

// Компонента зацепления
class link_component
{
public:
  // Последовательность точек (путь)
  list<point> points;
  // Каждый символ задает, под другой частью пути проходит путь ('-') или над ней ('+')
  string intersections;
  // Число ребер в компоненте зацепления
  unsigned edge_number;
  link_component(list<point> _points, string _intersections) : points(_points), intersections(_intersections) {}
};

ostream& operator<<(ostream& o, link_component lc)
{
  list<point>::iterator it;
  o << "way: ";
  for(it = lc.points.begin(); it != lc.points.end(); it++)
    o << *it << ",";
  o << "\nintersections=" << lc.intersections << "\nnumber of edges in componenta=" << lc.edge_number << "\n";
  return o;
}

list<int> link_graph::getUntangleSequence()
{
  list<int> l;
  if(vertices.size() == 0)
    return l;
  bool was[MAX_vertex_num];
  int second_vertex_number;
  for(int i = 0; i < MAX_vertex_num; i++)
    was[i] = false;
  map<int, list<pair<int, link_edge> > > component_lists;
  // Перебираем все ребра зацепления и кладем их по компонентам
  for(map<int, link_edge>::iterator eit = edges.begin(); eit != edges.end(); eit++)
    component_lists[eit->second.component_number].push_back(*eit);
  map<int, list<pair<int, link_edge> > >::iterator cit;
  list<pair<int, link_edge> > new_list;
  list<pair<int, link_edge> >::iterator ceit;

  for(cit = component_lists.begin(); cit != component_lists.end(); cit++)
  {
    make_component((cit->second.begin())->first, -1, &new_list);
    cit->second = new_list;
  }

  // Теперь будем перебирать все ребра по компонентам, а внутри каждой 
  // компоненты по порядку следования ребер вдоль нее (если второе условие не выполнено, то ошибка была только на узле 6_3)
  // 
   
  for(cit = component_lists.begin(); cit != component_lists.end(); cit++)
    for(ceit = cit->second.begin(); ceit != cit->second.end(); ceit++)
    {
      second_vertex_number = ceit->second.pa.second;
      if(vertices.find(second_vertex_number) == vertices.end())
        continue;
      //cout << ceit->first << ": " << ceit->second << "\n";
      if(!was[second_vertex_number]) // Если встретили вершину, в которую входит ребро, первый раз
      {
        was[second_vertex_number] = true;
        if(ceit->first == vertices[second_vertex_number].a) // Если ребро является ребром a для вершины, в которую оно входит
        {
          if(vertices[second_vertex_number].is_plus != 1)
          {
            //cout << "case 1";
            l.push_back(second_vertex_number);
          }
        }
        else if(ceit->first == vertices[second_vertex_number].c) // Если ребро является ребром c для вершины, в которую оно входит
        {
          if(vertices[second_vertex_number].is_plus != 0)
          {  
            //cout << "case 2";
            l.push_back(second_vertex_number);
          }
        }
        else
          assert(0); // Ребро всегда должно являться ребром a или c для вершины, в которую оно входит
      }
    }
  return l;
}

link_graph link_graph::get_L_wih_another_sign_on_this_place(int num)
{
  map<int, link_vertex> new_vertices = vertices;
  for(map<int, link_edge>::iterator it = edges.begin(); it != edges.end(); it++)
    if(it->second.pa.second == num)
    {
      assert(new_vertices.find(it->second.pa.second) != new_vertices.end());
      assert(vertices.find(it->second.pa.second) != vertices.end());
      new_vertices[it->second.pa.second].is_plus = 1 - vertices[it->second.pa.second].is_plus;
      new_vertices[it->second.pa.second].is_above = 1 - vertices[it->second.pa.second].is_above;
      break;
    }
  return link_graph(new_vertices, edges, component_number);
}

list<link_graph> link_graph::getLinkUntangleSequence(list<int> l)
{
  list<link_graph> link_list;
  list<link_graph> reverse_link_list;
  list<int>::iterator it;
  list<link_graph>::reverse_iterator rit;
  link_graph Link = *this;
  link_list.push_back(Link);
  for(it = l.begin(); it != l.end(); it++)
  {
    Link = Link.get_L_wih_another_sign_on_this_place(*it);
    link_list.push_back(Link);
  }
  for(rit = link_list.rbegin(); rit != link_list.rend(); rit++)
    reverse_link_list.push_back(*rit);
  return reverse_link_list;
}

void link_graph::make_component(int edge_num, int component_num, list<pair<int, link_edge> >* p_list)
{
  int current_edge_num = edge_num;
  link_vertex lv;
  assert(edges.find(current_edge_num) != edges.end());
  if(vertices.find(edges[current_edge_num].pa.second) == vertices.end())
    return;
  do
  {
    assert(edges.find(current_edge_num) != edges.end());
    assert(vertices.find(edges[current_edge_num].pa.second) != vertices.end());
    lv = vertices[edges[current_edge_num].pa.second];
    if(current_edge_num == lv.a)
      current_edge_num = lv.b; 
    else if(current_edge_num == lv.c)
      current_edge_num = lv.d; 
    else
      assert(0);
    assert(edges.find(current_edge_num) != edges.end());
    if(component_num == -1)
      p_list->push_back(make_pair(current_edge_num, edges[current_edge_num]));
    else
      edges[current_edge_num].component_number = component_num;
  }
  while(current_edge_num != edge_num);
}

bool link_graph::is_L_plus(int num)
{
  assert(vertices.find(num) != vertices.end());
  return vertices[num].is_plus;
}

void link_graph::change_vertices(int num)
{
  // У вершин, в которые входят ребра, исходящие из вершины num, нужно поменять номера входящих ребер
  
  assert(vertices.find(num) != vertices.end());
  assert(edges.find(vertices[num].b) != edges.end());
  assert(vertices.find(edges[vertices[num].b].pa.second) != vertices.end());
  link_vertex* lv = &vertices[edges[vertices[num].b].pa.second];

  if(lv->a == vertices[num].b)
    lv->a = vertices[num].c;
  else if(lv->c == vertices[num].b)    
    lv->c = vertices[num].c;
  else
    assert(0);

  assert(edges.find(vertices[num].d) != edges.end());
  assert(vertices.find(edges[vertices[num].d].pa.second) != vertices.end());
  lv = &vertices[edges[vertices[num].d].pa.second];
  
  if(lv->a == vertices[num].d)
    lv->a = vertices[num].a;
  else if(lv->c == vertices[num].d)    
    lv->c = vertices[num].a;
  else
    assert(0);

  // Удалить вершину num
  vertices.erase(vertices.find(num));
}

void link_graph::delete_edge(int num)
{
  map<int, link_edge>::iterator it = edges.find(num);
  // Если удалить ребро без следующего условия, то ошибка на тесте "links\\comp2\\link2_2.in"
  // Ошибка здесь также была бы на случае IIIa
  // Проверка, что ребро не ведет из вершины в нее же саму
  if(it->second.pa.first != it->second.pa.second) 
    edges.erase(it);
}

void link_graph::change_edges(link_vertex lv)
{
  
  // Здесь был большой баг
  // У ребер, входящих в вершину num, нужно поменять, куда они ведут
//  edges[lv.a].pa.second = edges[lv.b].pa.second;
//  edges[lv.c].pa.second = edges[lv.d].pa.second;


  // У ребер, входящих в вершину num, нужно поменять, куда они ведут
  assert(edges.find(lv.a) != edges.end());
  assert(edges.find(lv.b) != edges.end());
  assert(edges.find(lv.c) != edges.end());
  assert(edges.find(lv.d) != edges.end());
  edges[lv.a].pa.second = edges[lv.d].pa.second;
  edges[lv.c].pa.second = edges[lv.b].pa.second;



  // Удалить два ребра, исходящих из вершины num
//  if(!((lv.a == lv.d) && (lv.b == lv.c)))
  {
    delete_edge(lv.b);
    delete_edge(lv.d);
  }
}

void link_graph::change_components(link_vertex lv)
{
  if(vertices.size() == 0)
    component_number = edges.size();
  else
  {
    // Если пересекаются разные компоненты, то нужно сделать из них одну. Если одна, то нужно сделать разные
    // И изменить соответственно число компонент
    assert(edges.find(lv.a) != edges.end());
    assert(edges.find(lv.c) != edges.end());
    if(edges[lv.a].component_number != edges[lv.c].component_number)
    {
      make_component(lv.c, edges[lv.a].component_number);
      component_number--;
    }
    else
    {
      make_component(lv.c, MAXcomponent_number + 1);
      component_number++;
    }

    // Меняем номера компонент
    map<int, int> component_numbers;
    int i = 0;

    for(map<int, link_vertex>::iterator vit = vertices.begin(); vit != vertices.end(); vit++)
    {
      //assert(lg.edges[lg.vertices[i].a].component_number == lg.edges[lg.vertices[i].b].component_number);
      //assert(lg.edges[lg.vertices[i].c].component_number == lg.edges[lg.vertices[i].d].component_number);
      assert(edges.find(vit->second.a) != edges.end());
      assert(edges.find(vit->second.c) != edges.end());
      component_numbers[edges[vit->second.a].component_number] = 0;
      component_numbers[edges[vit->second.c].component_number] = 0;
    }
    for(map<int, int>::iterator it = component_numbers.begin(); it != component_numbers.end(); it++, i++)
      it->second = i;
    for(map<int, link_edge>::iterator mit = edges.begin(); mit != edges.end(); mit++)
      mit->second.component_number = component_numbers.find(mit->second.component_number)->second;
  }
}

link_graph link_graph::get_L_0(int num)
{
//  cout << "link_graph link_graph::get_L_0(int num)\n";

  assert(vertices.find(num) != vertices.end());

  link_vertex lv = vertices[num];
  link_graph lg(vertices, edges, component_number);
  
//  cout << "Now:\n";
//  lg.print_vertices(cout);
//  lg.print_edges(cout);

  lg.change_vertices(num);

//  cout << "change vertices:\n";
//  lg.print_vertices(cout);
//  lg.print_edges(cout);

  lg.change_edges(lv);

//  cout << "change edges:\n";
//  lg.print_vertices(cout);
//  lg.print_edges(cout);

  lg.change_components(lv);

//  cout << "change components:\n";
//  lg.print_vertices(cout);
//  lg.print_edges(cout);

  return lg;
}

polynom<int> link_graph::getJonesPolynomOfTrivialLink()
{
  polynom<int> res = one;
  int i;
  for(i = 1; i < component_number; i++)
    res = res * (-q_in_plus_1_plus_q_in_minus_1);
  return res; 
}

polynom<int> link_graph::getJonesPolynom(bool debug)
{
  if(debug) cout << "beg polynom<int> link_graph::getJonesPolynom()\n";

  list<int> l = getUntangleSequence();
  if(l.size() == 0)
    return getJonesPolynomOfTrivialLink();

  list<link_graph> link_sequence = getLinkUntangleSequence(l);
  
  list<link_graph>::iterator l_it = link_sequence.begin();
  // Первое зацепление в списке является тривиальным
  polynom<int> p = l_it -> getJonesPolynomOfTrivialLink();
  
  if(debug)
  cout << "Trivial link\n" << *l_it;
//  cout << "getJonesPolynomOfTrivialLink()=" << p << "\n";
  
  
  polynom<int> MinorJonesPolynom;

  if(debug)
  for(list<int>::reverse_iterator it = l.rbegin(); it != l.rend(); it++)
     cout << "untangle=" << *it << "\n";
    
  for(list<int>::reverse_iterator it = l.rbegin(); it != l.rend(); it++, l_it++)
  {
  if(debug)
  {  cout << "*it=" << *it << "\n";
    cout << "Checking knot:\n";
    cout << l_it -> get_L_0(*it);
  }
    MinorJonesPolynom = (l_it -> get_L_0(*it)).getJonesPolynom();




    if(l_it -> is_L_plus(*it))
    {
  if(debug)
      cout << "l_it -> is_L_plus(*it)   " << MinorJonesPolynom << "\n"; 
      p = (q_in_minus_2 * p - q_in_plus_1_minus_q_in_minus_1 * MinorJonesPolynom) * q_in_minus_2;
  if(debug)
      cout << "p= " << p;
    }
    else
    {
  if(debug)
      cout << "not l_it -> is_L_plus(*it)   " << MinorJonesPolynom << "\n"; 
      p = (q_in_plus_2 * p + q_in_plus_1_minus_q_in_minus_1 * MinorJonesPolynom) * q_in_plus_2;
  if(debug)
      cout << "p= "  << p;
    }  
  }
  if(debug)
  cout << "end link_graph::getJonesPolynom()\n"; 
  return p;
}

// here beg
// edges[, vertices[

// Плоская диаграмма зацепления
class link
{
public:
  // Список компонент зацепления
  vector<link_component> component_list;
  // Вершины зацепления 
  map<point, int> vertexMap;
  // Граф плоской диаграммы зацепления
  link_graph Graph;
  //
  link() {}
  //
  link(vector<link_component> _component_list);
};

link::link(vector<link_component> _component_list)
	: component_list(_component_list)
{
  unsigned k, c, i, prev_vertex, next_vertex;
  int vertex_number = 0;
  map<point, int> pointMap;
  vector<link_component>::iterator cit; 
  list<link_edge>::iterator lit;
  list<point>::iterator it, prev_vit, next_vit;
  
  Graph.component_number = component_list.size();
  // Делаем вершины графа
  for(cit = component_list.begin(); cit != component_list.end(); cit++)
    for(it = cit->points.begin(); it != cit->points.end(); it++)
    {
      if(pointMap.find(*it) == pointMap.end())
        pointMap.insert(make_pair(*it, 1));
      else
      {  
        vertexMap.insert(make_pair(*it, vertex_number));
        Graph.vertices[vertex_number].p = *it;
        vertex_number++;
      }
    }    

  // Делаем ребра графа
  for(k = 0, c = 0, cit = component_list.begin(); cit != component_list.end(); cit++, k += i, c++)
  {
    prev_vertex = -1;
    prev_vit = cit->points.begin();
    for(i = 0, it = cit->points.begin(); it != cit->points.end(); it++)
      if(vertexMap.find(*it) != vertexMap.end()) // Если текущая точка является вершиной
      {
        if(Graph.vertices[vertexMap[*it]].is_plus == -1) // Если она встретилась первый раз
        {
          if(cit->intersections[k + i] == '+')
            Graph.vertices[vertexMap[*it]].is_plus = Graph.vertices[vertexMap[*it]].is_above = 1;
          else
            Graph.vertices[vertexMap[*it]].is_plus = Graph.vertices[vertexMap[*it]].is_above = 0;
        }
        else // Если она встретилась второй раз
        {
          if(cit->intersections[k + i] == '+')
            assert(Graph.vertices[vertexMap[*it]].is_plus == 0);
          else
            ;//!!!!!!!!!!!!!!!!!!!!!!!!assert(Graph.vertices[vertexMap[*it]].is_plus == 1);
        }
        next_vertex = vertexMap[*it];
        next_vit = it;
        if(it != cit->points.end())
          next_vit++;
        else
          next_vit = cit->points.begin();
        Graph.edges.insert(make_pair(k + i, link_edge(c, *prev_vit, make_pair(prev_vertex, next_vertex))));
        i++;
        prev_vertex = next_vertex;
        prev_vit = next_vit;
      }
    cit->edge_number = i;
    Graph.edges[k].first_point = *prev_vit;    
    Graph.edges[k].pa.first = prev_vertex;
  }

  // Вершинам графа приписываем ребра графа
  for(k = 0, cit = component_list.begin(); cit != component_list.end(); cit++, k += i)
  {
    for(i = 0; i < cit->edge_number; i++)
    {
      if(Graph.vertices[Graph.edges[k + i].pa.second].a == -1)
      {
        Graph.vertices[Graph.edges[k + i].pa.second].a = k + i;
        Graph.vertices[Graph.edges[k + i].pa.second].b = k + (i + 1) % cit->edge_number;
      }
      else
      {
        Graph.vertices[Graph.edges[k + i].pa.second].c = k + i;
        Graph.vertices[Graph.edges[k + i].pa.second].d = k + (i + 1) % cit->edge_number;
      }
    }
  }
    
  // Расставляем правильно ребра у вершин
  for(k = 0; k < Graph.vertices.size(); k++)
  {
    if(vector_product(Graph.edges[Graph.vertices[k].d].first_point.first - Graph.vertices[k].p.first, 
    	Graph.edges[Graph.vertices[k].d].first_point.second - Graph.vertices[k].p.second, 
      	Graph.edges[Graph.vertices[k].b].first_point.first- Graph.vertices[k].p.first, 
      	Graph.edges[Graph.vertices[k].b].first_point.second - Graph.vertices[k].p.second) < 0)
    {
      swap(Graph.vertices[k].a, Graph.vertices[k].c);
      swap(Graph.vertices[k].b, Graph.vertices[k].d);
      Graph.vertices[k].is_plus = 1 - Graph.vertices[k].is_plus; 
    }
  }
}

ostream& operator<<(ostream& o, link l)
{
  int i;
  vector<link_component>::iterator it;
  list<int>::iterator lit;
  o << "Link:\n";
  for(it = l.component_list.begin(), i = 0; it != l.component_list.end(); it++, i++)
    o << "componenta " << i << ":\n" << *it << "\n";
  o << "Link graph:\n" << l.Graph << "\n";
  list<int> li = l.Graph.getUntangleSequence();
  cout << "Graph untangle sequence: ";
  for(lit = li.begin(); lit != li.end(); lit++)
    cout << *lit << " ";
  cout << "\n";

  return o;
}

// here end


void making_polynoms()
{
  list<int> l;
  
  l.push_back(1);
  one = polynom<int>(l, 0);
  l.clear();

  l.push_back(1);
  q_in_plus_2 = polynom<int>(l, 2);
  l.clear();

  l.push_back(1);
  q_in_minus_2 = polynom<int>(l, -2);
  l.clear();

  l.push_back(1);
  q_in_plus_1 = polynom<int>(l, 1);
  l.clear();

  l.push_back(1);
  q_in_minus_1 = polynom<int>(l, -1);
  l.clear();

  l.push_back(-1);
  l.push_back(0);
  l.push_back(1);
  q_in_plus_1_minus_q_in_minus_1 = polynom<int>(l, -1);
  l.clear();

  l.push_back(1);
  l.push_back(0);
  l.push_back(1);
  q_in_plus_1_plus_q_in_minus_1 = polynom<int>(l, -1);
  l.clear();
}

void print_polynoms()
{
  cout << "\n1=" << one;
  cout << "\nq^{2}=" << q_in_plus_2;
  cout << "\nq^{-2}=" << q_in_minus_2;
  cout << "\nq^{1}=" << q_in_plus_1;
  cout << "\nq^{-1}=" << q_in_minus_1;
  cout << "\nq^{1}-q^{-1}=" << q_in_plus_1_minus_q_in_minus_1;// << "=" << q_in_plus_1 - q_in_minus_1;
  cout << "\nq^{1}+q^{-1}=" << q_in_plus_1_plus_q_in_minus_1;// << "=" << q_in_plus_1 + q_in_minus_1;
  cout << "\n";

//  cout << "one * (-q_in_plus_1_plus_q_in_minus_1)=" << one * (-q_in_plus_1_plus_q_in_minus_1) << "\n";
  cout << "\n";
}


