随机收缩算法

来源:互联网 发布:死神方便知乎 编辑:程序博客网 时间:2024/05/18 00:58

随机收缩算法

  • 随机收缩算法
    • 一些基本定义
      • 图graph
      • 割cut
      • 连接边crossing edge
    • 最小割问题
    • Random Contraction Algorithm
    • 算法实现
      • 数据结构设计
      • coding

最近学习Tim Roughgarden 的Algorithm课程,就写一下笔记吧。

一些基本定义

图(graph)

一个图由两部分组成:顶点(vertex)和(edge)。顶点集用V表示,边集用E表示。
图可以分为有向图和无向图。

割(cut)

一个图(V,E)的指的是对图(V,E)的顶点集的一个分割,使得顶点集V分为两个非空子集A和B。
一个连通图的割的数量为22 – 2个。

连接边(crossing edge)

  • 无向图来说,连接边指的是边的两个顶点分别在A或B中。
  • 有向图来说,连接边指的是头在B中,尾在A中。

最小割问题

输入:一个无向图G=(V,E).
输出:图的一种割法,使得连接边的数量最少。

Random Contraction Algorithm

如其名,这是一个随机算法,由Karger在上世纪90年代初提出。其基本思想如下:

While there more than 2 vertices:

  1. pick a remaining edge (u,v) uniformly at random
  2. merge u and v into a single vertex
  3. remove self-loops

return cut represented by final 2 vertices.

算法实现

数据结构设计

每个顶点有2个属性:顶点的“名字”和顶点的邻接顶点。初始化时,每个顶点的“名字”都是它自己,但是随着收缩步骤的进行,顶点的名字会随之改变。如顶点2和顶点3合并后,将会由一个新“名字”:顶点23。顶点23和顶点34合并后,新顶点名字为234而不是2334,因为我们不需要重复。为了除重,我将顶点“名字”设计为集合类型。顶点的邻接顶点用一个列表表示。
顶点类的设计如下:

public class Vertice{    private HashSet<Integer> m_verticeInx;//vertex name    private ArrayList<Integer> m_adjacentNodes;}   

整个图可以用可以用一个Vertice的List表示。
这个算法实际上思路是很简单的,就分析到这了。

coding

用java实现。
MinCutTest类。

/** * A implementation of random contraction algorithm for computing  * the minimum cut of a undirected connected graph. *  * @author chenshiyang * */public class MinCutTest{    private ArrayList<Vertice> m_graph;    private ArrayList<Vertice> m_backGraph;    private int m_minCutMin = 1000;    private int m_nodeCount = 0;    public void recoverGraph(){        m_nodeCount = m_backGraph.size();        m_graph = new ArrayList<Vertice>();        for(int i = 0; i < m_backGraph.size(); i ++){            m_graph.add(new Vertice(m_backGraph.get(i)));        }    }    public void getGraphData(String fName) throws Exception{        BufferedReader reader = new BufferedReader(new FileReader(fName));        String lineString = "";        m_graph = new ArrayList<Vertice>();        m_backGraph = new ArrayList<Vertice>();        int  verticeInx = 1;        while((lineString = reader.readLine()) != null){            String[] sarry = lineString.split("\t");            ArrayList<Integer> nodes = new ArrayList<Integer>();            for(int i = 1; i < sarry.length; i ++){                nodes.add(Integer.parseInt(sarry[i].trim()));            }            Vertice vertice = new Vertice();            HashSet<Integer> verticeName = new HashSet<Integer>();            verticeName.add(verticeInx);            vertice.setVerticeInx(verticeName);            vertice.setAdjacentNodes(nodes);            m_graph.add(vertice);            Vertice backupVertice = new Vertice(vertice);            m_backGraph.add(backupVertice);            verticeInx ++;        }        m_nodeCount = m_graph.size();//      m_minCutMin = m_graph.get(0).getAdjacentNodes().size();        reader.close();/*      System.out.println(m_graph.size());        for(int i = 0; i < m_graph.size(); i ++){            System.out.println(m_graph.get(i).getAdjacentNodes().size());        }*/    }    public void randomContraction(int seed){        Random rand = new Random(seed);        while(m_graph.size() > 2){            int currentSize = m_graph.size();            // randomly choose first vertice            int firstNodeIndex = rand.nextInt(currentSize);            /***************method one *********************             * 遍历第一个点的邻接点             *    如果这个点出现在graph里的其他点中,则返回*/            int secondNodeIndex = -1;            int secondNodeIndexInFirst = rand.nextInt(m_graph.get(firstNodeIndex).getAdjacentNodes().size());            int vertexNum = m_graph.get(firstNodeIndex).getAdjacentNodes().get(secondNodeIndexInFirst);            for(int i = 0; i < m_graph.size(); i ++){                if(i == firstNodeIndex)                    continue;                if(m_graph.get(i).getVerticeInx().contains(vertexNum)){                    secondNodeIndex = i;                    break;                }            }            /***************method two **********************             * 遍历graph里的点。             * 对graph里的一个点             *    如果第一个点的邻接点点包含它则返回*//*          int secondNodeIndex = rand.nextInt(currentSize);            Iterator<Integer> iterator;            //indicates if second node is contained in the first node's adjacent nodes.            boolean contain = false;            while(!contain){                //randomly choose second node.                secondNodeIndex = rand.nextInt(currentSize);                //if the second node is not the first node's adjacent node, regenerate it.                while(secondNodeIndex == firstNodeIndex){                    secondNodeIndex = rand.nextInt(currentSize);                }                iterator = m_graph.get(secondNodeIndex).getVerticeInx().iterator();                while(iterator.hasNext()){                    int temp = iterator.next();                    if(m_graph.get(firstNodeIndex).getAdjacentNodes().contains(temp)){                        contain = true;                        break;                    }                }            }*/            //merge the two vertice            m_graph.get(firstNodeIndex).getAdjacentNodes().addAll(m_graph.get(secondNodeIndex).getAdjacentNodes());            //change the vertice name            m_graph.get(firstNodeIndex).getVerticeInx().addAll(m_graph.get(secondNodeIndex).getVerticeInx());            //remove self loop            m_graph.get(firstNodeIndex).getAdjacentNodes().removeAll(m_graph.get(firstNodeIndex).getVerticeInx());            //remove the second vertice            m_graph.remove(secondNodeIndex);        }        int currentMinCutCount = m_graph.get(0).getAdjacentNodes().size();        if(currentMinCutCount < m_minCutMin)            m_minCutMin = currentMinCutCount;//      System.out.println("Cut Number: " + m_minCutMin);    }    public void randomContractionAlgorithm(String fName) throws Exception{        getGraphData(fName);        int loopCount = (int)(Math.log(m_nodeCount) * Math.pow(m_nodeCount, 2));        for(int i = 0; i < loopCount; i ++){            randomContraction(i);            recoverGraph();//          System.out.println("node Count:" + m_nodeCount);        }    }}

Vertice 类

public class Vertice{    private HashSet<Integer> m_verticeInx;    private ArrayList<Integer> m_adjacentNodes;    public Vertice(){    }    public Vertice(Vertice vertix){        this.m_verticeInx = new HashSet<Integer>();        Iterator<Integer> iterator = vertix.m_verticeInx.iterator();        while(iterator.hasNext()){            m_verticeInx.add(iterator.next());        }        this.m_adjacentNodes = new ArrayList<Integer>();        iterator = vertix.m_adjacentNodes.iterator();        while(iterator.hasNext()){            this.m_adjacentNodes.add(iterator.next());        }    }    public HashSet<Integer> getVerticeInx() {        return m_verticeInx;    }    public void setVerticeInx(HashSet<Integer> verticeInx) {        this.m_verticeInx = verticeInx;    }    public ArrayList<Integer> getAdjacentNodes() {        return m_adjacentNodes;    }    public void setAdjacentNodes(ArrayList<Integer> adjacentNodes) {        this.m_adjacentNodes = adjacentNodes;    }}

博客真不好写,先写到这吧,慢慢加油。

0 0
原创粉丝点击