Add experiment logs to the monitoring page #48
@@ -1,10 +1,10 @@
|
|||||||
import { type Node } from '@xyflow/react';
|
import {getOutgoers, type Node} from '@xyflow/react';
|
||||||
import {type HandleRule, ruleResult} from "../HandleRuleLogic.ts";
|
import {type HandleRule, type RuleResult, ruleResult} from "../HandleRuleLogic.ts";
|
||||||
import useFlowStore from "../VisProgStores.tsx";
|
import useFlowStore from "../VisProgStores.tsx";
|
||||||
import {BasicBeliefReduce} from "./BasicBeliefNode.tsx";
|
import {BasicBeliefReduce} from "./BasicBeliefNode.tsx";
|
||||||
import {type InferredBeliefNodeData, InferredBeliefReduce} from "./InferredBeliefNode.tsx";
|
import {type InferredBeliefNodeData, InferredBeliefReduce} from "./InferredBeliefNode.tsx";
|
||||||
|
|
||||||
export function BeliefGlobals(beliefNode: Node, nodes: Node[]) {
|
export function BeliefGlobalReduce(beliefNode: Node, nodes: Node[]) {
|
||||||
switch (beliefNode.type) {
|
switch (beliefNode.type) {
|
||||||
case 'basic_belief':
|
case 'basic_belief':
|
||||||
return BasicBeliefReduce(beliefNode, nodes);
|
return BasicBeliefReduce(beliefNode, nodes);
|
||||||
@@ -17,9 +17,47 @@ export const noMatchingLeftRightBelief : HandleRule = (connection, _)=> {
|
|||||||
const { nodes } = useFlowStore.getState();
|
const { nodes } = useFlowStore.getState();
|
||||||
const thisNode = nodes.find(node => node.id === connection.target && node.type === 'inferred_belief');
|
const thisNode = nodes.find(node => node.id === connection.target && node.type === 'inferred_belief');
|
||||||
if (!thisNode) return ruleResult.satisfied;
|
if (!thisNode) return ruleResult.satisfied;
|
||||||
const iBelief = (thisNode.data as InferredBeliefNodeData).inferredBelief;
|
|
||||||
|
|
||||||
|
const iBelief = (thisNode.data as InferredBeliefNodeData).inferredBelief;
|
||||||
return (iBelief.left === connection.source || iBelief.right === connection.source)
|
return (iBelief.left === connection.source || iBelief.right === connection.source)
|
||||||
? ruleResult.notSatisfied("Connecting one belief to both input handles of an inferred belief node is not allowed")
|
? ruleResult.notSatisfied("Connecting one belief to both input handles of an inferred belief node is not allowed")
|
||||||
: ruleResult.satisfied;
|
: ruleResult.satisfied;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* makes it impossible to connect Inferred belief nodes
|
||||||
|
* if the connection would create a cyclical connection between inferred beliefs
|
||||||
|
*/
|
||||||
|
export const noBeliefCycles: HandleRule = (connection, _): RuleResult => {
|
||||||
|
const {nodes, edges} = useFlowStore.getState();
|
||||||
|
const defaultErrorMessage = "Cyclical connection exists between inferred beliefs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* recursively checks for cyclical connections between InferredBelief nodes
|
||||||
|
*
|
||||||
|
* to check for a cycle provide the source of an attempted connection as the targetNode for the cycle check,
|
||||||
|
* the currentNodeId should be initialised with the id of the targetNode of the attempted connection.
|
||||||
|
*
|
||||||
|
* @param {string} targetNodeId - the id of the node we are looking for as the endpoint of a cyclical connection
|
||||||
|
* @param {string} currentNodeId - the id of the node we are checking for outgoing connections to the provided target node
|
||||||
|
* @returns {RuleResult}
|
||||||
|
*/
|
||||||
|
function checkForCycle(targetNodeId: string, currentNodeId: string): RuleResult {
|
||||||
|
const outgoingBeliefs = getOutgoers({id: currentNodeId}, nodes, edges)
|
||||||
|
.filter(node => node.type === 'inferred_belief');
|
||||||
|
|
||||||
|
if (outgoingBeliefs.length === 0) return ruleResult.satisfied;
|
||||||
|
if (outgoingBeliefs.some(node => node.id === targetNodeId)) return ruleResult
|
||||||
|
.notSatisfied(defaultErrorMessage);
|
||||||
|
|
||||||
|
const next = outgoingBeliefs.map(node => checkForCycle(targetNodeId, node.id))
|
||||||
|
.find(result => !result.isSatisfied);
|
||||||
|
|
||||||
|
return next
|
||||||
|
? next
|
||||||
|
: ruleResult.satisfied;
|
||||||
|
}
|
||||||
|
|
||||||
|
return connection.source === connection.target
|
||||||
|
? ruleResult.notSatisfied(defaultErrorMessage)
|
||||||
|
: checkForCycle(connection.source, connection.target);
|
||||||
|
};
|
||||||
@@ -1,17 +1,11 @@
|
|||||||
import {
|
import {getConnectedEdges, type Node, type NodeProps, Position} from '@xyflow/react';
|
||||||
type NodeProps,
|
|
||||||
Position,
|
|
||||||
type Node,
|
|
||||||
getConnectedEdges, getOutgoers
|
|
||||||
} from '@xyflow/react';
|
|
||||||
import {useState} from "react";
|
import {useState} from "react";
|
||||||
import { Toolbar } from '../components/NodeComponents.tsx';
|
import styles from '../../VisProg.module.css';
|
||||||
import {type HandleRule, type RuleResult, ruleResult} from "../HandleRuleLogic.ts";
|
import {Toolbar} from '../components/NodeComponents.tsx';
|
||||||
import {BeliefGlobals, noMatchingLeftRightBelief} from "./BeliefGlobals.ts";
|
|
||||||
import {MultiConnectionHandle, SingleConnectionHandle} from "../components/RuleBasedHandle.tsx";
|
import {MultiConnectionHandle, SingleConnectionHandle} from "../components/RuleBasedHandle.tsx";
|
||||||
import {allowOnlyConnectionsFromType} from "../HandleRules.ts";
|
import {allowOnlyConnectionsFromType} from "../HandleRules.ts";
|
||||||
import useFlowStore from "../VisProgStores.tsx";
|
import useFlowStore from "../VisProgStores.tsx";
|
||||||
import styles from '../../VisProg.module.css';
|
import {BeliefGlobalReduce, noBeliefCycles, noMatchingLeftRightBelief} from "./BeliefGlobals.ts";
|
||||||
import switchStyles from './InferredBeliefNode.module.css';
|
import switchStyles from './InferredBeliefNode.module.css';
|
||||||
|
|
||||||
|
|
||||||
@@ -87,45 +81,6 @@ export function InferredBeliefDisconnectionSource(_thisNode: Node, _targetNodeId
|
|||||||
// no additional connection logic exists yet
|
// no additional connection logic exists yet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* makes it impossible to connect Inferred belief nodes
|
|
||||||
* if the connection would create a cyclical connection between inferred beliefs
|
|
||||||
*/
|
|
||||||
const noBeliefCycles : HandleRule = (connection, _): RuleResult => {
|
|
||||||
const { nodes, edges } = useFlowStore.getState();
|
|
||||||
const defaultErrorMessage = "Cyclical connection exists between inferred beliefs";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* recursively checks for cyclical connections between InferredBelief nodes
|
|
||||||
*
|
|
||||||
* to check for a cycle provide the source of an attempted connection as the targetNode for the cycle check,
|
|
||||||
* the currentNodeId should be initialised with the id of the targetNode of the attempted connection.
|
|
||||||
*
|
|
||||||
* @param {string} targetNodeId - the id of the node we are looking for as the endpoint of a cyclical connection
|
|
||||||
* @param {string} currentNodeId - the id of the node we are checking for outgoing connections to the provided target node
|
|
||||||
* @returns {RuleResult}
|
|
||||||
*/
|
|
||||||
function checkForCycle(targetNodeId: string, currentNodeId: string) : RuleResult {
|
|
||||||
const outgoingBeliefs = getOutgoers({id: currentNodeId}, nodes, edges)
|
|
||||||
.filter(node => node.type === 'inferred_belief');
|
|
||||||
|
|
||||||
if (outgoingBeliefs.length === 0) return ruleResult.satisfied;
|
|
||||||
if (outgoingBeliefs.some(node => node.id === targetNodeId)) return ruleResult
|
|
||||||
.notSatisfied(defaultErrorMessage);
|
|
||||||
|
|
||||||
const next = outgoingBeliefs.map(node => checkForCycle(targetNodeId, node.id))
|
|
||||||
.find(result => !result.isSatisfied);
|
|
||||||
|
|
||||||
return next
|
|
||||||
? next
|
|
||||||
: ruleResult.satisfied;
|
|
||||||
}
|
|
||||||
|
|
||||||
return connection.source === connection.target
|
|
||||||
? ruleResult.notSatisfied(defaultErrorMessage)
|
|
||||||
: checkForCycle(connection.source, connection.target);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -210,9 +165,9 @@ export function InferredBeliefReduce(node: Node, nodes: Node[]) {
|
|||||||
|
|
||||||
const result: Record<string, unknown> = {
|
const result: Record<string, unknown> = {
|
||||||
id: node.id,
|
id: node.id,
|
||||||
left: BeliefGlobals(leftBelief, nodes),
|
left: BeliefGlobalReduce(leftBelief, nodes),
|
||||||
operator: data.inferredBelief.operator ? "AND" : "OR",
|
operator: data.inferredBelief.operator ? "AND" : "OR",
|
||||||
right: BeliefGlobals(rightBelief, nodes),
|
right: BeliefGlobalReduce(rightBelief, nodes),
|
||||||
};
|
};
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { TextField } from '../../../../components/TextField';
|
|||||||
import {MultiConnectionHandle, SingleConnectionHandle} from "../components/RuleBasedHandle.tsx";
|
import {MultiConnectionHandle, SingleConnectionHandle} from "../components/RuleBasedHandle.tsx";
|
||||||
import {allowOnlyConnectionsFromHandle, allowOnlyConnectionsFromType} from "../HandleRules.ts";
|
import {allowOnlyConnectionsFromHandle, allowOnlyConnectionsFromType} from "../HandleRules.ts";
|
||||||
import useFlowStore from '../VisProgStores';
|
import useFlowStore from '../VisProgStores';
|
||||||
import {BeliefGlobals} from "./BeliefGlobals.ts";
|
import {BeliefGlobalReduce} from "./BeliefGlobals.ts";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default data dot a phase node
|
* The default data dot a phase node
|
||||||
@@ -108,7 +108,7 @@ export function NormReduce(node: Node, nodes: Node[]) {
|
|||||||
const conditionNode = nodes.find((node) => node.id === data.condition);
|
const conditionNode = nodes.find((node) => node.id === data.condition);
|
||||||
// In case something went wrong, and our condition doesn't actually exist;
|
// In case something went wrong, and our condition doesn't actually exist;
|
||||||
if (conditionNode == undefined) return result;
|
if (conditionNode == undefined) return result;
|
||||||
result["condition"] = BeliefGlobals(conditionNode, nodes)
|
result["condition"] = BeliefGlobalReduce(conditionNode, nodes)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import {allowOnlyConnectionsFromHandle, allowOnlyConnectionsFromType} from "../H
|
|||||||
import useFlowStore from '../VisProgStores';
|
import useFlowStore from '../VisProgStores';
|
||||||
import { PlanReduce, type Plan } from '../components/Plan';
|
import { PlanReduce, type Plan } from '../components/Plan';
|
||||||
import PlanEditorDialog from '../components/PlanEditor';
|
import PlanEditorDialog from '../components/PlanEditor';
|
||||||
import {BeliefGlobals} from "./BeliefGlobals.ts";
|
import {BeliefGlobalReduce} from "./BeliefGlobals.ts";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default data structure for a Trigger node
|
* The default data structure for a Trigger node
|
||||||
@@ -92,7 +92,7 @@ export default function TriggerNode(props: NodeProps<TriggerNode>) {
|
|||||||
export function TriggerReduce(node: Node, nodes: Node[]) {
|
export function TriggerReduce(node: Node, nodes: Node[]) {
|
||||||
const data = node.data as TriggerNodeData;
|
const data = node.data as TriggerNodeData;
|
||||||
const conditionNode = data.condition ? nodes.find((n)=>n.id===data.condition) : undefined
|
const conditionNode = data.condition ? nodes.find((n)=>n.id===data.condition) : undefined
|
||||||
const conditionData = conditionNode ? BeliefGlobals(conditionNode, nodes) : ""
|
const conditionData = conditionNode ? BeliefGlobalReduce(conditionNode, nodes) : ""
|
||||||
return {
|
return {
|
||||||
id: node.id,
|
id: node.id,
|
||||||
condition: conditionData, // Make sure we have a condition before reducing, or default to ""
|
condition: conditionData, // Make sure we have a condition before reducing, or default to ""
|
||||||
|
|||||||
Reference in New Issue
Block a user