1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2015-2017
6 * EMAXA Kutato-fejleszto Kft. (EMAXA Research Ltd.)
8 * Permission to use, modify and distribute this software is granted
9 * provided that this copyright notice appears in all copies. For
10 * precise terms see the accompanying LICENSE file.
12 * This software is provided "AS IS" with no warranty of any kind,
13 * express or implied, and with no claim as to its suitability for any
18 #include <lemon/vf2pp.h>
19 #include <lemon/concepts/digraph.h>
20 #include <lemon/smart_graph.h>
21 #include <lemon/lgf_reader.h>
22 #include <lemon/concepts/maps.h>
23 #include <lemon/maps.h>
24 #include <lemon/list_graph.h>
26 #include <test/test_tools.h>
29 using namespace lemon;
149 SmartGraph petersen, c5, c7, c10, p10;
150 SmartGraph::NodeMap<int> petersen_col1(petersen);
151 SmartGraph::NodeMap<int> petersen_col2(petersen);
152 SmartGraph::NodeMap<int> c5_col(c5);
155 std::stringstream ss(petersen_lgf);
156 graphReader(petersen, ss)
157 .nodeMap("col1",petersen_col1)
158 .nodeMap("col2",petersen_col2)
166 .nodeMap("col",c5_col)
172 graphReader(c7, ss).run();
177 graphReader(c10, ss).run();
182 graphReader(p10, ss).run();
186 class IntConvertible1{
193 class IntConvertible2{
200 template<class G1,class G2>
201 void checkVf2Compile() {
204 concepts::ReadWriteMap<typename G1::Node, typename G2::Node> r;
206 ::lemon::ignore_unused_variable_warning(succ);
208 succ = vf2pp(g,h).run();
209 succ = vf2pp(g,h).induced().run();
210 succ = vf2pp(g,h).iso().run();
211 succ = vf2pp(g,h).mapping(r).run();
212 succ = vf2pp(g,h).induced().mapping(r).run();
213 succ = vf2pp(g,h).iso().mapping(r).run();
216 concepts::ReadMap<typename G1::Node, int> c1;
217 concepts::ReadMap<typename G2::Node, int> c2;
218 Vf2pp<G1,G2,concepts::ReadWriteMap<typename G1::Node, typename G2::Node>,
219 concepts::ReadMap<typename G1::Node, int>,
220 concepts::ReadMap<typename G2::Node, int> >
221 myVf2pp(g,h,r,c1,c2);
224 succ = vf2pp(g,h).nodeLabels(c1,c2).mapping(r).run();
225 succ = vf2pp(g,h).nodeLabels(c1,c2)
229 concepts::ReadMap<typename G1::Node, char> c1_c;
230 concepts::ReadMap<typename G2::Node, char> c2_c;
231 Vf2pp<G1,G2,concepts::ReadWriteMap<typename G1::Node, typename G2::Node>,
232 concepts::ReadMap<typename G1::Node, char>,
233 concepts::ReadMap<typename G2::Node, char> >
234 myVf2pp_c(g,h,r,c1_c,c2_c);
237 succ = vf2pp(g,h).nodeLabels(c1_c,c2_c).mapping(r).run();
238 succ = vf2pp(g,h).nodeLabels(c1_c,c2_c)
242 concepts::ReadMap<typename G1::Node, IntConvertible1> c1_IntConv;
243 concepts::ReadMap<typename G2::Node, IntConvertible2> c2_IntConv;
244 Vf2pp<G1,G2,concepts::ReadWriteMap<typename G1::Node, typename G2::Node>,
245 concepts::ReadMap<typename G1::Node, IntConvertible1>,
246 concepts::ReadMap<typename G2::Node, IntConvertible2> >
247 myVf2pp_IntConv(g,h,r,c1_IntConv,c2_IntConv);
248 myVf2pp_IntConv.find();
250 succ = vf2pp(g,h).nodeLabels(c1_IntConv,c2_IntConv).mapping(r).run();
251 succ = vf2pp(g,h).nodeLabels(c1_IntConv,c2_IntConv)
256 checkVf2Compile<concepts::Graph,concepts::Graph>();
257 checkVf2Compile<concepts::Graph,SmartGraph>();
258 checkVf2Compile<SmartGraph,concepts::Graph>();
261 template<class G1, class G2, class I>
262 void checkSub(const G1 &g1, const G2 &g2, const I &i) {
264 std::set<typename G2::Node> image;
265 for(typename G1::NodeIt n(g1);n!=INVALID;++n){
266 check(i[n]!=INVALID, "Wrong isomorphism: incomplete mapping.");
267 check(image.count(i[n])==0,"Wrong isomorphism: not injective.");
271 for(typename G1::EdgeIt e(g1);e!=INVALID;++e)
272 check(findEdge(g2,i[g1.u(e)],i[g1.v(e)])!=INVALID,
273 "Wrong isomorphism: missing edge(checkSub).");
276 template<class G1, class G2, class I>
277 void checkInd(const G1 &g1, const G2 &g2, const I &i) {
278 std::set<typename G2::Node> image;
279 for(typename G1::NodeIt n(g1);n!=INVALID;++n) {
280 check(i[n]!=INVALID, "Wrong isomorphism: incomplete mapping.");
281 check(image.count(i[n])==0,"Wrong isomorphism: not injective.");
284 for(typename G1::NodeIt n(g1); n!=INVALID; ++n)
285 for(typename G1::NodeIt m(g1); m!=INVALID; ++m)
286 if((findEdge(g1,n,m)==INVALID) != (findEdge(g2,i[n],i[m])==INVALID)) {
287 std::cout << "Wrong isomorphism: edge mismatch";
292 template<class G1,class G2>
293 int checkSub(const G1 &g1, const G2 &g2) {
294 typename G1:: template NodeMap<typename G2::Node> iso(g1,INVALID);
295 if(vf2pp(g1,g2).mapping(iso).run()){
303 template<class G1,class G2>
304 int checkInd(const G1 &g1, const G2 &g2) {
305 typename G1:: template NodeMap<typename G2::Node> iso(g1,INVALID);
306 if(vf2pp(g1,g2).induced().mapping(iso).run()) {
314 template<class G1,class G2>
315 int checkIso(const G1 &g1, const G2 &g2) {
316 typename G1:: template NodeMap<typename G2::Node> iso(g1,INVALID);
317 if(vf2pp(g1,g2).iso().mapping(iso).run()) {
318 check(countNodes(g1)==countNodes(g2),
319 "Wrong iso alg.: they are not isomophic.");
327 template<class G1, class G2, class L1, class L2, class I>
328 void checkLabel(const G1 &g1, const G2 &,
329 const L1 &l1, const L2 &l2,const I &i) {
330 for(typename G1::NodeIt n(g1);n!=INVALID;++n)
331 check(l1[n]==l2[i[n]],"Wrong isomorphism: label mismatch.");
334 template<class G1,class G2,class L1,class L2>
335 int checkSub(const G1 &g1, const G2 &g2, const L1 &l1, const L2 &l2) {
336 typename G1:: template NodeMap<typename G2::Node> iso(g1,INVALID);
337 if(vf2pp(g1,g2).nodeLabels(l1,l2).mapping(iso).run()) {
339 checkLabel(g1,g2,l1,l2,iso);
349 check(checkSub(c5,petersen), "There should exist a C5->Petersen mapping.");
350 check(!checkSub(c7,petersen),
351 "There should not exist a C7->Petersen mapping.");
352 check(checkSub(p10,petersen), "There should exist a P10->Petersen mapping.");
353 check(!checkSub(c10,petersen),
354 "There should not exist a C10->Petersen mapping.");
355 check(checkSub(petersen,petersen),
356 "There should exist a Petersen->Petersen mapping.");
358 check(checkInd(c5,petersen),
359 "There should exist a C5->Petersen spanned mapping.");
360 check(!checkInd(c7,petersen),
361 "There should exist a C7->Petersen spanned mapping.");
362 check(!checkInd(p10,petersen),
363 "There should not exist a P10->Petersen spanned mapping.");
364 check(!checkInd(c10,petersen),
365 "There should not exist a C10->Petersen spanned mapping.");
366 check(checkInd(petersen,petersen),
367 "There should exist a Petersen->Petersen spanned mapping.");
369 check(!checkSub(petersen,c10),
370 "There should not exist a Petersen->C10 mapping.");
371 check(checkSub(p10,c10),
372 "There should exist a P10->C10 mapping.");
373 check(!checkInd(p10,c10),
374 "There should not exist a P10->C10 spanned mapping.");
375 check(!checkSub(c10,p10),
376 "There should not exist a C10->P10 mapping.");
378 check(!checkIso(p10,c10),
379 "P10 and C10 are not isomorphic.");
380 check(checkIso(c10,c10),
381 "C10 and C10 are isomorphic.");
383 check(!vf2pp(p10,c10).iso().run(),
384 "P10 and C10 are not isomorphic.");
385 check(vf2pp(c10,c10).iso().run(),
386 "C10 and C10 are isomorphic.");
388 check(!checkSub(c5,petersen,c5_col,petersen_col1),
389 "There should exist a C5->Petersen mapping.");
390 check(checkSub(c5,petersen,c5_col,petersen_col2),
391 "There should exist a C5->Petersen mapping.");