如何在Orientdb中找到短路径(边缘而不是顶点)

时间:2016-03-09 07:24:01

标签: java orientdb

我有这张图:        A - > B,A - > C,B - > C,C - > D,A - > E

我想找到" A"之间的最短路径。和" D"在java中。我用过:

s= select from ( select expand( shortestPath("+ first_vertex.getId() +", "+ second_vertex.getId() +").outE()))

    for (Edge edge : (Iterable<Edge>) g.command(
        new OCommandSQL(s)).execute()) {
            System.out.println(edge);
        }

我得到的问题不是预期的结果:

      A - B
      A - C
      A - E 
      C - D

当我在顶点而不是边缘聚焦时,我得到了正确的短路径,即: A - &gt; C - &gt; d

为什么边缘不能像我一样工作?

编辑:

Updated graph

当我有附图中的图形时,我想找到&#34; A&#34;之间的最短路径。和&#34; D&#34;使用你的方法仍然没有边缘:SHORTEST PATH(顶点):C D最短路径(边缘):不应该是最短路径(顶点):A,F,E,D ?.如果我想找到&#34; D&#34;之间的最短路径。和&#34; A&#34;现在我在更新后也没有得到任何修改。

2 个答案:

答案 0 :(得分:2)

使用'select expand(shortestpath(...))'只返回顶点。

从最初的情况开始。 enter image description here

你的目标是提取形成最短路径的边缘(我想我理解),所以得到以下结果: enter image description here

这样做的一种方法是: - 找到最短路径(使用Vertex) - 获取最短路径的各个顶点,连接第一个顶点到最后一个顶点的边。

static final String REMOTE = "remote:localhost/";

static final String NOMEDB  = "shortpath";
static final String CURRENTPATH = REMOTE + NOMEDB;

public static void main(String[] args) throws IOException {
    OServerAdmin serverAdmin = new OServerAdmin(CURRENTPATH).connect("root", "root");

    OrientGraphNoTx g = new OrientGraphFactory(CURRENTPATH).getNoTx();

    showPath(g);
}

public static void showPath (OrientGraphNoTx  g) {
    String s = "";
    String V1 = "#12:0"; //Vertex A
    String V2 = "#12:3"; //Vertex D
    s= "select expand(shortestPath(" + V1 + ", " + V2+"))";

    Iterable<Vertex> result = g.command(new OSQLSynchQuery<Vertex>(s)).execute();
    List<OrientVertex> listaVertex = new ArrayList<OrientVertex>();
    CollectionUtils.addAll(listaVertex, result.iterator());

    List<String> out = new ArrayList<String>();
    List<String> in = new ArrayList<String>();
    List<String> edgePath = new ArrayList<String>();

    //for each vertices get edge out & in
    Iterable<Edge> tempOut;
    Iterable<Edge> tempIn;
    String singleIn = "";
    String singleOut = "";

    System.out.println("SHORTEST PATH (vertex):");
    for (int v=0; v<listaVertex.size(); v++) {
        System.out.print(listaVertex.get(v).getProperty("name")+ " " );
    }
    System.out.println("");

    for (int i=0; i<listaVertex.size(); i++) {

        tempOut = listaVertex.get(i).getEdges(Direction.OUT, "collega");
        tempIn = listaVertex.get(i).getEdges(Direction.IN, "collega");

        //get edge in
        for(Edge edgeIn : tempIn) {
            in.add(edgeIn.getId().toString());
        }

        //forech edge in, check if is in out
        for(int x=0; x<in.size(); x++) {
            singleIn = in.get(x);
            for(int z=0; z<out.size(); z++) {
                singleOut = out.get(z);
                if(singleIn.equals(singleOut)) {
                    edgePath.add(singleIn);
                }
            }
        }

        //to empty out list
        out.clear();

        //get edge out
        for(Edge edgeOut : tempOut) {
            out.add(edgeOut.getId().toString());
        }

        //to empty in list
        in.clear();

    }

    System.out.println("SHORTEST PATH (edge):");
    for (int ind=0; ind<edgePath.size(); ind++) {
        System.out.println(edgePath.get(ind));
    }

}

你得到的结果是:

enter image description here

A - #13:1 - &gt; C - 13:4 - &gt; d

编辑1

这肯定是一个改进:

//forech edge in, check if is in out
        boolean finded = false;                        //*******new
        for(int x=0; x<in.size(); x++) {
            singleIn = in.get(x);
            for(int z=0; z<out.size(); z++) {
                singleOut = out.get(z);
                if(singleIn.equals(singleOut)) {
                    edgePath.add(singleIn);
                    finded = true;          //*******new
                    break;              //*******new
                }
            } 
            if(finded)break;                //*******new
        }

避免不必要的检查。

编辑2

在结果中添加了边缘标签。

public static void showPath (OrientGraphNoTx  g) {
    String s = "";
    String V1 = "#12:0"; //Vertex A
    String V2 = "#12:3"; //Vertex D
    s= "select expand(shortestPath(" + V1 + ", " + V2+"))";

    Iterable<Vertex> result = g.command(new OSQLSynchQuery<Vertex>(s)).execute();
    List<OrientVertex> listaVertex = new ArrayList<OrientVertex>();
    CollectionUtils.addAll(listaVertex, result.iterator());

    List<String> out = new ArrayList<String>();
    List<String> in = new ArrayList<String>();
    List<String> inLabel = new ArrayList<String>();
    List<String> edgePath = new ArrayList<String>();

    //per ogni vertice recupera archi uscenti ed entranti
    Iterable<Edge> tempOut;
    Iterable<Edge> tempIn;
    String singleIn = "";
    String singleOut = "";

    System.out.println("SHORTEST PATH (vertex):");
    for (int v=0; v<listaVertex.size(); v++) {
        System.out.print(listaVertex.get(v).getProperty("name")+ " " );
    }
    System.out.println("");

    for (int i=0; i<listaVertex.size(); i++) {

        tempOut = listaVertex.get(i).getEdges(Direction.OUT, "collega");
        tempIn = listaVertex.get(i).getEdges(Direction.IN, "collega");

        //get edge in
        for(Edge edgeIn : tempIn) {
            in.add(edgeIn.getId().toString());  //list edge id
            inLabel.add(edgeIn.getLabel());     // list edge label
        }

        //forech edge in, check if is in out
        boolean finded = false;
        for(int x=0; x<in.size(); x++) {
            singleIn = in.get(x);
            for(int z=0; z<out.size(); z++) {
                singleOut = out.get(z);
                if(singleIn.equals(singleOut)) {
                    edgePath.add(singleIn);   //in edgePath[position] = id
                    edgePath.add(inLabel.get(x));   //in edgePAth[position+1] = label
                    finded = true;
                    break; 
                }
            } 
            if(finded)break;    
        }

        //to empty out list
        out.clear();

        //get edge out
        for(Edge edgeOut : tempOut) {
            out.add(edgeOut.getId().toString());
        }

        //to empty in list
        in.clear();

    }

    System.out.println("SHORTEST PATH (edge):");
    for (int ind=0; ind<edgePath.size(); ind=ind+2) {  //ind+2 so i get id[position x] and label [position x+1] 
        System.out.println("id:"+edgePath.get(ind)+", Label:"+edgePath.get(ind+1));
    }

}

结果如下:

enter image description here

编辑3

添加新顶点后,图形应为此。 (这是对的吗?) enter image description here

从这张图开始,我们有:

1)从“A”到“D”     最短路径(顶点):是A-C-D(对你而言正确)     最短路径(边缘):是edgeA-C,edgeC-D

enter image description here

2)从“D”到“A”     最短路径(顶点):是D-C-A(对你而言正确)     最短路径(边缘):是edgeD-C,edgeC-A(是你的#11:4,#11:1)

enter image description here

使用代码,自动提取最短路径(使用特定的orient函数),从而提取此路径中包含的边。手册中唯一的就是我放入了V1和V2 RID顶点的Start和End。

编辑4

enter image description here

答案 1 :(得分:1)

我创建了一个新的答案,因为代码与前一个完全不同。 使用此代码,您只需设置StartNode(Vstart)&amp; endNode(Vend),返回ShortestPath(指向edge),方向为'out'(与第一个节点相比),方向'in'(如果存在)始终与第一个节点进行比较。 该操作基于提取从Orient的工作ShortestPath()返回的顶点,因为每个顶点控制边缘。

public class PathEdge {


    static final String REMOTE = "remote:localhost/";

    static final String NOMEDB  = "ShortestPath2";
    static final String CURRENTPATH = REMOTE + NOMEDB;

public static void main(String[] args) throws IOException {

    OServerAdmin serverAdmin = new OServerAdmin(CURRENTPATH).connect("root", "root");

    OrientGraphNoTx g = new OrientGraphFactory(CURRENTPATH).getNoTx();

    String Vstart   = "a";  //----- to set
    String Vend     = "d";  // ---- to set
    String queryClassName   = "Nodo";  //----- to set
    String queryProperty    = "name"; //----- to set
    String edgeNAme = "is_a";   //----- to set
    String direction = "'OUT'";  //----- to set "BOTH" (incoming and outgoing), "OUT" (outgoing) and "IN" (incoming)

    String query1 = "select from "+queryClassName+" where "+queryProperty+" = '"+Vstart+"'";
    Iterable<Vertex> start = g.command(new OSQLSynchQuery<Vertex>(query1)).execute();

    String query2 = "select from "+queryClassName+" where "+queryProperty+" = '"+Vend+"'";  
    Iterable<Vertex> end = g.command(new OSQLSynchQuery<Vertex>(query2)).execute();

    long startTime = System.currentTimeMillis();
    showPath(g, start.iterator().next().getId().toString(), end.iterator().next().getId().toString(), edgeNAme, direction);
    long estimatedTime = System.currentTimeMillis() - startTime;
    System.out.println("");
    System.out.println("TIME EXECUTE: "+estimatedTime+"ms");
}

public static void showPath (OrientGraphNoTx  g, String Vstart, String Vend , String edge, String direction) {

     String s = "";
     int position = 0;
     int maxsize = 0;

     s= "select expand(shortestPath(" + Vstart + ", " + Vend+", "+direction+"))";

    Iterable<Vertex> result = g.command(new OSQLSynchQuery<Vertex>(s)).execute();
    List<OrientVertex> listaVertex = new ArrayList<OrientVertex>();
    CollectionUtils.addAll(listaVertex, result.iterator());

    List<String> listPRECout = new ArrayList<String>();
    List<String> listPRECin = new ArrayList<String>();
    List<String> listFOLLout = new ArrayList<String>();
    List<String> listFOLLin = new ArrayList<String>();

    List<String> resultOut = new ArrayList<String>();
    List<String> resultIn = new ArrayList<String>();

    //per ogni vertice recupera archi uscenti ed entranti
    Iterable<Edge> tempOut;
    Iterable<Edge> tempIn;
    String singleIn = "";
    String singleOut = "";
    boolean finded = false;

    System.out.println("SHORTEST PATH (vertex [direction "+direction+"]):");
    for (int v=0; v<listaVertex.size(); v++) {
        System.out.print(listaVertex.get(v).getProperty("name")+ " " );
    }
    System.out.println("");
    System.out.println("");
    maxsize = listaVertex.size()-1;
    for (int v=0; v<maxsize; v++) {

        //--------FIRST VERTEX OF THE SHORTEST PATH
        tempOut = listaVertex.get(v).getEdges(Direction.OUT, edge);
        tempIn = listaVertex.get(v).getEdges(Direction.IN, edge);

        //set listPRECin 
        for(Edge edgeIn : tempIn) {
            listPRECin.add(edgeIn.getId().toString());  //position x   = rid
            listPRECin.add(edgeIn.getLabel());          //position x+1 = label
        }

        //set listPRECout 
        for(Edge edgeOut : tempOut) {
            listPRECout.add(edgeOut.getId().toString());  //position x   = rid
            listPRECout.add(edgeOut.getLabel());          //position x+1 = label
        }

        //--------SECOND VERTEX OF THE SHORTEST PATH
        tempOut = listaVertex.get(v+1).getEdges(Direction.OUT, edge);
        tempIn = listaVertex.get(v+1).getEdges(Direction.IN, edge);

        //set listFOLLin 
        for(Edge edgeIn : tempIn) {
            listFOLLin.add(edgeIn.getId().toString());  //position x   = rid
            listFOLLin.add(edgeIn.getLabel());          //position x+1 = label
        }

        //set listFOLLout 
        for(Edge edgeOut : tempOut) {
            listFOLLout.add(edgeOut.getId().toString());  //position x   = rid
            listFOLLout.add(edgeOut.getLabel());          //position x+1 = label
        }


        //------MATCH LOGIC
        //...compare PRECin with FOLLout
        finded = false;
        for(int i = 0; i<listPRECin.size(); i=i+2) {
            singleIn = listPRECin.get(i);
            for(int o = 0; o<listFOLLout.size(); o=o+2){
                singleOut = listFOLLout.get(o);
                if(singleIn.equals(singleOut)) {

                    //check is there a hole
                    if(v==0) {
                        resultIn.add(singleIn);  //rid
                        resultIn.add(listPRECin.get(i+1)); //label
                        finded = true;
                        break; 
                    } else if((v*2) == resultIn.size()) {
                        resultIn.add(singleIn);  //rid
                        resultIn.add(listPRECin.get(i+1)); //label
                        finded = true;
                        break; 
                    }
                }
            }
            if(finded)break;    
        }

        finded = false;
        //...compare PRECout with FOLLin
        for(int i = 0; i<listPRECout.size(); i=i+2) {
            singleOut = listPRECout.get(i);
            for(int o = 0; o<listFOLLin.size(); o=o+2){
                singleIn = listFOLLin.get(o);
                if(singleOut.equals(singleIn)) {
                    //check is there a hole
                    if(v==0) {
                        resultOut.add(singleOut);  //rid
                        resultOut.add(listPRECout.get(i+1)); //label
                        finded = true;
                        break; 
                    } else if((v*2) == resultOut.size()) {
                        resultOut.add(singleOut);  //rid
                        resultOut.add(listPRECout.get(i+1)); //label
                        finded = true;
                        break; 
                    }
                }
            }
            if(finded)break;    
        }

        //to empty out list
        listPRECin.clear();
        listPRECout.clear();    
        listFOLLin.clear();
        listFOLLout.clear();    

        //cheack if it's in the penultimate vertex
        position = v+1;
        if( position==maxsize) {
            break;
        }

    }


    System.out.println("SHORTEST PATH (edge, out direction):");
    if(resultOut.size()>0) {
        for (int ind=0; ind<resultOut.size(); ind=ind+2) {  //ind+2 so i get id[position x] and label [position x+1] 
            System.out.println("id:"+resultOut.get(ind)+", Label:"+resultOut.get(ind+1));
        }
    } else {
        System.out.println("No edge in this direction (OUT)");
    }

    System.out.println("");
    System.out.println("SHORTEST PATH (edge, in direction):");
    if(resultIn.size()>0) {
        for (int ind=0; ind<resultIn.size(); ind=ind+2) {  //ind+2 so i get id[position x] and label [position x+1] 
            System.out.println("id:"+resultIn.get(ind)+", Label:"+resultIn.get(ind+1));
        }
    }else {
        System.out.println("No edge in this direction (IN)");
    }

}

}

enter image description here

编辑2

使用ShortestPath函数中的'direction'。 enter image description here