Skip to content

feat: add support for Vensim's ALLOCATE BY PRIORITY function#809

Open
NiharikaHari wants to merge 7 commits intoclimateinteractive:mainfrom
NiharikaHari:feat/allocate-by-priority
Open

feat: add support for Vensim's ALLOCATE BY PRIORITY function#809
NiharikaHari wants to merge 7 commits intoclimateinteractive:mainfrom
NiharikaHari:feat/allocate-by-priority

Conversation

@NiharikaHari
Copy link
Copy Markdown

@NiharikaHari NiharikaHari commented Apr 20, 2026

Fixes #792

Feature: Allocate by priority #792

  • Adds support for Vensim’s allocate by priority function in the C runtime.
  • Mirrors the structure and style of the existing allocate_available implementation for consistency.
  • Includes Vensim’s example model (with .dat file) under models/ for validation and comparison of outputs.
  • Note: JS support is not implemented yet.

@chrispcampbell
Copy link
Copy Markdown
Contributor

@NiharikaHari: Thank you for your contribution! I have some high priority tasks to attend to for the next couple days, but I will try my best to review your work by Thursday.

@chrispcampbell chrispcampbell self-requested a review April 24, 2026 00:29
Copy link
Copy Markdown
Contributor

@chrispcampbell chrispcampbell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @NiharikaHari for taking the time to contribute your work on this new function!

Most of my comments below are nitpicky things about code style. I haven't read the logic too closely for the _ALLOCATE_BY_PRIORITY C runtime function, but as long as it produces equivalent results to Vensim (and I can see that it does since the tests are passing), then I will trust that the logic works.

The test_js job is failing; that job does more than just run JS-related tests, it also runs the JS-level integration tests that exercise both C/Wasm and JS code gen, and there are Emscripten warnings flagged here (see build log) that will need to be resolved.

Also, please add at least one new test in gen-equation-c-from-vensim.spec.ts to verify that code gen works as expected. You can follow the patterns used in the existing should work for ALLOCATE AVAILABLE function (1D LHS, ...) test. Add your new test just after the last ALLOCATE AVAILABLE test in that file.


static double out_return[ALLOCATE_BY_PRIORITY_BUFSIZE];

fprintf(stderr, request_quantities);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We generally don't leave printf's in production code. I know that Todd included some printf's in the _ALLOCATE_AVAILABLE implementation above, which was fine because they are gated by #ifdef PRINT_ALLOCATIONS_DEBUG_INFO. So it's OK if you want to leave these fprintf calls here, but just make sure to wrap them in #ifdef PRINT_ALLOCATIONS_DEBUG_INFO / #endif blocks.

out_return[idx[i]] = out[i];
}

fprintf(stderr, out_return);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above about removing this or putting it in an #ifdef block.


fprintf(stderr, out_return);
return out_return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove these two blank lines.


// Reduce remaining supply
supply -= dx;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove blank line.

}

// Create the outputs array
for (size_t i = 0; i < num_requesters; i++) out_return[i] = 0.0;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of single-line loops or conditionals. Make this:

for (size_t i = 0; i < num_requesters; i++) {
  out_return[i] = 0.0;
}


// Continue allocating until supply is exhausted
while (supply > _epsilon) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove blank line.

break;
}
}
if (!any_active) break;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Convert single-line conditional to multiple lines with braces.

// smallest of (next completion, next activation, remaining supply)
double dx = dx_next_top;

if (!isnan(dx_next_start) && dx_next_start < dx) dx = dx_next_start;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Convert single-line conditional to multiple lines with braces.

double dx = dx_next_top;

if (!isnan(dx_next_start) && dx_next_start < dx) dx = dx_next_start;
if (supply < dx) dx = supply;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Convert single-line conditional to multiple lines with braces.

}
}
continue
} else if ((callExpr.fnId === '_ALLOCATE_BY_PRIORITY') & (index < 2)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a typo here: & should be &&.

Once you fix that, you should be able to remove the extra parentheses as they aren't needed.

Actually, I think you could probably just remove the index < 2 part here. Ideally we would have validation code here for each argument (similar to what the TODO comments say in the code that handles ALLOCATE AVAILABLE args above). But if we're not going to add that validation code now, I think you can drop the index < 2 part, otherwise it gives the impression that only those args need to be considered when really all args should get special treatment eventually.

@NiharikaHari
Copy link
Copy Markdown
Author

Thank you @chrispcampbell for taking the time to review this. I'll be able to work on these changes next week. The logic in _ALLOCATE_BY_PRIORITY C runtime function mirrors the algorithm used in PySD.

@travisfranck
Copy link
Copy Markdown
Collaborator

@NiharikaHari This is a useful addition to SDE. Thank you for contributing! Does you model run now?

@NiharikaHari
Copy link
Copy Markdown
Author

@travisfranck Yes, it does! Outside of this I'm doing some janky changes around setConstants and setLookups to read from CIN files and CSV respectively in C runtime. Excited to integrate SDE into our pipeline :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Vensim's ALLOCATE BY PRIORITY

3 participants