

Public Class PathsEntitiesAndRelationships
public class PathsEntitiesAndRelationships
{
//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);
});
}
{
//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'
});
}
{
//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 = FormatUID(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 FormatUID(string id)
{
id = id.ToUpperInvariant();
if (!id.StartsWith('{'))
id = '{' + id;
if (!id.EndsWith('}'))
id += '}';
return id;
}
{
//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 = "";
}
}
});
}
System.Object
ArcGIS.Core.Data.Knowledge.Analytics.PathsEntitiesAndRelationships
Target Platforms: Windows 11 Home, Pro, Enterprise (64 bit)