【问题标题】:How to calculate maximum degree of a directed graph using SPARQL?如何使用 SPARQL 计算有向图的最大度数?
【发布时间】:2014-06-17 18:05:51
【问题描述】:

我在两个单独的查询中计算了有向图中每个节点的入度和出度:

SELECT ?s (COUNT(*) AS ?outdegree) 
{ ?s ?p ?o }
GROUP BY ?s
ORDER BY DESC(?outdegree) 

SELECT ?o (COUNT(*) AS ?indegree) 
{ ?s ?p ?o }
GROUP BY ?o
ORDER BY DESC(?indegree)  

我需要计算图形的最大度数。由于有向图的最大度数是图的最大(入度+出度)值,我想知道如何结合上述两个查询的结果来计算它。

另外,如果有更有效的方法,也请提出建议。

【问题讨论】:

    标签: sparql jena fuseki


    【解决方案1】:

    您可以使用非常简单的查询来获取每个顶点的度数?x

    select ?x (count(*) as ?degree) { 
      { ?x ?p ?o } union
      { ?s ?p ?x }
    }
    group by ?x
    

    例如,在这个数据上:

    @prefix : <https://stackoverflow.com/q/24270532/1281433/> .
    
    #     a
    #     |
    #     V
    # b<--c-->d
    #     |
    #     V  
    #     e
    
    :a :p :c .
    :c :p :b, :d, :e .
    

    你会得到结果:

    ---------------
    | x  | degree |
    ===============
    | :a | 1      |
    | :b | 1      |
    | :c | 4      |
    | :d | 1      |
    | :e | 1      |
    ---------------
    

    现在,如果您想要最大值,您可以简单地订购并使用 1 的限制,例如,

    select ?x (count(*) as ?degree) { 
      { ?x ?p ?o } union
      { ?s ?p ?x }
    }
    group by ?x
    order by desc(?degree)
    limit 1
    
    ---------------
    | x  | degree |
    ===============
    | :c | 4      |
    ---------------
    

    如果只有一个度数最高的顶点,这将起作用。如果有多个相同的最高学位,你只会得到其中一个。

    如果你真的想组合你得到的两个查询,那么像Rob Hall's answer 这样的东西会起作用,除了因为子查询不会返回具有 0 入度或 0 出度的节点,它们不会出现在最终结果中,因为它们无法加入。因此,仅当您保证每个节点都具有非零入度和出度时才使用该方法。他的回答还可以作为一个示例,说明如何使用 Jena 以编程方式构建图形和运行这些查询。

    【讨论】:

      【解决方案2】:

      使用以下测试数据:

      <urn:ex:cent0>  <urn:ex:p>  <urn:ex:cent1> , <urn:ex:o1> , <urn:ex:o0> .
      <urn:ex:s1>  <urn:ex:p>  <urn:ex:cent0> .
      <urn:ex:cent1>  <urn:ex:p>  <urn:ex:o3> , <urn:ex:o2> .
      <urn:ex:s2>  <urn:ex:p>  <urn:ex:cent0> .
      <urn:ex:s0>  <urn:ex:p>  <urn:ex:cent0> .
      

      我执行了您的查询和以下查询:

      SELECT  ?cent (( ?indegree + ?outdegree ) AS ?degree)
      WHERE
        { { SELECT  (?s AS ?cent) (count(*) AS ?outdegree)
            WHERE
              { ?s ?p ?o }
            GROUP BY ?s
            ORDER BY DESC(?outdegree)
          }
          { SELECT  (?o AS ?cent) (count(*) AS ?indegree)
            WHERE
              { ?s ?p ?o }
            GROUP BY ?o
            ORDER BY DESC(?indegree)
          }
        }
      

      这导致了以下输出:

      -----------------------------
      | o              | indegree |
      =============================
      | <urn:ex:cent0> | 3        |
      | <urn:ex:cent1> | 1        |
      | <urn:ex:o0>    | 1        |
      | <urn:ex:o1>    | 1        |
      | <urn:ex:o2>    | 1        |
      | <urn:ex:o3>    | 1        |
      -----------------------------
      ------------------------------
      | s              | outdegree |
      ==============================
      | <urn:ex:cent0> | 3         |
      | <urn:ex:cent1> | 2         |
      | <urn:ex:s0>    | 1         |
      | <urn:ex:s1>    | 1         |
      | <urn:ex:s2>    | 1         |
      ------------------------------
      ---------------------------
      | cent           | degree |
      ===========================
      | <urn:ex:cent0> | 6      |
      | <urn:ex:cent1> | 3      |
      ---------------------------
      

      这满足了识别总度数最大的节点的目标。以下是我用来构建此模型并执行此测试的代码(如果您希望重现它):

      final Resource c0 = ResourceFactory.createResource("urn:ex:cent0");
      final Resource c1 = ResourceFactory.createResource("urn:ex:cent1");
      final Property p = ResourceFactory.createProperty("urn:ex:p");
      
      final Model model = new ModelCom(Factory.createDefaultGraph()){{
          this.add(this.createResource("urn:ex:s0"), p, c0);
          this.add(this.createResource("urn:ex:s1"), p, c0);
          this.add(this.createResource("urn:ex:s2"), p, c0);
      
          this.add(c0, p, this.createResource("urn:ex:o0"));
          this.add(c0, p, this.createResource("urn:ex:o1"));
          this.add(c0, p, c1);
      
          this.add(c1, p, this.createResource("urn:ex:o2"));
          this.add(c1, p, this.createResource("urn:ex:o3"));
      }};
      
      final Query outdeg = QueryFactory.create(
          "SELECT ?s (COUNT(*) AS ?outdegree)\n"+ 
          "{ ?s ?p ?o }\n"+
          "GROUP BY ?s\n"+
          "ORDER BY DESC(?outdegree)"
      );
      
      final Query indeg = QueryFactory.create(
          "SELECT ?o (COUNT(*) AS ?indegree)\n"+ 
          "{ ?s ?p ?o }\n"+
          "GROUP BY ?o\n"+
          "ORDER BY DESC(?indegree)"
      );
      
      final Query alldeg = QueryFactory.create(
          "SELECT ?cent ((?indegree+?outdegree) AS ?degree) WHERE {\n"+
          "  {SELECT (?s AS ?cent) (COUNT(*) AS ?outdegree)\n"+ 
          "    { ?s ?p ?o }\n"+
          "    GROUP BY ?s\n"+
          "    ORDER BY DESC(?outdegree)\n"+
          "  }\n"+
          "  {SELECT (?o AS ?cent) (COUNT(*) AS ?indegree)\n"+ 
          "    { ?s ?p ?o }\n"+
          "    GROUP BY ?o\n"+
          "    ORDER BY DESC(?indegree)\n"+
          "  }\n"+
          "}"
      );
      
      @Test
      public void test()
      {
          model.write(System.out, "TTL");
          System.out.println();
      
          System.out.println(alldeg);
      
          final QueryExecution exec0 = QueryExecutionFactory.create(indeg, model);
          ResultSetFormatter.out(exec0.execSelect(), indeg);
          exec0.close();
      
          final QueryExecution exec1 = QueryExecutionFactory.create(outdeg, model);
          ResultSetFormatter.out(exec1.execSelect(), outdeg);
          exec1.close();
      
          final QueryExecution exec2 = QueryExecutionFactory.create(alldeg, model);
          ResultSetFormatter.out(exec2.execSelect(), alldeg);
          exec2.close();
      }
      

      【讨论】:

      • 这将错过任何接收器或源节点,但是,因为在相应的子查询中找不到具有 0 入度或 0 出度的条目,因此不会在两个子查询。
      • 优秀的捕获。每当源或汇节点具有最高的入和/或出度时,这将导致错误的答案。您还发布了一个更优雅的解决方案,但我无法删除我投入时间的答案,哈哈。
      猜你喜欢
      • 2023-01-27
      • 2016-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-09
      • 1970-01-01
      • 1970-01-01
      • 2020-04-11
      相关资源
      最近更新 更多