Add experiment logs to the monitoring page #48

Merged
0950726 merged 122 commits from feat/experiment-logs into dev 2026-01-28 10:16:00 +00:00
Showing only changes of commit f8f0f12128 - Show all commits

View File

@@ -6,13 +6,14 @@ import {
} from '@xyflow/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 {BeliefReduce} from "./BeliefReduce.ts";
import switchStyles from './InferredBeliefNode.module.css';
import {MultiConnectionHandle, SingleConnectionHandle} from "../components/RuleBasedHandle.tsx";
import {allowOnlyConnectionsFromType} from "../HandleRules.ts";
import useFlowStore from "../VisProgStores.tsx";
import styles from '../../VisProg.module.css';
import switchStyles from './InferredBeliefNode.module.css';
/**
* The default data structure for an InferredBelief node
@@ -24,6 +25,11 @@ export type InferredBeliefNodeData = {
hasReduce: boolean;
};
/**
* stores a boolean to represent the operator
* and a left and right BeliefNode (can be both an inferred and a basic belief)
* in the form of their corresponding id's
*/
type InferredBelief = {
left: string | undefined,
operator: boolean,
@@ -82,17 +88,28 @@ export function InferredBeliefDisconnectionSource(_thisNode: Node, _targetNodeId
}
/**
* This rule makes it impossible to connect Inferred belief nodes
* if the connection would create a looping connection between inferred beliefs
* 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";
function checkForCycle(targetNodeId: string, current: string) : RuleResult {
const outgoingBeliefs = getOutgoers({id: current}, nodes, edges).filter(node => node.type === 'inferred_belief');
/**
* 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("Cyclical connection exists between inferred beliefs");
.notSatisfied(defaultErrorMessage);
const next = outgoingBeliefs.map(node => checkForCycle(targetNodeId, node.id)).find(result => !result.isSatisfied);
return next
@@ -101,15 +118,15 @@ const noBeliefCycles : HandleRule = (connection, _): RuleResult => {
}
return connection.source === connection.target
? ruleResult.notSatisfied("Cyclical connection exists between inferred beliefs")
? ruleResult.notSatisfied(defaultErrorMessage)
: checkForCycle(connection.source, connection.target);
}
/**
* Defines how a BasicBelief node should be rendered
* @param props - Node properties provided by React Flow, including `id` and `data`.
* @returns The rendered BasicBeliefNode React element (React.JSX.Element).
* Defines how an InferredBelief node should be rendered
* @param {NodeProps<InferredBeliefNode>} props - Node properties provided by React Flow, including `id` and `data`.
* @returns The rendered InferredBeliefNode React element. (React.JSX.Element)
*/
export default function InferredBeliefNode(props: NodeProps<InferredBeliefNode>) {
const data = props.data;
@@ -117,6 +134,7 @@ export default function InferredBeliefNode(props: NodeProps<InferredBeliefNode>)
// start of as an AND operator, true: "AND", false: "OR"
const [enforceAllBeliefs, setEnforceAllBeliefs] = useState(true);
// used to toggle operator
function onToggle() {
setEnforceAllBeliefs(!enforceAllBeliefs);
@@ -128,11 +146,12 @@ export default function InferredBeliefNode(props: NodeProps<InferredBeliefNode>)
}
});
}
return (
<>
<Toolbar nodeId={props.id} allowDelete={true}/>
<div className={`${styles.defaultNode} ${styles.nodeInferredBelief}`}>
{/* The checkbox used to toggle the operator between 'AND' and 'OR' */}
<label className={switchStyles.operatorSwitch}>
<input
type="checkbox"
@@ -169,8 +188,8 @@ export default function InferredBeliefNode(props: NodeProps<InferredBeliefNode>)
/**
* Reduces each BasicBelief, including its children down into its core data.
* @param node - The BasicBelief node to reduce.
* @param nodes - The list of all nodes in the current flow graph.
* @param {Node} node - The BasicBelief node to reduce.
* @param {Node[]} nodes - The list of all nodes in the current flow graph.
* @returns A simplified object containing the node label and its list of BasicBeliefs.
*/
export function InferredBeliefReduce(node: Node, nodes: Node[]) {
@@ -187,5 +206,6 @@ export function InferredBeliefReduce(node: Node, nodes: Node[]) {
operator: data.inferredBelief.operator ? "AND" : "OR",
right: BeliefReduce(rightBelief, nodes),
};
return result
}