ArcGIS Pro 3.6 API Reference Guide
ArcGIS.Core.Data.Knowledge.Analytics Namespace / PathsEntitiesAndRelationships Class
Members Example

In This Topic
    PathsEntitiesAndRelationships Class
    In This Topic
    Represents entities and relationships used in paths.
    Object Model
    PathsEntitiesAndRelationships ClassKnowledgeGraphIDSet Class
    Syntax
    public class PathsEntitiesAndRelationships 
    Public Class PathsEntitiesAndRelationships 
    Example
    Create Link Chart from FFP Results
        //using ArcGIS.Core.Data.Knowledge.Extensions;
    
        await QueuedTask.Run(async() =>
        {
            var ffp_config = new CIMFilteredFindPathsConfiguration();
            ffp_config.Name = "Create Link Chart from FFP Results";
    //set up config
    //...
            
            var results = kg.RunFilteredFindPaths(ffp_config);
    
            var pathsEntitiesAndRelationships = results.ExtractPathsEntitiesAndRelationships(null);
    
            //Create a KG layer id set
            var kgLayerIdSet = KnowledgeGraphLayerIDSet.FromKnowledgeGraphIDSet(
                pathsEntitiesAndRelationships.ToKnowledgeGraphIDSet(
                    KGResultContentFromFFP.EntitiesAndRelationships));
    
            //Create a brand new link chart with the results and show it
            var linkChart = MapFactory.Instance.CreateLinkChart(
                                                "KG Intro", kg, kgLayerIdSet);
    
            var mapPane = await FrameworkApplication.Panes.CreateMapPaneAsync(linkChart);
            var linkChartView = mapPane.MapView;
    
            //Change layout algo to match the default used by the UI after FFP
            await linkChartView.SetLinkChartLayoutAsync(
                KnowledgeLinkChartLayoutAlgorithm.Hierarchical_TopToBottom);
    
            //Set root nodes - they correspond to the origin nodes of the result paths
            var kgLayerIdSetForRootNodes = KnowledgeGraphLayerIDSet.FromKnowledgeGraphIDSet(
                pathsEntitiesAndRelationships.ToKnowledgeGraphIDSet(
                    KGResultContentFromFFP.OnlyPathsOriginEntities));
    
            //To correctly identify the ids in the link chart we must change the ids
            //from Geodatabase oids returned in the KnowledgeGraphLayerIDSet to the
    //temporary/synthetic oids used by layers in the link chart...
            var kg_layer = linkChart.GetLayersAsFlattenedList().OfType<KnowledgeGraphLayer>().First();
            var mapMembers = kg_layer.GetMapMembersAsFlattenedList();
            var oidDict = kgLayerIdSetForRootNodes.ToOIDDictionary();
            var mmDict = new Dictionary<MapMember, List<long>>();
            foreach (var kvp in oidDict)
            {
                var named_type = kvp.Key;
                foreach (var mm in mapMembers)
                {
                    if (mm is LinkChartFeatureLayer fl_lc && fl_lc.IsEntity)
                    {
                        if (fl_lc.GetTypeName().ToLower() == named_type.ToLower())
                        {
                            var lc_oids = new List<long>();
                            //these oids are from the geodatabase
                            var oid_field = $"{fl_lc.GetTypeName()}.objectid";
                            var id_list = string.Join(',', kvp.Value.ToArray());
                            var where = $"{fl_lc.GetTypeName()}.objectid IN ({id_list})";
    
                            var qf = new ArcGIS.Core.Data.QueryFilter()
                            {
                                WhereClause = where,
                                SubFields = $"LC.OID,{oid_field}"//the 'LC.OID' oids are the ones
                                               //we need for the mapmember id set
                                               //in the link chart
                            };
                            var rc = fl_lc.Search(qf);
                            var oid_idx = rc.FindField(oid_field);
                            while (rc.MoveNext())
                            {
                                var oid = (long)rc.Current[oid_idx];
                                var lc_oid = rc.Current.GetObjectID();
                                lc_oids.Add(lc_oid);
                            }
                            rc.Dispose();
                            mmDict[fl_lc] = lc_oids;
                            break;
                        }
                    }
                }
            }
    
            var mmIdSet = MapMemberIDSet.FromDictionary(mmDict);
            linkChartView.SetRootNodes(mmIdSet);
        });
    Append to Link Chart from FFP Results
    //using ArcGIS.Core.Data.Knowledge.Extensions;
    
    var linkChartView = MapView.Active;
    
    await QueuedTask.Run(async () =>
    {
        var ffp_config = new CIMFilteredFindPathsConfiguration();
        ffp_config.Name = "Append to Link Chart from FFP Results";
        //set up config
        //...
    
        var results = kg.RunFilteredFindPaths(ffp_config);
    
        var pathsEntitiesAndRelationships = results.ExtractPathsEntitiesAndRelationships(null);
    
        //Create a KG layer id set
        var kgLayerIdSet = KnowledgeGraphLayerIDSet.FromKnowledgeGraphIDSet(
            pathsEntitiesAndRelationships.ToKnowledgeGraphIDSet(
                KGResultContentFromFFP.EntitiesAndRelationships));
    
        var map = linkChartView.Map;
    
        if (!map.CanAppendToLinkChart(kgLayerIdSet))
            return;//not compatible
    
        map.AppendToLinkChart(kgLayerIdSet);
        //switch layout algo
        var algo = linkChartView.GetLinkChartLayout();
        if (algo != KnowledgeLinkChartLayoutAlgorithm.Hierarchical_TopToBottom)
        {
            //Change layout algo to match the default used by the UI after FFP
            await linkChartView.SetLinkChartLayoutAsync(
                KnowledgeLinkChartLayoutAlgorithm.Hierarchical_TopToBottom);
        }
    
        //To set link chart root nodes see 'Create Link Chart from FFP Results'
    });
    List out FFP Results by Path Length, Min Cost, Max Cost
        //using ArcGIS.Core.Data.Knowledge.Extensions;
    
        await QueuedTask.Run(async () =>
        {
            var ffp_config = new CIMFilteredFindPathsConfiguration();
            ffp_config.Name = "List out FFP Results by Path Length, Min Cost, Max Cost";
            //set up config
            //...
    
            var results = kg.RunFilteredFindPaths(ffp_config);
    
            if (results.CountPaths == 0)
            {
                System.Diagnostics.Debug.WriteLine("FFP returned no paths");
                return;
            }
    
            //print out paths by increasing length, min cost, max cost
            var path_by_len_indices = (IEnumerable<long>)results.PathIndicesOrderedByIncreasingPathLength
                                .Select(idx => idx.index);
            var path_by_min_cost = (IEnumerable<long>)results.PathIndicesOrderedByIncreasingMinPathCost
                                .Select(idx => idx.index);
    var path_by_max_cost = (IEnumerable<long>)results.PathIndicesOrderedByIncreasingMaxPathCost
                                                            .Select(idx => idx.index);
    
    var x = 0;
            StringBuilder sb = new StringBuilder();
    
            foreach (var path_indeces in new List<IEnumerable<long>> {
      path_by_len_indices,
      path_by_min_cost,
      path_by_max_cost})
    {
      if (x == 0)
                    sb.AppendLine($"Paths by length: {path_by_len_indices.Count()}");
                else if (x == 1)
                    sb.AppendLine($"Paths by min cost: {path_by_min_cost.Count()}");
                else if (x == 2)
                    sb.AppendLine($"Paths by max cost: {path_by_max_cost.Count()}");
      x++;
                foreach (var path_idx in path_indeces)
      {
                        var path = (ResultPath)results.MaterializePath(path_idx);
                        sb.AppendLine(
              $"Path[{path_idx}] length: {path.Length}, min: {path.MinCost} max: {path.MaxCost}");
                    var g = 0;
                    foreach (var rel_group in path.RelationshipGroups)
                    {
                        var first_entity = $"({rel_group.FirstEntity.TypeName}:{rel_group.FirstEntity.Uid})";
                        var second_entity = $"({rel_group.SecondEntity.TypeName}:{rel_group.SecondEntity.Uid})";
    
                        foreach (var relation in rel_group.Relationships)
                        {
                            sb.Append($"  [{g++}] ");
                            var arrow = relation.SameDirectionAsPath ? "->" : "<-";
                            var rel_uid = FormatID(relation.Relationship.Uid.ToString());
                            sb.Append($"{first_entity} '\r\n\t{relation.Relationship.TypeName}:{rel_uid}' {arrow}\r\n" +
                                $"\t\t{second_entity}");
                            sb.Append($" cost: {relation.Relationship.Cost}\r\n");
                        }
                    }
                }
            }
    
        });
    
        string FormatID(string id)
        {
            id = id.ToUpperInvariant();
            if (!id.StartsWith('{'))
                id = '{' + id;
            if (!id.EndsWith('}'))
                id += '}';
            return id;
        }
    List out FFP Results Origin, Destination, Other Entities
    //using ArcGIS.Core.Data.Knowledge.Extensions;
    
    await QueuedTask.Run(async () =>
    {
        var ffp_config = new CIMFilteredFindPathsConfiguration();
        ffp_config.Name = "List out FFP Results Origin, Destination, Other Entities";
        //set up config
        //...
    
        var results = kg.RunFilteredFindPaths(ffp_config);
    
        if (results.CountPaths == 0)
        {
            System.Diagnostics.Debug.WriteLine("FFP returned no paths");
            return;
        }
    
        //print out paths by increasing length, min cost, max cost
        var path_by_len_indices = (IEnumerable<long>)results.PathIndicesOrderedByIncreasingPathLength
                                                                .Select(idx => idx.index);
        var path_by_min_cost = (IEnumerable<long>)results.PathIndicesOrderedByIncreasingMinPathCost
                                                                .Select(idx => idx.index);
        var path_by_max_cost = (IEnumerable<long>)results.PathIndicesOrderedByIncreasingMaxPathCost
                                                                .Select(idx => idx.index);
    
        var x = 0;
        StringBuilder sb = new StringBuilder();
    
        foreach (var path_indeces in new List<IEnumerable<long>> {
            path_by_len_indices,
            path_by_min_cost,
            path_by_max_cost})
        {
            if (x == 0)
                sb.AppendLine($"Entities by length: {path_by_len_indices.Count()}");
            else if (x == 1)
                sb.AppendLine($"Entities by min cost: {path_by_min_cost.Count()}");
            else if (x == 2)
                sb.AppendLine($"Entities by max cost: {path_by_max_cost.Count()}");
            x++;
            foreach (var path_idx in path_indeces)
            {
                var path = (ResultPath)results.MaterializePath(path_idx);
                sb.AppendLine(
                    $"Path[{path_idx}] length: {path.Length}, min: {path.MinCost} max: {path.MaxCost}");
    
                var sorted_set = new SortedSet<ulong>();
                sorted_set.Add((ulong)path_idx);
                var per = results.ExtractPathsEntitiesAndRelationships(sorted_set);
    
                var origin_dest_uids = new List<string>();
                var sep = "";
    
                sb.Append(" Origin EntitiesUIDs: ");
                foreach (var idx in per.PathsOriginEntitiesUIDsIndexes)
                {
                    //See 'List out FFP Results by Path Length, Min Cost, Max Cost' for
      //FormatID method above
                    var uid = FormatID(per.EntitiesUIDs[idx].ToString());
                    origin_dest_uids.Add(uid);
    
                    var origin =
                        $"{sep}{per.EntityTypeNames[per.EntityTypes[idx]]}:{uid}";
                    sep = ", ";
                    sb.Append($"{origin}");
                }
                sb.AppendLine("");
    
                sep = "";
                sb.Append(" Destination EntitiesUIDs: ");
                foreach (var idx in per.PathsDestinationEntitiesUIDsIndexes)
                {
                    var uid = FormatID(per.EntitiesUIDs[idx].ToString());
                    origin_dest_uids.Add(uid);
    
                    var dest =
                        $"{sep}{per.EntityTypeNames[per.EntityTypes[idx]]}:{uid}";
                    sep = ", ";
                    sb.Append($"{dest}");
                }
                sb.AppendLine("");
    
                sep = "";
                var idx2 = 0;
                sb.Append(" Other EntitiesUIDs: ");
                bool wereAnyOthers = false;
                foreach (var raw_uid in per.EntitiesUIDs)
                {
                    var uid = FormatID(raw_uid.ToString());
                    if (!origin_dest_uids.Contains(uid))
                    {
                        var other =
                        $"{sep}{per.EntityTypeNames[per.EntityTypes[idx2]]}:{uid}";
                        sep = ", ";
                        sb.Append($"{other}");
                        wereAnyOthers = true;
                    }
                    idx2++;
                }
                if (!wereAnyOthers)
                    sb.Append(" <<none>>");
    
                //sb.AppendLine("");
    
                var entity_str = sb.ToString();
                System.Diagnostics.Debug.WriteLine(entity_str);
    
                sb.Clear();
                sep = "";
            }
        }
    
    });
    
    Inheritance Hierarchy

    System.Object
       ArcGIS.Core.Data.Knowledge.Analytics.PathsEntitiesAndRelationships

    Requirements

    Target Platforms: Windows 11, Windows 10

    ArcGIS Pro version: 3.6 or higher.
    See Also