├── .gitignore ├── 23c-graph-demos ├── BankGraphDataset │ ├── BANK_ACCOUNTS.csv │ ├── BANK_TRANSFERS.csv │ └── license.txt ├── oracle-graph-23c-sqldeveloper.sql └── oracle-graph-sample-23c.ipynb ├── CONTRIBUTING.md ├── LICENSE.txt ├── README.md ├── SECURITY.md ├── adb-client-jupyter └── adb-client-on-jupyter-notebook.ipynb ├── built-in-algorithms ├── README.md └── md │ ├── pgx_builtin_a1_prim.md │ ├── pgx_builtin_a1u_prim.md │ ├── pgx_builtin_c1_community_detection_label_propagation.md │ ├── pgx_builtin_c2_community_detection_conductance_minimization.md │ ├── pgx_builtin_c3_infomap.md │ ├── pgx_builtin_c4_louvain.md │ ├── pgx_builtin_c4b_louvain_directed.md │ ├── pgx_builtin_c5_speaker_listener_label_propagation.md │ ├── pgx_builtin_c5b_filtered_speaker_listener_label_propagation.md │ ├── pgx_builtin_c5c_filtered_weighted_speaker_listener_label_propagation.md │ ├── pgx_builtin_c6_weighted_speaker_listener_label_propagation.md │ ├── pgx_builtin_g2a_strongly_connected_components_kosaraju.md │ ├── pgx_builtin_g2b_strongly_connected_components_tarjan.md │ ├── pgx_builtin_g3_weakly_connected_components.md │ ├── pgx_builtin_k10_article_rank.md │ ├── pgx_builtin_k1a_pagerank.md │ ├── pgx_builtin_k1b_pagerank_approximate.md │ ├── pgx_builtin_k1c_pagerank_weighted.md │ ├── pgx_builtin_k2_personalized_pagerank.md │ ├── pgx_builtin_k2b_personalized_pagerank_from_set.md │ ├── pgx_builtin_k2c_personalized_weighted_pagerank.md │ ├── pgx_builtin_k2d_personalized_weighted_pagerank_from_set.md │ ├── pgx_builtin_k3a_node_betweenness_centrality.md │ ├── pgx_builtin_k3b_approx_node_betweenness_centrality.md │ ├── pgx_builtin_k3c_approx_node_betweenness_centrality_from_seeds.md │ ├── pgx_builtin_k4a_closeness_centrality_unit_length.md │ ├── pgx_builtin_k4b_closeness_centrality_double_length.md │ ├── pgx_builtin_k5_hits.md │ ├── pgx_builtin_k6_eigenvector_centrality.md │ ├── pgx_builtin_k7a_outdegree_centrality.md │ ├── pgx_builtin_k7b_indegree_centrality.md │ ├── pgx_builtin_k7c_degree_centrality.md │ ├── pgx_builtin_k8_random_walk_with_restart.md │ ├── pgx_builtin_k9_harmonic_centrality.md │ ├── pgx_builtin_l1_whom_to_follow.md │ ├── pgx_builtin_o10_all_reachable_vertices_edges.md │ ├── pgx_builtin_o12_enumerate_simple_paths.md │ ├── pgx_builtin_o1_filtered_bfs.md │ ├── pgx_builtin_o2_filtered_dfs.md │ ├── pgx_builtin_o6_compute_supernodes.md │ ├── pgx_builtin_o7_compute_distance_index.md │ ├── pgx_builtin_o8_limited_path_finding_undirected.md │ ├── pgx_builtin_o9_limited_path_finding_undirected_filtered.md │ ├── pgx_builtin_p1a_single_source_single_destination_dijkstra.md │ ├── pgx_builtin_p1au_single_source_single_destination_dijkstra_undirected.md │ ├── pgx_builtin_p1b_single_source_single_destination_filtered_dijkstra.md │ ├── pgx_builtin_p1bu_single_source_destination_filtered_dijkstra_undirected.md │ ├── pgx_builtin_p1c_single_source_all_destinations_dijkstra.md │ ├── pgx_builtin_p2_single_source_single_destination_bidirectional_dijkstra.md │ ├── pgx_builtin_p2b_single_source_single_destination_filtered_bidirectional_dijkstra.md │ ├── pgx_builtin_p2bu_single_source_single_destination_filtered_bidirectional_dijkstra_undirected.md │ ├── pgx_builtin_p2u_single_source_single_destination_bidirectional_dijkstra_undirected.md │ ├── pgx_builtin_p3_single_source_all_destinations_bellman_ford.md │ ├── pgx_builtin_p3a_single_source_single_destination_bellman_ford.md │ ├── pgx_builtin_p3r_single_source_all_destinations_bellman_ford_reverse.md │ ├── pgx_builtin_p3u_single_source_all_destinations_bellman_ford.md │ ├── pgx_builtin_p4_single_source_all_destinations_hop_distance.md │ ├── pgx_builtin_p4r_single_source_all_destinations_hop_distance_reverse.md │ ├── pgx_builtin_p4u_single_source_all_destinations_hop_distance_undirected.md │ ├── pgx_builtin_p5_fattest_path.md │ ├── pgx_builtin_p5u_fattest_path_undirected.md │ ├── pgx_builtin_r1b_salsa.md │ ├── pgx_builtin_r2_personalized_salsa.md │ ├── pgx_builtin_r2a_matrix_factorization_training.md │ ├── pgx_builtin_r2b_matrix_factorization_recommendations.md │ ├── pgx_builtin_r3_personalized_salsa_from_set.md │ ├── pgx_builtin_s10_bipartite_check.md │ ├── pgx_builtin_s11_diameter.md │ ├── pgx_builtin_s12_periphery.md │ ├── pgx_builtin_s13_local_clustering_coefficient.md │ ├── pgx_builtin_s13d_local_clustering_coefficient.md │ ├── pgx_builtin_s13u_local_clustering_coefficient.md │ ├── pgx_builtin_s14a_find_cycle.md │ ├── pgx_builtin_s14b_find_cycle_from_node.md │ ├── pgx_builtin_s15a_reachability.md │ ├── pgx_builtin_s15b_reachability_undirected.md │ ├── pgx_builtin_s16a_topological_sort.md │ ├── pgx_builtin_s16b_topological_schedule.md │ ├── pgx_builtin_s1_triangle_counting.md │ ├── pgx_builtin_s1b_triangle_counting_undirected.md │ ├── pgx_builtin_s2_adamic_adar_counting.md │ ├── pgx_builtin_s2d_adamic_adar_counting.md │ ├── pgx_builtin_s3_conductance.md │ ├── pgx_builtin_s4_partition_modularity.md │ ├── pgx_builtin_s5_partition_conductance.md │ ├── pgx_builtin_s6_out_degree_distribution.md │ ├── pgx_builtin_s7_in_degree_distribution.md │ └── pgx_builtin_s9_kcore.md ├── graph-studio-conda-interpreter ├── Graph Studio-Conda – Admin.dsnb └── Graph Studio-Conda – Graph User.dsnb ├── graphviz-demo ├── .gitignore ├── README.md ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── micronaut-cli.yml ├── screenshot.jpg ├── settings.gradle └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── oracle │ │ │ ├── example │ │ │ ├── Application.java │ │ │ ├── GraphClient.java │ │ │ ├── HRController.java │ │ │ └── response │ │ │ │ ├── Response.java │ │ │ │ ├── Result.java │ │ │ │ └── TokenResponse.java │ │ │ └── scripts │ │ │ ├── RunCreateScripts.java │ │ │ └── RunDropScripts.java │ └── resources │ │ ├── application.yml │ │ ├── dataset_property_graph │ │ ├── create_hr_dataset.sql │ │ ├── create_hr_property_graph.sql │ │ └── drop_hr.sql │ │ ├── logback.xml │ │ ├── my_sqlgraph_json.sql │ │ ├── pgview_dataset │ │ ├── create_hr_dataset.sql │ │ ├── create_hr_pgview.pgql │ │ └── drop_hr.sql │ │ └── public │ │ ├── index.html │ │ └── styles.css │ └── test │ └── java │ └── com │ └── oracle │ └── example │ └── GraphvizDemoTest.java └── pgql-graph-demos └── bank-graph-rdbms-samples ├── BANK_ACCOUNTS.csv ├── BANK_TRANSFERS.csv ├── CreateBankGraphDataset.sql ├── README.md ├── bank-graph-pgql └── license.txt /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle/ 2 | .idea/ 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /23c-graph-demos/BankGraphDataset/license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. 2 | 3 | You may not use the identified files except in compliance with the Universal Permissive License. 4 | 5 | You may obtain a copy of the License at https://oss.oracle.com/licenses/upl/ 6 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to this repository 2 | 3 | We welcome your contributions! There are multiple ways to contribute. 4 | 5 | ## Opening issues 6 | 7 | For bugs or enhancement requests, please file a GitHub issue unless it's 8 | security related. When filing a bug remember that the better written the bug is, 9 | the more likely it is to be fixed. If you think you've found a security 10 | vulnerability, do not raise a GitHub issue and follow the instructions in our 11 | [security policy](./SECURITY.md). 12 | 13 | ## Contributing code 14 | 15 | We welcome your code contributions. Before submitting code via a pull request, 16 | you will need to have signed the [Oracle Contributor Agreement][OCA] (OCA) and 17 | your commits need to include the following line using the name and e-mail 18 | address you used to sign the OCA: 19 | 20 | ```text 21 | Signed-off-by: Your Name 22 | ``` 23 | 24 | This can be automatically added to pull requests by committing with `--sign-off` 25 | or `-s`, e.g. 26 | 27 | ```text 28 | git commit --signoff 29 | ``` 30 | 31 | Only pull requests from committers that can be verified as having signed the OCA 32 | can be accepted. 33 | 34 | ## Pull request process 35 | 36 | 1. Ensure there is an issue created to track and discuss the fix or enhancement 37 | you intend to submit. 38 | 1. Fork this repository. 39 | 1. Create a branch in your fork to implement the changes. We recommend using 40 | the issue number as part of your branch name, e.g. `1234-fixes`. 41 | 1. Ensure that any documentation is updated with the changes that are required 42 | by your change. 43 | 1. Ensure that any samples are updated if the base image has been changed. 44 | 1. Submit the pull request. *Do not leave the pull request blank*. Explain exactly 45 | what your changes are meant to do and provide simple steps on how to validate. 46 | your changes. Ensure that you reference the issue you created as well. 47 | 1. We will assign the pull request to 2-3 people for review before it is merged. 48 | 49 | ## Code of conduct 50 | 51 | Follow the [Golden Rule](https://en.wikipedia.org/wiki/Golden_Rule). If you'd 52 | like more specific guidelines, see the [Contributor Covenant Code of Conduct][COC]. 53 | 54 | [OCA]: https://oca.opensource.oracle.com 55 | [COC]: https://www.contributor-covenant.org/version/1/4/code-of-conduct/ 56 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This software is licensed to you under the Universal Permissive License (UPL). See below for license terms. 4 | ____________________________ 5 | The Universal Permissive License (UPL), Version 1.0 6 | Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 7 | 8 | Subject to the condition set forth below, permission is hereby granted to any person obtaining a copy of this software, associated documentation and/or data (collectively the "Software"), free of charge and under any and all copyright rights in the Software, and any and all patent rights owned or freely licensable by each licensor hereunder covering either (i) the unmodified Software as contributed to or provided by such licensor, or (ii) the Larger Works (as defined below), to deal in both 9 | 10 | (a) the Software, and 11 | (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if one is included with the Software (each a "Larger Work" to which the Software is contributed by such licensors), 12 | 13 | without restriction, including without limitation the rights to copy, create derivative works of, display, perform, and distribute the Software and make, use, sell, offer for sale, import, export, have made, and have sold the Software and the Larger Work(s), and to sublicense the foregoing rights on either these or other terms. 14 | 15 | This license is subject to the following condition: 16 | 17 | The above copyright notice and either this complete permission notice or at a minimum a reference to the UPL must be included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PGX Samples 2 | 3 | PGX (Parallel Graph AnalytiX) is a graph toolkit that provides a graph query language, optimized analytics algorithms, and machine learning support to extract insights hidden in the connections across datasets at high-performance and extreme scale. 4 | 5 | While graphs have become ubiquitous nowadays as the backbone of multiple applications - from search engines and recommender systems to intelligent chatbots, PGX enables fast graph analysis on such industry-scale graphs (with trillions of edges) to reveal latent information between linked entities. 6 | 7 | ## Table of contents: 8 | 9 | - [Built-in Algorithms](./built-in-algorithms/README.md) 10 | 11 | ## Contributing 12 | 13 | This project welcomes contributions from the community. Before submitting a pull request, please [review our contribution guide](./CONTRIBUTING.md) 14 | 15 | ## Security 16 | 17 | Please consult the [security guide](./SECURITY.md) for our responsible security vulnerability disclosure process 18 | 19 | ## License 20 | 21 | Copyright (c) 2019, 2024 Oracle and/or its affiliates. 22 | 23 | Released under the Universal Permissive License v1.0 as shown at 24 | . 25 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Reporting security vulnerabilities 2 | 3 | Oracle values the independent security research community and believes that 4 | responsible disclosure of security vulnerabilities helps us ensure the security 5 | and privacy of all our users. 6 | 7 | Please do NOT raise a GitHub Issue to report a security vulnerability. If you 8 | believe you have found a security vulnerability, please submit a report to 9 | [secalert_us@oracle.com][1] preferably with a proof of concept. Please review 10 | some additional information on [how to report security vulnerabilities to Oracle][2]. 11 | We encourage people who contact Oracle Security to use email encryption using 12 | [our encryption key][3]. 13 | 14 | We ask that you do not use other channels or contact the project maintainers 15 | directly. 16 | 17 | Non-vulnerability related security issues including ideas for new or improved 18 | security features are welcome on GitHub Issues. 19 | 20 | ## Security updates, alerts and bulletins 21 | 22 | Security updates will be released on a regular cadence. Many of our projects 23 | will typically release security fixes in conjunction with the 24 | Oracle Critical Patch Update program. Additional 25 | information, including past advisories, is available on our [security alerts][4] 26 | page. 27 | 28 | ## Security-related information 29 | 30 | We will provide security related information such as a threat model, considerations 31 | for secure use, or any known security issues in our documentation. Please note 32 | that labs and sample code are intended to demonstrate a concept and may not be 33 | sufficiently hardened for production use. 34 | 35 | [1]: mailto:secalert_us@oracle.com 36 | [2]: https://www.oracle.com/corporate/security-practices/assurance/vulnerability/reporting.html 37 | [3]: https://www.oracle.com/security-alerts/encryptionkey.html 38 | [4]: https://www.oracle.com/security-alerts/ 39 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_a1_prim.md: -------------------------------------------------------------------------------- 1 | # Prim's Algorithm 2 | 3 | - **Category:** classic graph algorithms 4 | - **Algorithm ID:** pgx_builtin_a1_prim 5 | - **Time Complexity:** O(E + V log V) with V = number of vertices, E = number of edges 6 | - **Space Requirement:** O(2 * E + V) with V = number of vertices, E = number of edges 7 | - **Javadoc:** 8 | - [Analyst#prim(PgxGraph graph, EdgeProperty weight)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#prim_oracle_pgx_api_PgxGraph_oracle_pgx_api_EdgeProperty_) 9 | - [Analyst#prim(PgxGraph graph, EdgeProperty weight, EdgeProperty mst)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#prim_oracle_pgx_api_PgxGraph_oracle_pgx_api_EdgeProperty_oracle_pgx_api_EdgeProperty_) 10 | 11 | This implementation of Prim's algorithm works on undirected graphs that are connected and have no multi-edges (i.e. more than one edge connecting the same pair of vertices). The algorithm computes the minimum spanning tree (MST) of the graph using the weights associated to each edge. A minimum spanning tree is a subset of the edges that connects all the vertices in the graph such that it minimizes the total weight associated to the edges. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | | `weight` | edgeProp | edge property holding the weight of each edge in the graph. | 19 | 20 | | Output Argument | Type | Comment | 21 | | :--- | :--- | :--- | 22 | | `in_mst` | edgeProp | edge property holding the edges belonging to the minimum spanning tree of the graph (i.e. all the edges with in_mst=true). | 23 | 24 | | Return Value | Type | Comment | 25 | | :--- | :--- | :--- | 26 | | | double | the total weight associated to the MST. | 27 | 28 | ## Code 29 | 30 | ```java 31 | /* 32 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 33 | */ 34 | package oracle.pgx.algorithms; 35 | 36 | import oracle.pgx.algorithm.EdgeProperty; 37 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 38 | import oracle.pgx.algorithm.PgxEdge; 39 | import oracle.pgx.algorithm.PgxGraph; 40 | import oracle.pgx.algorithm.PgxMap; 41 | import oracle.pgx.algorithm.PgxVertex; 42 | import oracle.pgx.algorithm.VertexProperty; 43 | import oracle.pgx.algorithm.annotations.Out; 44 | 45 | @GraphAlgorithm 46 | public class Prim { 47 | public double mst(PgxGraph g, EdgeProperty weight, @Out EdgeProperty inMst) { 48 | if (g.getNumVertices() == 0) { 49 | return 0.0d; 50 | } 51 | 52 | PgxMap q = PgxMap.create(); 53 | PgxVertex root = g.getRandomVertex(); 54 | 55 | root.getOutNeighbors().filter(n -> n != root).forSequential(n -> { 56 | PgxEdge e = n.edge(); 57 | q.set(e, weight.get(e)); 58 | }); 59 | 60 | VertexProperty processed = VertexProperty.create(); 61 | processed.setAll(false); 62 | processed.set(root, true); 63 | inMst.setAll(false); 64 | 65 | int numNodes = 1; 66 | double totalWeight = 0.0d; 67 | 68 | while (numNodes < g.getNumVertices() && q.size() > 0) { 69 | PgxEdge newEdge = q.getKeyForMinValue(); 70 | PgxVertex u = newEdge.sourceVertex(); 71 | PgxVertex v = newEdge.destinationVertex(); 72 | 73 | if (processed.get(v)) { 74 | PgxVertex tmp = v; 75 | v = u; 76 | u = tmp; 77 | } 78 | 79 | q.remove(newEdge); 80 | 81 | if (processed.get(v) != processed.get(u)) { 82 | inMst.set(newEdge, true); 83 | processed.set(v, true); 84 | totalWeight += weight.get(newEdge); 85 | 86 | v.getOutNeighbors().forEach(n -> { 87 | PgxEdge e = n.edge(); 88 | if (processed.get(n)) { 89 | q.remove(e); 90 | } else { 91 | q.set(e, weight.get(e)); 92 | } 93 | }); 94 | numNodes++; 95 | } 96 | } 97 | 98 | return totalWeight; 99 | } 100 | } 101 | ``` 102 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_a1u_prim.md: -------------------------------------------------------------------------------- 1 | # Prim's Algorithm (Ignoring edge directions) 2 | 3 | - **Category:** classic graph algorithms 4 | - **Algorithm ID:** pgx_builtin_a1u_prim 5 | - **Time Complexity:** O(E + V log V) with V = number of vertices, E = number of edges 6 | - **Space Requirement:** O(2 * E + V) with V = number of vertices, E = number of edges 7 | - **Javadoc:** 8 | - [Analyst#prim(PgxGraph graph, EdgeProperty weight)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#prim_oracle_pgx_api_PgxGraph_oracle_pgx_api_EdgeProperty_) 9 | - [Analyst#prim(PgxGraph graph, EdgeProperty weight, EdgeProperty mst)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#prim_oracle_pgx_api_PgxGraph_oracle_pgx_api_EdgeProperty_oracle_pgx_api_EdgeProperty_) 10 | 11 | This implementation of Prim's algorithm works on directed graphs that are connected but ignores edge directions to interpret the graph as undirected. The algorithm computes the minimum spanning tree (MST) of the graph using the weights associated to each edge. A minimum spanning tree is a subset of the edges that connects all the vertices in the graph such that it minimizes the total weight associated to the edges. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | | `weight` | edgeProp | edge property holding the weight of each edge in the graph. | 19 | 20 | | Output Argument | Type | Comment | 21 | | :--- | :--- | :--- | 22 | | `in_mst` | edgeProp | edge property holding the edges belonging to the minimum spanning tree of the graph (i.e. all the edges with in_mst=true). | 23 | 24 | | Return Value | Type | Comment | 25 | | :--- | :--- | :--- | 26 | | | double | the total weight associated to the MST. | 27 | 28 | ## Code 29 | 30 | ```java 31 | /* 32 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 33 | */ 34 | package oracle.pgx.algorithms; 35 | 36 | import oracle.pgx.algorithm.EdgeProperty; 37 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 38 | import oracle.pgx.algorithm.PgxEdge; 39 | import oracle.pgx.algorithm.PgxGraph; 40 | import oracle.pgx.algorithm.PgxMap; 41 | import oracle.pgx.algorithm.PgxVertex; 42 | import oracle.pgx.algorithm.VertexProperty; 43 | import oracle.pgx.algorithm.annotations.Out; 44 | 45 | @GraphAlgorithm 46 | public class Prim { 47 | public double mst(PgxGraph g, EdgeProperty weight, @Out EdgeProperty inMst) { 48 | if (g.getNumVertices() == 0) { 49 | return 0.0d; 50 | } 51 | 52 | PgxMap q = PgxMap.create(); 53 | PgxVertex root = g.getRandomVertex(); 54 | 55 | root.getOutNeighbors().filter(n -> n != root).forSequential(n -> { 56 | PgxEdge e = n.edge(); 57 | q.set(e, weight.get(e)); 58 | }); 59 | 60 | root.getInNeighbors().filter(n -> (n != root && !n.hasEdgeFrom(root))).forSequential(n -> { 61 | PgxEdge e = n.edge(); 62 | q.set(e, weight.get(e)); 63 | }); 64 | 65 | VertexProperty processed = VertexProperty.create(); 66 | processed.setAll(false); 67 | processed.set(root, true); 68 | inMst.setAll(false); 69 | 70 | int numNodes = 1; 71 | double totalWeight = 0.0d; 72 | 73 | while (numNodes < g.getNumVertices() && q.size() > 0) { 74 | PgxEdge newEdge = q.getKeyForMinValue(); 75 | PgxVertex u = newEdge.sourceVertex(); 76 | PgxVertex v = newEdge.destinationVertex(); 77 | 78 | if (processed.get(v)) { 79 | PgxVertex tmp = v; 80 | v = u; 81 | u = tmp; 82 | } 83 | 84 | q.remove(newEdge); 85 | 86 | if (processed.get(v) != processed.get(u)) { 87 | inMst.set(newEdge, true); 88 | processed.set(v, true); 89 | totalWeight += weight.get(newEdge); 90 | 91 | v.getOutNeighbors().forEach(n -> { 92 | PgxEdge e = n.edge(); 93 | if (processed.get(n)) { 94 | q.remove(e); 95 | } else { 96 | q.set(e, weight.get(e)); 97 | } 98 | }); 99 | 100 | v.getInNeighbors().filter(n -> !n.hasEdgeFrom(v)).forEach(n -> { 101 | PgxEdge e = n.edge(); 102 | if (processed.get(n)) { 103 | q.remove(e); 104 | } else { 105 | q.set(e, weight.get(e)); 106 | } 107 | }); 108 | 109 | numNodes++; 110 | } 111 | } 112 | 113 | return totalWeight; 114 | } 115 | } 116 | ``` 117 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_c5_speaker_listener_label_propagation.md: -------------------------------------------------------------------------------- 1 | # Speaker Listener Label Propagation 2 | 3 | - **Category:** community detection 4 | - **Algorithm ID:** pgx_builtin_c5_speaker_listener_label_propagation 5 | - **Time Complexity:** O(max_iter * N) with N = number of neighbors of vertex1, max_iter = number of iterations 6 | - **Space Requirement:** O(N + V * max_iter) with N = number of neighbors of vertex1, max_iter = number of iterations 7 | - **Javadoc:** 8 | - [Analyst#speakerListenerLabelPropagation(PgxGraph graph, String labelPropName)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#speakerListenerLabelPropagation_oracle_pgx_api_PgxGraph_java_lang_String_) 9 | - [Analyst#speakerListenerLabelPropagation​(PgxGraph graph, java.lang.String labelsPropName, int maxIter, double threshold, java.lang.String delimiter)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#speakerListenerLabelPropagation_oracle_pgx_api_PgxGraph_java_lang_String_int_double_java_lang_String_) 10 | - [Analyst#speakerListenerLabelPropagation​(PgxGraph graph, VertexProperty labels, int maxIter, double threshold, java.lang.String delimiter)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#speakerListenerLabelPropagation_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_int_double_java_lang_String_) 11 | 12 | The speaker listener label propagation algorithm is an extension of the label propagation algorithm, which is able to detect overlapping communities. 13 | 14 | ## Signature 15 | 16 | | Input Argument | Type | Comment | 17 | | :--- | :--- | :--- | 18 | | `g` | graph | the graph. | 19 | | `max_iter` | int | number of iterations. | 20 | | `threshold` | double | minimum frequency for a label to retain a vertex. | 21 | | `delimiter` | string | string delimiter for labels. | 22 | 23 | | Output Argument | Type | Comment | 24 | | :--- | :--- | :--- | 25 | | `labels` | vertexProp | distinct vertex labels which meet the threshold parameter. | 26 | 27 | | Return Value | Type | Comment | 28 | | :--- | :--- | :--- | 29 | | | void | None | 30 | 31 | ## Code 32 | 33 | Not available in PGX Algorithm API. 34 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_c5b_filtered_speaker_listener_label_propagation.md: -------------------------------------------------------------------------------- 1 | # Filtered Speaker Listener Label Propagation 2 | 3 | - **Category:** community detection 4 | - **Algorithm ID:** pgx_builtin_c5b_filtered_speaker_listener_label_propagation 5 | - **Time Complexity:** O(max_iter * N) with N = number of neighbors of vertex1, max_iter = number of iterations 6 | - **Space Requirement:** O(N + V * max_iter) with N = number of neighbors of vertex1, max_iter = number of iterations 7 | - **Javadoc:** 8 | - [Analyst#filteredSpeakerListenerLabelPropagation​(PgxGraph graph, java.lang.String labelsPropName, EdgeFilter filter)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#filteredSpeakerListenerLabelPropagation_oracle_pgx_api_PgxGraph_java_lang_String_oracle_pgx_api_filter_EdgeFilter_) 9 | - [Analyst#filteredSpeakerListenerLabelPropagation​(PgxGraph graph, java.lang.String labelsPropName, int maxIter, double threshold, java.lang.String delimiter, EdgeFilter filter)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#filteredSpeakerListenerLabelPropagation_oracle_pgx_api_PgxGraph_java_lang_String_int_double_java_lang_String_oracle_pgx_api_filter_EdgeFilter_) 10 | - [Analyst#filteredSpeakerListenerLabelPropagation(PgxGraph graph, VertexProperty labels, int maxIter, double threshold, java.lang.String delimiter, EdgeFilter filter)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#filteredSpeakerListenerLabelPropagationAsync_oracle_pgx_api_PgxGraph_java_lang_String_int_double_java_lang_String_oracle_pgx_api_filter_EdgeFilter_) 11 | 12 | The speaker listener label propagation algorithm is an extension of the label propagation algorithm, which is able to detect overlapping communities. This variant utilizes an edge filter to select which neighbors to listen to. 13 | 14 | ## Signature 15 | 16 | | Input Argument | Type | Comment | 17 | | :--- | :--- | :--- | 18 | | `g` | graph | the graph. | 19 | | `max_iter` | int | number of iterations. | 20 | | `threshold` | double | minimum frequency for a label to retain a vertex. | 21 | | `delimiter` | string | string delimiter for labels. | 22 | | `filter` | edgeFilter | The filter to be used on edges when listening to neighbors. | 23 | 24 | | Output Argument | Type | Comment | 25 | | :--- | :--- | :--- | 26 | | `labels` | vertexProp | distinct vertex labels which meet the threshold parameter. | 27 | 28 | | Return Value | Type | Comment | 29 | | :--- | :--- | :--- | 30 | | | void | None | 31 | 32 | ## Code 33 | 34 | Not available in PGX Algorithm API. 35 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_c5c_filtered_weighted_speaker_listener_label_propagation.md: -------------------------------------------------------------------------------- 1 | # Filtered Weighted Speaker Listener Label Propagation 2 | 3 | - **Category:** community detection 4 | - **Algorithm ID:** pgx_builtin_c5c_filtered_weighted_speaker_listener_label_propagation 5 | - **Time Complexity:** O(max_iter * N) with N = number of neighbors of vertex1, max_iter = number of iterations 6 | - **Space Requirement:** O(N + V * max_iter) with N = number of neighbors of vertex1, max_iter = number of iterations 7 | - **Javadoc:** 8 | - [Analyst#filteredWeightedSpeakerListenerLabelPropagation(PgxGraph graph, String labelPropName, EdgeProperty weight, EdgeFilter filter)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#filteredWeightedSpeakerListenerLabelPropagation_oracle_pgx_api_PgxGraph_java_lang_String_oracle_pgx_api_EdgeProperty_oracle_pgx_api_filter_EdgeFilter_) 9 | - [Analyst#filteredWeightedSpeakerListenerLabelPropagation(PgxGraph graph, java.lang.String labelsPropName, int maxIter, double threshold, java.lang.String delimiter, EdgeProperty weight, EdgeFilter filter)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#filteredWeightedSpeakerListenerLabelPropagation_oracle_pgx_api_PgxGraph_java_lang_String_int_double_java_lang_String_oracle_pgx_api_EdgeProperty_oracle_pgx_api_filter_EdgeFilter_) 10 | - [Analyst#filteredWeightedSpeakerListenerLabelPropagation(PgxGraph graph, VertexProperty labels, int maxIter, double threshold, java.lang.String delimiter, EdgeProperty weight, EdgeFilter filter)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#filteredWeightedSpeakerListenerLabelPropagation_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_int_double_java_lang_String_oracle_pgx_api_EdgeProperty_oracle_pgx_api_filter_EdgeFilter_) 11 | 12 | The speaker listener label propagation algorithm is an extension of the label propagation algorithm, which is able to detect overlapping communities. This variant utilizes an edge filter to select which neighbors to listen to and uses the edges' weight to update the frequency of listened labels. 13 | 14 | ## Signature 15 | 16 | | Input Argument | Type | Comment | 17 | | :--- | :--- | :--- | 18 | | `g` | graph | the graph. | 19 | | `max_iter` | int | number of iterations. | 20 | | `threshold` | double | minimum frequency for a label to retain a vertex. | 21 | | `delimiter` | string | string delimiter for labels. | 22 | | `filter` | edgeFilter | The filter to be used on edges when listening to neighbors. | 23 | 24 | | Output Argument | Type | Comment | 25 | | :--- | :--- | :--- | 26 | | `labels` | vertexProp | distinct vertex labels which meet the threshold parameter. | 27 | 28 | | Return Value | Type | Comment | 29 | | :--- | :--- | :--- | 30 | | | void | None | 31 | 32 | ## Code 33 | 34 | Not available in PGX Algorithm API. 35 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_c6_weighted_speaker_listener_label_propagation.md: -------------------------------------------------------------------------------- 1 | # Speaker Listener Label Propagation 2 | 3 | - **Category:** community detection 4 | - **Algorithm ID:** pgx_builtin_c6_weighted_speaker_listener_label_propagation 5 | - **Time Complexity:** O(max_iter * N) with N = number of neighbors of vertex1, max_iter = number of iterations 6 | - **Space Requirement:** O(N + V * max_iter) with N = number of neighbors of vertex1, max_iter = number of iterations 7 | - **Javadoc:** 8 | - [Analyst#weightedSpeakerListenerLabelPropagation(PgxGraph graph, String labelPropName, EdgeProperty weight)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#weightedSpeakerListenerLabelPropagation_oracle_pgx_api_PgxGraph_java_lang_String_oracle_pgx_api_EdgeProperty_) 9 | - [Analyst#weightedSpeakerListenerLabelPropagation(PgxGraph graph, java.lang.String labelsPropName, int maxIter, double threshold, java.lang.String delimiter, EdgeProperty weight)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#weightedSpeakerListenerLabelPropagation_oracle_pgx_api_PgxGraph_java_lang_String_int_double_java_lang_String_oracle_pgx_api_EdgeProperty_) 10 | - [Analyst#weightedSpeakerListenerLabelPropagation(PgxGraph graph, VertexProperty labels, int maxIter, double threshold, java.lang.String delimiter, EdgeProperty weight)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#weightedSpeakerListenerLabelPropagation_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_int_double_java_lang_String_oracle_pgx_api_EdgeProperty_) 11 | 12 | The speaker listener label propagation algorithm is an extension of the label propagation algorithm, which is able to detect overlapping communities. This variant uses the edges weight to find those communities. 13 | 14 | ## Signature 15 | 16 | | Input Argument | Type | Comment | 17 | | :--- | :--- | :--- | 18 | | `g` | graph | the graph. | 19 | | `max_iter` | int | number of iterations. | 20 | | `threshold` | double | minimum frequency for a label to retain a vertex. | 21 | | `delimiter` | string | string delimiter for labels. | 22 | | `weight` | edgeProp | edge property holding the weight of each edge in the graph. | 23 | 24 | | Output Argument | Type | Comment | 25 | | :--- | :--- | :--- | 26 | | `labels` | vertexProp | distinct vertex labels which meet the threshold parameter. | 27 | 28 | | Return Value | Type | Comment | 29 | | :--- | :--- | :--- | 30 | | | void | None | 31 | 32 | ## Code 33 | 34 | Not available in PGX Algorithm API. 35 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_g2a_strongly_connected_components_kosaraju.md: -------------------------------------------------------------------------------- 1 | # Strongly Connected Components (SCC) via Kosaraju's algorithm 2 | 3 | - **Category:** connected components 4 | - **Algorithm ID:** pgx_builtin_g2a_strongly_connected_components_kosaraju 5 | - **Time Complexity:** O(V + E) with V = number of vertices, E = number of edges 6 | - **Space Requirement:** O(3 * V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#sccKosaraju(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#sccKosaraju_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#sccKosaraju(PgxGraph graph, VertexProperty partitionDistribution)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#sccKosaraju_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_) 10 | 11 | Kosaraju's algorithm works on directed graphs for finding strongly connected components (SCC). A SCC is a maximal subset of vertices of the graph with the particular characteristic that every vertex in the SCC can be reachable from any other other vertex in the SCC. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | 19 | | Output Argument | Type | Comment | 20 | | :--- | :--- | :--- | 21 | | `scc` | vertexProp | vertex property holding the label of the SCC assigned to each vertex. | 22 | 23 | | Return Value | Type | Comment | 24 | | :--- | :--- | :--- | 25 | | | long | the total number of SCC found in the graph. | 26 | 27 | ## Code 28 | 29 | ```java 30 | /* 31 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 32 | */ 33 | package oracle.pgx.algorithms; 34 | 35 | import oracle.pgx.algorithm.PgxGraph; 36 | import oracle.pgx.algorithm.Scalar; 37 | import oracle.pgx.algorithm.VertexProperty; 38 | import oracle.pgx.algorithm.VertexSequence; 39 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 40 | import oracle.pgx.algorithm.annotations.Out; 41 | 42 | import static oracle.pgx.algorithm.Traversal.Direction.IN_EDGES; 43 | import static oracle.pgx.algorithm.Traversal.inBFS; 44 | import static oracle.pgx.algorithm.Traversal.inDFS; 45 | 46 | @GraphAlgorithm 47 | public class Kosaraju { 48 | public long kosaraju(PgxGraph g, @Out VertexProperty scc) { 49 | scc.setAll(-1L); 50 | 51 | VertexProperty checked = VertexProperty.create(); 52 | checked.setAll(false); 53 | 54 | // [Phase 1] 55 | // Obtain reverse-post-DFS-order of node sequence. 56 | // nodeOrder can be also used here but nodeSeq is faster 57 | VertexSequence queue = VertexSequence.create(); 58 | g.getVertices().filter(t -> !checked.get(t)).forSequential(t -> 59 | inDFS(g, t) 60 | .navigator(n -> !checked.get(n)) 61 | .backward(n -> { 62 | checked.set(n, true); 63 | queue.pushFront(n); 64 | }) 65 | ); 66 | 67 | // [Phase 2] 68 | // Starting from each vertex in the sequence 69 | // do BFS on the transposed graph g^. 70 | // and every vertices that are (newly) visited compose one SCC. 71 | Scalar compId = Scalar.create(0L); 72 | queue.filter(t -> scc.get(t) == -1).forSequential(t -> { 73 | inBFS(g, t) 74 | .navigator(n -> scc.get(n) == -1) 75 | .forward(n -> scc.set(n, compId.get())) 76 | .direction(IN_EDGES); 77 | 78 | compId.increment(); 79 | }); 80 | 81 | return compId.get(); 82 | } 83 | } 84 | ``` 85 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_g2b_strongly_connected_components_tarjan.md: -------------------------------------------------------------------------------- 1 | # Strongly Connected Components (SCC) via Tarjan's algorithm 2 | 3 | - **Category:** connected components 4 | - **Algorithm ID:** pgx_builtin_g2b_strongly_connected_components_tarjan 5 | - **Time Complexity:** O(V + E) with V = number of vertices, E = number of edges 6 | - **Space Requirement:** O(5 * V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#sccTarjan(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#sccTarjan_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#sccTarjan(PgxGraph graph, VertexProperty partitionDistribution)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#sccTarjan_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_) 10 | 11 | Tarjan's algorithm works on directed graphs for finding strongly connected components (SCC). A SCC is a maximal subset of vertices of the graph with the particular characteristic that every vertex in the SCC can be reachable from any other other vertex in the SCC. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | 19 | | Output Argument | Type | Comment | 20 | | :--- | :--- | :--- | 21 | | `scc` | vertexProp | vertex property holding the label of the SCC assigned to each vertex. | 22 | 23 | | Return Value | Type | Comment | 24 | | :--- | :--- | :--- | 25 | | | long | the total number of SCC found in the graph. | 26 | 27 | ## Code 28 | 29 | ```java 30 | /* 31 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 32 | */ 33 | package oracle.pgx.algorithms; 34 | 35 | import oracle.pgx.algorithm.PgxGraph; 36 | import oracle.pgx.algorithm.PgxVertex; 37 | import oracle.pgx.algorithm.Scalar; 38 | import oracle.pgx.algorithm.VertexProperty; 39 | import oracle.pgx.algorithm.VertexSequence; 40 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 41 | import oracle.pgx.algorithm.annotations.Out; 42 | 43 | import static oracle.pgx.algorithm.Traversal.inDFS; 44 | 45 | @GraphAlgorithm 46 | public class Tarjan { 47 | public long tarjan(PgxGraph g, @Out VertexProperty scc) { 48 | VertexProperty inStack = VertexProperty.create(); 49 | VertexProperty lowLink = VertexProperty.create(); 50 | VertexProperty index = VertexProperty.create(); 51 | VertexSequence stack = VertexSequence.create(); 52 | 53 | // sequentially initialize, otherwise compiler flags this algorithm as parallel in nature 54 | g.getVertices().forSequential(n -> { 55 | scc.set(n, -1L); 56 | inStack.set(n, false); 57 | index.set(n, -1L); 58 | }); 59 | 60 | Scalar numScc = Scalar.create(0L); 61 | 62 | // DFS 63 | g.getVertices().filter(n -> scc.get(n) == -1).forSequential(n -> { 64 | Scalar dfsIndex = Scalar.create(0L); 65 | 66 | inDFS(g, n) 67 | .navigator(t -> index.get(t) == -1) 68 | .forward(t -> { 69 | stack.pushBack(t); 70 | inStack.set(t, true); 71 | lowLink.set(t, dfsIndex.get()); 72 | index.set(t, dfsIndex.get()); 73 | dfsIndex.increment(); 74 | }) 75 | .backward(t -> { 76 | t.getOutNeighbors().filter(k -> scc.get(k) == -1).forSequential(k -> { 77 | lowLink.reduceMin(t, lowLink.get(k)); 78 | }); 79 | 80 | if (lowLink.get(t) == index.get(t)) { 81 | PgxVertex w = stack.popBack(); 82 | while (w != t) { 83 | inStack.set(w, false); 84 | scc.set(w, numScc.get()); 85 | w = stack.popBack(); 86 | } 87 | inStack.set(w, false); 88 | scc.set(w, numScc.get()); 89 | numScc.increment(); 90 | } 91 | }); 92 | }); 93 | 94 | return numScc.get(); 95 | } 96 | } 97 | ``` 98 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_g3_weakly_connected_components.md: -------------------------------------------------------------------------------- 1 | # Weakly Connected Components (WCC) 2 | 3 | - **Category:** connected components 4 | - **Algorithm ID:** pgx_builtin_g3_weakly_connected_components 5 | - **Time Complexity:** O(E * d) with d = diameter of the graph 6 | - **Space Requirement:** O(2 * V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#wcc(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#wcc_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#wcc(PgxGraph graph, VertexProperty partitionDistribution)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#wcc_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_) 10 | 11 | This algorithm finds weakly connected components (WCC) in a directed graph. A WCC is a maximal subset of vertices of the graph with the particular characteristic that for every pair of vertices U and V in the WCC there must be a path connecting U to V, ignoring the direction of edges. It is a non-deterministic algorithm because of its parallelized implementation. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | 19 | | Output Argument | Type | Comment | 20 | | :--- | :--- | :--- | 21 | | `comp_id` | vertexProp | vertex property holding the label of the WCC assigned to each vertex. | 22 | 23 | | Return Value | Type | Comment | 24 | | :--- | :--- | :--- | 25 | | | long | the total number of WCC found in the graph. | 26 | 27 | ## Code 28 | 29 | ```java 30 | /* 31 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 32 | */ 33 | package oracle.pgx.algorithms; 34 | 35 | import java.util.function.Function; 36 | 37 | import oracle.pgx.algorithm.PgxGraph; 38 | import oracle.pgx.algorithm.PgxVertex; 39 | import oracle.pgx.algorithm.Scalar; 40 | import oracle.pgx.algorithm.VertexProperty; 41 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 42 | import oracle.pgx.algorithm.annotations.Out; 43 | 44 | @GraphAlgorithm 45 | public class Wcc { 46 | public long wcc(PgxGraph g, @Out VertexProperty compId) { 47 | VertexProperty wcc = VertexProperty.create(); 48 | 49 | // Initialize 50 | wcc.setAll(Function.identity()); 51 | 52 | Scalar changed = Scalar.create(); 53 | do { 54 | changed.set(false); 55 | 56 | // kernel 1 (get 'maximum' value among neighbors) 57 | g.getVertices().forEach(u -> { 58 | u.getInNeighbors().forSequential(v -> { 59 | if (wcc.get(u).lessThan(wcc.get(v))) { 60 | changed.reduceOr(true); 61 | wcc.set(u, wcc.get(v)); 62 | } 63 | }); 64 | 65 | u.getOutNeighbors().forSequential(v -> { 66 | if (wcc.get(u).lessThan(wcc.get(v))) { 67 | changed.reduceOr(true); 68 | wcc.set(u, wcc.get(v)); 69 | } 70 | }); 71 | }); 72 | 73 | // kernel 2 74 | g.getVertices().forEach(u -> { 75 | if (wcc.get(u) != u) { 76 | PgxVertex v = wcc.get(u); 77 | if (wcc.get(v) != v) { 78 | wcc.set(u, wcc.get(v)); 79 | } 80 | } 81 | }); 82 | } while (changed.get()); 83 | 84 | // Create output format 85 | Scalar numComp = Scalar.create(0L); 86 | g.getVertices().forSequential(n -> { 87 | if (wcc.get(n) == n) { 88 | compId.set(n, numComp.get()); 89 | numComp.increment(); 90 | } 91 | }); 92 | 93 | g.getVertices().filter(n -> wcc.get(n) != n).forEach(n -> { 94 | PgxVertex v = wcc.get(n); 95 | compId.set(n, compId.get(v)); 96 | }); 97 | 98 | return numComp.get(); 99 | } 100 | } 101 | ``` 102 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_k10_article_rank.md: -------------------------------------------------------------------------------- 1 | # ArticleRank 2 | 3 | - **Category:** ranking and walking 4 | - **Algorithm ID:** pgx_builtin_k10_article_rank 5 | - **Time Complexity:** O(E * k) with E = number of edges, k <= maximum number of iterations 6 | - **Space Requirement:** O(V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#articleRank(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#articleRank_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#articleRank(PgxGraph graph, boolean norm)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#articleRank_oracle_pgx_api_PgxGraph_boolean_) 10 | - [Analyst#articleRank(PgxGraph graph, double e, double d, int max)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#articleRank_oracle_pgx_api_PgxGraph_double_double_int_) 11 | - [Analyst#articleRank(PgxGraph graph, double e, double d, int max, boolean norm)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#articleRank_oracle_pgx_api_PgxGraph_double_double_int_boolean_) 12 | - [Analyst#articleRank(PgxGraph graph, double e, double d, int max, boolean norm, VertexProperty rank)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#articleRank_oracle_pgx_api_PgxGraph_double_double_int_boolean_oracle_pgx_api_VertexProperty_) 13 | - [Analyst#articleRank(PgxGraph graph, double e, double d, int max, VertexProperty rank)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#articleRank_oracle_pgx_api_PgxGraph_double_double_int_oracle_pgx_api_VertexProperty_) 14 | 15 | ArticleRank is a variant of the PageRank algorithm and operates in a similar way. It computes the ranking score for the vertices by analyzing the incoming edges, while reducing the assumption that relationships with nodes that have a low out-degree are of higher importance. 16 | 17 | ## Signature 18 | 19 | | Input Argument | Type | Comment | 20 | | :--- | :--- | :--- | 21 | | `G` | graph | the graph. | 22 | | `tol` | double | maximum tolerated error value. The algorithm will stop once the sum of the error values of all vertices becomes smaller than this value. | 23 | | `damp` | double | damping factor. | 24 | | `max_iter` | int | maximum number of iterations that will be performed. | 25 | | `norm` | boolean | boolean flag to determine whether the algorithm will take into account dangling vertices for the ranking scores. | 26 | 27 | | Output Argument | Type | Comment | 28 | | :--- | :--- | :--- | 29 | | `rank` | vertexProp | vertex property holding the (normalized) ArticleRank value for each vertex (a value between 0 and 1). | 30 | 31 | | Return Value | Type | Comment | 32 | | :--- | :--- | :--- | 33 | | | void | None | 34 | 35 | ## Code 36 | 37 | ```java 38 | /* 39 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 40 | */ 41 | package oracle.pgx.algorithms; 42 | 43 | import oracle.pgx.algorithm.PgxGraph; 44 | import oracle.pgx.algorithm.Scalar; 45 | import oracle.pgx.algorithm.VertexProperty; 46 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 47 | import oracle.pgx.algorithm.annotations.Out; 48 | 49 | @GraphAlgorithm 50 | public class ArticleRank { 51 | public void articleRank(PgxGraph g, double tol, double damp, int maxIter, boolean norm, 52 | @Out VertexProperty rank) { 53 | Scalar diff = Scalar.create(); 54 | int cnt = 0; 55 | double n = g.getNumVertices(); 56 | double avgOutDegree = g.getVertices().avg(w -> w.getOutDegree()); 57 | rank.setAll(1 / n); 58 | 59 | do { 60 | diff.set(0.0); 61 | Scalar danglingFactor = Scalar.create(0d); 62 | if (norm) { 63 | danglingFactor.set(damp / n * g.getVertices().filter(v -> v.getOutDegree() == 0).sum(rank::get)); 64 | } 65 | 66 | g.getVertices().forEach(t -> { 67 | double inSum = t.getInNeighbors().sum(w -> rank.get(w) / (w.getOutDegree() + avgOutDegree)); 68 | double val = (1 - damp) / n + damp * inSum + danglingFactor.get(); 69 | diff.reduceAdd(Math.abs(val - rank.get(t))); 70 | rank.setDeferred(t, val); 71 | }); 72 | cnt++; 73 | } while (diff.get() > tol && cnt < maxIter); 74 | } 75 | } 76 | ``` 77 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_k3a_node_betweenness_centrality.md: -------------------------------------------------------------------------------- 1 | # Vertex Betweenness Centrality 2 | 3 | - **Category:** ranking and walking 4 | - **Algorithm ID:** pgx_builtin_k3a_node_betweenness_centrality 5 | - **Time Complexity:** O(V * E) with V = number of vertices, E = number of edges 6 | - **Space Requirement:** O(3 * V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#vertexBetweennessCentrality(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#vertexBetweennessCentrality_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#vertexBetweennessCentrality(PgxGraph graph, VertexProperty bc)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#vertexBetweennessCentrality_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_) 10 | 11 | The Betweenness Centrality of a vertex V in a graph is the sum of the fraction of shortest paths that pass through V from all the possible shortest paths connecting every possible pair of vertices S, T in the graph, such that V is different from S and T. Because of its definition, the algorithm is meant for connected graphs. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | 19 | | Output Argument | Type | Comment | 20 | | :--- | :--- | :--- | 21 | | `bc` | vertexProp | vertex property holding the betweenness centrality value for each vertex. | 22 | 23 | | Return Value | Type | Comment | 24 | | :--- | :--- | :--- | 25 | | | void | None | 26 | 27 | ## Code 28 | 29 | ```java 30 | /* 31 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 32 | */ 33 | package oracle.pgx.algorithms; 34 | 35 | import oracle.pgx.algorithm.PgxGraph; 36 | import oracle.pgx.algorithm.VertexProperty; 37 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 38 | import oracle.pgx.algorithm.annotations.Out; 39 | 40 | import static oracle.pgx.algorithm.Traversal.inBFS; 41 | 42 | @GraphAlgorithm 43 | public class BetweennessCentrality { 44 | public void bcFull(PgxGraph g, @Out VertexProperty bc) { 45 | bc.setAll(0d); // Initialize 46 | 47 | g.getVertices().forEach(s -> { 48 | // temporary values per vertex 49 | VertexProperty sigma = VertexProperty.create(); 50 | VertexProperty delta = VertexProperty.create(); 51 | sigma.setAll(0d); 52 | sigma.set(s, 1d); 53 | 54 | // BFS order iteration from s 55 | inBFS(g, s) 56 | .filter(v -> v != s) 57 | .forward(v -> sigma.set(v, v.getUpNeighbors().sum(sigma))) 58 | .backwardFilter(v -> v != s) 59 | .backward(v -> { 60 | delta.set(v, v.getDownNeighbors().sum(w -> (1 + delta.get(w)) / sigma.get(w)) * sigma.get(v)); 61 | bc.reduceAdd(v, delta.get(v)); 62 | }); 63 | }); 64 | } 65 | } 66 | ``` 67 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_k3b_approx_node_betweenness_centrality.md: -------------------------------------------------------------------------------- 1 | # Approximate Vertex Betweenness Centrality with Random Seeds 2 | 3 | - **Category:** ranking and walking 4 | - **Algorithm ID:** pgx_builtin_k3b_approx_node_betweenness_centrality 5 | - **Time Complexity:** O(V * E) with V = number of vertices, E = number of edges 6 | - **Space Requirement:** O(3 * V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#approximateVertexBetweennessCentrality(PgxGraph graph, int k)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#approximateVertexBetweennessCentrality_oracle_pgx_api_PgxGraph_int_) 9 | - [Analyst#approximateVertexBetweennessCentrality(PgxGraph graph, int k, VertexProperty bc)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#approximateVertexBetweennessCentrality_oracle_pgx_api_PgxGraph_int_oracle_pgx_api_VertexProperty_) 10 | 11 | This variant of betweenness centrality approximates the centrality of the vertices by just using k random vertices as starting points for the BFS traversals of the graph, instead of computing the exact value by using all the vertices in the graph. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | | `num_seeds` | int | number of random vertices to be used to compute the approximated betweenness centrality coefficients. | 19 | 20 | | Output Argument | Type | Comment | 21 | | :--- | :--- | :--- | 22 | | `bc` | vertexProp | vertex property holding the betweenness centrality value for each vertex. | 23 | 24 | | Return Value | Type | Comment | 25 | | :--- | :--- | :--- | 26 | | | void | None | 27 | 28 | ## Code 29 | 30 | ```java 31 | /* 32 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 33 | */ 34 | package oracle.pgx.algorithms; 35 | 36 | import oracle.pgx.algorithm.PgxGraph; 37 | import oracle.pgx.algorithm.VertexProperty; 38 | import oracle.pgx.algorithm.VertexSet; 39 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 40 | import oracle.pgx.algorithm.annotations.Out; 41 | 42 | import static oracle.pgx.algorithm.Traversal.inBFS; 43 | 44 | @GraphAlgorithm 45 | public class BetweennessCentralityApproximate { 46 | public void betweennessCentralityApproximate(PgxGraph g, int numSeeds, @Out VertexProperty bc) { 47 | bc.setAll(0d); // Initialize 48 | 49 | long maxSeeds = (g.getNumVertices() > numSeeds) ? numSeeds : g.getNumVertices(); 50 | 51 | VertexSet seeds = VertexSet.create(); 52 | while (seeds.size() < maxSeeds) { 53 | seeds.add(g.getRandomVertex()); 54 | } 55 | 56 | seeds.forEach(s -> { 57 | // temporary values per vertex 58 | VertexProperty sigma = VertexProperty.create(); 59 | VertexProperty delta = VertexProperty.create(); 60 | sigma.setAll(0d); 61 | sigma.set(s, 1d); 62 | 63 | // BFS order iteration from s 64 | inBFS(g, s) 65 | .filter(v -> v != s) 66 | .forward(v -> sigma.set(v, v.getUpNeighbors().sum(sigma))) 67 | .backwardFilter(v -> v != s) 68 | .backward(v -> { 69 | delta.set(v, v.getDownNeighbors().sum(w -> sigma.get(v) / sigma.get(w) * (1 + delta.get(w)))); 70 | bc.reduceAdd(v, delta.get(v)); 71 | }); 72 | }); 73 | } 74 | } 75 | ``` 76 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_k3c_approx_node_betweenness_centrality_from_seeds.md: -------------------------------------------------------------------------------- 1 | # Approximate Vertex Betweenness Centrality From seeds 2 | 3 | - **Category:** ranking and walking 4 | - **Algorithm ID:** pgx_builtin_k3c_approx_node_betweenness_centrality_from_seeds 5 | - **Time Complexity:** O(V * E) with V = number of vertices, E = number of edges 6 | - **Space Requirement:** O(3 * V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#approximateVertexBetweennessCentralityFromSeeds(PgxGraph graph, PgxVertex... seeds)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#approximateVertexBetweennessCentralityFromSeeds_oracle_pgx_api_PgxGraph_oracle_pgx_api_PgxVertex____) 9 | - [Analyst#approximateVertexBetweennessCentralityFromSeeds(PgxGraph graph, VertexProperty bc, PgxVertex... seeds)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#approximateVertexBetweennessCentralityFromSeeds_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_oracle_pgx_api_PgxVertex____) 10 | 11 | This variant of betweenness centrality approximates the centrality of the vertices by just using the vertices from the given sequence as starting points for the BFS traversals of the graph, instead of computing the exact value by using all the vertices in the graph. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | | `seeds` | nodeSeq | the (unique) chosen vertices to be used to compute the approximated betweenness centrality coefficients. | 19 | 20 | | Output Argument | Type | Comment | 21 | | :--- | :--- | :--- | 22 | | `bc` | vertexProp | vertex property holding the betweenness centrality value for each vertex. | 23 | 24 | | Return Value | Type | Comment | 25 | | :--- | :--- | :--- | 26 | | | void | None | 27 | 28 | ## Code 29 | 30 | ```java 31 | /* 32 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 33 | */ 34 | package oracle.pgx.algorithms; 35 | 36 | import oracle.pgx.algorithm.PgxGraph; 37 | import oracle.pgx.algorithm.VertexProperty; 38 | import oracle.pgx.algorithm.VertexSequence; 39 | import oracle.pgx.algorithm.VertexSet; 40 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 41 | import oracle.pgx.algorithm.annotations.Out; 42 | 43 | import static oracle.pgx.algorithm.Traversal.inBFS; 44 | 45 | @GraphAlgorithm 46 | public class BetweennessCentralityApproximateSeeds { 47 | public void betweennessCentralityApproximate(PgxGraph g, VertexSequence seeds, @Out VertexProperty bc) { 48 | bc.setAll(0d); // Initialize 49 | 50 | VertexSet set = VertexSet.create(); 51 | seeds.forSequential(set::add); 52 | 53 | set.forSequential(s -> { 54 | // temporary values per vertex 55 | VertexProperty sigma = VertexProperty.create(); 56 | VertexProperty delta = VertexProperty.create(); 57 | sigma.setAll(0d); 58 | sigma.set(s, 1d); 59 | 60 | // BFS order iteration from s 61 | inBFS(g, s) // 62 | .filter(v -> v != s) // 63 | .forward(v -> sigma.set(v, v.getUpNeighbors().sum(sigma))) // 64 | .backwardFilter(v -> v != s) // 65 | .backward(v -> { 66 | delta.set(v, v.getDownNeighbors().sum(w -> sigma.get(v) / sigma.get(w) * (1 + delta.get(w)))); 67 | bc.reduceAdd(v, delta.get(v)); 68 | }); 69 | }); 70 | } 71 | } 72 | ``` 73 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_k4a_closeness_centrality_unit_length.md: -------------------------------------------------------------------------------- 1 | # Closeness Centrality (Unit Length) 2 | 3 | - **Category:** ranking and walking 4 | - **Algorithm ID:** pgx_builtin_k4a_closeness_centrality_unit_length 5 | - **Time Complexity:** O(V * E) with V = number of vertices, E = number of edges 6 | - **Space Requirement:** O(V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#closenessCentralityUnitLength(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#closenessCentralityUnitLength_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#closenessCentralityUnitLength(PgxGraph graph, VertexProperty cc)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#closenessCentralityUnitLength_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_) 10 | 11 | The Closeness Centrality of a node V is the reciprocal of the sum of all the distances from the possible shortest paths starting from V. Thus the higher the centrality value of V, the closer it is to all the other vertices in the graph. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | 19 | | Output Argument | Type | Comment | 20 | | :--- | :--- | :--- | 21 | | `cc` | vertexProp | node property holding the closeness centrality value for each node. | 22 | 23 | | Return Value | Type | Comment | 24 | | :--- | :--- | :--- | 25 | | | bool | returns true if the graph is connected, false otherwise. | 26 | 27 | ## Code 28 | 29 | ```java 30 | /* 31 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 32 | */ 33 | package oracle.pgx.algorithms; 34 | 35 | import oracle.pgx.algorithm.PgxGraph; 36 | import oracle.pgx.algorithm.Scalar; 37 | import oracle.pgx.algorithm.VertexProperty; 38 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 39 | import oracle.pgx.algorithm.annotations.Out; 40 | 41 | import static oracle.pgx.algorithm.Traversal.currentLevel; 42 | import static oracle.pgx.algorithm.Traversal.inBFS; 43 | 44 | @GraphAlgorithm 45 | public class ClosenessCentrality { 46 | public boolean closenessCentrality(PgxGraph g, @Out VertexProperty cc) { 47 | Scalar connected = Scalar.create(true); 48 | 49 | g.getVertices().forEach(s -> { 50 | Scalar foundNodes = Scalar.create(0); 51 | Scalar levelSum = Scalar.create(0); 52 | 53 | inBFS(g, s).direction(Traversal.Direction.IN_OUT_EDGES).forward(v -> { 54 | foundNodes.increment(); 55 | levelSum.reduceAdd(currentLevel()); 56 | }); 57 | 58 | if (foundNodes.get() != g.getNumVertices() || levelSum.get() == 0) { 59 | connected.reduceAnd(false); 60 | } else { 61 | cc.set(s, 1.0 / levelSum.get()); 62 | } 63 | }); 64 | 65 | if (connected.get()) { 66 | return true; 67 | } else { 68 | cc.setAll(0.0); 69 | 70 | return false; 71 | } 72 | } 73 | } 74 | ``` 75 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_k5_hits.md: -------------------------------------------------------------------------------- 1 | # Hyperlink-Induced Topic Search (HITS) 2 | 3 | - **Category:** ranking and walking 4 | - **Algorithm ID:** pgx_builtin_k5_hits 5 | - **Time Complexity:** O(E * k) with E = number of edges, k <= maximum number of iterations 6 | - **Space Requirement:** O(2 * V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#hits(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#hits_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#hits(PgxGraph graph, int max)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#hits_oracle_pgx_api_PgxGraph_int_) 10 | - [Analyst#hits(PgxGraph graph, int max, VertexProperty auth, VertexProperty hubs)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#hits_oracle_pgx_api_PgxGraph_int_oracle_pgx_api_VertexProperty_oracle_pgx_api_VertexProperty_) 11 | - [Analyst#hits(PgxGraph graph, VertexProperty auth, VertexProperty hubs)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#hits_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_oracle_pgx_api_VertexProperty_) 12 | 13 | HITS is an algorithm that computes two ranking scores (authority and hub)for each vertex in the graph. The idea of hubs and authorities comes from the web pages: a hub is regarded as a page that is not authoritative in a specific topic, but it has instead links to authority pages, which are regarded as meaningful sources for a particular topic by many hubs. Thus a good hub will point to many authorities, while a good authority will be pointed by many hubs. The authority score of a vertex V is computed by adding all the hub scores of its incoming neighbors (i.e. vertices with edges pointing to V). The hub score is computed in a similar way, using the authority scores instead. 14 | 15 | ## Signature 16 | 17 | | Input Argument | Type | Comment | 18 | | :--- | :--- | :--- | 19 | | `G` | graph | the graph. | 20 | | `max_iter` | int | number of iterations that will be performed. | 21 | 22 | | Output Argument | Type | Comment | 23 | | :--- | :--- | :--- | 24 | | `auth` | vertexProp | vertex property holding the authority score for each vertex. | 25 | | `hub` | vertexProp | vertex property holding the hub score for each vertex. | 26 | 27 | | Return Value | Type | Comment | 28 | | :--- | :--- | :--- | 29 | | | void | None | 30 | 31 | ## Code 32 | 33 | ```java 34 | /* 35 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 36 | */ 37 | package oracle.pgx.algorithms; 38 | 39 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 40 | import oracle.pgx.algorithm.PgxGraph; 41 | import oracle.pgx.algorithm.Scalar; 42 | import oracle.pgx.algorithm.VertexProperty; 43 | import oracle.pgx.algorithm.annotations.Out; 44 | 45 | import static java.lang.Math.sqrt; 46 | 47 | @GraphAlgorithm 48 | public class Hits { 49 | public void hits(PgxGraph g, int maxIter, @Out VertexProperty auth, @Out VertexProperty hub) { 50 | auth.setAll(1.0); 51 | hub.setAll(1.0); 52 | 53 | int k = 0; 54 | while (k < maxIter) { 55 | Scalar norm = Scalar.create(); 56 | 57 | // phase 1. update auth from hub 58 | norm.set(0d); 59 | 60 | g.getVertices().forEach(p -> { 61 | double v = p.getInNeighbors().sum(hub); 62 | norm.reduceAdd(v * v); 63 | auth.set(p, v); 64 | }); 65 | norm.set(sqrt(norm.get())); 66 | auth.setAll(v -> auth.get(v) / norm.get()); 67 | 68 | // phase 2. hub from auth 69 | norm.set(0d); 70 | 71 | g.getVertices().forEach(p -> { 72 | double v = p.getOutNeighbors().sum(auth); 73 | norm.reduceAdd(v * v); 74 | hub.set(p, v); 75 | }); 76 | norm.set(sqrt(norm.get())); 77 | hub.setAll(v -> hub.get(v) / norm.get()); 78 | 79 | k++; 80 | } 81 | } 82 | } 83 | ``` 84 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_k6_eigenvector_centrality.md: -------------------------------------------------------------------------------- 1 | # Eigenvector Centrality 2 | 3 | - **Category:** ranking and walking 4 | - **Algorithm ID:** pgx_builtin_k6_eigenvector_centrality 5 | - **Time Complexity:** O(V * k) with V = number of vertices, k <= maximum number of iterations 6 | - **Space Requirement:** O(2 * V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#eigenvectorCentrality(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#eigenvectorCentrality_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#eigenvectorCentrality(PgxGraph graph, int max, double maxDiff, boolean useL2Norm, boolean useInEdge)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#eigenvectorCentrality_oracle_pgx_api_PgxGraph_int_double_boolean_boolean_) 10 | - [Analyst#eigenvectorCentrality(PgxGraph graph, int max, double maxDiff, boolean useL2Norm, boolean useInEdge, VertexProperty ec)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#eigenvectorCentrality_oracle_pgx_api_PgxGraph_int_double_boolean_boolean_oracle_pgx_api_VertexProperty_) 11 | - [Analyst#eigenvectorCentrality(PgxGraph graph, VertexProperty ec)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#eigenvectorCentrality_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_) 12 | 13 | The Eigenvector Centrality determines the centrality of a vertex by adding and weighting the centrality of its neighbors. Using outgoing or incoming edges when computing the eigenvector centrality will be equivalent to do so with the normal or the transpose adjacency matrix, respectively leading to the "right" and "left" eigenvectors. 14 | 15 | ## Signature 16 | 17 | | Input Argument | Type | Comment | 18 | | :--- | :--- | :--- | 19 | | `G` | graph | the graph. | 20 | | `max_iter` | int | maximum number of iterations that will be performed. | 21 | | `max_diff` | double | maximum tolerated error value. The algorithm will stop once the sum of the error values of all vertices becomes smaller than this value. | 22 | | `use_l2norm` | boolean | boolean flag to determine whether the algorithm will use the l2 norm (Euclidean norm) or the l1 norm (absolute value) to normalize the centrality scores. | 23 | | `use_inEdges` | boolean | boolean flag to determine whether the algorithm will use the incoming or the outgoing edges in the graph for the computations. | 24 | 25 | | Output Argument | Type | Comment | 26 | | :--- | :--- | :--- | 27 | | `ec` | vertexProp | vertex property holding the normalized centrality value for each vertex. | 28 | 29 | | Return Value | Type | Comment | 30 | | :--- | :--- | :--- | 31 | | | void | None | 32 | 33 | ## Code 34 | 35 | ```java 36 | /* 37 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 38 | */ 39 | package oracle.pgx.algorithms; 40 | 41 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 42 | import oracle.pgx.algorithm.PgxGraph; 43 | import oracle.pgx.algorithm.Scalar; 44 | import oracle.pgx.algorithm.VertexProperty; 45 | import oracle.pgx.algorithm.annotations.Out; 46 | 47 | import static java.lang.Math.abs; 48 | import static java.lang.Math.sqrt; 49 | 50 | @GraphAlgorithm 51 | public class EigenvectorCentrality { 52 | public void eigenvectorCentrality(PgxGraph g, int maxIter, double maxDiff, boolean useL2Norm, boolean useInedges, 53 | @Out VertexProperty ec) { 54 | VertexProperty ecUnnormal = VertexProperty.create(); 55 | 56 | // Initialize 57 | ec.setAll(1.0 / (double) g.getNumVertices()); 58 | 59 | int iter = 0; 60 | Scalar diff = Scalar.create(); 61 | diff.set(0.0); 62 | 63 | do { 64 | // compute unnormalized sum 65 | g.getVertices().forEach(n -> { 66 | if (useInedges) { 67 | ecUnnormal.set(n, n.getInNeighbors().sum(ec)); 68 | } else { 69 | ecUnnormal.set(n, n.getOutNeighbors().sum(ec)); 70 | } 71 | }); 72 | 73 | double s; 74 | if (useL2Norm) { 75 | // L2 Norm Normalization 76 | double l2Sum = g.getVertices().sum(n -> ecUnnormal.get(n) * ecUnnormal.get(n)); 77 | s = (l2Sum == 0) ? 1.0 : 1 / sqrt(l2Sum); 78 | } else { 79 | // L1 Norm Normalization 80 | double l1Sum = g.getVertices().sum(n -> abs(ecUnnormal.get(n))); 81 | s = (l1Sum == 0) ? 1.0 : 1 / (l1Sum); 82 | } 83 | 84 | // update for next step 85 | diff.set(0.0); 86 | g.getVertices().forEach(n -> { 87 | double val = ecUnnormal.get(n) * s; 88 | diff.reduceAdd(abs(ec.get(n) - val)); 89 | ec.set(n, val); 90 | }); 91 | iter++; 92 | } while ((iter < maxIter) && (diff.get() > maxDiff)); 93 | } 94 | } 95 | ``` 96 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_k7a_outdegree_centrality.md: -------------------------------------------------------------------------------- 1 | # Out-Degree Centrality 2 | 3 | - **Category:** ranking and walking 4 | - **Algorithm ID:** pgx_builtin_k7a_outdegree_centrality 5 | - **Time Complexity:** O(V) with V = number of vertices 6 | - **Space Requirement:** O(V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#outDegreeCentrality(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#outDegreeCentrality_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#outDegreeCentrality(PgxGraph graph, VertexProperty dc)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#outDegreeCentrality_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_) 10 | 11 | Out-Degree centrality returns the sum of the number of outgoing edges for each vertex in the graph. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | 19 | | Output Argument | Type | Comment | 20 | | :--- | :--- | :--- | 21 | | `oc` | vertexProp | vertex property holding the degree centrality value for each vertex in the graph. | 22 | 23 | | Return Value | Type | Comment | 24 | | :--- | :--- | :--- | 25 | | | void | None | 26 | 27 | ## Code 28 | 29 | ```java 30 | /* 31 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 32 | */ 33 | package oracle.pgx.algorithms; 34 | 35 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 36 | import oracle.pgx.algorithm.PgxGraph; 37 | import oracle.pgx.algorithm.VertexProperty; 38 | import oracle.pgx.algorithm.annotations.Out; 39 | import oracle.pgx.algorithm.ControlFlow; 40 | 41 | @GraphAlgorithm 42 | public class OutdegreeCentrality { 43 | public void outdegreeCentrality(PgxGraph g, @Out VertexProperty outdegreeCentrality) { 44 | long numberOfStepsEstimatedForCompletion = g.getNumVertices(); 45 | ControlFlow.setNumberOfStepsEstimatedForCompletion(numberOfStepsEstimatedForCompletion); 46 | g.getVertices().forEach(n -> 47 | outdegreeCentrality.set(n, (int) n.getOutDegree()) 48 | ); 49 | } 50 | } 51 | ``` 52 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_k7b_indegree_centrality.md: -------------------------------------------------------------------------------- 1 | # In-Degree Centrality 2 | 3 | - **Category:** ranking and walking 4 | - **Algorithm ID:** pgx_builtin_k7b_indegree_centrality 5 | - **Time Complexity:** O(V) with V = number of vertices 6 | - **Space Requirement:** O(V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#inDegreeCentrality(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#inDegreeCentrality_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#inDegreeCentrality(PgxGraph graph, VertexProperty dc)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#inDegreeCentrality_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_) 10 | 11 | In-Degree centrality returns the sum of the number of incoming edges for each vertex in the graph. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | 19 | | Output Argument | Type | Comment | 20 | | :--- | :--- | :--- | 21 | | `ic` | vertexProp | vertex property holding the degree centrality value for each vertex in the graph. | 22 | 23 | | Return Value | Type | Comment | 24 | | :--- | :--- | :--- | 25 | | | void | | 26 | 27 | ## Code 28 | 29 | ```java 30 | /* 31 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 32 | */ 33 | package oracle.pgx.algorithms; 34 | 35 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 36 | import oracle.pgx.algorithm.PgxGraph; 37 | import oracle.pgx.algorithm.VertexProperty; 38 | import oracle.pgx.algorithm.annotations.Out; 39 | import oracle.pgx.algorithm.ControlFlow; 40 | 41 | @GraphAlgorithm 42 | public class IndegreeCentrality { 43 | public void indegreeCentrality(PgxGraph g, @Out VertexProperty indegreeCentrality) { 44 | long numberOfStepsEstimatedForCompletion = g.getNumVertices(); 45 | ControlFlow.setNumberOfStepsEstimatedForCompletion(numberOfStepsEstimatedForCompletion); 46 | g.getVertices().forEach(n -> 47 | indegreeCentrality.set(n, (int) n.getInDegree()) 48 | ); 49 | } 50 | } 51 | ``` 52 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_k7c_degree_centrality.md: -------------------------------------------------------------------------------- 1 | # Degree Centrality 2 | 3 | - **Category:** ranking and walking 4 | - **Algorithm ID:** pgx_builtin_k7c_degree_centrality 5 | - **Time Complexity:** O(V) with V = number of vertices 6 | - **Space Requirement:** O(V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#degreeCentrality(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#degreeCentrality_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#degreeCentrality(PgxGraph graph, VertexProperty dc)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#degreeCentrality_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_) 10 | 11 | Degree centrality counts the number of outgoing and incoming edges for each vertex in the graph. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | 19 | | Output Argument | Type | Comment | 20 | | :--- | :--- | :--- | 21 | | `dc` | vertexProp | vertex property holding the degree centrality value for each vertex in the graph. | 22 | 23 | | Return Value | Type | Comment | 24 | | :--- | :--- | :--- | 25 | | | void | None | 26 | 27 | ## Code 28 | 29 | ```java 30 | /* 31 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 32 | */ 33 | package oracle.pgx.algorithms; 34 | 35 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 36 | import oracle.pgx.algorithm.PgxGraph; 37 | import oracle.pgx.algorithm.VertexProperty; 38 | import oracle.pgx.algorithm.annotations.Out; 39 | import oracle.pgx.algorithm.ControlFlow; 40 | 41 | @GraphAlgorithm 42 | public class DegreeCentrality { 43 | public void degreeCentrality(PgxGraph g, @Out VertexProperty degreeCentrality) { 44 | long numberOfStepsEstimatedForCompletion = g.getNumVertices(); 45 | ControlFlow.setNumberOfStepsEstimatedForCompletion(numberOfStepsEstimatedForCompletion); 46 | g.getVertices().forEach(n -> 47 | degreeCentrality.set(n, (int) (n.getOutDegree() + n.getInDegree())) 48 | ); 49 | } 50 | } 51 | ``` 52 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_k8_random_walk_with_restart.md: -------------------------------------------------------------------------------- 1 | # Random Walk with Restart 2 | 3 | - **Category:** ranking and walking 4 | - **Algorithm ID:** pgx_builtin_k8_random_walk_with_restart 5 | - **Time Complexity:** O(L) with L = length of the random walk 6 | - **Space Requirement:** O(V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#randomWalkWithRestart(PgxGraph graph, ID source, int length, java.math.BigDecimal reset_prob, PgxMap,java.lang.Integer> visitCount)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#randomWalkWithRestart_oracle_pgx_api_PgxGraph_ID_int_java_math_BigDecimal_oracle_pgx_api_PgxMap_) 9 | - [Analyst#randomWalkWithRestart(PgxGraph graph, PgxVertex source, int length, double resetProb, PgxMap,​java.lang.Integer> visitCount)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#randomWalkWithRestart_oracle_pgx_api_PgxGraph_oracle_pgx_api_PgxVertex_int_double_oracle_pgx_api_PgxMap_) 10 | 11 | This algorithm performs a random walk over the graph. The walk will start at the given source vertex and will randomly visit neighboring vertices in the graph, with a probability equal to the value of reset_probability of going back to the starting point. The random walk will also go back to the starting point every time it reaches a vertex with no outgoing edges. The algorithm will stop once it reaches the specified walk length. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | | `source` | node | starting point of the random walk. | 19 | | `length` | int | length (number of steps) of the random walk. | 20 | | `reset_prob` | double | probability value for resetting the random walk. | 21 | 22 | | Output Argument | Type | Comment | 23 | | :--- | :--- | :--- | 24 | | `visit_count` | map | map holding the number of visits during the random walk for each vertex in the graph. | 25 | 26 | | Return Value | Type | Comment | 27 | | :--- | :--- | :--- | 28 | | | void | None | 29 | 30 | ## Code 31 | 32 | ```java 33 | /* 34 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 35 | */ 36 | package oracle.pgx.algorithms; 37 | 38 | import oracle.pgx.algorithm.PgxGraph; 39 | import oracle.pgx.algorithm.PgxMap; 40 | import oracle.pgx.algorithm.PgxVertex; 41 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 42 | import oracle.pgx.algorithm.annotations.Out; 43 | 44 | import static oracle.pgx.algorithm.Random.uniform; 45 | 46 | @GraphAlgorithm 47 | public class RandomWalkWithRestart { 48 | public void randomWalkWithRestart(PgxGraph g, PgxVertex source, int length, double resetProb, 49 | @Out PgxMap visitCount) { 50 | if (length <= 0) { 51 | return; 52 | } 53 | 54 | PgxVertex n = source; 55 | int current = 0; 56 | 57 | while (current < length) { 58 | double beta = uniform(); 59 | 60 | if (beta < resetProb || n.getDegree() == 0) { 61 | n = source; 62 | } else { 63 | n = n.getRandomOutNeighbor(); 64 | } 65 | visitCount.increment(n); 66 | current++; 67 | } 68 | } 69 | } 70 | ``` 71 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_k9_harmonic_centrality.md: -------------------------------------------------------------------------------- 1 | # Harmonic Centrality 2 | 3 | - **Category:** ranking and walking 4 | - **Algorithm ID:** pgx_builtin_k9_harmonic_centrality 5 | - **Time Complexity:** O(V * (V + E)) with V = number of vertices, E = number of edgeswalk 6 | - **Space Requirement:** O(V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#harmonicCentrality(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#harmonicCentrality_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#harmonicCentrality(PgxGraph graph, VertexProperty hc](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#harmonicCentrality_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_) 10 | 11 | Harmonic centrality computes the centrality of each vertex by taking the reciprocal of the sum of the shortest path distances from that vertex to all other vertices in the graph. This metric highlights the importance of vertices that efficiently connect disparate parts of the network 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | 19 | | Output Argument | Type | Comment | 20 | | :--- | :--- | :--- | 21 | | `hc` | vertexProp | vertex property holding the harmonic centrality value for each vertex in the graph. | 22 | 23 | | Return Value | Type | Comment | 24 | | :--- | :--- | :--- | 25 | | | void | None | 26 | 27 | ## Code 28 | 29 | ```java 30 | /* 31 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 32 | */ 33 | package oracle.pgx.algorithms; 34 | 35 | import oracle.pgx.algorithm.PgxGraph; 36 | import oracle.pgx.algorithm.Scalar; 37 | import oracle.pgx.algorithm.VertexProperty; 38 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 39 | import oracle.pgx.algorithm.annotations.Out; 40 | 41 | import static oracle.pgx.algorithm.Traversal.currentLevel; 42 | import static oracle.pgx.algorithm.Traversal.inBFS; 43 | 44 | @GraphAlgorithm 45 | public class HarmonicCentrality { 46 | public void harmonicCentrality(PgxGraph g, @Out VertexProperty harmonicCentrality) { 47 | g.getVertices().forEach(root -> { 48 | Scalar rootSum = Scalar.create(0.0); 49 | 50 | inBFS(g, root).filter(v -> v != root).forward(v -> 51 | rootSum.reduceAdd(1.0 / currentLevel()) 52 | ); 53 | 54 | harmonicCentrality.set(root, rootSum.get()); 55 | }); 56 | } 57 | } 58 | ``` 59 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_o12_enumerate_simple_paths.md: -------------------------------------------------------------------------------- 1 | # Enumerate Simple Paths 2 | 3 | - **Category:** path finding 4 | - **Algorithm ID:** pgx_builtin_o12_enumerate_simple_paths 5 | - **Time Complexity:** O(E * k) with E = number of edges, k <= maximum number of iterations 6 | - **Space Requirement:** O(V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#enumerateSimplePaths(PgxGraph graph, PgxVertex src, PgxVertex dst, int k, VertexSet verticesOnPath, EdgeSet edgesOnPath, PgxMap, Integer> dist)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#enumerateSimplePaths_oracle_pgx_api_PgxGraph_oracle_pgx_api_PgxVertex_oracle_pgx_api_PgxVertex_int_oracle_pgx_api_VertexSet_oracle_pgx_api_EdgeSet_oracle_pgx_api_PgxMap_) 9 | 10 | Enumerate all simple paths between the source and destination vertex 11 | 12 | ## Signature 13 | 14 | | Input Argument | Type | Comment | 15 | | :--- | :--- | :--- | 16 | | `G` | graph | the graph. | 17 | | `src` | node | the source vertex. | 18 | | `dst` | node | the destination vertex. | 19 | | `k` | int | the dimension of the distances property; i.e. number of high-degree vertices. | 20 | | `verticesOnPath` | nodeSet | the vertices on the path. | 21 | | `edgesOnPath` | edgeSet | the edges on the path. | 22 | | `f_dist` | map | map containing the distance from the source vertex for each vertex on a path. | 23 | 24 | | Output Argument | Type | Comment | 25 | | :--- | :--- | :--- | 26 | | `pathLengths` | sequence | sequence containing the path lengths. | 27 | | `pathVertices` | nodeSeq | vertex-sequence containing the vertices on the paths. | 28 | | `pathEdges` | edgeSeq | edge-sequence containing the edges on the paths. | 29 | 30 | | Return Value | Type | Comment | 31 | | :--- | :--- | :--- | 32 | | | void | None | 33 | 34 | ## Code 35 | 36 | Not available in PGX Algorithm API. 37 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_o6_compute_supernodes.md: -------------------------------------------------------------------------------- 1 | # Compute High-Degree Vertices 2 | 3 | - **Category:** path finding 4 | - **Algorithm ID:** pgx_builtin_o6_compute_supernodes 5 | - **Time Complexity:** O(N log N) with N = number of vertices 6 | - **Space Requirement:** O(k) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#computeHighDegreeVertices(PgxGraph graph, int k)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#computeHighDegreeVertices_oracle_pgx_api_PgxGraph_int_) 9 | - [Analyst#computeHighDegreeVertices(PgxGraph graph, int k, PgxMap> highDegreeVertexMapping, VertexSet highDegreeVertices)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#computeHighDegreeVertices_oracle_pgx_api_PgxGraph_int_oracle_pgx_api_PgxMap_oracle_pgx_api_VertexSet_) 10 | 11 | Computes the k vertices with the highest degrees in the graph. The resulting map will contain a mapping with the sorted index to the high-degree vertex with the index. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | | `k` | int | number of high-degree vertices to be computed. | 19 | 20 | | Output Argument | Type | Comment | 21 | | :--- | :--- | :--- | 22 | | `superNodes` | nodeSet | the high-degree vertices. | 23 | | `superNodeMapping` | map | the high-degree vertices. | 24 | 25 | | Return Value | Type | Comment | 26 | | :--- | :--- | :--- | 27 | | | void | None | 28 | 29 | ## Code 30 | 31 | ```java 32 | /* 33 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 34 | */ 35 | package oracle.pgx.algorithms; 36 | 37 | import oracle.pgx.algorithm.PgxGraph; 38 | import oracle.pgx.algorithm.PgxMap; 39 | import oracle.pgx.algorithm.PgxVertex; 40 | import oracle.pgx.algorithm.Scalar; 41 | import oracle.pgx.algorithm.VertexSet; 42 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 43 | import oracle.pgx.algorithm.annotations.Out; 44 | 45 | @GraphAlgorithm 46 | public class HopDistPathComputeSupernodes { 47 | public void computeSuperNodes(PgxGraph g, int k, @Out PgxMap superNodeMapping, 48 | VertexSet superNodes) { 49 | PgxMap vertexDegrees = PgxMap.create(); 50 | g.getVertices().forSequential(n -> { 51 | long deg = n.getInDegree() + n.getOutDegree(); 52 | if (vertexDegrees.size() < k) { 53 | vertexDegrees.set(n, deg); 54 | } else { 55 | PgxVertex other = vertexDegrees.getKeyForMinValue(); 56 | if (deg > vertexDegrees.get(other)) { 57 | vertexDegrees.remove(other); 58 | vertexDegrees.set(n, deg); 59 | } 60 | } 61 | }); 62 | 63 | // assert vertexDegrees.size() <= k 64 | Scalar counter = Scalar.create(0); 65 | vertexDegrees.keys().forSequential(superNode -> { 66 | long deg = vertexDegrees.get(superNode); 67 | superNodes.add(superNode); 68 | superNodeMapping.set(counter.get(), superNode); 69 | counter.increment(); 70 | }); 71 | } 72 | } 73 | ``` 74 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_o7_compute_distance_index.md: -------------------------------------------------------------------------------- 1 | # Compute Distance Index 2 | 3 | - **Category:** path finding 4 | - **Algorithm ID:** pgx_builtin_o7_compute_distance_index 5 | - **Time Complexity:** O(E * k) with E = number of edges, k <= number of high-degree vertices 6 | - **Space Requirement:** O(V * k) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#createDistanceIndex(PgxGraph graph, PgxMap> highDegreeVertexMapping, VertexSet highDegreeVertices)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#createDistanceIndex_oracle_pgx_api_PgxGraph_oracle_pgx_api_PgxMap_oracle_pgx_api_VertexSet_) 9 | - [Analyst#createDistanceIndex(PgxGraph graph, PgxMap> highDegreeVertexMapping, VertexSet highDegreeVertices, VertexProperty> index)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#createDistanceIndex_oracle_pgx_api_PgxGraph_oracle_pgx_api_PgxMap_oracle_pgx_api_VertexSet_oracle_pgx_api_VertexProperty_) 10 | 11 | Computes an index which contains the distance to the given high-degree vertices for every node in the graph. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | | `k` | int | the dimension of the distances property; i.e. number of high-degree vertices. | 19 | | `superNodeMapping` | map | map containing the high-degree vertices as values and indices from 0 to k as keys. | 20 | | `superNodes` | nodeSet | a set containing the high-degree vertices. | 21 | 22 | | Output Argument | Type | Comment | 23 | | :--- | :--- | :--- | 24 | | `distances` | vertexProp[k]> | the index containing the distances to each high-degree vertex for all vertices. | 25 | 26 | | Return Value | Type | Comment | 27 | | :--- | :--- | :--- | 28 | | | void | None | 29 | 30 | ## Code 31 | 32 | ```java 33 | /* 34 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 35 | */ 36 | package oracle.pgx.algorithms; 37 | 38 | import oracle.pgx.algorithm.PgxGraph; 39 | import oracle.pgx.algorithm.PgxMap; 40 | import oracle.pgx.algorithm.PgxVect; 41 | import oracle.pgx.algorithm.PgxVertex; 42 | import oracle.pgx.algorithm.Scalar; 43 | import oracle.pgx.algorithm.Traversal; 44 | import oracle.pgx.algorithm.VertexProperty; 45 | import oracle.pgx.algorithm.VertexSet; 46 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 47 | import oracle.pgx.algorithm.annotations.Length; 48 | import oracle.pgx.algorithm.annotations.Out; 49 | 50 | import static oracle.pgx.algorithm.Traversal.currentLevel; 51 | import static oracle.pgx.algorithm.Traversal.inBFS; 52 | 53 | @GraphAlgorithm 54 | public class HopDistPathIndexCreation { 55 | 56 | public void createDistanceIndex(PgxGraph g, int k, PgxMap superNodeMapping, 57 | VertexSet superNodes, @Out VertexProperty<@Length("k") PgxVect> distances) { 58 | g.getVertices().forEach(n -> { 59 | @Length("k") 60 | PgxVect tmp = PgxVect.create(Integer.MAX_VALUE); 61 | distances.set(n, tmp); 62 | }); 63 | 64 | Scalar i = Scalar.create(0); 65 | 66 | while (i.get() < k) { 67 | PgxVertex superNode = superNodeMapping.get(i.get()); 68 | 69 | inBFS(g, superNode).direction(Traversal.Direction.IN_OUT_EDGES).forward(n -> { 70 | @Length("k") 71 | PgxVect tmp = distances.get(n); 72 | tmp.set(i.get(), currentLevel()); 73 | distances.set(n, tmp); 74 | }); 75 | 76 | i.increment(); 77 | } 78 | } 79 | } 80 | 81 | /* 82 | // use graph instead of dGraph until GM-16698 is fixed 83 | proc createDistanceIndex(graph g, int k, map superNodeMapping, nodeSet superNodes; nodeProp[k]> 84 | distances) { 85 | 86 | foreach(n: g.nodes) { 87 | iVect[k] tmp = INF; 88 | n.distances = tmp; 89 | } 90 | 91 | int i = 0; 92 | while (i < k) { 93 | node superNode = superNodeMapping[i]; 94 | superNodes.add(superNode); 95 | 96 | inBFS(n: g.nodes from superNode using inOutEdges) { 97 | vect[k] tmp = n.distances; 98 | tmp[i] = currentLevel(); 99 | n.distances = tmp; 100 | } 101 | i++; 102 | } 103 | } 104 | */ 105 | ``` 106 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_p1a_single_source_single_destination_dijkstra.md: -------------------------------------------------------------------------------- 1 | # Classic Dijkstra Algorithm 2 | 3 | - **Category:** path finding 4 | - **Algorithm ID:** pgx_builtin_p1a_single_source_single_destination_dijkstra 5 | - **Time Complexity:** O(E + V log V) with V = number of vertices, E = number of edges 6 | - **Space Requirement:** O(4 * V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#shortestPathDijkstra(PgxGraph graph, ID srcId, ID dstId, EdgeProperty cost)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#shortestPathDijkstra_oracle_pgx_api_PgxGraph_ID_ID_oracle_pgx_api_EdgeProperty_) 9 | - [Analyst#shortestPathDijkstra(PgxGraph graph, ID srcId, ID dstId, EdgeProperty cost, VertexProperty> parent, VertexProperty parentEd)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#shortestPathDijkstra_oracle_pgx_api_PgxGraph_ID_ID_oracle_pgx_api_EdgeProperty_oracle_pgx_api_VertexProperty_oracle_pgx_api_VertexProperty_) 10 | 11 | Dijkstra's algorithm tries to find the shortest path (if there is one) between the given source and destination vertices, while minimizing the distance or cost associated to each edge in the graph. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | | `weight` | edgeProp | edge property holding the (positive) weight of each edge in the graph. | 19 | | `root` | node | the source vertex from the graph for the path. | 20 | | `dest` | node | the destination vertex from the graph for the path. | 21 | 22 | | Output Argument | Type | Comment | 23 | | :--- | :--- | :--- | 24 | | `parent` | vertexProp | vertex property holding the parent vertex of the each vertex in the shortest path. | 25 | | `parent_edge` | vertexProp | vertex property holding the edge ID linking the current vertex in the path with the previous vertex in the path. | 26 | 27 | | Return Value | Type | Comment | 28 | | :--- | :--- | :--- | 29 | | | bool | true if there is a path connecting source and destination vertices, false otherwise | 30 | 31 | ## Code 32 | 33 | ```java 34 | /* 35 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 36 | */ 37 | package oracle.pgx.algorithms; 38 | 39 | import oracle.pgx.algorithm.EdgeProperty; 40 | import oracle.pgx.algorithm.PgxEdge; 41 | import oracle.pgx.algorithm.PgxGraph; 42 | import oracle.pgx.algorithm.PgxMap; 43 | import oracle.pgx.algorithm.PgxVertex; 44 | import oracle.pgx.algorithm.VertexProperty; 45 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 46 | import oracle.pgx.algorithm.annotations.Out; 47 | import oracle.pgx.algorithm.ControlFlow; 48 | 49 | @GraphAlgorithm 50 | public class Dijkstra { 51 | public boolean dijkstra(PgxGraph g, EdgeProperty weight, PgxVertex root, PgxVertex dest, 52 | @Out VertexProperty parent, @Out VertexProperty parentEdge) { 53 | if (g.getNumVertices() == 0) { 54 | return false; 55 | } 56 | 57 | VertexProperty reached = VertexProperty.create(); 58 | 59 | // sequentially initialize, otherwise compiler flags this algorithm as 60 | //parallel in nature 61 | g.getVertices().forSequential(n -> { 62 | parent.set(n, PgxVertex.NONE); 63 | parentEdge.set(n, PgxEdge.NONE); 64 | reached.set(n, false); 65 | }); 66 | 67 | long searchAndUpdateLoop = g.getNumVertices(); 68 | ControlFlow.setNumberOfStepsEstimatedForCompletion(searchAndUpdateLoop); 69 | 70 | PgxMap reachable = PgxMap.create(); 71 | reachable.set(root, 0d); 72 | 73 | //------------------------------- 74 | // look up the vertex 75 | //------------------------------- 76 | boolean found = false; 77 | 78 | // Search and updating loop 79 | while (!found && reachable.size() > 0) { 80 | PgxVertex next = reachable.getKeyForMinValue(); 81 | if (next == dest) { 82 | found = true; 83 | } else { 84 | reached.set(next, true); 85 | double dist = reachable.get(next); 86 | reachable.remove(next); 87 | next.getOutNeighbors().filter(v -> !reached.get(v)).forSequential(v -> { 88 | PgxEdge e = v.edge(); 89 | if (!reachable.containsKey(v) || reachable.get(v) > dist + weight.get(e)) { 90 | reachable.set(v, dist + weight.get(e)); 91 | parent.set(v, next); 92 | parentEdge.set(v, e); 93 | } 94 | }); 95 | } 96 | } 97 | 98 | // return false if not reachable 99 | return found; 100 | } 101 | } 102 | ``` 103 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_p1c_single_source_all_destinations_dijkstra.md: -------------------------------------------------------------------------------- 1 | # Dijkstra Multi-Destination Algorithm 2 | 3 | - **Category:** path finding 4 | - **Algorithm ID:** pgx_builtin_p1c_single_source_all_destinations_dijkstra 5 | - **Time Complexity:** O(E + V log V) with V = number of vertices, E = number of edges 6 | - **Space Requirement:** O(4 * V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#singleSourceMultiDestination(PgxGraph graph, PgxVertex src, EdgeProperty cost)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#shortestPathMultiDestinationDijkstra_oracle_pgx_api_PgxGraph_oracle_pgx_api_PgxVertex_oracle_pgx_api_EdgeProperty_) 9 | - [Analyst#singleSourceMultiDestination(PgxGraph graph, PgxVertex src, EdgeProperty cost, VertexProperty distance, VertexProperty> parent, VertexProperty parentEdge)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#shortestPathMultiDestinationDijkstra_oracle_pgx_api_PgxGraph_oracle_pgx_api_PgxVertex_oracle_pgx_api_EdgeProperty_oracle_pgx_api_VertexProperty_oracle_pgx_api_VertexProperty_oracle_pgx_api_VertexProperty_) 10 | 11 | This variant of the Dijkstra's algorithm tries to find the shortest path ignoring edges directions for directed graphs while also taking into account a filter expression, which will add restrictions over the potential edges when looking for the shortest path between the source and destination vertices. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | | `weight` | edgeProp | edge property holding the (positive) weight of each edge in the graph. | 19 | | `root` | node | the source vertex from the graph for the path. | 20 | 21 | | Output Argument | Type | Comment | 22 | | :--- | :--- | :--- | 23 | | `dist` | vertexProp | vertex property holding the distance to the source vertex for each vertex in the graph. | 24 | | `parent` | vertexProp | vertex property holding the parent vertex of the each vertex in the shortest path. | 25 | | `parent_edge` | vertexProp | vertex property holding the edge ID linking the current vertex in the path with the previous vertex in the path. | 26 | 27 | ## Code 28 | 29 | ```java 30 | /* 31 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 32 | */ 33 | package oracle.pgx.algorithms; 34 | 35 | import oracle.pgx.algorithm.EdgeProperty; 36 | import oracle.pgx.algorithm.PgxEdge; 37 | import oracle.pgx.algorithm.PgxGraph; 38 | import oracle.pgx.algorithm.PgxMap; 39 | import oracle.pgx.algorithm.PgxVertex; 40 | import oracle.pgx.algorithm.VertexProperty; 41 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 42 | import oracle.pgx.algorithm.annotations.Out; 43 | import oracle.pgx.algorithm.ControlFlow; 44 | 45 | 46 | @GraphAlgorithm 47 | public class DijkstraMultiDestination { 48 | public void newDijkstra(PgxGraph g, EdgeProperty weight, PgxVertex root, 49 | @Out VertexProperty distance, @Out VertexProperty parent, 50 | @Out VertexProperty parentEdge) { 51 | 52 | VertexProperty reached = VertexProperty.create(); 53 | 54 | // sequentially initialize, otherwise compiler flags this algorithm as 55 | //parallel in nature 56 | g.getVertices().forSequential(n -> { 57 | parent.set(n, PgxVertex.NONE); 58 | parentEdge.set(n, PgxEdge.NONE); 59 | reached.set(n, false); 60 | distance.set(n, Double.POSITIVE_INFINITY); 61 | }); 62 | 63 | long searchLoop = g.getNumVertices(); 64 | ControlFlow.setNumberOfStepsEstimatedForCompletion(searchLoop); 65 | 66 | distance.set(root, 0d); 67 | 68 | PgxMap reachable = PgxMap.create(); 69 | reachable.set(root, 0d); 70 | 71 | // Search loop 72 | while (reachable.size() > 0) { 73 | PgxVertex next = reachable.getKeyForMinValue(); 74 | reached.set(next, true); 75 | double dist = reachable.get(next); 76 | reachable.remove(next); 77 | next.getOutNeighbors().filter(v -> !reached.get(v)).forSequential(v -> { 78 | PgxEdge e = v.edge(); 79 | if (!reachable.containsKey(v) || reachable.get(v) > dist + weight.get(e)) { 80 | reachable.set(v, dist + weight.get(e)); 81 | distance.set(v, dist + weight.get(e)); 82 | parent.set(v, next); 83 | parentEdge.set(v, e); 84 | } 85 | }); 86 | } 87 | } 88 | } 89 | ``` 90 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_p4_single_source_all_destinations_hop_distance.md: -------------------------------------------------------------------------------- 1 | # Hop Distance 2 | 3 | - **Category:** path finding 4 | - **Algorithm ID:** pgx_builtin_p4_single_source_all_destinations_hop_distance 5 | - **Time Complexity:** O(V + E) with V = number of vertices, E = number of edges 6 | - **Space Requirement:** O(3 * V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#shortestPathHopDist(PgxGraph graph, PgxVertex src)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#shortestPathHopDist_oracle_pgx_api_PgxGraph_oracle_pgx_api_PgxVertex_) 9 | - [Analyst#shortestPathHopDist(PgxGraph graph, PgxVertex src, VertexProperty distance, VertexProperty> parent, VertexProperty parentEdge)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#shortestPathHopDist_oracle_pgx_api_PgxGraph_oracle_pgx_api_PgxVertex_oracle_pgx_api_VertexProperty_oracle_pgx_api_VertexProperty_oracle_pgx_api_VertexProperty_) 10 | 11 | The Hop distance of two vertices S and V in a graph is the number of edges that are in a shortest path connecting them. This algorithm will return the distance of each vertex with respect to the given source vertex in the input and will also return the parent vertex and linking edge for each vertex. The returned information allows to trace back shortest paths from any reachable vertex to the source vertex. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | | `root` | node | the source vertex from the graph for the path. | 19 | 20 | | Output Argument | Type | Comment | 21 | | :--- | :--- | :--- | 22 | | `dist` | vertexProp | vertex property holding the hop distance to the source vertex for each vertex in the graph. | 23 | | `prev` | vertexProp | vertex property holding the parent vertex of the each vertex in the shortest path. | 24 | | `prev_edge` | vertexProp | vertex property holding the edge ID linking the current vertex in the path with the previous vertex in the path. | 25 | 26 | | Return Value | Type | Comment | 27 | | :--- | :--- | :--- | 28 | | | void | None | 29 | 30 | ## Code 31 | 32 | ```java 33 | /* 34 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 35 | */ 36 | package oracle.pgx.algorithms; 37 | 38 | import oracle.pgx.algorithm.PgxEdge; 39 | import oracle.pgx.algorithm.PgxGraph; 40 | import oracle.pgx.algorithm.PgxVertex; 41 | import oracle.pgx.algorithm.VertexProperty; 42 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 43 | import oracle.pgx.algorithm.annotations.Out; 44 | 45 | import static oracle.pgx.algorithm.Traversal.currentLevel; 46 | import static oracle.pgx.algorithm.Traversal.inBFS; 47 | import oracle.pgx.algorithm.ControlFlow; 48 | 49 | @GraphAlgorithm 50 | public class HopDistance { 51 | public void hopDist(PgxGraph g, PgxVertex root, @Out VertexProperty dist, @Out VertexProperty prev, 52 | @Out VertexProperty prevEdge) { 53 | if (g.getNumVertices() == 0) { 54 | return; 55 | } 56 | 57 | long initializations = 3 * g.getNumVertices(); 58 | ControlFlow.setNumberOfStepsEstimatedForCompletion(initializations); 59 | 60 | // Initializations 61 | dist.setAll(Double.POSITIVE_INFINITY); 62 | prev.setAll(PgxVertex.NONE); 63 | prevEdge.setAll(PgxEdge.NONE); 64 | dist.set(root, 0d); 65 | 66 | inBFS(g, root).forward(n -> { 67 | dist.set(n, (double) currentLevel()); 68 | prev.set(n, n.parentVertex()); 69 | prevEdge.set(n, n.parentEdge()); 70 | }); 71 | } 72 | } 73 | ``` 74 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_p4r_single_source_all_destinations_hop_distance_reverse.md: -------------------------------------------------------------------------------- 1 | # Hop Distance (Backwards) 2 | 3 | - **Category:** path finding 4 | - **Algorithm ID:** pgx_builtin_p4r_single_source_all_destinations_hop_distance_reverse 5 | - **Time Complexity:** O(V + E) with V = number of vertices, E = number of edges 6 | - **Space Requirement:** O(3 * V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#shortestPathHopDistReverse(PgxGraph graph, PgxVertex src)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#shortestPathHopDistReverse_oracle_pgx_api_PgxGraph_oracle_pgx_api_PgxVertex_) 9 | - [Analyst#shortestPathHopDistReverse(PgxGraph graph, PgxVertex src, VertexProperty distance, VertexProperty> parent, VertexProperty parentEdge)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#shortestPathHopDistReverse_oracle_pgx_api_PgxGraph_oracle_pgx_api_PgxVertex_oracle_pgx_api_VertexProperty_oracle_pgx_api_VertexProperty_oracle_pgx_api_VertexProperty_) 10 | 11 | The Hop distance of two vertices S and V in a graph is the number of edges that are in a shortest path connecting them. This algorithm will return the distance of each node with respect to the given source node in the input and will also return the parent node and linking edge for each node. The returned information allows to trace back shortest paths from any reachable node to the source node. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | | `root` | node | the source node from the graph for the path. | 19 | 20 | | Output Argument | Type | Comment | 21 | | :--- | :--- | :--- | 22 | | `dist` | vertexProp | node property holding the hop distance to the source node for each node in the graph. | 23 | | `prev` | vertexProp | node property holding the parent node of the each node in the shortest path. | 24 | | `prev_edge` | vertexProp | node property holding the edge ID linking the current node in the path with the previous node in the path. | 25 | 26 | | Return Value | Type | Comment | 27 | | :--- | :--- | :--- | 28 | | | void | None | 29 | 30 | ## Code 31 | 32 | ```java 33 | /* 34 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 35 | */ 36 | package oracle.pgx.algorithms; 37 | 38 | import oracle.pgx.algorithm.PgxEdge; 39 | import oracle.pgx.algorithm.PgxGraph; 40 | import oracle.pgx.algorithm.PgxVertex; 41 | import oracle.pgx.algorithm.VertexProperty; 42 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 43 | import oracle.pgx.algorithm.annotations.Out; 44 | 45 | import static oracle.pgx.algorithm.Traversal.Direction.IN_EDGES; 46 | import static oracle.pgx.algorithm.Traversal.currentLevel; 47 | import static oracle.pgx.algorithm.Traversal.inBFS; 48 | import oracle.pgx.algorithm.ControlFlow; 49 | 50 | @GraphAlgorithm 51 | public class HopDistanceBackward { 52 | public void hopDistBackward(PgxGraph g, PgxVertex root, @Out VertexProperty dist, 53 | @Out VertexProperty prev, @Out VertexProperty prevEdge) { 54 | if (g.getNumVertices() == 0) { 55 | return; 56 | } 57 | 58 | long initializations = 3 * g.getNumVertices(); 59 | ControlFlow.setNumberOfStepsEstimatedForCompletion(initializations); 60 | 61 | // Initializations 62 | dist.setAll(Double.POSITIVE_INFINITY); 63 | prev.setAll(PgxVertex.NONE); 64 | prevEdge.setAll(PgxEdge.NONE); 65 | dist.set(root, 0d); 66 | 67 | inBFS(g, root).forward(n -> { 68 | dist.set(n, (double) currentLevel()); 69 | prev.set(n, n.parentVertex()); 70 | prevEdge.set(n, n.parentEdge()); 71 | }).direction(IN_EDGES); 72 | } 73 | } 74 | ``` 75 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_p4u_single_source_all_destinations_hop_distance_undirected.md: -------------------------------------------------------------------------------- 1 | # Hop Distance (undirected) 2 | 3 | - **Category:** path finding 4 | - **Algorithm ID:** pgx_builtin_p4u_single_source_all_destinations_hop_distance_undirected 5 | - **Time Complexity:** O(V + E) with V = number of vertices, E = number of edges 6 | - **Space Requirement:** O(3 * V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#shortestPathHopDistUndirected(PgxGraph graph, PgxVertex src)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#shortestPathHopDistUndirected_oracle_pgx_api_PgxGraph_oracle_pgx_api_PgxVertex_) 9 | - [Analyst#shortestPathHopDistReverse(PgxGraph graph, PgxVertex src, VertexProperty distance, VertexProperty> parent, VertexProperty parentEdge)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#shortestPathHopDistUndirected_oracle_pgx_api_PgxGraph_oracle_pgx_api_PgxVertex_oracle_pgx_api_VertexProperty_oracle_pgx_api_VertexProperty_oracle_pgx_api_VertexProperty_) 10 | 11 | The Hop distance of two vertices S and V in a graph is the number of edges that are in a shortest path connecting them. This algorithm will return the distance of each node with respect to the given source node in the input and will also return the parent node and linking edge for each node. The returned information allows to trace back shortest paths from any reachable node to the source node. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | | `root` | node | the source node from the graph for the path. | 19 | 20 | | Output Argument | Type | Comment | 21 | | :--- | :--- | :--- | 22 | | `dist` | vertexProp | node property holding the hop distance to the source node for each node in the graph. | 23 | | `prev` | vertexProp | node property holding the parent node of the each node in the shortest path. | 24 | | `prev_edge` | vertexProp | node property holding the edge ID linking the current node in the path with the previous node in the path. | 25 | 26 | | Return Value | Type | Comment | 27 | | :--- | :--- | :--- | 28 | | | void | None | 29 | 30 | ## Code 31 | 32 | ```java 33 | /* 34 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 35 | */ 36 | package oracle.pgx.algorithms; 37 | 38 | import oracle.pgx.algorithm.PgxEdge; 39 | import oracle.pgx.algorithm.PgxGraph; 40 | import oracle.pgx.algorithm.PgxVertex; 41 | import oracle.pgx.algorithm.VertexProperty; 42 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 43 | import oracle.pgx.algorithm.annotations.Out; 44 | 45 | import static oracle.pgx.algorithm.Traversal.currentLevel; 46 | import static oracle.pgx.algorithm.Traversal.inBFS; 47 | import oracle.pgx.algorithm.ControlFlow; 48 | 49 | @GraphAlgorithm 50 | public class HopDistance { 51 | public void hopDist(PgxGraph g, PgxVertex root, @Out VertexProperty dist, @Out VertexProperty prev, 52 | @Out VertexProperty prevEdge) { 53 | if (g.getNumVertices() == 0) { 54 | return; 55 | } 56 | 57 | long initializations = 3 * g.getNumVertices(); 58 | ControlFlow.setNumberOfStepsEstimatedForCompletion(initializations); 59 | 60 | // Initializations 61 | dist.setAll(Double.POSITIVE_INFINITY); 62 | prev.setAll(PgxVertex.NONE); 63 | prevEdge.setAll(PgxEdge.NONE); 64 | dist.set(root, 0d); 65 | 66 | inBFS(g, root).forward(n -> { 67 | dist.set(n, (double) currentLevel()); 68 | prev.set(n, n.parentVertex()); 69 | prevEdge.set(n, n.parentEdge()); 70 | }); 71 | } 72 | } 73 | ``` 74 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_p5_fattest_path.md: -------------------------------------------------------------------------------- 1 | # Fattest Path 2 | 3 | - **Category:** path finding 4 | - **Algorithm ID:** pgx_builtin_p5_fattest_path 5 | - **Time Complexity:** O(E + V log V) with V = number of vertices, E = number of edges 6 | - **Space Requirement:** O(4 * V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#fattestPath(PgxGraph graph, PgxVertex root, EdgeProperty capacity)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#fattestPath_oracle_pgx_api_PgxGraph_oracle_pgx_api_PgxVertex_oracle_pgx_api_EdgeProperty_) 9 | - [PgxGraph graph, PgxVertex root, EdgeProperty capacity, VertexProperty distance, VertexProperty> parent, VertexProperty parentEdge)](https://docs.oracle.com/en/database/oracle/property-graph/24.4/spgjv/oracle/pgx/api/Analyst.html#fattestPath_oracle_pgx_api_PgxGraph_oracle_pgx_api_PgxVertex_oracle_pgx_api_EdgeProperty_oracle_pgx_api_VertexProperty_oracle_pgx_api_VertexProperty_oracle_pgx_api_VertexProperty_) 10 | 11 | The Fattest path algorithm can be regarded as a variant of Dijkstra's algorithm, it tries to find the fattest path between the given source and all the reachable vertices in the graph. The fatness of a path is equal to the minimum value of the capacity from the edges that take part in the path, thus a fattest path is conformed by the edges with the largest possible capacity. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | | `capacity` | edgeProp | edge property holding the capacity of each edge in the graph. | 19 | | `root` | node | the source vertex from the graph for the path. | 20 | 21 | | Output Argument | Type | Comment | 22 | | :--- | :--- | :--- | 23 | | `parent_node` | vertexProp | vertex property holding the parent vertex of the each vertex in the fattest path. | 24 | | `parent_edge` | vertexProp | vertex property holding the edge ID linking the current vertex in the path with the previous vertex in the path. | 25 | | `fat` | vertexProp | vertex property holding the capacity value of the fattest path up to the current vertex. The fatness value for the source vertex will be INF, while it will be 0 for all the vertices that are not reachable from the source. | 26 | 27 | | Return Value | Type | Comment | 28 | | :--- | :--- | :--- | 29 | | | void | None | 30 | 31 | ## Code 32 | 33 | ```java 34 | /* 35 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 36 | */ 37 | package oracle.pgx.algorithms; 38 | 39 | import oracle.pgx.algorithm.EdgeProperty; 40 | import oracle.pgx.algorithm.PgxEdge; 41 | import oracle.pgx.algorithm.PgxGraph; 42 | import oracle.pgx.algorithm.PgxMap; 43 | import oracle.pgx.algorithm.PgxVertex; 44 | import oracle.pgx.algorithm.VertexProperty; 45 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 46 | import oracle.pgx.algorithm.annotations.Out; 47 | 48 | import static java.lang.Double.POSITIVE_INFINITY; 49 | import oracle.pgx.algorithm.ControlFlow; 50 | 51 | @GraphAlgorithm 52 | public class FattestPath { 53 | public void fattestPath(PgxGraph g, EdgeProperty capacity, PgxVertex root, 54 | @Out VertexProperty parentNode, @Out VertexProperty parentEdge, 55 | @Out VertexProperty fat) { 56 | if (g.getNumVertices() == 0) { 57 | return; 58 | } 59 | 60 | long updatingLoop = g.getNumVertices(); 61 | ControlFlow.setNumberOfStepsEstimatedForCompletion(updatingLoop); 62 | 63 | // sequentially initialize, otherwise compiler flags this algorithm as parallel in nature 64 | g.getVertices().forSequential(n -> { 65 | parentNode.set(n, PgxVertex.NONE); 66 | parentEdge.set(n, PgxEdge.NONE); 67 | fat.set(n, (double) 0); 68 | }); 69 | 70 | fat.set(root, POSITIVE_INFINITY); 71 | 72 | // create 'queue' 73 | PgxMap q = PgxMap.create(); 74 | q.set(root, POSITIVE_INFINITY); 75 | 76 | // Updating loop 77 | while (q.size() > 0) { 78 | PgxVertex u = q.getKeyForMaxValue(); 79 | q.remove(u); 80 | 81 | u.getOutEdges().forEach(e -> { 82 | PgxVertex v = e.destinationVertex(); 83 | double minCap = (fat.get(u) < capacity.get(e)) ? fat.get(u) : capacity.get(e); 84 | if (fat.get(v) < minCap) { 85 | fat.set(v, minCap); 86 | q.set(v, fat.get(v)); 87 | parentNode.set(v, u); 88 | parentEdge.set(v, e); 89 | } 90 | }); 91 | } 92 | } 93 | } 94 | ``` 95 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_r2a_matrix_factorization_training.md: -------------------------------------------------------------------------------- 1 | # Matrix Factorization (Gradient Descent) 2 | 3 | - **Category:** matrix factorization 4 | - **Algorithm ID:** pgx_builtin_r2a_matrix_factorization_training 5 | - **Time Complexity:** O(E * k * s) with E = number of edges, k = maximum number of iteration, s = size of the feature vectors 6 | - **Space Requirement:** O(2 * V * s) with V = number of vertices, s = size of the feature vectors 7 | - **Javadoc:** 8 | - [Analyst#matrixFactorizationGradientDescent(BipartiteGraph graph, EdgeProperty weight)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#matrixFactorizationGradientDescent_oracle_pgx_api_BipartiteGraph_oracle_pgx_api_EdgeProperty_) 9 | - [Analyst#matrixFactorizationGradientDescent(BipartiteGraph graph, EdgeProperty weight, double learningRate, double changePerStep, double lambda, int maxStep, int vectorLength)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#matrixFactorizationGradientDescent_oracle_pgx_api_BipartiteGraph_oracle_pgx_api_EdgeProperty_double_double_double_int_int_) 10 | - [Analyst#matrixFactorizationGradientDescent(BipartiteGraph graph, EdgeProperty weight, double learningRate, double changePerStep, double lambda, int maxStep, int vectorLength, VertexProperty> features)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#matrixFactorizationGradientDescent_oracle_pgx_api_BipartiteGraph_oracle_pgx_api_EdgeProperty_double_double_double_int_int_oracle_pgx_api_VertexProperty_) 11 | - [Analyst#matrixFactorizationGradientDescent(BipartiteGraph graph, EdgeProperty weight, VertexProperty> features)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#matrixFactorizationGradientDescent_oracle_pgx_api_BipartiteGraph_oracle_pgx_api_EdgeProperty_oracle_pgx_api_VertexProperty_) 12 | 13 | This algorithm needs a [bipartite](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgdg/graph-mutation-and-subgraphs.html) graph to generate feature vectors that factorize the given set of left vertices (users) and right vertices (items), so that the inner product of such feature vectors can recover the information from the original graph structure, which can be seen as a sparse matrix. The generated feature vectors can be used for making recommendations with the given set of users, where a good recommendation for a given user will be a dot (inner) product between the feature vector of the user and the corresponding feature vector of a vertex from the item set, such that the result of that dot product returns a high score. 14 | 15 | ## Signature 16 | 17 | | Input Argument | Type | Comment | 18 | | :--- | :--- | :--- | 19 | | `G` | graph | the graph. | 20 | | `is_left` | vertexProp | boolean vertex property stating the side of the vertices in the [bipartite](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgdg/graph-mutation-and-subgraphs.html) graph (left for users, right for items). | 21 | | `weight` | edgeProp | edge property holding the rating weight of each edge in the graph. The weight needs to be pre-scaled into the range 1-5. If the weight values are not between 1 and 5, the result will become inaccurate. | 22 | | `learning_rate` | double | learning rate for the optimization process. | 23 | | `change_per_step` | double | parameter used to modulate the learning rate during the optimization process. | 24 | | `lambda` | double | penalization parameter to avoid overfitting during optimization process. | 25 | | `max_step` | int | maximum number of iterations that will be performed. | 26 | | `vector_length` | int | size of the feature vectors to be generated for the factorization. | 27 | 28 | | Output Argument | Type | Comment | 29 | | :--- | :--- | :--- | 30 | | `dest_property` | vertexProp[vector_length]> | vertex property holding the generated feature vectors for each vertex. | 31 | 32 | | Return Value | Type | Comment | 33 | | :--- | :--- | :--- | 34 | | | double | the root mean square error. | 35 | 36 | ## Code 37 | 38 | Not available in PGX Algorithm API. 39 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_r2b_matrix_factorization_recommendations.md: -------------------------------------------------------------------------------- 1 | # Estimate Rating 2 | 3 | - **Category:** matrix factorization 4 | - **Algorithm ID:** pgx_builtin_r2b_matrix_factorization_recommendations 5 | - **Time Complexity:** O(V) with V = number of vertices 6 | - **Space Requirement:** O(V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#matrixFactorizationRecommendations​(BipartiteGraph graph, ID user, int vectorLength, VertexProperty> feature, VertexProperty estimatedRating))](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#matrixFactorizationRecommendations_oracle_pgx_api_BipartiteGraph_ID_int_oracle_pgx_api_VertexProperty_oracle_pgx_api_VertexProperty_) 9 | 10 | This algorithm is a complement for Matrix Factorization, thus it needs a bipartite graph and the generated feature vectors from such algorithm. The generated feature vectors will be used for making predictions in cases where the given user vertex has not been related to a particular item from the item set. Similarly to the recommendations from matrix factorization, this algorithm will perform dot products between the given user vertex and the rest of vertices in the graph, giving a score of 0 to the items that are already related to the user and to the products with other user vertices, hence returning the results of the dot products for the unrelated item vertices. The scores from those dot products can be interpreted as the predicted scores for the unrelated items given a particular user vertex. 11 | 12 | ## Signature 13 | 14 | | Input Argument | Type | Comment | 15 | | :--- | :--- | :--- | 16 | | `G` | graph | the graph. | 17 | | `user` | node | vertex from the left (user) side of the graph. | 18 | | `is_left` | vertexProp | boolean vertex property stating the side of the vertices in the bipartite graph (left for users, right for items). | 19 | | `vector_length` | int | size of the feature vectors. | 20 | | `feature` | vertexProp[vector_length]> | vertex property holding the feature vectors for each vertex. | 21 | 22 | | Output Argument | Type | Comment | 23 | | :--- | :--- | :--- | 24 | | `estimated_rating` | vertexProp[vector_length]> | vertex property holding the estimated rating score for each vertex. | 25 | 26 | | Return Value | Type | Comment | 27 | | :--- | :--- | :--- | 28 | | | void | None | 29 | 30 | ## Code 31 | 32 | Not available in PGX Algorithm API. 33 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_s10_bipartite_check.md: -------------------------------------------------------------------------------- 1 | # Bipartite Check 2 | 3 | - **Category:** structure evaluation 4 | - **Algorithm ID:** pgx_builtin_s10_bipartite_check 5 | - **Time Complexity:** O(E) with E = number of edges 6 | - **Space Requirement:** O(2 * V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#bipartiteCheck(PgxGraph graph, VertexProperty isLeft)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#bipartiteCheck_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_) 9 | 10 | This algorithm checks whether the given directed graph is bipartite. It assumes that all the edges are going in the same direction since the method relies on BFS traversals of the graph. If the graph is bipartite the algorithm will return the side of each vertex in the graph with the is_left vertex property. 11 | 12 | ## Signature 13 | 14 | | Input Argument | Type | Comment | 15 | | :--- | :--- | :--- | 16 | | `G` | graph | the graph. | 17 | 18 | | Output Argument | Type | Comment | 19 | | :--- | :--- | :--- | 20 | | `is_left` | vertexProp | vertex property holding the side of each vertex in a bipartite graph (true for left, false for right). | 21 | 22 | | Return Value | Type | Comment | 23 | | :--- | :--- | :--- | 24 | | | bool | true if the graph is bipartite, false otherwise. | 25 | 26 | ## Code 27 | 28 | ```java 29 | /* 30 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 31 | */ 32 | package oracle.pgx.algorithms; 33 | 34 | import oracle.pgx.algorithm.PgxGraph; 35 | import oracle.pgx.algorithm.Scalar; 36 | import oracle.pgx.algorithm.VertexProperty; 37 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 38 | import oracle.pgx.algorithm.annotations.Out; 39 | 40 | import static oracle.pgx.algorithm.Traversal.currentLevel; 41 | import static oracle.pgx.algorithm.Traversal.inBFS; 42 | 43 | @GraphAlgorithm 44 | public class BipartiteCheck { 45 | public boolean bipartiteCheck(PgxGraph g, @Out VertexProperty isLeft) { 46 | VertexProperty visited = VertexProperty.create(false); 47 | isLeft.setAll(false); 48 | 49 | Scalar isBipartiteGraph = Scalar.create(true); 50 | 51 | // assumption: edges only go from left to right 52 | g.getVertices().filter(root_node -> !visited.get(root_node) && root_node.getOutDegree() > 0) 53 | .forSequential(root_node -> { 54 | isLeft.set(root_node, true); 55 | 56 | inBFS(g, root_node).forward(n -> { 57 | boolean levelIsLeft = currentLevel() % 2 == 0; 58 | visited.set(n, true); 59 | isLeft.set(n, levelIsLeft); 60 | 61 | if (levelIsLeft && n.getInDegree() > 0) { 62 | isBipartiteGraph.set(false); 63 | } else if (!levelIsLeft && n.getOutDegree() > 0) { 64 | isBipartiteGraph.set(false); 65 | } 66 | }); 67 | }); 68 | 69 | return isBipartiteGraph.get(); 70 | } 71 | } 72 | ``` 73 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_s11_diameter.md: -------------------------------------------------------------------------------- 1 | # Diameter / Radius 2 | 3 | - **Category:** structure evaluation 4 | - **Algorithm ID:** pgx_builtin_s11_diameter 5 | - **Time Complexity:** O(V * E) with V = number of vertices, E = number of edges 6 | - **Space Requirement:** O(V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#radius(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#radius_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#radius(PgxGraph graph, Scalar radius, VertexProperty eccentricity](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#radius_oracle_pgx_api_PgxGraph_oracle_pgx_api_Scalar_oracle_pgx_api_VertexProperty_) 10 | 11 | The diameter of a graph is the maximal value of eccentricity of all the vertices in the graph, while the radius is the minimum graph eccentricity. The eccentricity of a vertex is the maximum distance via shortest paths to any other vertex in the graph. This algorithm will compute the eccentricity of all the vertices and will also return the diameter or radius value depending on the request. The algorithm will return an INF eccentricity and diameter/radius, for graphs with more than one strongly connected component. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | | `diameterOn` | boolean | boolean flag to determine whether the algorithm will return the diameter or radius of the graph. | 19 | 20 | | Output Argument | Type | Comment | 21 | | :--- | :--- | :--- | 22 | | `eccentricity` | vertexProp | vertex property holding the eccentricity value for each vertex. | 23 | 24 | | Return Value | Type | Comment | 25 | | :--- | :--- | :--- | 26 | | | int | value of the diameter or radius, depending the chosen option. | 27 | 28 | ## Code 29 | 30 | ```java 31 | /* 32 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 33 | */ 34 | package oracle.pgx.algorithms; 35 | 36 | import oracle.pgx.algorithm.PgxGraph; 37 | import oracle.pgx.algorithm.Scalar; 38 | import oracle.pgx.algorithm.VertexProperty; 39 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 40 | import oracle.pgx.algorithm.annotations.Out; 41 | 42 | import static oracle.pgx.algorithm.Traversal.currentLevel; 43 | import static oracle.pgx.algorithm.Traversal.inBFS; 44 | import static java.lang.Integer.MAX_VALUE; 45 | 46 | @GraphAlgorithm 47 | public class Diameter { 48 | public int diameter(PgxGraph g, boolean diameterOn, @Out VertexProperty eccentricity) { 49 | eccentricity.setAll(0); 50 | long n = g.getNumVertices(); 51 | Scalar diameter = Scalar.create(0); 52 | Scalar radius = Scalar.create(MAX_VALUE); 53 | Scalar disconnected = Scalar.create(false); 54 | 55 | g.getVertices().filter(s -> !disconnected.get()).forEach(s -> { 56 | Scalar visited = Scalar.create(1); 57 | Scalar maxLevel = Scalar.create(0); 58 | 59 | inBFS(g, s).filter(v -> v != s).forward(v -> { 60 | maxLevel.reduceMax(currentLevel()); 61 | visited.increment(); 62 | }); 63 | 64 | disconnected.set(visited.get() < n); 65 | diameter.reduceMax(maxLevel.get()); 66 | radius.reduceMin(maxLevel.get()); 67 | eccentricity.set(s, maxLevel.get()); 68 | }); 69 | 70 | if (disconnected.get()) { 71 | eccentricity.setAll(MAX_VALUE); 72 | return MAX_VALUE; 73 | } 74 | 75 | if (diameterOn) { 76 | return diameter.get(); 77 | } else { 78 | return radius.get(); 79 | } 80 | } 81 | } 82 | ``` 83 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_s12_periphery.md: -------------------------------------------------------------------------------- 1 | # Periphery / Center 2 | 3 | - **Category:** structure evaluation 4 | - **Algorithm ID:** pgx_builtin_s12_periphery 5 | - **Time Complexity:** O(V * E) with V = number of vertices, E = number of edges 6 | - **Space Requirement:** O(V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#periphery(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#periphery_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#periphery(PgxGraph graph, VertexSet periphery)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#periphery_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexSet_) 10 | 11 | The periphery of a graph is the set of vertices that have an eccentricity value equal to the diameter of the graph. Similarly, the center is comprised by the set of vertices with eccentricity equal to the radius of the graph. The diameter of a graph is the maximal value of eccentricity of all the vertices in the graph, while the radius is the minimum graph eccentricity. The eccentricity of a vertex is the maximum distance via shortest paths to any other vertex in the graph. This algorithm will return the set of vertices from the periphery or the center of the graph, depending on the request. The algorithm will return a set with all the vertices for graphs with more than one strongly connected component. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | | `peripheryOn` | boolean | boolean flag to determine whether the algorithm will return the periphery or center of the graph. | 19 | 20 | | Output Argument | Type | Comment | 21 | | :--- | :--- | :--- | 22 | | `periphery` | nodeSet | vertex set holding the vertices from the periphery or center of the graph. | 23 | 24 | | Return Value | Type | Comment | 25 | | :--- | :--- | :--- | 26 | | | void | None | 27 | 28 | ## Code 29 | 30 | ```java 31 | /* 32 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 33 | */ 34 | package oracle.pgx.algorithms; 35 | 36 | import oracle.pgx.algorithm.PgxGraph; 37 | import oracle.pgx.algorithm.Scalar; 38 | import oracle.pgx.algorithm.VertexProperty; 39 | import oracle.pgx.algorithm.VertexSet; 40 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 41 | import oracle.pgx.algorithm.annotations.Out; 42 | 43 | import static oracle.pgx.algorithm.Traversal.currentLevel; 44 | import static oracle.pgx.algorithm.Traversal.inBFS; 45 | import static java.lang.Integer.MAX_VALUE; 46 | 47 | @GraphAlgorithm 48 | public class Periphery { 49 | public void periphery(PgxGraph g, boolean peripheryOn, @Out VertexSet periphery) { 50 | VertexProperty eccentricity = VertexProperty.create(); 51 | 52 | eccentricity.setAll(0); 53 | Scalar diameter = Scalar.create(0); 54 | Scalar radius = Scalar.create(MAX_VALUE); 55 | long n = g.getNumVertices(); 56 | Scalar disconnected = Scalar.create(false); 57 | 58 | g.getVertices().filter(s -> !disconnected.get()).forEach(s -> { 59 | Scalar visited = Scalar.create(1); 60 | Scalar maxLevel = Scalar.create(0); 61 | 62 | inBFS(g, s).filter(v -> v != s).forward(v -> { 63 | maxLevel.reduceMax(currentLevel()); 64 | visited.increment(); 65 | }); 66 | 67 | disconnected.set(visited.get() < n); 68 | diameter.reduceMax(maxLevel.get()); 69 | radius.reduceMin(maxLevel.get()); 70 | eccentricity.set(s, maxLevel.get()); 71 | }); 72 | 73 | if (disconnected.get()) { 74 | g.getVertices().forEach(periphery::add); 75 | } else { 76 | int chosen = peripheryOn ? diameter.get() : radius.get(); 77 | g.getVertices().forEach(w -> { 78 | if (eccentricity.get(w) == chosen) { 79 | periphery.add(w); 80 | } 81 | }); 82 | } 83 | } 84 | } 85 | ``` 86 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_s13_local_clustering_coefficient.md: -------------------------------------------------------------------------------- 1 | # Local Clustering Coefficient (LCC) 2 | 3 | - **Category:** structure evaluation 4 | - **Algorithm ID:** pgx_builtin_s13_local_clustering_coefficient 5 | - **Time Complexity:** O(V ^ 2) with V = number of vertices 6 | - **Space Requirement:** O(V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#localClusteringCoefficient(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#localClusteringCoefficient_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#localClusteringCoefficient(PgxGraph graph, boolean ignoreEdgeDirection)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#localClusteringCoefficient_oracle_pgx_api_PgxGraph_boolean_) 10 | - [Analyst#localClusteringCoefficient(PgxGraph graph, VertexProperty lcc)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#localClusteringCoefficient_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_) 11 | - [Analyst#localClusteringCoefficient(PgxGraph graph, VertexProperty lcc, boolean ignoreEdgeDirection)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#localClusteringCoefficient_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_boolean_) 12 | 13 | The LCC of a vertex V is the fraction of connections between each pair of neighbors of V, i.e. the fraction of existing triangles from all the possible triangles involving V and every other pair of neighbor vertices of V. This implementation is intended for undirected graphs. Nodes with a degree smaller than 2 will be assigned a LCC value of 0. 14 | 15 | ## Signature 16 | 17 | | Input Argument | Type | Comment | 18 | | :--- | :--- | :--- | 19 | | `G` | graph | the graph. | 20 | 21 | | Output Argument | Type | Comment | 22 | | :--- | :--- | :--- | 23 | | `lcc` | vertexProp | vertex property holding the lcc value for each vertex. | 24 | 25 | | Return Value | Type | Comment | 26 | | :--- | :--- | :--- | 27 | | | void | None | 28 | 29 | ## Code 30 | 31 | ```java 32 | /* 33 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 34 | */ 35 | package oracle.pgx.algorithms; 36 | 37 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 38 | import oracle.pgx.algorithm.PgxGraph; 39 | import oracle.pgx.algorithm.Scalar; 40 | import oracle.pgx.algorithm.VertexProperty; 41 | import oracle.pgx.algorithm.annotations.Out; 42 | 43 | @GraphAlgorithm 44 | public class ClusteringCoefficient { 45 | public void localClusteringCoefficient(PgxGraph g, @Out VertexProperty lcc) { 46 | lcc.setAll(0d); 47 | 48 | g.getVertices().filter(v -> v.getOutDegree() >= 2).forEach(v -> { 49 | Scalar lcount = Scalar.create(0L); 50 | v.getOutNeighbors().forEach(m -> 51 | v.getOutNeighbors().filter(m::lessThan).forEach(n -> { 52 | if (m.hasEdgeTo(n)) { 53 | lcount.increment(); 54 | } 55 | }) 56 | ); 57 | lcc.set(v, (2.0 * lcount.get()) / ((double) v.getOutDegree() * (v.getOutDegree() - 1))); 58 | }); 59 | } 60 | } 61 | ``` 62 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_s13d_local_clustering_coefficient.md: -------------------------------------------------------------------------------- 1 | # Local Clustering Coefficient for Directed Graphs (LCC) 2 | 3 | - **Category:** structure evaluation 4 | - **Algorithm ID:** pgx_builtin_s13d_local_clustering_coefficient 5 | - **Time Complexity:** O(V ^ 2) with V = number of vertices 6 | - **Space Requirement:** O(V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#localClusteringCoefficient(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#localClusteringCoefficient_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#localClusteringCoefficient(PgxGraph graph, boolean ignoreEdgeDirection)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#localClusteringCoefficient_oracle_pgx_api_PgxGraph_boolean_) 10 | - [Analyst#localClusteringCoefficient(PgxGraph graph, VertexProperty lcc)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#localClusteringCoefficient_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_) 11 | - [Analyst#localClusteringCoefficient(PgxGraph graph, VertexProperty lcc, boolean ignoreEdgeDirection)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#localClusteringCoefficient_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_boolean_) 12 | 13 | The LCC of a vertex V is the fraction of connections between each pair of neighbors of V, i.e. the fraction of existing triangles from all the possible triangles involving V and every other pair of neighbor vertices of V. This implementation is intended for directed graphs. Nodes with a degree smaller than 2 will be assigned a LCC value of 0. 14 | 15 | ## Signature 16 | 17 | | Input Argument | Type | Comment | 18 | | :--- | :--- | :--- | 19 | | `G` | graph | the graph. | 20 | 21 | | Output Argument | Type | Comment | 22 | | :--- | :--- | :--- | 23 | | `lcc` | vertexProp | vertex property holding the lcc value for each vertex. | 24 | 25 | | Return Value | Type | Comment | 26 | | :--- | :--- | :--- | 27 | | | void | None | 28 | 29 | ## Code 30 | 31 | ```java 32 | /* 33 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 34 | */ 35 | package oracle.pgx.algorithms; 36 | 37 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 38 | import oracle.pgx.algorithm.PgxGraph; 39 | import oracle.pgx.algorithm.VertexProperty; 40 | import oracle.pgx.algorithm.annotations.Out; 41 | 42 | @GraphAlgorithm 43 | public class ClusteringCoefficientDirected { 44 | public void localClusteringCoefficient(PgxGraph g, @Out VertexProperty lcc) { 45 | lcc.setAll(0d); 46 | 47 | g.getVertices().filter(v -> v.getOutDegree() >= 2).forEach(v -> { 48 | double count = 0; 49 | v.getOutNeighbors().forEach(m -> { 50 | v.getOutNeighbors().filter(n -> (m != n)).forEach(n -> { 51 | if (m.hasEdgeTo(n)) { 52 | count++; 53 | } 54 | }); 55 | }); 56 | lcc.set(v, count / ((double) v.getOutDegree() * (v.getOutDegree() - 1))); 57 | 58 | }); 59 | } 60 | } 61 | ``` 62 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_s13u_local_clustering_coefficient.md: -------------------------------------------------------------------------------- 1 | # Local Clustering Coefficient for ignoring edge directions (LCC) 2 | 3 | - **Category:** structure evaluation 4 | - **Algorithm ID:** pgx_builtin_s13u_local_clustering_coefficient 5 | - **Time Complexity:** O(V ^ 2) with V = number of vertices 6 | - **Space Requirement:** O(V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#localClusteringCoefficient(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#localClusteringCoefficient_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#localClusteringCoefficient(PgxGraph graph, boolean ignoreEdgeDirection)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#localClusteringCoefficient_oracle_pgx_api_PgxGraph_boolean_) 10 | - [Analyst#localClusteringCoefficient(PgxGraph graph, VertexProperty lcc)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#localClusteringCoefficient_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_) 11 | - [Analyst#localClusteringCoefficient(PgxGraph graph, VertexProperty lcc, boolean ignoreEdgeDirection)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#localClusteringCoefficient_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_boolean_) 12 | 13 | The LCC of a vertex V is the fraction of connections between each pair of neighbors of V, i.e. the fraction of existing triangles from all the possible triangles involving V and every other pair of neighbor vertices of V. This implementation is intended for directed graphs and interprets them as undirected. Nodes with a degree smaller than 2 will be assigned a LCC value of 0. 14 | 15 | ## Signature 16 | 17 | | Input Argument | Type | Comment | 18 | | :--- | :--- | :--- | 19 | | `G` | graph | the graph. | 20 | 21 | | Output Argument | Type | Comment | 22 | | :--- | :--- | :--- | 23 | | `lcc` | vertexProp | vertex property holding the lcc value for each vertex. | 24 | 25 | | Return Value | Type | Comment | 26 | | :--- | :--- | :--- | 27 | | | void | None | 28 | 29 | ## Code 30 | 31 | ```java 32 | /* 33 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 34 | */ 35 | package oracle.pgx.algorithms; 36 | 37 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 38 | import oracle.pgx.algorithm.PgxGraph; 39 | import oracle.pgx.algorithm.VertexProperty; 40 | import oracle.pgx.algorithm.annotations.Out; 41 | import oracle.pgx.algorithm.annotations.Out; 42 | 43 | @GraphAlgorithm 44 | public class ClusteringCoefficientUndirected { 45 | public void localClusteringCoefficient(PgxGraph g, @Out VertexProperty lcc) { 46 | lcc.setAll(0d); 47 | 48 | VertexProperty degree = VertexProperty.create(); 49 | 50 | g.getVertices().forEach(v -> { 51 | degree.set(v, v.getOutDegree() + v.getInDegree() - v.getOutNeighbors().filter(v1 -> (v.hasEdgeFrom(v1))).size()); 52 | }); 53 | 54 | g.getVertices().filter(v -> degree.get(v) >= 2).forEach(v -> { 55 | long count = 0; 56 | v.getOutNeighbors().forEach(m -> { 57 | count += v.getOutNeighbors() 58 | .filter(n -> m.lessThan(n) && (m.hasEdgeTo(n) || n.hasEdgeTo(m))) 59 | .size(); 60 | count += v.getInNeighbors() 61 | .filter(n -> !v.hasEdgeTo(n) && m.lessThan(n) && (m.hasEdgeTo(n) || n.hasEdgeTo(m))) 62 | .size(); 63 | }); 64 | v.getInNeighbors().filter(m -> !v.hasEdgeTo(m)).forEach(m -> { 65 | count += v.getOutNeighbors() 66 | .filter(n -> m.lessThan(n) && (m.hasEdgeTo(n) || n.hasEdgeTo(m))) 67 | .size(); 68 | count += v.getInNeighbors() 69 | .filter(n -> !v.hasEdgeTo(n) && m.lessThan(n) && (m.hasEdgeTo(n) || n.hasEdgeTo(m))) 70 | .size(); 71 | }); 72 | lcc.set(v, (2.0 * count) / ((double) degree.get(v) * (degree.get(v) - 1))); 73 | }); 74 | } 75 | } 76 | ``` 77 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_s14b_find_cycle_from_node.md: -------------------------------------------------------------------------------- 1 | # Find Cycle from Node 2 | 3 | - **Category:** structure evaluation 4 | - **Algorithm ID:** pgx_builtin_s14b_find_cycle_from_node 5 | - **Time Complexity:** O(V + E) with V = number of vertices, E = number of edges 6 | - **Space Requirement:** O(4 * V + E) with V = number of vertices, E = number of edges 7 | - **Javadoc:** 8 | - [Analyst#findCycle(PgxGraph graph, PgxVertex src)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#findCycle_oracle_pgx_api_PgxGraph_oracle_pgx_api_PgxVertex_) 9 | - [Analyst#findCycle(PgxGraph graph, PgxVertex src, VertexSequence nodeSeq, EdgeSequence edgeSeq)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#findCycle_oracle_pgx_api_PgxGraph_oracle_pgx_api_PgxVertex_oracle_pgx_api_VertexSequence_oracle_pgx_api_EdgeSequence_) 10 | 11 | This implementation tries to find a cycle in a directed graph using the given vertex as starting point for the DFS traversal and will return the first cycle found, if there is one. In such case, the vertices and edges involved in the cycle will be returned in the order of visit. Restricting the DFS traversal to a single starting point means that some parts of the graph may not get explored. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | | `s` | node | source vertex for the search. | 19 | 20 | | Output Argument | Type | Comment | 21 | | :--- | :--- | :--- | 22 | | `cycle_nodes` | nodeSeq | vertex sequence holding the vertices in the cycle. | 23 | | `cycle_edges` | edgeSeq | edge sequence holding the edges in the cycle. | 24 | 25 | | Return Value | Type | Comment | 26 | | :--- | :--- | :--- | 27 | | | bool | true if there is a cycle in the graph, false otherwise. | 28 | 29 | ## Code 30 | 31 | ```java 32 | /* 33 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 34 | */ 35 | package oracle.pgx.algorithms; 36 | 37 | import oracle.pgx.algorithm.EdgeSequence; 38 | import oracle.pgx.algorithm.PgxEdge; 39 | import oracle.pgx.algorithm.PgxGraph; 40 | import oracle.pgx.algorithm.PgxVertex; 41 | import oracle.pgx.algorithm.Scalar; 42 | import oracle.pgx.algorithm.VertexProperty; 43 | import oracle.pgx.algorithm.VertexSequence; 44 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 45 | import oracle.pgx.algorithm.annotations.Out; 46 | 47 | import static oracle.pgx.algorithm.Traversal.inDFS; 48 | 49 | @GraphAlgorithm 50 | public class FindCycleFromNode { 51 | public boolean findCycle(PgxGraph g, PgxVertex s, @Out VertexSequence cycleNodes, @Out EdgeSequence cycleEdges) { 52 | VertexProperty source = VertexProperty.create(); 53 | VertexProperty deg = VertexProperty.create(); 54 | VertexProperty inPath = VertexProperty.create(); 55 | 56 | deg.setAll(PgxVertex::getOutDegree); 57 | inPath.setAll(false); 58 | Scalar foundCycle = Scalar.create(false); 59 | Scalar pivotNode = Scalar.create(); 60 | 61 | inDFS(g, s).navigator(v -> !foundCycle.get()).filter(v -> v.getDegree() > 0).forward(v -> { 62 | inPath.set(v, true); 63 | 64 | v.getOutNeighbors().forEach(w -> { 65 | source.set(w, v); 66 | if (inPath.get(w)) { 67 | foundCycle.set(true); 68 | pivotNode.set(w); 69 | } 70 | }); 71 | }).backwardFilter(v -> !foundCycle.get()).backward(v -> { 72 | v.getInNeighbors().forEach(w -> { 73 | if (deg.get(w) > 0) { 74 | deg.set(w, deg.get(w) - 1); 75 | } 76 | }); 77 | pivotNode.set(source.get(v)); 78 | if (deg.get(pivotNode.get()) == 0) { 79 | inPath.set(pivotNode.get(), false); 80 | } 81 | }); 82 | 83 | if (foundCycle.get()) { 84 | PgxVertex firstInCycle = pivotNode.get(); 85 | cycleNodes.pushFront(pivotNode.get()); 86 | pivotNode.set(source.get(pivotNode.get())); 87 | 88 | Scalar e = Scalar.create(); 89 | while (pivotNode.get() != firstInCycle) { 90 | cycleNodes.pushFront(pivotNode.get()); 91 | 92 | pivotNode.get().getOutNeighbors().filter(inPath).forSequential(v -> e.set(v.edge())); 93 | cycleEdges.pushFront(e.get()); 94 | 95 | pivotNode.set(source.get(pivotNode.get())); 96 | } 97 | cycleNodes.pushFront(pivotNode.get()); 98 | pivotNode.get().getOutNeighbors().filter(inPath).forSequential(v -> e.set(v.edge())); 99 | 100 | cycleEdges.pushFront(e.get()); 101 | } 102 | 103 | return foundCycle.get(); 104 | } 105 | } 106 | ``` 107 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_s15a_reachability.md: -------------------------------------------------------------------------------- 1 | # Reachability 2 | 3 | - **Category:** structure evaluation 4 | - **Algorithm ID:** pgx_builtin_s15a_reachability 5 | - **Time Complexity:** O(V + E) with V = number of vertices, E = number of edges 6 | - **Space Requirement:** O(1) 7 | - **Javadoc:** 8 | - [Analyst#reachability(PgxGraph graph, PgxVertex source, PgxVertex dest, int maxHops, boolean ignoreEdgeDirection)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#reachability_oracle_pgx_api_PgxGraph_oracle_pgx_api_PgxVertex_oracle_pgx_api_PgxVertex_int_boolean_) 9 | 10 | This algorithm tries to find if the destination vertex is reachable given the source vertex and the maximum hop distance set by the user. The search can be performed in a directed or undirected way. These options may lead to different hop distances, since an undirected search has less restrictions on the possible paths connecting vertices than the directed option. Hence hop distances from an undirected search can be smaller than the ones from the directed cases. 11 | 12 | ## Signature 13 | 14 | | Input Argument | Type | Comment | 15 | | :--- | :--- | :--- | 16 | | `G` | graph | the graph. | 17 | | `source` | node | source vertex for the search. | 18 | | `dest` | node | destination vertex for the search. | 19 | | `maxHops` | int | maximum hop distance between the source and destination vertices. | 20 | 21 | | Return Value | Type | Comment | 22 | | :--- | :--- | :--- | 23 | | | int | the number of hops between the vertices. It will return -1 if the vertices are not connected or are not reachable given the condition of the maximum hop distance allowed. | 24 | 25 | ## Code 26 | 27 | ```java 28 | /* 29 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 30 | */ 31 | package oracle.pgx.algorithms; 32 | 33 | import oracle.pgx.algorithm.PgxGraph; 34 | import oracle.pgx.algorithm.PgxVertex; 35 | import oracle.pgx.algorithm.Scalar; 36 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 37 | 38 | import static oracle.pgx.algorithm.ControlFlow.exit; 39 | import static oracle.pgx.algorithm.Traversal.currentLevel; 40 | import static oracle.pgx.algorithm.Traversal.inBFS; 41 | import static oracle.pgx.algorithm.Traversal.stopTraversal; 42 | 43 | @GraphAlgorithm 44 | public class Reachability { 45 | public int reachability(PgxGraph g, PgxVertex source, PgxVertex dest, int maxHops) { 46 | Scalar giveup = Scalar.create(false); 47 | int threshold = 10000000; 48 | 49 | // 0 hop 50 | if (source == dest) { 51 | return 0; 52 | } else if (maxHops == 0) { 53 | return -1; 54 | } 55 | 56 | // 1 hop 57 | if (source.hasEdgeTo(dest)) { 58 | return 1; 59 | } else if (maxHops == 1) { 60 | return -1; 61 | } 62 | 63 | Scalar s = Scalar.create(0); 64 | // 2, 3, 4 hop 65 | source.getOutNeighbors().filter(l1 -> !giveup.get()).forSequential(l1 -> { 66 | s.increment(); 67 | if (s.get() >= threshold) { 68 | giveup.set(true); 69 | } 70 | l1.getOutNeighbors().filter(l2 -> !giveup.get()).forSequential(l2 -> { 71 | if (l2 == dest) { 72 | exit(2); 73 | } 74 | s.increment(); 75 | if (s.get() >= threshold) { 76 | giveup.set(true); 77 | } 78 | if (!giveup.get() && maxHops >= 3) { 79 | l2.getOutNeighbors().filter(l3 -> !giveup.get()).forSequential(l3 -> { 80 | if (l3 == dest) { 81 | exit(3); 82 | } 83 | s.increment(); 84 | if (s.get() >= threshold) { 85 | giveup.set(true); 86 | } 87 | if (!giveup.get() && maxHops >= 4) { 88 | l3.getOutNeighbors().filter(l4 -> !giveup.get()).forSequential(l4 -> { 89 | if (l4 == dest) { 90 | exit(4); 91 | } 92 | s.increment(); 93 | if (s.get() >= threshold) { 94 | giveup.set(true); 95 | } 96 | }); 97 | } 98 | }); 99 | } 100 | }); 101 | }); 102 | 103 | if (!giveup.get() && maxHops <= 4) { 104 | return -1; 105 | } 106 | 107 | Scalar found = Scalar.create(-1); 108 | 109 | inBFS(g, source) // 110 | .filter(n -> found.get() == -1) // 111 | .navigator(n -> (found.get() == -1) && currentLevel() < maxHops) // 112 | .forward(n -> { 113 | if (n == dest) { 114 | found.set(currentLevel()); 115 | stopTraversal(); 116 | } 117 | }); 118 | 119 | return found.get(); 120 | } 121 | } 122 | ``` 123 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_s16a_topological_sort.md: -------------------------------------------------------------------------------- 1 | # Topological Sort 2 | 3 | - **Category:** structure evaluation 4 | - **Algorithm ID:** pgx_builtin_s16a_topological_sort 5 | - **Time Complexity:** O(V + E) with V = number of vertices, E = number of edges 6 | - **Space Requirement:** O(2 * V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#topologicalSort(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#topologicalSort_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#topologicalSort(PgxGraph graph, VertexProperty topoSort)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#topologicalSort_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_) 10 | 11 | Topological sort tries to set an order over the vertices in a graph using the direction of the edges. A directed graph has a topological order if and only if it has no cycles, i.e. it is a directed acyclic graph. The algorithm visits the vertices in a DFS-like fashion to set up their order. The order of the vertices is returned as a vertex property, and the values will be set to -1 if there is a cycle in the graph. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | 19 | | Output Argument | Type | Comment | 20 | | :--- | :--- | :--- | 21 | | `top_order` | vertexProp | vertex property holding the topological order of each vertex. | 22 | 23 | | Return Value | Type | Comment | 24 | | :--- | :--- | :--- | 25 | | | bool | true if the graph has a topological order, false otherwise. | 26 | 27 | ## Code 28 | 29 | ```java 30 | /* 31 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 32 | */ 33 | package oracle.pgx.algorithms; 34 | 35 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 36 | import oracle.pgx.algorithm.PgxGraph; 37 | import oracle.pgx.algorithm.PgxVertex; 38 | import oracle.pgx.algorithm.Scalar; 39 | import oracle.pgx.algorithm.VertexProperty; 40 | import oracle.pgx.algorithm.VertexSequence; 41 | import oracle.pgx.algorithm.annotations.Out; 42 | 43 | @GraphAlgorithm 44 | public class TopologicalSort { 45 | public boolean topologicalSort(PgxGraph g, @Out VertexProperty topologicalOrder) { 46 | boolean sorted = true; 47 | VertexProperty deg = VertexProperty.create(); 48 | VertexSequence s = VertexSequence.create(); 49 | Scalar e = Scalar.create(g.getNumEdges()); 50 | 51 | g.getVertices().filter(n -> n.getInDegree() == 0).forSequential(s::pushBack); 52 | 53 | topologicalOrder.setAll(-1); 54 | deg.setAll(PgxVertex::getInDegree); 55 | int visited = 0; 56 | 57 | while (s.size() > 0) { 58 | PgxVertex n = s.front(); 59 | topologicalOrder.set(n, visited); 60 | visited++; 61 | n.getOutNeighbors().forSequential(nbr -> { 62 | deg.set(nbr, deg.get(nbr) - 1); 63 | e.set(e.get() - 1); 64 | if (deg.get(nbr) == 0) { 65 | s.pushBack(nbr); 66 | } 67 | }); 68 | s.popFront(); 69 | } 70 | 71 | if (e.get() > 0) { 72 | topologicalOrder.setAll(-1); 73 | sorted = false; 74 | } 75 | return sorted; 76 | } 77 | } 78 | ``` 79 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_s16b_topological_schedule.md: -------------------------------------------------------------------------------- 1 | # Topological Schedule 2 | 3 | - **Category:** structure evaluation 4 | - **Algorithm ID:** pgx_builtin_s16b_topological_schedule 5 | - **Time Complexity:** O(k * (V + E)) with V = number of vertices, E = number of edges, k = size of the source set 6 | - **Space Requirement:** O(V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#topologicalSchedule(PgxGraph graph, VertexSet source)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#topologicalSchedule_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexSet_) 9 | - [Analyst#topologicalSchedule(PgxGraph graph, VertexSet source, VertexProperty topoSched)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#topologicalSchedule_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexSet_oracle_pgx_api_VertexProperty_) 10 | 11 | Topological schedule sets an order over the vertices in a graph based on the proximity these have to the vertices from the given source. The algorithm does a BFS traversal for each vertex from the source set in order to assign the correct scheduling order to all the reachable, even if the graph is undirected or has cycles. The vertices that are not reachable will be assigned a value of -1. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | | `source` | nodeSet | set of vertices to be used as the starting points for the scheduling order. | 19 | 20 | | Output Argument | Type | Comment | 21 | | :--- | :--- | :--- | 22 | | `top_sched` | vertexProp | vertex property holding the scheduled order of each vertex. | 23 | 24 | | Return Value | Type | Comment | 25 | | :--- | :--- | :--- | 26 | | | void | None | 27 | 28 | ## Code 29 | 30 | ```java 31 | /* 32 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 33 | */ 34 | package oracle.pgx.algorithms; 35 | 36 | import oracle.pgx.algorithm.PgxGraph; 37 | import oracle.pgx.algorithm.VertexProperty; 38 | import oracle.pgx.algorithm.VertexSet; 39 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 40 | import oracle.pgx.algorithm.annotations.Out; 41 | 42 | import static oracle.pgx.algorithm.Traversal.currentLevel; 43 | import static oracle.pgx.algorithm.Traversal.inBFS; 44 | 45 | @GraphAlgorithm 46 | public class TopologicalSchedule { 47 | public void topologicalSchedule(PgxGraph g, VertexSet source, @Out VertexProperty schedule) { 48 | schedule.setAll(-1); 49 | 50 | source.forEach(n -> inBFS(g, n).forward(v -> { 51 | if (schedule.get(v) > currentLevel() || schedule.get(v) == -1) { 52 | schedule.set(v, currentLevel()); 53 | } 54 | })); 55 | } 56 | } 57 | ``` 58 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_s1_triangle_counting.md: -------------------------------------------------------------------------------- 1 | # Triangle Counting 2 | 3 | - **Category:** structure evaluation 4 | - **Algorithm ID:** pgx_builtin_s1_triangle_counting 5 | - **Time Complexity:** O(E ^ 1.5) with E = number of edges 6 | - **Space Requirement:** O(V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#countTriangles(PgxGraph graph, boolean sortVerticesByDegree)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#countTriangles_oracle_pgx_api_PgxGraph_boolean_) 9 | 10 | This algorithm is intended for directed graphs and will count all the existing triangles on it. To run the algorithm on undirected graphs, use the undirected version. 11 | 12 | ## Signature 13 | 14 | | Input Argument | Type | Comment | 15 | | :--- | :--- | :--- | 16 | | `G` | graph | the graph. | 17 | 18 | | Return Value | Type | Comment | 19 | | :--- | :--- | :--- | 20 | | | long | returns the total number of triangles found. | 21 | 22 | ## Code 23 | 24 | ```java 25 | /* 26 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 27 | */ 28 | package oracle.pgx.algorithms; 29 | 30 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 31 | import oracle.pgx.algorithm.PgxGraph; 32 | import oracle.pgx.algorithm.Scalar; 33 | 34 | @GraphAlgorithm 35 | public class TriangleCounting { 36 | public long triangleCounting(PgxGraph g) { 37 | Scalar t = Scalar.create(0L); 38 | 39 | g.getVertices().forEach(u -> u.getInOutNeighbors().filter(v -> v.greaterThan(u)).forEach(v -> { 40 | u.getInOutNeighbors().filter(w -> w.greaterThan(v)).forEach(w -> { 41 | if (v.hasEdgeTo(w)) { 42 | t.increment(); 43 | } 44 | if (v.hasEdgeFrom(w)) { 45 | t.increment(); 46 | } 47 | }); 48 | })); 49 | 50 | return t.get(); 51 | } 52 | } 53 | ``` 54 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_s1b_triangle_counting_undirected.md: -------------------------------------------------------------------------------- 1 | # Triangle Counting (undirected) 2 | 3 | - **Category:** structure evaluation 4 | - **Algorithm ID:** pgx_builtin_s1b_triangle_counting_undirected 5 | - **Time Complexity:** O(E ^ 1.5) with E = number of edges 6 | - **Space Requirement:** O(V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#countTrianglesAsync(PgxGraph graph, boolean sortVerticesByDegree)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#countTrianglesAsync_oracle_pgx_api_PgxGraph_boolean_) 9 | 10 | This algorithm is intended for undirected graphs and will count all the existing triangles on it. If the graph is a directed one, the algorithm will not count correctly the triangles in it. 11 | 12 | ## Signature 13 | 14 | | Input Argument | Type | Comment | 15 | | :--- | :--- | :--- | 16 | | `G` | graph | the graph. | 17 | 18 | | Return Value | Type | Comment | 19 | | :--- | :--- | :--- | 20 | | | long | returns the total number of triangles found. | 21 | 22 | ## Code 23 | 24 | ```java 25 | /* 26 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 27 | */ 28 | package oracle.pgx.algorithms; 29 | 30 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 31 | import oracle.pgx.algorithm.PgxGraph; 32 | import oracle.pgx.algorithm.Scalar; 33 | 34 | @GraphAlgorithm 35 | public class TriangleCountingUndirected { 36 | public long triangleCounting(PgxGraph g) { 37 | Scalar t = Scalar.create(0L); 38 | 39 | g.getVertices().forEach(u -> u.getOutNeighbors().filter(v -> v.greaterThan(u)).forEach(v -> { 40 | u.getOutNeighbors().filter(w -> w.greaterThan(v)).forEach(w -> { 41 | if (v.hasEdgeTo(w)) { 42 | t.increment(); 43 | } 44 | }); 45 | })); 46 | 47 | return t.get(); 48 | } 49 | } 50 | ``` 51 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_s2_adamic_adar_counting.md: -------------------------------------------------------------------------------- 1 | # Adamic-Adar index 2 | 3 | - **Category:** structure evaluation 4 | - **Algorithm ID:** pgx_builtin_s2_adamic_adar_counting 5 | - **Time Complexity:** O(E) with E = number of edges 6 | - **Space Requirement:** O(E) with E = number of edges 7 | - **Javadoc:** 8 | - [Analyst#adamicAdarCounting(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#adamicAdarCounting_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#adamicAdarCounting(PgxGraph graph, EdgeProperty aa)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#adamicAdarCounting_oracle_pgx_api_PgxGraph_oracle_pgx_api_EdgeProperty_) 10 | 11 | The Adamic-Adar index is meant for undirected graphs, since it is computed using the degree of the shared neighbors by two vertices in the graph. This implementation computes the index for every pair of vertices connected by an edge and associates it with that edge. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | 19 | | Output Argument | Type | Comment | 20 | | :--- | :--- | :--- | 21 | | `adamic_adar` | edgeProp | edge property holding the Adamic-Adar index of each edge in the graph. | 22 | 23 | | Return Value | Type | Comment | 24 | | :--- | :--- | :--- | 25 | | | void | None | 26 | 27 | ## Code 28 | 29 | ```java 30 | /* 31 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 32 | */ 33 | package oracle.pgx.algorithms; 34 | 35 | import oracle.pgx.algorithm.EdgeProperty; 36 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 37 | import oracle.pgx.algorithm.PgxGraph; 38 | import oracle.pgx.algorithm.PgxVertex; 39 | import oracle.pgx.algorithm.annotations.Out; 40 | 41 | import static java.lang.Math.log10; 42 | 43 | @GraphAlgorithm 44 | public class AdamicAdar { 45 | public void adamicAdar(PgxGraph g, @Out EdgeProperty aa) { 46 | g.getEdges().forEach(e -> { 47 | PgxVertex src = e.sourceVertex(); 48 | PgxVertex dst = e.destinationVertex(); 49 | 50 | double value = src.getOutNeighbors() 51 | .filter(n -> n.hasEdgeFrom(dst)) 52 | .sum(n -> 1 / log10(n.getDegree())); 53 | 54 | aa.set(e, value); 55 | }); 56 | } 57 | } 58 | ``` 59 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_s2d_adamic_adar_counting.md: -------------------------------------------------------------------------------- 1 | # Adamic-Adar index (Ignoring edge direction) 2 | 3 | - **Category:** structure evaluation 4 | - **Algorithm ID:** pgx_builtin_s2d_adamic_adar_counting 5 | - **Time Complexity:** O(E) with E = number of edges 6 | - **Space Requirement:** O(E) with E = number of edges 7 | - **Javadoc:** 8 | - [Analyst#adamicAdarCountingAsync(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#adamicAdarCountingAsync_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#adamicAdarCountingAsync(PgxGraph graph, EdgeProperty aa)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#adamicAdarCountingAsync_oracle_pgx_api_PgxGraph_oracle_pgx_api_EdgeProperty_) 10 | 11 | The Adamic-Adar index is meant for undirected graphs, since it is computed using the degree of the shared neighbors by two vertices in the graph. This implementation is intended for directed graphs but ignores edge direction to interpret the graph as undirected. It computes the index for every pair of vertices connected by an edge and associates it with that edge. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | 19 | | Output Argument | Type | Comment | 20 | | :--- | :--- | :--- | 21 | | `adamic_adar` | edgeProp | edge property holding the Adamic-Adar index of each edge in the graph. | 22 | 23 | | Return Value | Type | Comment | 24 | | :--- | :--- | :--- | 25 | | | void | None | 26 | 27 | ## Code 28 | 29 | ```java 30 | /* 31 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 32 | */ 33 | package oracle.pgx.algorithms; 34 | 35 | import oracle.pgx.algorithm.EdgeProperty; 36 | import oracle.pgx.algorithm.VertexProperty; 37 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 38 | import oracle.pgx.algorithm.PgxGraph; 39 | import oracle.pgx.algorithm.PgxVertex; 40 | import oracle.pgx.algorithm.annotations.Out; 41 | 42 | import static java.lang.Math.log10; 43 | 44 | @GraphAlgorithm 45 | public class AdamicAdarDirected { 46 | public void adamicAdarDirected(PgxGraph g, @Out EdgeProperty aa) { 47 | VertexProperty index = VertexProperty.create(); 48 | 49 | g.getVertices().forEach(v -> { 50 | double filter = v.getInNeighbors().filter(v1 -> (v1.hasEdgeFrom(v) && v.hasEdgeFrom(v1))).sum(h -> 1); 51 | index.set(v, 1 / log10(v.getInDegree() + v.getDegree() - filter)); 52 | }); 53 | 54 | g.getEdges() 55 | .forEach(e -> { 56 | PgxVertex src = e.sourceVertex(); 57 | PgxVertex dst = e.destinationVertex(); 58 | 59 | double valueOut = src.getOutNeighbors() 60 | .filter(n -> (n.hasEdgeFrom(dst) || dst.hasEdgeFrom(n))) 61 | .sum(n -> index.get(n)); 62 | 63 | double valueIn = src.getInNeighbors() 64 | .filter(n -> (!n.hasEdgeFrom(src) && (n.hasEdgeFrom(dst) || dst.hasEdgeFrom(n)))) 65 | .sum(n -> index.get(n)); 66 | 67 | aa.set(e, valueIn + valueOut); 68 | }); 69 | } 70 | } 71 | ``` 72 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_s3_conductance.md: -------------------------------------------------------------------------------- 1 | # Conductance 2 | 3 | - **Category:** structure evaluation 4 | - **Algorithm ID:** pgx_builtin_s3_conductance 5 | - **Time Complexity:** O(V) with V = number of vertices 6 | - **Space Requirement:** O(1) 7 | - **Javadoc:** 8 | - [Analyst#conductance(PgxGraph graph, Partition partition, long partitionIndex)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#conductance_oracle_pgx_api_PgxGraph_oracle_pgx_api_Partition_long_) 9 | - [Analyst#conductance(PgxGraph graph, Partition partition, long partitionIndex, Scalar conductance)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#conductance_oracle_pgx_api_PgxGraph_oracle_pgx_api_Partition_long_oracle_pgx_api_Scalar_) 10 | 11 | Conductance in a graph is computed for a specific cut of it. A cut is a partition of the graph into two subsets (components), disconnecting the graph if the edges from the cut are removed. Thus the algorithm requires a labeling for the vertices in the different subsets of the graph, then the conductance is computed by the ratio of the edges belonging to the given cut (i.e. the edges that split the graph into disconnected components) and the edges belonging to each of these subsets. If there is more than one cut (or partition), this implementation will take the given component number as reference to compute the conductance associated with that particular cut. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | | `member` | vertexProp | vertex property with the component label for each vertex in the graph. | 19 | | `num` | long | number of the component to be used for computing its conductance. | 20 | 21 | | Return Value | Type | Comment | 22 | | :--- | :--- | :--- | 23 | | | double | conductance value of the graph cut. | 24 | 25 | ## Code 26 | 27 | ```java 28 | /* 29 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 30 | */ 31 | package oracle.pgx.algorithms; 32 | 33 | import oracle.pgx.algorithm.PgxGraph; 34 | import oracle.pgx.algorithm.PgxVertex; 35 | import oracle.pgx.algorithm.VertexProperty; 36 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 37 | 38 | import static java.lang.Double.POSITIVE_INFINITY; 39 | 40 | @GraphAlgorithm 41 | public class Conductance { 42 | public double conductance(PgxGraph g, VertexProperty member, long num) { 43 | long dIn = g 44 | .getVertices() 45 | .filter(u -> member.get(u) == num) 46 | .sum(PgxVertex::getOutDegree); 47 | 48 | long dOut = g 49 | .getVertices() 50 | .filter(u -> member.get(u) != num) 51 | .sum(PgxVertex::getOutDegree); 52 | 53 | long cross = g 54 | .getVertices() 55 | .filter(u -> member.get(u) == num) 56 | .sum(u -> u.getOutNeighbors().filter(j -> member.get(j) != num).size()); 57 | 58 | double m = dIn < dOut ? dIn : dOut; 59 | 60 | if (m == 0) { 61 | return cross == 0 ? 0.0 : POSITIVE_INFINITY; 62 | } else { 63 | return cross / m; 64 | } 65 | } 66 | } 67 | ``` 68 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_s4_partition_modularity.md: -------------------------------------------------------------------------------- 1 | # Modularity 2 | 3 | - **Category:** structure evaluation 4 | - **Algorithm ID:** pgx_builtin_s4_partition_modularity 5 | - **Time Complexity:** O(E * c) with E = number of edges, c = number of components 6 | - **Space Requirement:** O(V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#partitionModularity(PgxGraph graph, Partition partition)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#partitionModularity_oracle_pgx_api_PgxGraph_oracle_pgx_api_Partition_) 9 | - [Analyst#partitionModularity(PgxGraph graph, Partition partition, Scalar modularity)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#partitionModularity_oracle_pgx_api_PgxGraph_oracle_pgx_api_Partition_oracle_pgx_api_Scalar_) 10 | 11 | Modularity in a graph is a measure for assessing the quality of the partition induced by the components (or community structures) within the graph found by any clustering algorithm (e.g. label propagation, Infomap, WCC, etc.). It compares the number of the edges between the vertices within a component against the expected number of edges if these were generated at random (assuming a uniform probability distribution). A positive modularity value means that, on average, there are more edges within the components than the amount expected (meaning stronger components), and vice-versa for a negative modularity value. This implementation is intended for directed graphs. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | | `member` | vertexProp | vertex property with the component label for each vertex in the graph. | 19 | | `num_comp` | long | number of components in the graph found by any clustering algorithm. | 20 | 21 | | Return Value | Type | Comment | 22 | | :--- | :--- | :--- | 23 | | | double | modularity value corresponding to the given components in the graph. | 24 | 25 | ## Code 26 | 27 | ```java 28 | /* 29 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 30 | */ 31 | package oracle.pgx.algorithms; 32 | 33 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 34 | import oracle.pgx.algorithm.PgxGraph; 35 | import oracle.pgx.algorithm.PgxVertex; 36 | import oracle.pgx.algorithm.Scalar; 37 | import oracle.pgx.algorithm.VertexProperty; 38 | 39 | @GraphAlgorithm 40 | public class PartitionModularity { 41 | public double modularitySmallPartition(PgxGraph g, VertexProperty member, long numComp) { 42 | Scalar firstTerm = Scalar.create(0D); 43 | double secondTerm = 0; 44 | double m1 = 1 / (double) g.getNumEdges(); 45 | 46 | // compute first term: fraction of edges inside community 47 | g.getVertices().forEach(n -> { 48 | n.getOutNeighbors().forEach(m -> { 49 | if (member.get(n) == member.get(m)) { 50 | firstTerm.increment(); 51 | } 52 | }); 53 | }); 54 | 55 | firstTerm.set(firstTerm.get() * m1); 56 | 57 | // compute second term: expected number of edges inside community when 58 | // uniform 59 | Scalar num = Scalar.create(0L); 60 | while (num.get() < numComp) { 61 | long dIn = g.getVertices().filter(u -> member.get(u) == num.get()).sum(PgxVertex::getInDegree); 62 | long dOut = g.getVertices().filter(u -> member.get(u) == num.get()).sum(PgxVertex::getOutDegree); 63 | 64 | secondTerm += m1 * dIn * dOut; // avoid overflow 65 | num.increment(); 66 | } 67 | secondTerm = secondTerm * m1; 68 | 69 | return firstTerm.get() - secondTerm; 70 | } 71 | } 72 | ``` 73 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_s5_partition_conductance.md: -------------------------------------------------------------------------------- 1 | # Partition Conductance 2 | 3 | - **Category:** structure evaluation 4 | - **Algorithm ID:** pgx_builtin_s5_partition_conductance 5 | - **Time Complexity:** O(E) with E = number of edges 6 | - **Space Requirement:** O(1) 7 | - **Javadoc:** 8 | - [Analyst#partitionConductance(PgxGraph graph, Partition partition)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#partitionConductance_oracle_pgx_api_PgxGraph_oracle_pgx_api_Partition_) 9 | - [Analyst#PgxGraph graph, Partition partition, Scalar avgConductance, Scalar minConductance](https://docs.oracle.com/en/database/oracle/property-graph/24.4/spgjv/oracle/pgx/api/Analyst.html#partitionConductance_oracle_pgx_api_PgxGraph_oracle_pgx_api_Partition_oracle_pgx_api_Scalar_oracle_pgx_api_Scalar_) 10 | 11 | This variant of the conductance algorithm will compute the conductance for the given number of components, returning an output with the minimum value of conductance found from the corresponding partitions and their average conductance value. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | | `member` | vertexProp | vertex property with the component label for each vertex in the graph. | 19 | | `num_comp` | long | number of components in the graph. | 20 | 21 | | Output Argument | Type | Comment | 22 | | :--- | :--- | :--- | 23 | | `min_cond` | double | minimum conductance value found from the given partitions. | 24 | 25 | | Return Value | Type | Comment | 26 | | :--- | :--- | :--- | 27 | | | double | average conductance value of the partitions in the graph. | 28 | 29 | ## Code 30 | 31 | ```java 32 | /* 33 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 34 | */ 35 | package oracle.pgx.algorithms; 36 | 37 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 38 | import oracle.pgx.algorithm.PgxGraph; 39 | import oracle.pgx.algorithm.PgxVertex; 40 | import oracle.pgx.algorithm.Scalar; 41 | import oracle.pgx.algorithm.VertexProperty; 42 | import oracle.pgx.algorithm.annotations.Out; 43 | 44 | @GraphAlgorithm 45 | public class PartitionConductance { 46 | public double conductanceSmallPartition(PgxGraph g, VertexProperty member, long numComp, 47 | @Out Scalar minCond) { 48 | Scalar num = Scalar.create(0L); 49 | minCond.set(0D); 50 | double sumCondcond = 0; 51 | 52 | while (num.get() < numComp) { 53 | long dIn = g.getVertices() // 54 | .filter(u -> member.get(u) == num.get()) // 55 | .sum(PgxVertex::getOutDegree); 56 | 57 | long dOut = g.getVertices() // 58 | .filter(u -> member.get(u) != num.get()) // 59 | .sum(PgxVertex::getOutDegree); 60 | 61 | long cross = g.getVertices() // 62 | .filter(u -> member.get(u) == num.get()) // 63 | .sum(u -> u.getOutNeighbors().filter(j -> member.get(j) != num.get()).size()); 64 | 65 | double m = dIn < dOut ? dIn : dOut; 66 | double cond = m == 0 ? 0.0 : cross / m; 67 | minCond.reduceMin(cond); 68 | sumCondcond += cond; 69 | num.increment(); 70 | } 71 | 72 | return numComp == 0 ? 0 : sumCondcond / numComp; 73 | } 74 | } 75 | ``` 76 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_s6_out_degree_distribution.md: -------------------------------------------------------------------------------- 1 | # Out-Degree Distribution 2 | 3 | - **Category:** structure evaluation 4 | - **Algorithm ID:** pgx_builtin_s6_out_degree_distribution 5 | - **Time Complexity:** O(V) with V = number of vertices 6 | - **Space Requirement:** O(V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#outDegreeCentrality(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#outDegreeCentrality_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#outDegreeCentrality(PgxGraph graph, VertexProperty dc)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#outDegreeCentrality_oracle_pgx_api_PgxGraph_oracle_pgx_api_VertexProperty_) 10 | 11 | This version of the degree distribution will return a map with the distribution of the out-degree (i.e. just outgoing edges) of the graph. For undirected graphs the algorithm will consider all the edges (incoming and outgoing) for the distribution. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | 19 | | Output Argument | Type | Comment | 20 | | :--- | :--- | :--- | 21 | | `distribution` | map | map holding a histogram of the node degrees in the graph. | 22 | 23 | | Return Value | Type | Comment | 24 | | :--- | :--- | :--- | 25 | | | void | None | 26 | 27 | ## Code 28 | 29 | ```java 30 | /* 31 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 32 | */ 33 | package oracle.pgx.algorithms; 34 | 35 | import oracle.pgx.algorithm.PgxGraph; 36 | import oracle.pgx.algorithm.PgxMap; 37 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 38 | import oracle.pgx.algorithm.annotations.Out; 39 | 40 | @GraphAlgorithm 41 | public class OutdegreeDistribution { 42 | public void outdegreeDistribution(PgxGraph g, @Out PgxMap distribution) { 43 | g.getVertices().forSequential(n -> { 44 | long degree = n.getOutDegree(); 45 | 46 | distribution.increment(degree); 47 | }); 48 | } 49 | } 50 | ``` 51 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_s7_in_degree_distribution.md: -------------------------------------------------------------------------------- 1 | # In-Degree Distribution 2 | 3 | - **Category:** structure evaluation 4 | - **Algorithm ID:** pgx_builtin_s7_in_degree_distribution 5 | - **Time Complexity:** O(V) with V = number of vertices 6 | - **Space Requirement:** O(V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#inDegreeDistribution(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#inDegreeDistribution_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#inDegreeDistribution(PgxGraph graph, PgxMap distribution)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#inDegreeDistribution_oracle_pgx_api_PgxGraph_oracle_pgx_api_PgxMap_) 10 | 11 | This version of the degree distribution will return a map with the distribution of the in-degree (i.e. just incoming edges) of the graph. For undirected graphs the algorithm will consider all the edges (incoming and outgoing) for the distribution. 12 | 13 | ## Signature 14 | 15 | | Input Argument | Type | Comment | 16 | | :--- | :--- | :--- | 17 | | `G` | graph | the graph. | 18 | 19 | | Output Argument | Type | Comment | 20 | | :--- | :--- | :--- | 21 | | `distribution` | map | map holding a histogram of the vertex degrees in the graph. | 22 | 23 | | Return Value | Type | Comment | 24 | | :--- | :--- | :--- | 25 | | | void | None | 26 | 27 | ## Code 28 | 29 | ```java 30 | /* 31 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 32 | */ 33 | package oracle.pgx.algorithms; 34 | 35 | import oracle.pgx.algorithm.PgxGraph; 36 | import oracle.pgx.algorithm.PgxMap; 37 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 38 | import oracle.pgx.algorithm.annotations.Out; 39 | 40 | @GraphAlgorithm 41 | public class IndegreeDistribution { 42 | public void indegreeDistribution(PgxGraph g, @Out PgxMap distribution) { 43 | g.getVertices().forSequential(n -> { 44 | long degree = n.getInDegree(); 45 | 46 | distribution.increment(degree); 47 | }); 48 | } 49 | } 50 | ``` 51 | -------------------------------------------------------------------------------- /built-in-algorithms/md/pgx_builtin_s9_kcore.md: -------------------------------------------------------------------------------- 1 | # K-Core 2 | 3 | - **Category:** structure evaluation 4 | - **Algorithm ID:** pgx_builtin_s9_kcore 5 | - **Time Complexity:** O(E * k) with E = number of edges, k <= maximum number of iterations 6 | - **Space Requirement:** O(3 * V) with V = number of vertices 7 | - **Javadoc:** 8 | - [Analyst#kcore(PgxGraph graph)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#kcore_oracle_pgx_api_PgxGraph_) 9 | - [Analyst#kcore(PgxGraph graph, int minCore, int maxCore)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#kcore_oracle_pgx_api_PgxGraph_int_int_) 10 | - [Analyst#kcore(PgxGraph graph, int minCore, int maxCore, Scalar maxKCore, VertexProperty kcore)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#kcore_oracle_pgx_api_PgxGraph_int_int_oracle_pgx_api_Scalar_oracle_pgx_api_VertexProperty_) 11 | - [Analyst#kcore(PgxGraph graph, Scalar maxKCore, VertexProperty kcore)](https://docs.oracle.com/en/database/oracle/property-graph/25.1/spgjv/oracle/pgx/api/Analyst.html#kcore_oracle_pgx_api_PgxGraph_oracle_pgx_api_Scalar_oracle_pgx_api_VertexProperty_) 12 | 13 | A k-core is a maximal subgraph in which all of its vertices are connected and have the property that all of them have a degree of at least k. The k-cores can be regarded as layers in a graph, since a (k+1)-core will always be a subgraph of a k-core. This means that the larger k becomes, the smaller its k-core (i.e. its corresponding subgraph) will be. The k-core value (or coreness) assigned to a vertex will correspond to the core with the greatest degree from all the cores where it belongs. This implementation of k-core will look for cores lying within the interval set by the min_core and max_core input variables. 14 | 15 | ## Signature 16 | 17 | | Input Argument | Type | Comment | 18 | | :--- | :--- | :--- | 19 | | `G` | graph | the graph. | 20 | | `min_core` | long | minimum k-core value. | 21 | | `max_core` | long | maximum k-core value. | 22 | 23 | | Output Argument | Type | Comment | 24 | | :--- | :--- | :--- | 25 | | `k_core` | vertexProp | vertex property with the largest k-core value for each vertex. | 26 | 27 | | Return Value | Type | Comment | 28 | | :--- | :--- | :--- | 29 | | | long | the largest k-core value found. | 30 | 31 | ## Code 32 | 33 | ```java 34 | /* 35 | * Copyright (C) 2013 - 2025 Oracle and/or its affiliates. All rights reserved. 36 | */ 37 | package oracle.pgx.algorithms; 38 | 39 | import oracle.pgx.algorithm.annotations.GraphAlgorithm; 40 | import oracle.pgx.algorithm.PgxGraph; 41 | import oracle.pgx.algorithm.Scalar; 42 | import oracle.pgx.algorithm.VertexProperty; 43 | import oracle.pgx.algorithm.annotations.Out; 44 | 45 | @GraphAlgorithm 46 | public class Kcore { 47 | public long kcore(PgxGraph g, long minCore, long maxCore, @Out VertexProperty kcore) { 48 | VertexProperty activeNbrs = VertexProperty.create(); 49 | VertexProperty active = VertexProperty.create(); 50 | VertexProperty justDeleted = VertexProperty.create(); 51 | 52 | Scalar currentKcore = Scalar.create(); 53 | currentKcore.set(minCore); 54 | Scalar nodesJustDeleted = Scalar.create(); 55 | nodesJustDeleted.set(false); 56 | Scalar activeNodesLeft = Scalar.create(); 57 | activeNodesLeft.set(true); 58 | 59 | kcore.setAll(0L); 60 | active.setAll(true); 61 | justDeleted.setAll(false); 62 | activeNbrs.setAll(v -> v.getOutDegree() + v.getInDegree()); 63 | 64 | while (currentKcore.get() <= maxCore && activeNodesLeft.get()) { 65 | do { 66 | activeNodesLeft.set(false); 67 | nodesJustDeleted.set(false); 68 | 69 | // Notify neighbors that vertex is deleted 70 | g.getVertices().filter(justDeleted).forEach(n -> { 71 | //n.getOutNeighbors().forEach(v -> activeNbrs.decrement(v)); 72 | n.getOutNeighbors().forEach(activeNbrs::decrement); 73 | n.getInNeighbors().forEach(activeNbrs::decrement); 74 | }); 75 | 76 | // Consolidate 77 | g.getVertices().filter(active).forEach(n -> { 78 | if (justDeleted.get(n)) { 79 | justDeleted.set(n, false); 80 | active.set(n, false); 81 | } else if (activeNbrs.get(n) < currentKcore.get()) { 82 | justDeleted.set(n, true); 83 | kcore.set(n, currentKcore.get() - 1); 84 | activeNodesLeft.reduceOr(true); 85 | nodesJustDeleted.reduceOr(true); 86 | } else { 87 | activeNodesLeft.reduceOr(true); 88 | } 89 | }); 90 | } while (nodesJustDeleted.get()); 91 | currentKcore.increment(); 92 | } 93 | 94 | return currentKcore.get() - 2; 95 | } 96 | } 97 | ``` 98 | -------------------------------------------------------------------------------- /graphviz-demo/.gitignore: -------------------------------------------------------------------------------- 1 | src/main/resources/public/alta.css 2 | src/main/resources/public/index.d.ts 3 | src/main/resources/public/index.js 4 | Thumbs.db 5 | .DS_Store 6 | .gradle 7 | build/ 8 | target/ 9 | out/ 10 | .micronaut/ 11 | .idea 12 | *.iml 13 | *.ipr 14 | *.iws 15 | .project 16 | .settings 17 | .classpath 18 | .factorypath 19 | -------------------------------------------------------------------------------- /graphviz-demo/README.md: -------------------------------------------------------------------------------- 1 | # Oracle Graph Visualization Demo Application 2 | 3 | An example Java web application based on [Micronaut](https://docs.micronaut.io/) which embeds Oracle's Graph 4 | Visualization library. The server queries the graph data from an Oracle Database using 5 | SQL. 6 | 7 | The key source files to look at are 8 | 9 | * `src/main/resources/public/index.html`: the HTML file served in the browser embedding the visualization library 10 | * `src/main/java/com/oracle/example/HRController.java`: implements the REST endpoints called by `index.html` 11 | * `src/main/java/com/oracle/example/GraphClient.java`: wraps the graph server APIs, called by HRController 12 | 13 | 14 | ## Pre-requisites 15 | 16 | 1. Oracle JDK 11 (or OpenJDK 11) 17 | 2. A running Oracle Database, version 23.4 or newer (e.g. [Autonomous Database](https://www.oracle.com/autonomous-database/)) 18 | 3. Import the Human Resources dataset and create a Property Graph by running `./gradlew createHrDatasetAndPropertyGraph -Pjdbc_url= -Pusername= -Ppassword=` 19 | 20 | * Note: The user must have `GRANT CREATE SESSION, CREATE TABLE, CREATE VIEW, CREATE SEQUENCE grants on the Database` 21 | * Note 2: You can drop the HR dataset and the created Property Graph by running the following command: `./gradlew dropHrDatasetAndPropertyGraph -Pjdbc_url= -Pusername= -Ppassword=` 22 | 23 | ## Usage 24 | 25 | 1. Clone this repository 26 | 2. Download the "Oracle Graph Visualization library" [from oracle.com](https://www.oracle.com/database/technologies/spatialandgraph/property-graph-features/graph-server-and-client/graph-server-and-client-downloads.html) 27 | 3. Unzip the library into the `src/main/resources/public` directory. For example: 28 | 29 | ``` 30 | unzip oracle-graph-visualization-library-24.2.0.zip -d src/main/resources/public/ 31 | ``` 32 | 33 | 4. Run the following command to start the example app locally: 34 | 35 | ``` 36 | ./gradlew run --args='-oracle.jdbc-url= -oracle.username= -oracle.password=' 37 | ``` 38 | 39 | with 40 | 41 | * `` being the JDBC URL of the Oracle Database should connect to, e.g. `jdbc:oracle:thin:@myhost:1521/orcl` 42 | * `` being the Oracle Database username to authenticate the example application, e.g. `scott` 43 | * `` being the Oracle Database password to authenticate the example application, e.g. `tiger` 44 | 45 | Then open your browser at `http://localhost:8080`. 46 | 47 | When you click on the Query button, a request is made to `/hr/directs`, which fetches the direct reports of 48 | the given employee (by default `SKING`) from the HR graph using a SQL query. 49 | 50 | ![](screenshot.jpg) 51 | 52 | When you right-click on one of the resulting nodes and then select Expand, a request to `/hr/neighbors` is being 53 | made, which fetches the neighbors of that node via another SQL query. 54 | 55 | ## Troubleshooting 56 | 57 | If you get any errors, 58 | * check the log output from the server on the terminal where the Gradle command is running 59 | * use browser debug tools (e.g. Chrome Developer Tools) to inspect request/response and console logs -------------------------------------------------------------------------------- /graphviz-demo/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.github.johnrengelman.shadow") version "7.1.2" 3 | id("io.micronaut.application") version "3.6.3" 4 | } 5 | 6 | version = "0.1" 7 | group = "com.oracle.example" 8 | 9 | ext { 10 | jdbc_url = project.findProperty('jdbc_url') 11 | username = project.findProperty('username') 12 | password = project.findProperty('password') 13 | } 14 | 15 | repositories { 16 | mavenCentral() 17 | maven { url "https://artifacts.metaborg.org/content/repositories/releases" } 18 | maven { url "https://artifacts.metaborg.org/content/repositories/usethesource/" } 19 | } 20 | 21 | dependencies { 22 | annotationProcessor("io.micronaut:micronaut-http-validation") 23 | implementation("io.micronaut:micronaut-http-client") 24 | implementation("io.micronaut:micronaut-jackson-databind") 25 | implementation("jakarta.annotation:jakarta.annotation-api") 26 | runtimeOnly("ch.qos.logback:logback-classic") 27 | compileOnly("org.graalvm.nativeimage:svm") 28 | 29 | implementation("io.micronaut:micronaut-validation") 30 | implementation("com.oracle.database.graph:opg-client:23.1.0") 31 | implementation("commons-io:commons-io:2.11.0") 32 | } 33 | 34 | application { 35 | mainClass.set("com.oracle.example.Application") 36 | } 37 | java { 38 | sourceCompatibility = JavaVersion.toVersion("11") 39 | targetCompatibility = JavaVersion.toVersion("11") 40 | } 41 | 42 | graalvmNative.toolchainDetection = false 43 | micronaut { 44 | runtime("netty") 45 | testRuntime("junit5") 46 | processing { 47 | incremental(true) 48 | annotations("com.oracle.example.*") 49 | } 50 | } 51 | 52 | task createHrDataSetAndPropertyGraph(type: JavaExec) { 53 | outputs.upToDateWhen { false } 54 | 55 | environment("JDBC_URL", jdbc_url) 56 | environment("USERNAME", username) 57 | environment("PASSWORD", password) 58 | mainClass.set("com.oracle.scripts.RunCreateScripts") 59 | classpath = sourceSets.main.runtimeClasspath 60 | } 61 | 62 | task dropHrDataSetAndPropertyGraph(type: JavaExec) { 63 | outputs.upToDateWhen { false } 64 | 65 | environment("JDBC_URL", jdbc_url) 66 | environment("USERNAME", username) 67 | environment("PASSWORD", password) 68 | mainClass.set("com.oracle.scripts.RunDropScripts") 69 | classpath = sourceSets.main.runtimeClasspath 70 | } 71 | 72 | 73 | -------------------------------------------------------------------------------- /graphviz-demo/gradle.properties: -------------------------------------------------------------------------------- 1 | micronautVersion=3.7.3 2 | -------------------------------------------------------------------------------- /graphviz-demo/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-samples/pgx-samples/f8b4ea6c4db5f0362283e73afba1036a08695305/graphviz-demo/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /graphviz-demo/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /graphviz-demo/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if %ERRORLEVEL% equ 0 goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if %ERRORLEVEL% equ 0 goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | set EXIT_CODE=%ERRORLEVEL% 84 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 85 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 86 | exit /b %EXIT_CODE% 87 | 88 | :mainEnd 89 | if "%OS%"=="Windows_NT" endlocal 90 | 91 | :omega 92 | -------------------------------------------------------------------------------- /graphviz-demo/micronaut-cli.yml: -------------------------------------------------------------------------------- 1 | applicationType: default 2 | defaultPackage: com.oracle.example 3 | testFramework: junit 4 | sourceLanguage: java 5 | buildTool: gradle 6 | features: [annotation-api, app-name, graalvm, gradle, http-client, jackson-databind, java, java-application, junit, logback, micronaut-build, netty-server, readme, shade, yaml] 7 | -------------------------------------------------------------------------------- /graphviz-demo/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-samples/pgx-samples/f8b4ea6c4db5f0362283e73afba1036a08695305/graphviz-demo/screenshot.jpg -------------------------------------------------------------------------------- /graphviz-demo/settings.gradle: -------------------------------------------------------------------------------- 1 | 2 | rootProject.name="graphviz-demo" 3 | 4 | -------------------------------------------------------------------------------- /graphviz-demo/src/main/java/com/oracle/example/Application.java: -------------------------------------------------------------------------------- 1 | package com.oracle.example; 2 | 3 | import io.micronaut.runtime.Micronaut; 4 | 5 | public class Application { 6 | public static void main(String[] args) { 7 | Micronaut.run(Application.class, args); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /graphviz-demo/src/main/java/com/oracle/example/GraphClient.java: -------------------------------------------------------------------------------- 1 | package com.oracle.example; 2 | 3 | import java.nio.charset.StandardCharsets; 4 | import java.sql.Connection; 5 | import java.sql.DriverManager; 6 | import java.sql.PreparedStatement; 7 | import java.sql.ResultSet; 8 | 9 | import io.micronaut.context.annotation.Value; 10 | import io.micronaut.http.client.HttpClient; 11 | import jakarta.inject.Singleton; 12 | 13 | import org.apache.commons.io.IOUtils; 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | 17 | /** 18 | * Micronaut client wrapper around Oracle Graph Visualization REST endpoints. 19 | * See the Oracle Graph documentation 20 | * for details about that API: 21 | * 22 | * https://docs.oracle.com/en/database/oracle/property-graph/22.4/spgdg/rest-endpoints-graph-visualization-application.html 23 | */ 24 | @Singleton 25 | public class GraphClient { 26 | 27 | private static Logger log = LoggerFactory.getLogger(GraphClient.class); 28 | 29 | HttpClient httpClient; 30 | 31 | @Value("${oracle.jdbc-url}") 32 | String jdbcUrl; 33 | 34 | @Value("${oracle.username}") 35 | String username; 36 | 37 | @Value("${oracle.password}") 38 | String password; 39 | 40 | private static final String anonymousFunction; 41 | 42 | static { 43 | try { 44 | anonymousFunction = IOUtils.toString( 45 | GraphClient.class.getResourceAsStream("/my_sqlgraph_json.sql"), 46 | StandardCharsets.UTF_8); 47 | } catch (Exception e) { 48 | log.error("Cannot locate anonymous function file"); 49 | throw new RuntimeException(e); 50 | } 51 | } 52 | 53 | public String query(String query, String parameter) throws Exception { 54 | 55 | String wrapQuery = anonymousFunction + "SELECT MY_SQLGRAPH_JSON('" + query + "') as result from dual"; 56 | String resultString = null; 57 | try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password)) { 58 | try (PreparedStatement ps = conn.prepareStatement(wrapQuery)) { 59 | ps.setString(1, parameter); 60 | log.info("running: {}", wrapQuery); 61 | log.info("replaced parameter: {}", parameter); 62 | try (ResultSet resultSet = ps.executeQuery()) { 63 | if (resultSet.next()) { 64 | resultString = resultSet.getString(1); 65 | } 66 | } 67 | } 68 | } 69 | return resultString; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /graphviz-demo/src/main/java/com/oracle/example/HRController.java: -------------------------------------------------------------------------------- 1 | package com.oracle.example; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.Collectors; 5 | 6 | import io.micronaut.http.HttpRequest; 7 | import io.micronaut.http.HttpResponse; 8 | import io.micronaut.http.MediaType; 9 | import io.micronaut.http.annotation.Controller; 10 | import io.micronaut.http.annotation.Get; 11 | import io.micronaut.http.annotation.Error; 12 | import io.micronaut.http.annotation.Produces; 13 | import io.micronaut.http.annotation.QueryValue; 14 | import io.micronaut.http.hateoas.JsonError; 15 | import io.micronaut.http.hateoas.Link; 16 | import io.micronaut.web.router.exceptions.UnsatisfiedQueryValueRouteException; 17 | import org.slf4j.Logger; 18 | import org.slf4j.LoggerFactory; 19 | 20 | @Controller("/hr") 21 | public class HRController { 22 | 23 | private static Logger log = LoggerFactory.getLogger(HRController.class); 24 | 25 | GraphClient graphClient; 26 | 27 | public HRController(GraphClient graphClient) { 28 | this.graphClient = graphClient; 29 | } 30 | 31 | @Get("/directs") 32 | @Produces(MediaType.APPLICATION_JSON) 33 | public String getDirects(@QueryValue String email) throws Exception { 34 | String query = "SELECT * FROM GRAPH_TABLE(\n" 35 | + "MYHR\n" 36 | + "MATCH (m)-[e]->(n IS employees WHERE n.email =''' || ? ||''')\n" 37 | + "COLUMNS (vertex_id(m) as m_id, edge_id(e) as e_id, vertex_id(n) as n_id)\n" 38 | + ")"; 39 | return graphClient.query(query, email); 40 | } 41 | 42 | @Get("/neighbors") 43 | @Produces(MediaType.APPLICATION_JSON) 44 | public String getNeighbors(@QueryValue String ids) throws Exception { 45 | ids = Arrays.stream(ids.split(",")).map(String::trim).collect(Collectors.joining("','")); 46 | String query = "SELECT * FROM GRAPH_TABLE(\n" 47 | + "MYHR\n" 48 | + "MATCH (m)-[e]->(n)\n" 49 | + "WHERE JSON_value(vertex_id(m), ''$.ELEM_TABLE'') || json_query(vertex_id(m), ''$.KEY_VALUE'' returning varchar2) in (''' || ? || ''') \n" 50 | + "COLUMNS (vertex_id(m) as m_id, edge_id(e) as e_id, vertex_id(n) as n_id)\n" 51 | + ")"; 52 | return graphClient.query(query, ids); 53 | } 54 | 55 | @Error(global = true) 56 | public HttpResponse error(HttpRequest request, Throwable e) { 57 | log.error("processing exception {}", e.getMessage(), e); 58 | JsonError error = new JsonError(e.getMessage()).link(Link.SELF, Link.of(request.getUri())); 59 | if (e.getClass() == IllegalArgumentException.class || e.getClass() == UnsatisfiedQueryValueRouteException.class) { 60 | return HttpResponse.badRequest().body(error); 61 | } 62 | return HttpResponse.serverError().body(error); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /graphviz-demo/src/main/java/com/oracle/example/response/Response.java: -------------------------------------------------------------------------------- 1 | package com.oracle.example.response; 2 | 3 | import java.util.List; 4 | 5 | public class Response { 6 | private List results; 7 | 8 | public void setResults(List results) { 9 | this.results = results; 10 | } 11 | 12 | public List getResults() { 13 | return this.results; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /graphviz-demo/src/main/java/com/oracle/example/response/Result.java: -------------------------------------------------------------------------------- 1 | package com.oracle.example.response; 2 | 3 | public class Result { 4 | private String pgqlStatement; 5 | private String result; 6 | private boolean success; 7 | private Object error; 8 | private String started; 9 | private String ended; 10 | 11 | public void setPgqlStatement(String pgqlStatement) { 12 | this.pgqlStatement = pgqlStatement; 13 | } 14 | 15 | public void setResult(String result) { 16 | this.result = result; 17 | } 18 | 19 | public void setSuccess(boolean success) { 20 | this.success = success; 21 | } 22 | 23 | public void setError(Object error) { 24 | this.error = error; 25 | } 26 | 27 | public void setStarted(String started) { 28 | this.started = started; 29 | } 30 | 31 | public void setEnded(String ended) { 32 | this.ended = ended; 33 | } 34 | 35 | public String getPgqlStatement() { 36 | return this.pgqlStatement; 37 | } 38 | 39 | public String getResult() { 40 | return this.result; 41 | } 42 | 43 | public boolean getSuccess() { 44 | return this.success; 45 | } 46 | 47 | public Object getError() { 48 | return this.error; 49 | } 50 | 51 | public String getStarted() { 52 | return this.started; 53 | } 54 | 55 | public String getEnded() { 56 | return this.ended; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /graphviz-demo/src/main/java/com/oracle/example/response/TokenResponse.java: -------------------------------------------------------------------------------- 1 | package com.oracle.example.response; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | public class TokenResponse { 6 | @JsonProperty("access_token") 7 | private String accessToken; 8 | 9 | @JsonProperty("token_type") 10 | private String tokenType; 11 | 12 | @JsonProperty("expires_in") 13 | private int expiresIn; 14 | 15 | public String getAccessToken() { 16 | return accessToken; 17 | } 18 | 19 | public String getTokenType() { 20 | return tokenType; 21 | } 22 | 23 | public int getExpiresIn() { 24 | return expiresIn; 25 | } 26 | 27 | public void setAccessToken(String accessToken) { 28 | this.accessToken = accessToken; 29 | } 30 | 31 | public void setTokenType(String tokenType) { 32 | this.tokenType = tokenType; 33 | } 34 | 35 | public void setExpiresIn(int expiresIn) { 36 | this.expiresIn = expiresIn; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /graphviz-demo/src/main/java/com/oracle/scripts/RunCreateScripts.java: -------------------------------------------------------------------------------- 1 | package com.oracle.scripts; 2 | 3 | import org.apache.commons.io.IOUtils; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import java.io.BufferedReader; 8 | import java.io.InputStream; 9 | import java.io.InputStreamReader; 10 | import java.nio.charset.StandardCharsets; 11 | import java.sql.Connection; 12 | import java.sql.DriverManager; 13 | import java.sql.SQLException; 14 | import java.sql.Statement; 15 | 16 | public class RunCreateScripts { 17 | 18 | private static final Logger LOG = LoggerFactory.getLogger(RunCreateScripts.class); 19 | 20 | private static final String JDBC_URL = getEnvValue("JDBC_URL"); 21 | 22 | private static final String USERNAME = getEnvValue("USERNAME"); 23 | 24 | private static final String PASSWORD = getEnvValue("PASSWORD"); 25 | 26 | private static final int TABLE_ALREADY_EXISTS = 1950; 27 | 28 | private static final int ORA_NAME_IS_ALREADY_USED = 955; //ORA-00955: name is already used by an existing object\ 29 | 30 | private static String getEnvValue(String envName) { 31 | String property = System.getenv(envName); 32 | if (property == null) { 33 | throw new IllegalArgumentException(envName + " not set"); 34 | } 35 | return property; 36 | } 37 | 38 | public static void main(String[] args) throws Exception { 39 | createHrTables(); 40 | createHrPg(); 41 | } 42 | 43 | private static void createHrTables() throws Exception { 44 | try (Connection conn = DriverManager.getConnection(JDBC_URL, USERNAME, PASSWORD)) { 45 | StringBuilder buffer = new StringBuilder(); 46 | InputStream is = RunCreateScripts.class.getResourceAsStream("/dataset_property_graph/create_hr_dataset.sql"); 47 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); 48 | String line; 49 | while ((line = bufferedReader.readLine()) != null) { 50 | String sql = line.trim(); 51 | try (Statement stmt = conn.createStatement()) { 52 | LOG.info("Creating test data || {}", sql); 53 | try { 54 | stmt.execute(sql); 55 | } catch (SQLException e) { 56 | if (e.getErrorCode() == TABLE_ALREADY_EXISTS || e.getErrorCode() == ORA_NAME_IS_ALREADY_USED) { 57 | LOG.info("Table already exists, just ignored."); 58 | } else { 59 | throw e; 60 | } 61 | } 62 | buffer.setLength(0); 63 | } 64 | } 65 | } 66 | } 67 | 68 | private static void createHrPg() throws Exception { 69 | try (Connection conn = DriverManager.getConnection(JDBC_URL, USERNAME, PASSWORD)) { 70 | executeSqlScripts(conn, "/dataset_property_graph/create_hr_property_graph.sql"); 71 | } 72 | } 73 | 74 | private static void executeSqlScripts(Connection conn, String sqlFile) throws Exception { 75 | String script = IOUtils.toString(RunCreateScripts.class.getResourceAsStream(sqlFile), StandardCharsets.UTF_8); 76 | LOG.info("Executing statements {}", script); 77 | try { 78 | conn.createStatement().execute(script); 79 | } catch (SQLException e) { 80 | LOG.info(e.getMessage()); 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /graphviz-demo/src/main/java/com/oracle/scripts/RunDropScripts.java: -------------------------------------------------------------------------------- 1 | package com.oracle.scripts; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.InputStream; 8 | import java.io.InputStreamReader; 9 | import java.nio.charset.StandardCharsets; 10 | import java.sql.Connection; 11 | import java.sql.DriverManager; 12 | import java.sql.SQLException; 13 | import java.sql.Statement; 14 | 15 | public class RunDropScripts { 16 | 17 | private static final Logger LOG = LoggerFactory.getLogger(RunDropScripts.class); 18 | 19 | private static final String JDBC_URL = getEnvValue("JDBC_URL"); 20 | 21 | private static final String USERNAME = getEnvValue("USERNAME"); 22 | 23 | private static final String PASSWORD = getEnvValue("PASSWORD"); 24 | 25 | private static final int TABLE_OR_VIEW_DOES_NOT_EXISTS = 942; 26 | 27 | private static final int SEQUENCE_DOES_NOT_EXISTS = 2289; 28 | 29 | private static String getEnvValue(String envName) { 30 | String property = System.getenv(envName); 31 | if (property == null) { 32 | throw new IllegalArgumentException(envName + " not set"); 33 | } 34 | return property; 35 | } 36 | 37 | public static void main(String[] args) throws Exception { 38 | dropHrPg(); 39 | dropHrTables(); 40 | } 41 | 42 | private static void dropHrTables() throws Exception { 43 | try (Connection conn = DriverManager.getConnection(JDBC_URL, USERNAME, PASSWORD)) { 44 | StringBuilder buffer = new StringBuilder(); 45 | InputStream is = RunDropScripts.class.getResourceAsStream("/dataset_property_graph/drop_hr.sql"); 46 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); 47 | String line; 48 | while ((line = bufferedReader.readLine()) != null) { 49 | String sql = line.trim(); 50 | try (Statement stmt = conn.createStatement()) { 51 | LOG.info("Dropping test data || {}", sql); 52 | try { 53 | stmt.execute(sql); 54 | } catch (SQLException e) { 55 | if (e.getErrorCode() == TABLE_OR_VIEW_DOES_NOT_EXISTS || e.getErrorCode() == SEQUENCE_DOES_NOT_EXISTS) { 56 | LOG.info("Table, view or sequence doest not exists, just ignored."); 57 | } else { 58 | throw e; 59 | } 60 | } 61 | buffer.setLength(0); 62 | } 63 | } 64 | } 65 | } 66 | 67 | private static void dropHrPg() throws Exception { 68 | try (Connection conn = DriverManager.getConnection(JDBC_URL, USERNAME, PASSWORD)) { 69 | String dropPg = "DROP PROPERTY GRAPH MYHR"; 70 | LOG.info("Dropping test data || {}", dropPg); 71 | try { 72 | conn.createStatement().execute(dropPg); 73 | } catch (SQLException e) { 74 | LOG.info(e.getMessage()); 75 | } 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /graphviz-demo/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | application: 3 | name: graphvizDemo 4 | http: 5 | client: 6 | read-timeout: 2m 7 | router: 8 | static-resources: 9 | default: 10 | enabled: true 11 | paths: classpath:public 12 | netty: 13 | default: 14 | allocator: 15 | max-order: 3 16 | -------------------------------------------------------------------------------- /graphviz-demo/src/main/resources/dataset_property_graph/create_hr_property_graph.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE PROPERTY GRAPH myhr 2 | VERTEX TABLES ( 3 | countries 4 | KEY ( country_id ) 5 | PROPERTIES ( country_id, country_name, region_id ), 6 | departments 7 | KEY ( department_id ) 8 | PROPERTIES ( department_id, department_name, location_id, manager_id ), 9 | locations 10 | KEY ( location_id ) 11 | PROPERTIES ( city, country_id, location_id, postal_code, state_province, street_address ), 12 | jobs 13 | KEY ( job_id ) 14 | PROPERTIES ( job_id, job_title, max_salary, min_salary ), 15 | employees 16 | KEY ( employee_id ) 17 | PROPERTIES ( commission_pct, department_id, email, employee_id, first_name, hire_date, job_id, last_name, manager_id, phone_number, salary ), 18 | regions 19 | KEY ( region_id ) 20 | PROPERTIES ( region_id, region_name ) 21 | ) 22 | EDGE TABLES ( 23 | countries AS countries_regions 24 | SOURCE KEY ( country_id ) REFERENCES countries ( country_id ) 25 | DESTINATION KEY ( region_id ) REFERENCES regions ( region_id ) 26 | NO PROPERTIES, 27 | departments AS departments_employees 28 | SOURCE KEY ( department_id ) REFERENCES departments ( department_id ) 29 | DESTINATION KEY ( manager_id ) REFERENCES employees ( employee_id ) 30 | NO PROPERTIES, 31 | departments AS departments_locations 32 | SOURCE KEY ( department_id ) REFERENCES departments ( department_id ) 33 | DESTINATION KEY ( location_id ) REFERENCES locations ( location_id ) 34 | NO PROPERTIES, 35 | locations AS locations_countries 36 | SOURCE KEY ( location_id ) REFERENCES locations ( location_id ) 37 | DESTINATION KEY ( country_id ) REFERENCES countries ( country_id ) 38 | NO PROPERTIES, 39 | employees AS employees_jobs 40 | SOURCE KEY ( employee_id ) REFERENCES employees ( employee_id ) 41 | DESTINATION KEY ( job_id ) REFERENCES jobs ( job_id ) 42 | NO PROPERTIES, 43 | employees AS employees_departments 44 | SOURCE KEY ( employee_id ) REFERENCES employees ( employee_id ) 45 | DESTINATION KEY ( department_id ) REFERENCES departments ( department_id ) 46 | NO PROPERTIES, 47 | employees AS employees_employees 48 | SOURCE KEY ( employee_id ) REFERENCES employees ( employee_id ) 49 | DESTINATION KEY ( manager_id ) REFERENCES employees ( employee_id ) 50 | NO PROPERTIES 51 | ) -------------------------------------------------------------------------------- /graphviz-demo/src/main/resources/dataset_property_graph/drop_hr.sql: -------------------------------------------------------------------------------- 1 | DROP VIEW emp_details_view 2 | DROP SEQUENCE departments_seq 3 | DROP SEQUENCE employees_seq 4 | DROP SEQUENCE locations_seq 5 | DROP TABLE regions CASCADE CONSTRAINTS 6 | DROP TABLE departments CASCADE CONSTRAINTS 7 | DROP TABLE locations CASCADE CONSTRAINTS 8 | DROP TABLE jobs CASCADE CONSTRAINTS 9 | DROP TABLE job_history CASCADE CONSTRAINTS 10 | DROP TABLE employees CASCADE CONSTRAINTS 11 | DROP TABLE countries CASCADE CONSTRAINTS 12 | COMMIT -------------------------------------------------------------------------------- /graphviz-demo/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | 7 | 8 | %cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /graphviz-demo/src/main/resources/my_sqlgraph_json.sql: -------------------------------------------------------------------------------- 1 | WITH 2 | FUNCTION MY_SQLGRAPH_JSON ( 3 | QUERY VARCHAR2, 4 | PAGE_START NUMBER DEFAULT NULL, 5 | PAGE_SIZE NUMBER DEFAULT NULL 6 | ) RETURN CLOB 7 | IS 8 | INCUR SYS_REFCURSOR; 9 | L_CUR NUMBER; 10 | RETVALUE CLOB; 11 | BEGIN 12 | OPEN INCUR FOR QUERY; 13 | L_CUR := DBMS_SQL.TO_CURSOR_NUMBER(INCUR); 14 | RETVALUE := ORA_SQLGRAPH_TO_JSON(L_CUR, PAGE_START, PAGE_SIZE); 15 | DBMS_SQL.CLOSE_CURSOR(L_CUR); 16 | RETURN RETVALUE; 17 | END; 18 | 19 | -------------------------------------------------------------------------------- /graphviz-demo/src/main/resources/pgview_dataset/create_hr_pgview.pgql: -------------------------------------------------------------------------------- 1 | CREATE PROPERTY GRAPH myhr 2 | VERTEX TABLES ( 3 | countries 4 | KEY ( country_id ) 5 | PROPERTIES ( country_id, country_name, region_id ), 6 | departments 7 | KEY ( department_id ) 8 | PROPERTIES ( department_id, department_name, location_id, manager_id ), 9 | locations 10 | KEY ( location_id ) 11 | PROPERTIES ( city, country_id, location_id, postal_code, state_province, street_address ), 12 | jobs 13 | KEY ( job_id ) 14 | PROPERTIES ( job_id, job_title, max_salary, min_salary ), 15 | employees 16 | KEY ( employee_id ) 17 | PROPERTIES ( commission_pct, department_id, email, employee_id, first_name, hire_date, job_id, last_name, manager_id, phone_number, salary ), 18 | regions 19 | KEY ( region_id ) 20 | PROPERTIES ( region_id, region_name ) 21 | ) 22 | EDGE TABLES ( 23 | countries AS countries_regions 24 | SOURCE KEY ( country_id ) REFERENCES countries 25 | DESTINATION KEY ( region_id ) REFERENCES regions 26 | NO PROPERTIES, 27 | departments AS departments_employees 28 | SOURCE KEY ( department_id ) REFERENCES departments 29 | DESTINATION KEY ( manager_id ) REFERENCES employees 30 | NO PROPERTIES, 31 | departments AS departments_locations 32 | SOURCE KEY ( department_id ) REFERENCES departments 33 | DESTINATION KEY ( location_id ) REFERENCES locations 34 | NO PROPERTIES, 35 | locations AS locations_countries 36 | SOURCE KEY ( location_id ) REFERENCES locations 37 | DESTINATION KEY ( country_id ) REFERENCES countries 38 | NO PROPERTIES, 39 | employees AS employees_jobs 40 | SOURCE KEY ( employee_id ) REFERENCES employees 41 | DESTINATION KEY ( job_id ) REFERENCES jobs 42 | NO PROPERTIES, 43 | employees AS employees_departments 44 | SOURCE KEY ( employee_id ) REFERENCES employees 45 | DESTINATION KEY ( department_id ) REFERENCES departments 46 | NO PROPERTIES, 47 | employees AS employees_employees 48 | SOURCE KEY ( employee_id ) REFERENCES employees 49 | DESTINATION KEY ( manager_id ) REFERENCES employees 50 | NO PROPERTIES 51 | ) 52 | OPTIONS(PG_VIEW) 53 | -------------------------------------------------------------------------------- /graphviz-demo/src/main/resources/pgview_dataset/drop_hr.sql: -------------------------------------------------------------------------------- 1 | DROP VIEW emp_details_view 2 | DROP SEQUENCE departments_seq 3 | DROP SEQUENCE employees_seq 4 | DROP SEQUENCE locations_seq 5 | DROP TABLE regions CASCADE CONSTRAINTS 6 | DROP TABLE departments CASCADE CONSTRAINTS 7 | DROP TABLE locations CASCADE CONSTRAINTS 8 | DROP TABLE jobs CASCADE CONSTRAINTS 9 | DROP TABLE job_history CASCADE CONSTRAINTS 10 | DROP TABLE employees CASCADE CONSTRAINTS 11 | DROP TABLE countries CASCADE CONSTRAINTS 12 | COMMIT -------------------------------------------------------------------------------- /graphviz-demo/src/main/resources/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Oracle Graph Visualization Example 8 | 9 | 10 | 11 | 12 | 13 | 92 | 93 | 94 |
95 |
96 |

Human Resources Visualization

97 |
98 | 99 | 100 | 101 |
102 |
103 |
104 | 107 |
108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 |
116 |
117 |
118 |
119 | 120 | 121 | -------------------------------------------------------------------------------- /graphviz-demo/src/main/resources/public/styles.css: -------------------------------------------------------------------------------- 1 | html, 2 | body, 3 | #graphviz { 4 | height: 100%; 5 | } 6 | 7 | body { 8 | margin: 0; 9 | padding: 8px; 10 | box-sizing: border-box; 11 | font-family: 'Tahoma', sans-serif; 12 | } 13 | 14 | .container { 15 | display: flex; 16 | flex-wrap: wrap; 17 | } 18 | 19 | .example { 20 | flex: 1 1 auto; 21 | } 22 | 23 | #visualization { 24 | display: none; 25 | margin-top: 1em; 26 | } -------------------------------------------------------------------------------- /graphviz-demo/src/test/java/com/oracle/example/GraphvizDemoTest.java: -------------------------------------------------------------------------------- 1 | package com.oracle.example; 2 | 3 | import io.micronaut.runtime.EmbeddedApplication; 4 | import io.micronaut.test.extensions.junit5.annotation.MicronautTest; 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.Assertions; 7 | 8 | import jakarta.inject.Inject; 9 | 10 | @MicronautTest 11 | class GraphvizDemoTest { 12 | 13 | @Inject 14 | EmbeddedApplication application; 15 | 16 | @Test 17 | void testItWorks() { 18 | Assertions.assertTrue(application.isRunning()); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /pgql-graph-demos/bank-graph-rdbms-samples/CreateBankGraphDataset.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE BANK_TRANSFERS; 2 | DROP TABLE BANK_ACCOUNTS; 3 | 4 | -- create BANK ACCOUNTS table 5 | CREATE TABLE BANK_ACCOUNTS ( 6 | ID NUMBER, 7 | NAME VARCHAR(400), 8 | BALANCE NUMBER(20,2) 9 | ); 10 | 11 | -- create BANK_TRANSFERS table 12 | CREATE TABLE BANK_TRANSFERS ( 13 | TXN_ID NUMBER, 14 | SRC_ACCT_ID NUMBER, 15 | DST_ACCT_ID NUMBER, 16 | DESCRIPTION VARCHAR(400), 17 | AMOUNT NUMBER 18 | ); 19 | 20 | ALTER TABLE BANK_ACCOUNTS ADD PRIMARY KEY (ID); 21 | ALTER TABLE BANK_TRANSFERS ADD PRIMARY KEY (TXN_ID); 22 | ALTER TABLE BANK_TRANSFERS MODIFY SRC_ACCT_ID REFERENCES BANK_ACCOUNTS (ID); 23 | ALTER TABLE BANK_TRANSFERS MODIFY DST_ACCT_ID REFERENCES BANK_ACCOUNTS (ID); 24 | 25 | -- At this point, you should load the BANK_ACCOUNTS.csv and BANK_TRANSFERS.csv files into the BANK_ACCOUNTS and BANK_TRANSACTIONS tables respectively 26 | -------------------------------------------------------------------------------- /pgql-graph-demos/bank-graph-rdbms-samples/README.md: -------------------------------------------------------------------------------- 1 | # PGQL on RDBMS Samples 2 | 3 | Oracle Graph has the ability to run PGQL queries using the in memory server (PGX) or in database (RDBMS). This directory contains sample queries for using PGQL on RDBMS, using the Bank Graph Dataset. 4 | 5 | ## Prerequisites 6 | 1. SQL Developer 23.1 is installed 7 | 2. A graph enabled user exists in the connected database 8 | 9 | ## Load Bank Graph Dataset 10 | 1. Open SQL Developer 11 | 2. Create tables from Bank Graph Dataset, using CreateBankGraphDataset.sql 12 | 3. Load BANK_ACCOUNTS.csv into BANK_ACCOUNTS table 13 | 4. Load BANK_TRANSFERS.csv into BANK_TRANSFERS table 14 | 15 | ## Run Examples on a PGQL Worksheet 16 | 1. Open PGQL Worksheet 17 | 2. Copy Create Proprty Graph statement from bank-graph-pgql and run the statement 18 | 3. Copy and paste queries from bank-graph-pgql to PGQL worksheet 19 | 4. Highlight individual queries and run -------------------------------------------------------------------------------- /pgql-graph-demos/bank-graph-rdbms-samples/bank-graph-pgql: -------------------------------------------------------------------------------- 1 | DROP PROPERTY GRAPH BANK_GRAPH_PGQL; 2 | 3 | CREATE PROPERTY GRAPH BANK_GRAPH_PGQL 4 | VERTEX TABLES ( 5 | BANK_ACCOUNTS 6 | KEY ( ID ) 7 | LABEL accounts PROPERTIES ( ID, name ) 8 | ) 9 | EDGE TABLES ( 10 | BANK_TRANSFERS 11 | SOURCE KEY ( src_acct_id ) REFERENCES BANK_ACCOUNTS(ID) 12 | DESTINATION KEY ( dst_acct_id ) REFERENCES BANK_ACCOUNTS(ID) 13 | LABEL transfers PROPERTIES ( amount, description, src_acct_id, dst_acct_id, txn_id ) 14 | ) OPTIONS (PG_VIEW); 15 | 16 | -- Find the top 10 accounts by incoming transfers 17 | SELECT dst.id as acct_id, COUNT(1) AS Num_Transfers 18 | FROM MATCH (src) - [:TRANSFERS] -> (dst) 19 | ON BANK_GRAPH_PGQL 20 | GROUP BY dst.id ORDER BY Num_Transfers DESC FETCH FIRST 10 ROWS ONLY; 21 | 22 | -- Find the top 10 accounts in the middle of a 2-hop chain of transfers 23 | SELECT via.id AS acct_id, COUNT(1) AS Num_In_Middle 24 | FROM MATCH (src) - [:TRANSFERS] -> (via) - [:TRANSFERS] -> (dst) 25 | ON BANK_GRAPH_PGQL 26 | GROUP BY acct_id 27 | ORDER BY Num_In_Middle DESC 28 | FETCH FIRST 10 ROWS ONLY; 29 | 30 | -- List accounts that received a transfer from account 387 in 1, 2, or 3 hops 31 | SELECT v1.id AS account_id1, v2.id AS account_id2 32 | FROM MATCH (v1)-[:TRANSFERS]->{1,3}(v2) 33 | ON BANK_GRAPH_PGQL 34 | WHERE v1.id = 387; 35 | 36 | -- Check if there are any 3-hop (triangles) transfers that start and end at the same account 37 | SELECT src.id AS acct_id, COUNT(1) AS Num_Triangles 38 | FROM MATCH (src) - []->{3} (src) 39 | ON BANK_GRAPH_PGQL 40 | GROUP BY acct_id 41 | ORDER BY Num_Triangles DESC; 42 | 43 | -- Check if there are any 4-hop transfers that start and end at the same account 44 | SELECT src.id AS acct_id, COUNT(1) AS Num_4hop_Chains 45 | FROM MATCH (src) - []->{4} (src) 46 | ON BANK_GRAPH_PGQL 47 | GROUP BY acct_id 48 | ORDER BY Num_4hop_Chains DESC; 49 | 50 | -- Check if there are any 5-hop transfers that start and end at the same account 51 | SELECT src.id AS acct_id, COUNT(1) AS Num_5hop_Chains 52 | FROM MATCH (src) - []->{5} (src) 53 | ON BANK_GRAPH_PGQL 54 | GROUP BY acct_id 55 | ORDER BY Num_5hop_Chains DESC; 56 | 57 | -- List some (any 10) accounts which had a 3 to 5 hop circular payment chain 58 | SELECT DISTINCT(v1.id) AS account_id 59 | FROM MATCH (v1)-[:TRANSFERS]->{3,5}(v1) 60 | ON BANK_GRAPH_PGQL 61 | FETCH FIRST 10 ROWS ONLY; 62 | 63 | -- Query accounts by number of 3 to 5 hops cycles in descending order. Show top 10. 64 | SELECT DISTINCT(v1.id) AS account_id, COUNT(1) AS Num_Cycles 65 | FROM MATCH (v1)-[:TRANSFERS]->{3, 5}(v1) 66 | ON BANK_GRAPH_PGQL 67 | GROUP BY account_id 68 | ORDER BY Num_Cycles DESC 69 | FETCH FIRST 10 ROWS ONLY; -------------------------------------------------------------------------------- /pgql-graph-demos/bank-graph-rdbms-samples/license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. 2 | 3 | You may not use the identified files except in compliance with the Universal Permissive License. 4 | 5 | You may obtain a copy of the License at https://oss.oracle.com/licenses/upl/ 6 | --------------------------------------------------------------------------------