equinor / equinor/prisma-decision-api
non-requisite arcs and isolated nodes
- Dominant language
- C#
- Stars
- 3
- Forks
- 3
- Avg merge
- 1d 21h
- Merged PRs (30d)
- 29
Description
When creating a LIMID, some arcs may be non-requisite (not contributing to the MEU) and if removed (reducing the LIMID), some nodes may become isolated (neither parents nor children).
Having access to this gives a valuable feedback to the modeller: the LIMID may not represent the problem the modeller has in mind.
A way of doing this in pyagrum is by
```python
def non_requisit_arcs_and_isolated_nodes(
*,
limid: "gum.LIMID",
ie: "gum.LIMIDInferenceEngine" = None,
verbose=False
) -> tuple[list[dict], list[dict]]:
"""
This function identifies non-requisite arcs and isolated nodes in a given LIMID.
Args:
limid (gum.LIMID): The LIMID to analyze. Must be passed as a keyword argument.
ie (gum.LIMIDInferenceEngine, optional): The inference engine to use for reducing the LIMID.
If None, a new inference engine is created. Must be passed as a keyword argument.
verbose (bool): If True, prints detailed information about removed arcs and non-connected nodes.
Must be passed as a keyword argument.
Returns:
tuple[list[dict], list[dict]]: A tuple containing two lists:
- removed_arcs: A list of dictionaries representing removed arcs.
- non_connected_nodes: A list of dictionaries representing non-connected nodes.
"""
if ie is None:
ie = gum.ShaferShenoyLIMIDInference(limid)
ie.makeInference()
reduced_limid = ie.reducedLIMID()
limid_arcs = limid.arcs()
reduced_limid_arcs = reduced_limid.arcs()
removed_arcs = [
{arc: (limid.variable(arc[0]).name(), limid.variable(arc[1]).name())}
for arc in set(limid_arcs) - set(reduced_limid_arcs)
]
non_connected_nodes = [
{node: reduced_limid.variable(node).name()} for node in reduced_limid.nodes() \
if len(reduced_limid.parents(node)) == 0 and len(reduced_limid.children(node)) == 0
]
if verbose:
print("Original LIMID arcs:", limid_arcs)
print("Reduced LIMID arcs:", reduced_limid_arcs)
print("Removed arcs:", removed_arcs)
print("Non-connected nodes:", non_connected_nodes)
return removed_arcs, non_connected_nodes
```
which can be used as
```bash
_ = non_requisit_arcs_and_isolated_nodes(limid=diag, verbose=True)
```
```bash
Original LIMID arcs: {(2, 3), (0, 2), (2, 1), (1, 4)}
Reduced LIMID arcs: {(2, 3), (2, 1), (1, 4)}
Removed arcs: [{(0, 2): ('U1', 'D1')}]
Non-connected nodes: [{0: 'U1'}]
```
Would the function be implemented in Prisma, further tests need to be implemented (in particular when several arcs and nodes are removed).
Contributor guide
Research direction
Start by locating Prisma's LIMID and inference integration, especially the entry point corresponding to reducedLIMID(). Use the proposed function and supplied example as the behavioral reference, then add tests for multiple removed arcs and isolated nodes; done means the API reports both categories consistently.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp, python
- Domain
- backend-api-design
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 50/100