简体   繁体   English

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

[英]how to find shortpath in Orientdb (edges instead of vertexes)

I have this graph: A-->B, A-->C, B-->C, C-->D, A-->E 我有这个图:A - > B,A - > C,B - > C,C - > D,A - > E.

I want to find the shortest path between "A" and "D" in java. 我想在java中找到“A”和“D”之间的最短路径。 I used: 我用了:

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);
        }

The problem I get not the desired result: 我得到的问题不是预期的结果:

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

When I focus in vertex instead of Edges I got the correct short path which is: A -> C -> D 当我在顶点而不是边缘聚焦时,我得到了正确的短路径:A - > C - > D.

Why edges is not working as I did? 为什么边缘不能像我一样工作?

EDIT: 编辑:

Updated graph 更新的图表

When I have the graph as it is in the attached image and I want to find the shortest path between "A" and "D" using your method still I got no edges: SHORTEST PATH (vertex): ACD SHORTEST PATH (edge): shouldn't the SHORTEST PATH (vertex) be: A, F, E, D ?. 当我有附图中的图形并且我想使用你的方法找到“A”和“D”之间的最短路径时,我没有边缘:SHORTEST PATH(vertex):ACD SHORTEST PATH(edge):不应该是最短路径(顶点)是:A,F,E,D ?. If I want to find the shortest path between "D" and "A" now I also get no edages after your update. 如果我想找到“D”和“A”之间的最短路径,那么在更新后我也没有得到任何修改。

Using 'select expand(shortestpath(...))' only returns vertices. 使用'select expand(shortestpath(...))'只返回顶点。

Starting from your initial situation. 从你最初的情况开始。 在此输入图像描述

Your goal is to extract the edges forming the shortest path (I think I understand), so to have the following result: 你的目标是提取形成最短路径的边缘(我想我理解),所以得到以下结果: 在此输入图像描述

One way to do this would be: - Find the shortest path (with Vertex) - get for individual Vertices of the shortest path, the edges connecting the first vertex until the last 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));
    }

}

The result you get is this: 你得到的结果是这样的:

在此输入图像描述

A --#13:1--> C --13:4--> D A - #13:1 - > C - 13:4 - > D.

EDIT 1 编辑1

Definitely an improvement is this: 绝对是一个改进是这样的:

//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
        }

avoids unnecessary checks. 避免不必要的检查。

EDIT 2 编辑2

Added edge label in the result. 在结果中添加了边缘标签。

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));
    }

}

This is the result: 这是结果:

在此输入图像描述

EDIT 3 编辑3

With the addition of new vertices, the graph should be this. 通过添加新顶点,图形应为此。 (Is it correct?) (这是正确的吗?) 在此输入图像描述

Starting from this graph, we have: 从这张图开始,我们有:

1) from "A" to "D" SHORTEST PATH(vertex): is ACD (correct with you) SHORTEST PATH(edge): is edgeA-C, edgeC-D 1)从“A”到“D”SHORTEST PATH(顶点):是ACD(对你来说是正确的)最短路径(边缘):是edgeA-C,edgeC-D

在此输入图像描述

2) from "D" to "A" SHORTEST PATH(vertex): is DCA (correct with you) SHORTEST PATH(edge): is edgeD-C, edgeC-A (is your #11:4, #11:1) 2)从“D”到“A”最短路径(顶点):是DCA(对你来说是正确的)最短路径(边缘):是edgeD-C,edgeC-A(是你的#11:4,#11:1)

在此输入图像描述

Using the code, automatically extracts the shortest path (using the specific function of orient) and consequently the extraction of edges that are contained in this path. 使用该代码,自动提取最短路径(使用orient的特定功能),从而提取此路径中包含的边缘。 The only thing the manual, is that I put in V1 and V2 RID vertices Start and End. 手册中唯一的东西就是我放入了V1和V2 RID顶点的Start和End。

EDIT 4 编辑4

在此输入图像描述

I created a new answer because the code is quite different from the previous one. 我创建了一个新答案,因为代码与前一个代码完全不同。 With this code you just set StartNode (Vstart) & endNode (Vend), and returns the ShortestPath (referring to edge) with direction 'out' (compared to the first node) and direction 'in' (if present) always compared to the first node. 使用此代码,您只需设置StartNode(Vstart)和endNode(Vend),并返回ShortestPath(指向edge),方向为“out”(与第一个节点相比),方向“in”(如果存在)始终与第一个节点。 The operation is based on extracting vertices who returned from work ShortestPath() of orient,for each of these vertices controls the edge. 该操作基于提取从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)");
    }

}

} }

在此输入图像描述

EDIT 2 编辑2

Using the 'direction' in the ShortestPath function. 使用ShortestPath函数中的'direction'。 在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM