-
Notifications
You must be signed in to change notification settings - Fork 114
H-5641: Probability Distributions in Petrinaut #8463
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
kube
merged 15 commits into
main
from
cf/h-5641-add-input-for-probabilistic-transition-kernels
Mar 9, 2026
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
ebf0d3d
H-5641: Extract virtual file generation and add global Distribution type
kube b7a426b
H-5641: Change DistributionGaussian to Distribution.Gaussian namespace
kube 172e432
H-5641: Add runtime support for probabilistic transition kernels
kube 9813382
H-5641: Add changeset for probabilistic transition kernels
kube f7d34b4
H-5641: Add Distribution.map() and satellites launcher example
kube c3e4427
H-5641: Fix ESLint errors in distribution and transition code
kube b7ee80c
H-5641: Add Distribution.Lognormal(mu, sigma) support
kube e60e8f4
Remove width/height from example
kube 76a1dab
Update changeset to patch
kube 0580476
H-5641: Fix review feedback and enable supply chain examples
kube ed260ed
Update changeset
kube 0e399ad
Rename defect_threshold to quality_threshold in supply chain example
kube 676b471
Fix
kube 7d91cc5
Fix
kube 033dfd6
Last fix
kube File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@hashintel/petrinaut": patch | ||
| --- | ||
|
|
||
| Add probability distribution support to transition kernels (`Distribution.Gaussian`, `Distribution.Uniform`, `Distribution.Lognormal`) |
344 changes: 344 additions & 0 deletions
344
libs/@hashintel/petrinaut/src/examples/satellites-launcher.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,344 @@ | ||
| import type { SDCPN } from "../core/types/sdcpn"; | ||
|
|
||
| export const probabilisticSatellitesSDCPN: { | ||
| title: string; | ||
| petriNetDefinition: SDCPN; | ||
| } = { | ||
| title: "Probabilistic Satellites Launcher", | ||
| petriNetDefinition: { | ||
| places: [ | ||
| { | ||
| id: "3cbc7944-34cb-4eeb-b779-4e392a171fe1", | ||
| name: "Space", | ||
| colorId: "f8e9d7c6-b5a4-3210-fedc-ba9876543210", | ||
| dynamicsEnabled: true, | ||
| differentialEquationId: "1a2b3c4d-5e6f-7890-abcd-1234567890ab", | ||
| visualizerCode: `export default Visualization(({ tokens, parameters }) => { | ||
| const { satellite_radius, earth_radius } = parameters; | ||
|
|
||
| const width = 800; | ||
| const height = 600; | ||
|
|
||
| const centerX = width / 2; | ||
| const centerY = height / 2; | ||
|
|
||
| return ( | ||
| <svg | ||
| viewBox={\`0 0 \${width} \${height}\`} | ||
| style={{ borderRadius: "4px", width: "100%" }} | ||
| > | ||
| {/* Background */} | ||
| <rect width={width} height={height} fill="#000014" /> | ||
|
|
||
| {/* Earth at center */} | ||
| <circle | ||
| cx={centerX} | ||
| cy={centerY} | ||
| r={earth_radius} | ||
| fill="#2196f3" | ||
| stroke="#1976d2" | ||
| strokeWidth="2" | ||
| /> | ||
|
|
||
| {/* Satellites */} | ||
| {tokens.map(({ x, y, direction, velocity }, index) => { | ||
| // Convert satellite coordinates to screen coordinates | ||
| // Assuming satellite coordinates are relative to Earth center | ||
| const screenX = centerX + x; | ||
| const screenY = centerY + y; | ||
|
|
||
| return ( | ||
| <g key={index}> | ||
| {/* Satellite */} | ||
| <circle | ||
| cx={screenX} | ||
| cy={screenY} | ||
| r={satellite_radius} | ||
| fill="#ff5722" | ||
| stroke="#d84315" | ||
| strokeWidth="1" | ||
| /> | ||
|
|
||
| {/* Velocity vector indicator */} | ||
| {velocity > 0 && ( | ||
| <line | ||
| x1={screenX} | ||
| y1={screenY} | ||
| x2={screenX + Math.cos(direction) * Math.log(velocity) * 10} | ||
| y2={screenY + Math.sin(direction) * Math.log(velocity) * 10} | ||
| stroke="#ffc107" | ||
| strokeWidth="2" | ||
| markerEnd="url(#arrowhead)" | ||
| /> | ||
| )} | ||
| </g> | ||
| ); | ||
| })} | ||
|
|
||
| {/* Arrow marker for velocity vectors */} | ||
| <defs> | ||
| <marker | ||
| id="arrowhead" | ||
| markerWidth="8" | ||
| markerHeight="8" | ||
| refX="7" | ||
| refY="4" | ||
| orient="auto" | ||
| markerUnits="strokeWidth" | ||
| > | ||
| <polygon | ||
| points="0 0, 8 4, 0 8" | ||
| fill="#ffc107" | ||
| stroke="#f57f17" | ||
| strokeWidth="0.5" | ||
| /> | ||
| </marker> | ||
| </defs> | ||
| </svg> | ||
| ); | ||
| });`, | ||
| x: 30, | ||
| y: 90, | ||
| }, | ||
| { | ||
| id: "ea42ba61-03ea-4940-b2e2-b594d5331a71", | ||
| name: "Debris", | ||
| colorId: "f8e9d7c6-b5a4-3210-fedc-ba9876543210", | ||
| dynamicsEnabled: false, | ||
| differentialEquationId: null, | ||
| x: 510, | ||
| y: 75, | ||
| }, | ||
| ], | ||
| transitions: [ | ||
| { | ||
| id: "d25015d8-7aac-45ff-82b0-afd943f1b7ec", | ||
| name: "Collision", | ||
| inputArcs: [ | ||
| { | ||
| placeId: "3cbc7944-34cb-4eeb-b779-4e392a171fe1", | ||
| weight: 2, | ||
| }, | ||
| ], | ||
| outputArcs: [ | ||
| { | ||
| placeId: "ea42ba61-03ea-4940-b2e2-b594d5331a71", | ||
| weight: 2, | ||
| }, | ||
| ], | ||
| lambdaType: "predicate", | ||
| lambdaCode: `// Check if two satellites collide (are within collision threshold) | ||
| export default Lambda((tokens, parameters) => { | ||
| const { satellite_radius } = parameters; | ||
|
|
||
| // Get the two satellites | ||
| const [a, b] = tokens.Space; | ||
|
|
||
| // Calculate distance between satellites | ||
| const distance = Math.hypot(b.x - a.x, b.y - a.y); | ||
|
|
||
| // Collision occurs if distance is less than threshold | ||
| return distance < satellite_radius; | ||
| })`, | ||
kube marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| transitionKernelCode: `// When satellites collide, they become debris (lose velocity) | ||
| export default TransitionKernel((tokens) => { | ||
| // Both satellites become stationary debris at their collision point | ||
| return { | ||
| Debris: [ | ||
| // Position preserved, direction and velocity zeroed | ||
| { | ||
| x: tokens.Space[0].x, | ||
| y: tokens.Space[0].y, | ||
| velocity: 0, | ||
| direction: 0 | ||
| }, | ||
| { | ||
| x: tokens.Space[1].x, | ||
| y: tokens.Space[1].y, | ||
| velocity: 0, | ||
| direction: 0 | ||
| }, | ||
| ] | ||
| }; | ||
| })`, | ||
| x: 255, | ||
| y: 180, | ||
| }, | ||
| { | ||
| id: "716fe1e5-9b35-413f-83fe-99b28ba73945", | ||
| name: "Crash", | ||
| inputArcs: [ | ||
| { | ||
| placeId: "3cbc7944-34cb-4eeb-b779-4e392a171fe1", | ||
| weight: 1, | ||
| }, | ||
| ], | ||
| outputArcs: [ | ||
| { | ||
| placeId: "ea42ba61-03ea-4940-b2e2-b594d5331a71", | ||
| weight: 1, | ||
| }, | ||
| ], | ||
| lambdaType: "predicate", | ||
| lambdaCode: `// Check if satellite crashes into Earth (within crash threshold of origin) | ||
| export default Lambda((tokens, parameters) => { | ||
| const { earth_radius, crash_threshold, satellite_radius } = parameters; | ||
|
|
||
| // Get satellite position | ||
| const { x, y } = tokens.Space[0]; | ||
|
|
||
| // Calculate distance from Earth center (origin) | ||
| const distance = Math.hypot(x, y); | ||
|
|
||
| // Crash occurs if satellite is too close to Earth | ||
| return distance < earth_radius + crash_threshold + satellite_radius; | ||
| })`, | ||
| transitionKernelCode: `// When satellite crashes into Earth, it becomes debris at crash site | ||
| export default TransitionKernel((tokens) => { | ||
| return { | ||
| Debris: [ | ||
| { | ||
| // Position preserved, direction and velocity zeroed | ||
| x: tokens.Space[0].x, | ||
| y: tokens.Space[0].y, | ||
| direction: 0, | ||
| velocity: 0 | ||
| }, | ||
| ] | ||
| }; | ||
| })`, | ||
| x: 255, | ||
| y: 30, | ||
| }, | ||
| { | ||
| id: "transition__c7008acb-b0e7-468e-a5d3-d56eaa1fe806", | ||
| name: "LaunchSatellite", | ||
| inputArcs: [], | ||
| outputArcs: [ | ||
| { | ||
| placeId: "3cbc7944-34cb-4eeb-b779-4e392a171fe1", | ||
| weight: 1, | ||
| }, | ||
| ], | ||
| lambdaType: "stochastic", | ||
| lambdaCode: `export default Lambda((tokensByPlace, parameters) => { | ||
| return 1; | ||
| });`, | ||
| transitionKernelCode: `export default TransitionKernel((tokensByPlace, parameters) => { | ||
| const distance = 80; | ||
| const angle = Distribution.Uniform(0, Math.PI * 2); | ||
|
|
||
| return { | ||
| Space: [ | ||
| { | ||
| x: angle.map(a => Math.cos(a) * distance), | ||
| y: angle.map(a => Math.sin(a) * distance), | ||
| direction: Distribution.Uniform(0, Math.PI * 2), | ||
| velocity: Distribution.Gaussian(60, 20) | ||
| } | ||
| ], | ||
| }; | ||
| });`, | ||
| x: -225, | ||
| y: 75, | ||
| }, | ||
| ], | ||
| types: [ | ||
| { | ||
| id: "f8e9d7c6-b5a4-3210-fedc-ba9876543210", | ||
| name: "Satellite", | ||
| iconSlug: "9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d", | ||
| displayColor: "#1E90FF", | ||
| elements: [ | ||
| { | ||
| elementId: "2b3c4d5e-6f7a-8b9c-0d1e-2f3a4b5c6d7e", | ||
| name: "x", | ||
| type: "real", | ||
| }, | ||
| { | ||
| elementId: "3c4d5e6f-7a8b-9c0d-1e2f-3a4b5c6d7e8f", | ||
| name: "y", | ||
| type: "real", | ||
| }, | ||
| { | ||
| elementId: "4d5e6f7a-8b9c-0d1e-2f3a-4b5c6d7e8f9a", | ||
| name: "direction", | ||
| type: "real", | ||
| }, | ||
| { | ||
| elementId: "5e6f7a8b-9c0d-1e2f-3a4b-5c6d7e8f9a0b", | ||
| name: "velocity", | ||
| type: "real", | ||
| }, | ||
| ], | ||
| }, | ||
| ], | ||
| differentialEquations: [ | ||
| { | ||
| id: "1a2b3c4d-5e6f-7890-abcd-1234567890ab", | ||
| colorId: "f8e9d7c6-b5a4-3210-fedc-ba9876543210", | ||
| name: "Satellite Orbit Dynamics", | ||
| code: `// Example of ODE for Satellite in orbit (simplified) | ||
| export default Dynamics((tokens, parameters) => { | ||
| const mu = parameters.gravitational_constant; // Gravitational parameter | ||
|
|
||
| // Process each token (satellite) | ||
| return tokens.map(({ x, y, direction, velocity }) => { | ||
| const r = Math.hypot(x, y); // Distance to Earth center | ||
|
|
||
| // Gravitational acceleration vector (points toward origin) | ||
| const ax = (-mu * x) / (r * r * r); | ||
| const ay = (-mu * y) / (r * r * r); | ||
|
|
||
| // Return derivatives for this token | ||
| return { | ||
| x: velocity * Math.cos(direction), | ||
| y: velocity * Math.sin(direction), | ||
| direction: | ||
| (-ax * Math.sin(direction) + ay * Math.cos(direction)) / velocity, | ||
| velocity: | ||
| ax * Math.cos(direction) + ay * Math.sin(direction), | ||
| } | ||
| }) | ||
| })`, | ||
| }, | ||
| ], | ||
| parameters: [ | ||
| { | ||
| id: "6f7a8b9c-0d1e-2f3a-4b5c-6d7e8f9a0b1c", | ||
| name: "Earth Radius", | ||
| variableName: "earth_radius", | ||
| type: "real", | ||
| defaultValue: "50.0", | ||
| }, | ||
| { | ||
| id: "7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d", | ||
| name: "Satellite Radius", | ||
| variableName: "satellite_radius", | ||
| type: "real", | ||
| defaultValue: "4.0", | ||
| }, | ||
| { | ||
| id: "8b9c0d1e-2f3a-4b5c-6d7e-8f9a0b1c2d3e", | ||
| name: "Collision Threshold", | ||
| variableName: "collision_threshold", | ||
| type: "real", | ||
| defaultValue: "10.0", | ||
| }, | ||
| { | ||
| id: "9c0d1e2f-3a4b-5c6d-7e8f-9a0b1c2d3e4f", | ||
| name: "Crash Threshold", | ||
| variableName: "crash_threshold", | ||
| type: "real", | ||
| defaultValue: "5.0", | ||
| }, | ||
| { | ||
| id: "0d1e2f3a-4b5c-6d7e-8f9a-0b1c2d3e4f5a", | ||
| name: "Gravitational Constant", | ||
| variableName: "gravitational_constant", | ||
| type: "real", | ||
| defaultValue: "400000.0", | ||
| }, | ||
| ], | ||
| }, | ||
| }; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.