madarasip@1350: /* -*- mode: C++; indent-tabs-mode: nil; -*- madarasip@1350: * madarasip@1350: * This file is a part of LEMON, a generic C++ optimization library. madarasip@1350: * madarasip@1405: * Copyright (C) 2015-2017 madarasip@1350: * EMAXA Kutato-fejleszto Kft. (EMAXA Research Ltd.) madarasip@1350: * madarasip@1350: * Permission to use, modify and distribute this software is granted madarasip@1350: * provided that this copyright notice appears in all copies. For madarasip@1350: * precise terms see the accompanying LICENSE file. madarasip@1350: * madarasip@1350: * This software is provided "AS IS" with no warranty of any kind, madarasip@1350: * express or implied, and with no claim as to its suitability for any madarasip@1350: * purpose. madarasip@1350: * madarasip@1350: */ madarasip@1350: madarasip@1350: #include kpeter@1406: #include madarasip@1350: #include madarasip@1350: #include madarasip@1350: #include madarasip@1350: #include madarasip@1350: madarasip@1350: #include madarasip@1350: #include madarasip@1350: madarasip@1350: using namespace lemon; madarasip@1350: madarasip@1350: char petersen_lgf[] = madarasip@1350: "@nodes\n" madarasip@1350: "label col1 col2\n" madarasip@1350: "0 1 1\n" madarasip@1350: "1 1 2\n" madarasip@1350: "2 1 3\n" madarasip@1350: "3 1 4\n" madarasip@1350: "4 2 5\n" madarasip@1350: "5 2 1\n" madarasip@1350: "6 2 2\n" madarasip@1350: "7 2 3\n" madarasip@1350: "8 2 4\n" madarasip@1350: "9 2 5\n" madarasip@1350: "@arcs\n" madarasip@1350: " -\n" madarasip@1350: "0 1\n" madarasip@1350: "1 2\n" madarasip@1350: "2 3\n" madarasip@1350: "3 4\n" madarasip@1350: "4 0\n" madarasip@1350: "0 5\n" madarasip@1350: "1 6\n" madarasip@1350: "2 7\n" madarasip@1350: "3 8\n" madarasip@1350: "4 9\n" madarasip@1350: "5 8\n" madarasip@1350: "5 7\n" madarasip@1350: "9 6\n" madarasip@1350: "9 7\n" madarasip@1350: "6 8\n"; madarasip@1350: madarasip@1350: char c5_lgf[] = madarasip@1350: "@nodes\n" madarasip@1350: "label col\n" madarasip@1350: "0 1\n" madarasip@1350: "1 2\n" madarasip@1350: "2 3\n" madarasip@1350: "3 4\n" madarasip@1350: "4 5\n" madarasip@1350: "@arcs\n" madarasip@1350: " -\n" madarasip@1350: "0 1\n" madarasip@1350: "1 2\n" madarasip@1350: "2 3\n" madarasip@1350: "3 4\n" madarasip@1350: "4 0\n"; madarasip@1350: madarasip@1350: char c7_lgf[] = madarasip@1350: "@nodes\n" madarasip@1350: "label\n" madarasip@1350: "0\n" madarasip@1350: "1\n" madarasip@1350: "2\n" madarasip@1350: "3\n" madarasip@1350: "4\n" madarasip@1350: "5\n" madarasip@1350: "6\n" madarasip@1350: "@arcs\n" madarasip@1350: " -\n" madarasip@1350: "0 1\n" madarasip@1350: "1 2\n" madarasip@1350: "2 3\n" madarasip@1350: "3 4\n" madarasip@1350: "4 5\n" madarasip@1350: "5 6\n" madarasip@1350: "6 0\n"; madarasip@1350: madarasip@1350: char c10_lgf[] = madarasip@1350: "@nodes\n" madarasip@1350: "label\n" madarasip@1350: "0\n" madarasip@1350: "1\n" madarasip@1350: "2\n" madarasip@1350: "3\n" madarasip@1350: "4\n" madarasip@1350: "5\n" madarasip@1350: "6\n" madarasip@1350: "7\n" madarasip@1350: "8\n" madarasip@1350: "9\n" madarasip@1350: "@arcs\n" madarasip@1350: " -\n" madarasip@1350: "0 1\n" madarasip@1350: "1 2\n" madarasip@1350: "2 3\n" madarasip@1350: "3 4\n" madarasip@1350: "4 5\n" madarasip@1350: "5 6\n" madarasip@1350: "6 7\n" madarasip@1350: "7 8\n" madarasip@1350: "8 9\n" madarasip@1350: "9 0\n"; madarasip@1350: madarasip@1350: char p10_lgf[] = madarasip@1350: "@nodes\n" madarasip@1350: "label\n" madarasip@1350: "0\n" madarasip@1350: "1\n" madarasip@1350: "2\n" madarasip@1350: "3\n" madarasip@1350: "4\n" madarasip@1350: "5\n" madarasip@1350: "6\n" madarasip@1350: "7\n" madarasip@1350: "8\n" madarasip@1350: "9\n" madarasip@1350: "@arcs\n" madarasip@1350: " -\n" madarasip@1350: "0 1\n" madarasip@1350: "1 2\n" madarasip@1350: "2 3\n" madarasip@1350: "3 4\n" madarasip@1350: "4 5\n" madarasip@1350: "5 6\n" madarasip@1350: "6 7\n" madarasip@1350: "7 8\n" madarasip@1350: "8 9\n"; madarasip@1350: madarasip@1350: SmartGraph petersen, c5, c7, c10, p10; madarasip@1350: SmartGraph::NodeMap petersen_col1(petersen); madarasip@1350: SmartGraph::NodeMap petersen_col2(petersen); madarasip@1350: SmartGraph::NodeMap c5_col(c5); madarasip@1350: madarasip@1350: void make_graphs() { madarasip@1350: std::stringstream ss(petersen_lgf); madarasip@1350: graphReader(petersen, ss) kpeter@1406: .nodeMap("col1", petersen_col1) kpeter@1406: .nodeMap("col2", petersen_col2) madarasip@1350: .run(); madarasip@1350: madarasip@1350: ss.clear(); madarasip@1350: ss.str(""); kpeter@1406: ss << c5_lgf; madarasip@1350: //std::stringstream ss2(c5_lgf); madarasip@1350: graphReader(c5, ss) kpeter@1406: .nodeMap("col", c5_col) madarasip@1350: .run(); madarasip@1350: madarasip@1350: ss.clear(); madarasip@1350: ss.str(""); kpeter@1406: ss << c7_lgf; madarasip@1350: graphReader(c7, ss).run(); madarasip@1350: madarasip@1350: ss.clear(); madarasip@1350: ss.str(""); kpeter@1406: ss << c10_lgf; madarasip@1350: graphReader(c10, ss).run(); madarasip@1350: madarasip@1350: ss.clear(); madarasip@1350: ss.str(""); kpeter@1406: ss << p10_lgf; madarasip@1350: graphReader(p10, ss).run(); madarasip@1350: madarasip@1350: } madarasip@1350: madarasip@1350: class EqComparable { madarasip@1350: public: madarasip@1405: bool operator==(const EqComparable&) { madarasip@1405: return false; madarasip@1405: } madarasip@1350: }; madarasip@1350: madarasip@1350: template madarasip@1350: class EqClass { madarasip@1350: public: madarasip@1405: bool operator()(A, B){ madarasip@1405: return false; madarasip@1405: } madarasip@1350: }; madarasip@1350: kpeter@1406: class IntConvertible1 { kpeter@1406: public: kpeter@1406: operator int() { kpeter@1406: return 0; kpeter@1406: } kpeter@1406: }; kpeter@1406: kpeter@1406: class IntConvertible2 { kpeter@1406: public: kpeter@1406: operator int() { kpeter@1406: return 0; kpeter@1406: } kpeter@1406: }; kpeter@1406: madarasip@1350: template madarasip@1405: void checkVf2Compile() { madarasip@1350: G1 g; madarasip@1350: G2 h; madarasip@1350: concepts::ReadWriteMap r; madarasip@1350: bool succ; madarasip@1350: ::lemon::ignore_unused_variable_warning(succ); madarasip@1350: madarasip@1350: succ = vf2(g,h).run(); madarasip@1350: succ = vf2(g,h).induced().run(); madarasip@1350: succ = vf2(g,h).iso().run(); madarasip@1350: succ = vf2(g,h).mapping(r).run(); madarasip@1405: madarasip@1405: Vf2, madarasip@1405: EqClass > madarasip@1405: myVf2(g,h,r,EqClass()); madarasip@1405: myVf2.find(); madarasip@1405: madarasip@1350: succ = vf2(g,h).induced().mapping(r).run(); madarasip@1350: succ = vf2(g,h).iso().mapping(r).run(); madarasip@1405: madarasip@1350: concepts::ReadMap l1; madarasip@1350: concepts::ReadMap l2; madarasip@1350: succ = vf2(g,h).nodeLabels(l1,l2).mapping(r).run(); madarasip@1350: succ = vf2(g,h).nodeEq(EqClass()) madarasip@1350: .mapping(r).run(); madarasip@1350: } madarasip@1350: kpeter@1406: void vf2Compile() { madarasip@1350: checkVf2Compile(); madarasip@1350: checkVf2Compile(); madarasip@1350: checkVf2Compile(); madarasip@1350: } madarasip@1350: kpeter@1406: template kpeter@1406: void checkVf2ppCompile() { kpeter@1406: G1 g; kpeter@1406: G2 h; kpeter@1406: concepts::ReadWriteMap r; kpeter@1406: bool succ; kpeter@1406: ::lemon::ignore_unused_variable_warning(succ); kpeter@1406: kpeter@1406: succ = vf2pp(g,h).run(); kpeter@1406: succ = vf2pp(g,h).induced().run(); kpeter@1406: succ = vf2pp(g,h).iso().run(); kpeter@1406: succ = vf2pp(g,h).mapping(r).run(); kpeter@1406: succ = vf2pp(g,h).induced().mapping(r).run(); kpeter@1406: succ = vf2pp(g,h).iso().mapping(r).run(); kpeter@1406: kpeter@1406: concepts::ReadMap c1; kpeter@1406: concepts::ReadMap c2; kpeter@1406: Vf2pp, kpeter@1406: concepts::ReadMap, kpeter@1406: concepts::ReadMap > kpeter@1406: myVf2pp(g,h,r,c1,c2); kpeter@1406: myVf2pp.find(); kpeter@1406: kpeter@1406: succ = vf2pp(g,h).nodeLabels(c1,c2).mapping(r).run(); kpeter@1406: succ = vf2pp(g,h).nodeLabels(c1,c2).mapping(r).run(); kpeter@1406: kpeter@1406: concepts::ReadMap c1_c; kpeter@1406: concepts::ReadMap c2_c; kpeter@1406: Vf2pp, kpeter@1406: concepts::ReadMap, kpeter@1406: concepts::ReadMap > kpeter@1406: myVf2pp_c(g,h,r,c1_c,c2_c); kpeter@1406: myVf2pp_c.find(); kpeter@1406: kpeter@1406: succ = vf2pp(g,h).nodeLabels(c1_c,c2_c).mapping(r).run(); kpeter@1406: succ = vf2pp(g,h).nodeLabels(c1_c,c2_c).mapping(r).run(); kpeter@1406: kpeter@1406: concepts::ReadMap c1_IntConv; kpeter@1406: concepts::ReadMap c2_IntConv; kpeter@1406: Vf2pp, kpeter@1406: concepts::ReadMap, kpeter@1406: concepts::ReadMap > kpeter@1406: myVf2pp_IntConv(g,h,r,c1_IntConv,c2_IntConv); kpeter@1406: myVf2pp_IntConv.find(); kpeter@1406: kpeter@1406: succ = vf2pp(g,h).nodeLabels(c1_IntConv,c2_IntConv).mapping(r).run(); kpeter@1406: succ = vf2pp(g,h).nodeLabels(c1_IntConv,c2_IntConv).mapping(r).run(); kpeter@1406: } kpeter@1406: kpeter@1406: void vf2ppCompile() { kpeter@1406: checkVf2ppCompile(); kpeter@1406: checkVf2ppCompile(); kpeter@1406: checkVf2ppCompile(); madarasip@1350: } madarasip@1350: madarasip@1350: template kpeter@1406: void checkSubIso(const G1 &g1, const G2 &g2, const I &i) { madarasip@1350: std::set image; kpeter@1406: for (typename G1::NodeIt n(g1);n!=INVALID;++n){ madarasip@1350: check(i[n]!=INVALID, "Wrong isomorphism: incomplete mapping."); madarasip@1350: check(image.count(i[n])==0,"Wrong isomorphism: not injective."); madarasip@1350: image.insert(i[n]); madarasip@1405: } kpeter@1406: for (typename G1::EdgeIt e(g1);e!=INVALID;++e) { kpeter@1406: check(findEdge(g2,i[g1.u(e)],i[g1.v(e)])!=INVALID, kpeter@1406: "Wrong isomorphism: missing edge(checkSub)."); kpeter@1406: } kpeter@1406: } kpeter@1406: kpeter@1406: template kpeter@1406: void checkIndIso(const G1 &g1, const G2 &g2, const I &i) { kpeter@1406: std::set image; kpeter@1406: for (typename G1::NodeIt n(g1);n!=INVALID;++n) { kpeter@1406: check(i[n]!=INVALID, "Wrong isomorphism: incomplete mapping."); kpeter@1406: check(image.count(i[n])==0,"Wrong isomorphism: not injective."); kpeter@1406: image.insert(i[n]); kpeter@1406: } kpeter@1406: for (typename G1::NodeIt n(g1); n!=INVALID; ++n) { kpeter@1406: for (typename G1::NodeIt m(g1); m!=INVALID; ++m) { madarasip@1405: if((findEdge(g1,n,m)==INVALID) != (findEdge(g2,i[n],i[m])==INVALID)) { madarasip@1350: std::cout << "Wrong isomorphism: edge mismatch"; madarasip@1350: exit(1); madarasip@1405: } kpeter@1406: } kpeter@1406: } madarasip@1350: } madarasip@1350: kpeter@1406: template kpeter@1406: bool checkSub(const G1 &g1, const G2 &g2, const T &vf2) { madarasip@1350: typename G1:: template NodeMap iso(g1,INVALID); kpeter@1406: if (const_cast(vf2).mapping(iso).run()) { kpeter@1406: checkSubIso(g1,g2,iso); madarasip@1405: return true; madarasip@1405: } kpeter@1406: return false; madarasip@1350: } madarasip@1350: kpeter@1406: template kpeter@1406: bool checkInd(const G1 &g1, const G2 &g2, const T &vf2) { madarasip@1350: typename G1:: template NodeMap iso(g1,INVALID); kpeter@1406: if (const_cast(vf2).induced().mapping(iso).run()) { kpeter@1406: checkIndIso(g1,g2,iso); madarasip@1405: return true; madarasip@1405: } kpeter@1406: return false; madarasip@1405: } madarasip@1405: kpeter@1406: template kpeter@1406: bool checkIso(const G1 &g1, const G2 &g2, const T &vf2) { madarasip@1405: typename G1:: template NodeMap iso(g1,INVALID); kpeter@1406: if (const_cast(vf2).iso().mapping(iso).run()) { madarasip@1405: check(countNodes(g1)==countNodes(g2), madarasip@1405: "Wrong iso alg.: they are not isomophic."); kpeter@1406: checkIndIso(g1,g2,iso); madarasip@1405: return true; madarasip@1405: } kpeter@1406: return false; madarasip@1350: } madarasip@1350: madarasip@1350: template madarasip@1350: void checkLabel(const G1 &g1, const G2 &, kpeter@1406: const L1 &l1, const L2 &l2, const I &i) { kpeter@1406: for (typename G1::NodeIt n(g1);n!=INVALID;++n) { madarasip@1405: check(l1[n]==l2[i[n]],"Wrong isomorphism: label mismatch."); kpeter@1406: } kpeter@1406: } kpeter@1406: kpeter@1406: template kpeter@1406: bool checkSub(const G1 &g1, const G2 &g2, const L1 &l1, const L2 &l2, const T &vf2) { kpeter@1406: typename G1:: template NodeMap iso(g1,INVALID); kpeter@1406: if (const_cast(vf2).nodeLabels(l1,l2).mapping(iso).run()){ kpeter@1406: checkSubIso(g1,g2,iso); kpeter@1406: checkLabel(g1,g2,l1,l2,iso); kpeter@1406: return true; kpeter@1406: } kpeter@1406: return false; kpeter@1406: } kpeter@1406: kpeter@1406: template kpeter@1406: void checkSub(const G1 &g1, const G2 &g2, bool expected, const char* msg) { kpeter@1406: check(checkSub(g1,g2,vf2(g1,g2)) == expected, msg); kpeter@1406: check(checkSub(g1,g2,vf2pp(g1,g2)) == expected, msg); kpeter@1406: } kpeter@1406: kpeter@1406: template kpeter@1406: void checkInd(const G1 &g1, const G2 &g2, bool expected, const char* msg) { kpeter@1406: check(checkInd(g1,g2,vf2(g1,g2)) == expected, msg); kpeter@1406: check(checkInd(g1,g2,vf2pp(g1,g2)) == expected, msg); kpeter@1406: } kpeter@1406: kpeter@1406: template kpeter@1406: void checkIso(const G1 &g1, const G2 &g2, bool expected, const char* msg) { kpeter@1406: check(checkIso(g1,g2,vf2(g1,g2)) == expected, msg); kpeter@1406: check(checkIso(g1,g2,vf2pp(g1,g2)) == expected, msg); madarasip@1350: } madarasip@1350: madarasip@1350: template kpeter@1406: void checkSub(const G1 &g1, const G2 &g2, const L1 &l1, const L2 &l2, bool expected, const char* msg) { kpeter@1406: check(checkSub(g1,g2,l1,l2,vf2(g1,g2)) == expected, msg); kpeter@1406: check(checkSub(g1,g2,l1,l2,vf2pp(g1,g2)) == expected, msg); madarasip@1350: } madarasip@1350: madarasip@1350: int main() { madarasip@1350: make_graphs(); madarasip@1350: kpeter@1406: checkSub(c5,petersen,true, kpeter@1406: "There should exist a C5->Petersen mapping."); kpeter@1406: checkSub(c7,petersen,false, kpeter@1406: "There should not exist a C7->Petersen mapping."); kpeter@1406: checkSub(p10,petersen,true, kpeter@1406: "There should exist a P10->Petersen mapping."); kpeter@1406: checkSub(c10,petersen,false, kpeter@1406: "There should not exist a C10->Petersen mapping."); kpeter@1406: checkSub(petersen,petersen,true, kpeter@1406: "There should exist a Petersen->Petersen mapping."); kpeter@1406: kpeter@1406: checkInd(c5,petersen,true, kpeter@1406: "There should exist a C5->Petersen spanned mapping."); kpeter@1406: checkInd(c7,petersen,false, kpeter@1406: "There should exist a C7->Petersen spanned mapping."); kpeter@1406: checkInd(p10,petersen,false, kpeter@1406: "There should not exist a P10->Petersen spanned mapping."); kpeter@1406: checkInd(c10,petersen,false, kpeter@1406: "There should not exist a C10->Petersen spanned mapping."); kpeter@1406: checkInd(petersen,petersen,true, madarasip@1350: "There should exist a Petersen->Petersen spanned mapping."); madarasip@1350: kpeter@1406: checkSub(petersen,c10,false, kpeter@1406: "There should not exist a Petersen->C10 mapping."); kpeter@1406: checkSub(p10,c10,true, kpeter@1406: "There should exist a P10->C10 mapping."); kpeter@1406: checkInd(p10,c10,false, kpeter@1406: "There should not exist a P10->C10 spanned mapping."); kpeter@1406: checkSub(c10,p10,false, kpeter@1406: "There should not exist a C10->P10 mapping."); madarasip@1350: kpeter@1406: checkIso(p10,c10,false, kpeter@1406: "P10 and C10 are not isomorphic."); kpeter@1406: checkIso(c10,c10,true, kpeter@1406: "C10 and C10 are isomorphic."); alpar@1352: kpeter@1406: checkSub(c5,petersen,c5_col,petersen_col1,false, kpeter@1406: "There should exist a C5->Petersen mapping."); kpeter@1406: checkSub(c5,petersen,c5_col,petersen_col2,true, kpeter@1406: "There should exist a C5->Petersen mapping."); madarasip@1350: kpeter@1406: check(!vf2(p10,c10).iso().run(), "P10 and C10 are not isomorphic."); kpeter@1406: check(!vf2pp(p10,c10).iso().run(), "P10 and C10 are not isomorphic."); kpeter@1406: kpeter@1406: check(vf2(c10,c10).iso().run(), "C10 and C10 are isomorphic."); kpeter@1406: check(vf2pp(c10,c10).iso().run(), "C10 and C10 are isomorphic."); madarasip@1350: }