📄 adjacency.cc
字号:
/* * adjacency.cc -- adjacency matrices for Click routers * Eddie Kohler * * Copyright (c) 1999-2000 Massachusetts Institute of Technology * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, subject to the conditions * listed in the Click LICENSE file. These conditions include: you must * preserve this copyright notice, and you cannot mention the copyright * holders in advertising related to the Software without their permission. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This * notice is a summary of the Click LICENSE file; the license in that file is * legally binding. */#include <click/config.h>#include "adjacency.hh"#include "routert.hh"#include <stdio.h>AdjacencyMatrix::AdjacencyMatrix(RouterT *r) : _x(0){ init(r);}AdjacencyMatrix::~AdjacencyMatrix(){ delete[] _x;}static inline unsignedtype_indicator(ElementClassT *t){ return (unsigned) (reinterpret_cast<uintptr_t>(t));}static inline unsignedconnection_indicator(int fromport, int toport){ int p1 = fromport % 16; int p2 = toport % 16; return (1U<<p1) | (1U<<(p2+16));}voidAdjacencyMatrix::init(RouterT *r){ _router = r; int n = _n = r->nelements(); _cap = 0; for (int i = 1; i < n; i *= 2) _cap++; int cap = _cap; delete[] _x; _x = new unsigned[1<<(2*cap)]; for (int i = 0; i < (1<<(2*cap)); i++) _x[i] = 0; _default_match.assign(n, -2); ElementClassT *tunnelt = ElementClassT::tunnel_type(); for (int i = 0; i < r->nelements(); i++) { const ElementT *e = r->element(i); if (e->type() != tunnelt) { _x[i + (i<<cap)] = type_indicator(e->type()); _default_match[i] = -1; } } // add connections int nh = r->nconnections(); if (nh) { // avoid bounds checks const ConnectionT *conn = &(r->connections()[0]); for (int i = 0; i < nh; i++) if (conn[i].live() && conn[i].from_eindex() != conn[i].to_eindex()) _x[ conn[i].from_eindex() + (conn[i].to_eindex()<<cap) ] |= connection_indicator(conn[i].from_port(), conn[i].to_port()); } _output_0_of.clear();}voidAdjacencyMatrix::update(const Vector<int> &changed_eindexes){ RouterT *r = _router; int cap = _cap; if (r->nelements() > (1<<cap) || r->nelements() >= r->n_live_elements() + 500) { r->remove_dead_elements(); init(r); return; } _n = r->nelements(); // clear out columns and rows _default_match.resize(_n, -2); Vector<int> updated_eindexes(_n, 0); ElementClassT *tunnelt = ElementClassT::tunnel_type(); for (int i = 0; i < changed_eindexes.size(); i++) { int j = changed_eindexes[i]; if (updated_eindexes[j]) continue; // clear column and row for (int k = 0; k < (1<<cap); k++) _x[ k + (j<<cap) ] = _x[ j + (k<<cap) ] = 0; // set type ElementClassT *t = r->element(j)->type(); if (t != tunnelt) { _x[ j + (j<<cap) ] = type_indicator(t); _default_match[j] = -1; } else _default_match[j] = -2; updated_eindexes[j] = 1; } // now set new connections int nh = r->nconnections(); if (nh) { // avoid bounds checks const ConnectionT *conn = &(r->connections()[0]); for (int i = 0; i < nh; i++) if (conn[i].live() && conn[i].from_eindex() != conn[i].to_eindex()) _x[ conn[i].from_eindex() + (conn[i].to_eindex()<<cap) ] |= connection_indicator(conn[i].from_port(), conn[i].to_port()); } _output_0_of.clear();}voidAdjacencyMatrix::init_pattern() const{ // checking for a single connection from output 0 RouterT *r = _router; Vector<int> output_0(_n, -1); const Vector<ConnectionT> &conn = r->connections(); for (int i = 0; i < conn.size(); i++) if (conn[i].live() && conn[i].from_port() == 0) { int fromi = conn[i].from_eindex(); if (conn[i].to_eindex() == fromi || output_0[fromi] >= 0) output_0[fromi] = -2; else if (output_0[fromi] == -1) output_0[fromi] = conn[i].to_eindex(); } // set _output_0_of _output_0_of.assign(_n, -1); for (int i = 0; i < _n; i++) if (output_0[i] >= 0) { int o = output_0[i]; if (_default_match[o] >= -1 && _default_match[i] >= -1 && o > i) _output_0_of[o] = i; }}voidAdjacencyMatrix::print() const{ for (int i = 0; i < _n; i++) { for (int j = 0; j < _n; j++) fprintf(stderr, "%3x ", _x[(i<<_cap) + j]); fprintf(stderr, "\n"); } fprintf(stderr, "\n");}boolAdjacencyMatrix::next_subgraph_isomorphism(const AdjacencyMatrix *input, Vector<ElementT *> &matchv_e) const{ int pat_n = _n; int pat_cap = _cap; unsigned *pat_x = _x; int input_cap = input->_cap; unsigned *input_x = input->_x; RouterT *input_r = input->_router; // assign 'matchv' from 'matchv_e' Vector<int> matchv(_default_match); int match_eindex; int direction; if (matchv_e.size() == 0) { match_eindex = 0; direction = 1; } else { for (int i = 0; i < matchv.size(); i++) if (matchv[i] == -1) matchv[i] = matchv_e[i]->eindex(); match_eindex = pat_n - 1; direction = -1; } int *match = &matchv[0]; // avoid bounds checks if (!_output_0_of.size()) init_pattern(); int *output_0_of = &_output_0_of[0]; //print(); //fprintf(stderr, "input:\n"); //input->print(); while (match_eindex >= 0 && match_eindex < pat_n) { int rover = match[match_eindex] + 1; int max_rover; if (rover < 0) { match_eindex += direction; continue; } else if (output_0_of[match_eindex] >= 0) { // Speed hack: often we have E1[0] -> [p]E2, the only connection from // E1[0], where E1 and E2 are both real elements in the pattern (not // 'input' or 'output'). In this case, the match to E2 will be the // single element connected from (match[E1])[0]. Find it directly so we // don't have to scan over all elements in the input. PortT output(input_r->element(match[output_0_of[match_eindex]]), 0), result; if (rover > 0 || !input_r->find_connection_from(output, result)) max_rover = -1; else { rover = result.eindex(); max_rover = rover + 1; } } else max_rover = input->_n; while (rover < max_rover) { // S_{k,k}(input) =? S_{k,n}(P) * M * (S_{k,n}(P))^T // first check the diagonal (where element type) if (pat_x[ (match_eindex<<pat_cap) + match_eindex ] != input_x[ (rover<<input_cap) + rover ]) goto failure; // test only the new border for (int i = 0; i < match_eindex; i++) { int m = match[i]; if (m >= 0) { unsigned px = pat_x[ (i<<pat_cap) + match_eindex ]; unsigned ix = input_x[ (m<<input_cap) + rover ]; if ((px & ix) != px) goto failure; } } for (int j = 0; j < match_eindex; j++) { int m = match[j]; if (m >= 0) { unsigned px = pat_x[ (match_eindex<<pat_cap) + j ]; unsigned ix = input_x[ (rover<<input_cap) + m ]; if ((px & ix) != px) goto failure; } } break; failure: rover++; } if (rover < max_rover) { match[match_eindex] = rover; match_eindex++; direction = 1; } else { match[match_eindex] = -1; match_eindex--; direction = -1; } } // initialize 'matchv_e' from 'matchv' matchv_e.assign(matchv.size(), 0); for (int i = 0; i < match_eindex; i++) if (match[i] >= 0) matchv_e[i] = input_r->element(match[i]); //for (int i = 0; i < pat_n; i++) fprintf(stderr,"%d ", match[i]);/* >= 0 ? input->_crap->ename(match[i]).cc() : "<crap>");*/fputs("\n",stderr); return (match_eindex >= 0 ? true : false);}boolcheck_subgraph_isomorphism(const RouterT *pat, const RouterT *input, const Vector<ElementT *> &match){ // check connections const Vector<ConnectionT> &conn = pat->connections(); int nh = conn.size(); for (int i = 0; i < nh; i++) { int fi = conn[i].from_eindex(), ti = conn[i].to_eindex(); if (!match[fi] || !match[ti]) continue; if (!input->has_connection(PortT(match[fi], conn[i].from_port()), PortT(match[ti], conn[i].to_port()))) return false; } return true;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -