From c659952fa7839e208a5805de56121d59bdfadbe8 Mon Sep 17 00:00:00 2001 From: Nico Date: Tue, 10 Mar 2026 16:58:52 +0530 Subject: [PATCH 1/6] feat: generate code for allocate by priority --- packages/compile/src/generate/gen-expr.js | 88 ++++++++++++++++++++ packages/compile/src/model/read-equations.js | 8 ++ 2 files changed, 96 insertions(+) diff --git a/packages/compile/src/generate/gen-expr.js b/packages/compile/src/generate/gen-expr.js index d05f5b98..9c525bda 100644 --- a/packages/compile/src/generate/gen-expr.js +++ b/packages/compile/src/generate/gen-expr.js @@ -345,6 +345,12 @@ function generateFunctionCall(callExpr, ctx) { } return generateAllocateAvailableCall(callExpr, ctx) + case '_ALLOCATE_BY_PRIORITY': + if (ctx.outFormat === 'js') { + throw new Error(`${callExpr.fnName} function not yet implemented for JS code gen`) + } + return generateAllocateByPriorityCall(callExpr, ctx) + case '_ELMCOUNT': { // Emit the size of the dimension in place of the dimension name const dimArg = callExpr.args[0] @@ -891,6 +897,88 @@ function generateAllocateAvailableCall(callExpr, ctx) { return `${tmpVarId}[${allocDimId}[${allocLoopIndexVar}]]` } +/** + * Generate C/JS code for an `ALLOCATE BY PRIORITY` function call. + * + * @param {*} callExpr The function call expression from the parsed model. + * @param {GenExprContext} ctx The context used when generating code for the expression. + * @return {string} The generated C/JS code. + */ +function generateAllocateByPriorityCall(callExpr, ctx) { + function validateArg(index, name) { + const arg = callExpr.args[index] + if (arg.kind === 'variable-ref') { + return arg + } else { + throw new Error(`ALLOCATE BY PRIORITY argument '${name}' must be a variable reference`) + } + } + + // Given a C/JS variable reference string (e.g., '_var[i][j]'), return that + // string without the last N array index parts + function cVarRefWithoutLastIndices(arg, count) { + const varRef = ctx.cVarRef(arg) + const origIndexParts = Model.splitRefId(varRef).subscripts + if (origIndexParts < count) { + throw new Error(`ALLOCATE BY PRIORITY argument '${arg}' should have at least ${count} subscripts`) + } + const newIndexParts = origIndexParts.slice(0, -count) + if (newIndexParts.length > 0) { + return `${arg.varId}${newIndexParts.map(x => `[${x}]`).join('')}` + } else { + return arg.varId + } + } + + // Process the request argument. Only include subscripts up until the last one; + // the implementation function will iterate over the requesters array. + const reqArg = validateArg(0, 'req') + const reqRef = cVarRefWithoutLastIndices(reqArg, 1) + + // Process the priority argument. Only include subscripts up until the + // last one; the implementation function will iterate over the priorities + // array. + const priorityArg = validateArg(1, 'priority') + const priorityRef = cVarRefWithoutLastIndices(priorityArg, 1) + + // Process the size argument + const sizeArg = generateExpr(callExpr.args[2], ctx) + + // Process the width argument + const widthArg = generateExpr(callExpr.args[3], ctx) + + // Process the supply argument + const supplyArg = generateExpr(callExpr.args[4], ctx) + + // The `ALLOCATE BY PRIORITY` function iterates over the last subscript in its first + // argument, allocating the available quantity according to the priority values given + // in the second argument. The `readEquation` process will have already verified that + // the last dimension of both arguments matches the last dimension of the LHS. + const allocDimId = reqArg.subscriptRefs[reqArg.subscriptRefs.length - 1].subId + const allocLoopIndexVar = ctx.loopIndexVars.index(allocDimId) + + // Generate the code that is emitted before the entire block (before any loops are opened) + const tmpVarId = newTmpVarName() + const numRequesters = sub(allocDimId).size + switch (ctx.outFormat) { + case 'c': + ctx.emitPreInnerLoop( + ` double* ${tmpVarId} = _ALLOCATE_BY_PRIORITY(${reqRef}, ${priorityRef}, ${sizeArg}, ${widthArg}, ${supplyArg}, ${numRequesters});` + ) + break + case 'js': + ctx.emitPreInnerLoop( + ` let ${tmpVarId} = fns.ALLOCATE_BY_PRIORITY(${reqRef}, ${priorityRef}, ${sizeArg}, ${widthArg}, ${supplyArg}, ${numRequesters});` + ) + break + default: + throw new Error(`Unhandled output format '${ctx.outFormat}'`) + } + + // Generate the RHS expression used in the inner loop + return `${tmpVarId}[${allocDimId}[${allocLoopIndexVar}]]` +} + /** * Recursively traverse the given expression and call the function when visiting a variable ref. * diff --git a/packages/compile/src/model/read-equations.js b/packages/compile/src/model/read-equations.js index 0c630830..c64a9ae5 100644 --- a/packages/compile/src/model/read-equations.js +++ b/packages/compile/src/model/read-equations.js @@ -471,6 +471,11 @@ function visitFunctionCall(v, callExpr, context) { validateCallArgs(callExpr, 3) break + case '_ALLOCATE_BY_PRIORITY': + validateCallDepth(callExpr, context) + validateCallArgs(callExpr, 5) + break + case '_DELAY1': case '_DELAY1I': case '_DELAY3': @@ -698,6 +703,9 @@ function visitFunctionCall(v, callExpr, context) { } } continue + } else if ((callExpr.fnId === '_ALLOCATE_BY_PRIORITY') & (index < 2)) { + // TODO: Throw an error if the last dimension of arg0 does not match last dimension of LHS + // TODO: Throw an error if the last dimension of arg1 does not match last dimension of LHS } context.setArgIndex(index, argModes[index]) From 4a65f7afc472966d071ddceb64f5df0184fa5832 Mon Sep 17 00:00:00 2001 From: Nico Date: Tue, 10 Mar 2026 16:59:09 +0530 Subject: [PATCH 2/6] test: add example model for allocate by priority --- .../allocate_by_priority.mdl | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 models/allocate_by_priority/allocate_by_priority.mdl diff --git a/models/allocate_by_priority/allocate_by_priority.mdl b/models/allocate_by_priority/allocate_by_priority.mdl new file mode 100644 index 00000000..af7e11cb --- /dev/null +++ b/models/allocate_by_priority/allocate_by_priority.mdl @@ -0,0 +1,152 @@ +{UTF-8} +total shipments= + SUM(shipments[region!]) + ~ Widget/Month + ~ | + +priority[region]= + 1,2,3 + ~ dmnl + ~ | + +Final Supply= + 10 + ~ Widget/Month + ~ | + +Initial Supply= + 0 + ~ Widget/Month + ~ | + +total supply available= + Initial Supply + (Final Supply-Initial Supply) * (Time-INITIAL TIME)/(FINAL TIME-INITIAL TIME\ + ) + ~ Widget/Month + ~ Test input for total supply - creates a ramp over time. + | + +region: + Boston,Dayton,Fresno + ~ + ~ | + +pprofile : ptype, ppriority, pwidth, pextra + ~ + ~ | + +demand[region]= + 3,2,4 + ~ Widget/Month + ~ | + +shipments[region]= + ALLOCATE BY PRIORITY(demand[region],priority[region], + ELMCOUNT(region),priority width,total supply available) + ~ Widget/Month + ~ | + +******************************************************** + .Control +********************************************************~ + Simulation Control Parameters + | + +priority width= + 1 + ~ dmnl [0.01,5] + ~ | + +FINAL TIME = 12 + ~ Month + ~ The final time for the simulation. + | + +INITIAL TIME = 0 + ~ Month + ~ The initial time for the simulation. + | + +SAVEPER = + TIME STEP + ~ Month [0,?] + ~ The frequency with which output is stored. + | + +TIME STEP = 1 + ~ Month [0,?] + ~ The time step for the simulation. + | + +\\\---/// Sketch information - do not modify anything except names +V300 Do not put anything below this section - it will be ignored +*View 1 +$192-192-192,0,Times New Roman|12||0-0-0|0-0-0|0-0-255|-1--1--1|-1--1--1|96,96,100,0 +12,1,0,295,85,212,28,8,135,0,18,-1,0,0,0,-1--1--1,0-0-0,|12|B|128-0-0 +ALLOCATE BY PRIORITY - one-sided market allocating a total quantity to multiple suppliers or demanders +10,2,demand,125,160,26,11,8,3,0,16,-1,0,0,0,0-0-0,0-0-0,|12|U|0-0-0 +10,3,shipments,258,227,36,11,8,3,0,16,-1,0,0,0,0-0-0,0-0-0,|12|BU|0-0-0 +1,4,2,3,0,0,0,0,0,0,0,-1--1--1,,1|(184,190)| +10,5,total supply available,429,221,37,19,8,3,0,0,-1,0,0,0 +1,6,5,3,0,0,0,0,0,0,0,-1--1--1,,1|(349,223)| +10,7,priority,120,210,24,11,8,3,0,16,-1,0,0,0,0-0-0,0-0-0,|12|U|0-0-0 +10,8,priority width,125,265,42,11,8,3,0,0,-1,0,0,0 +10,9,Final Supply,593,361,40,11,8,3,0,0,-1,0,0,0 +1,10,9,5,0,0,0,0,0,64,0,-1--1--1,,1|(521,299)| +10,11,FINAL TIME,609,311,55,11,8,2,0,3,-1,0,0,0,128-128-128,0-0-0,|12||128-128-128 +1,12,11,5,0,0,0,0,0,64,0,-1--1--1,,1|(532,272)| +10,13,Initial Supply,611,218,41,11,8,3,0,0,-1,0,0,0 +1,14,13,5,0,0,0,0,0,64,0,-1--1--1,,1|(524,218)| +10,15,INITIAL TIME,593,164,60,11,8,2,0,3,-1,0,0,0,128-128-128,0-0-0,|12||128-128-128 +1,16,15,5,0,0,0,0,0,64,0,-1--1--1,,1|(520,189)| +10,17,Time,602,265,26,11,8,2,0,3,-1,0,0,0,128-128-128,0-0-0,|12||128-128-128 +1,18,17,5,0,0,0,0,0,64,0,-1--1--1,,1|(527,246)| +12,19,0,316,541,196,155,3,188,0,0,1,0,0,0 +Allocation +10,20,total shipments,279,298,47,11,8,3,0,0,0,0,0,0 +1,21,3,20,0,0,0,0,0,64,0,-1--1--1,,1|(266,255)| +1,22,7,3,0,0,0,0,0,64,0,-1--1--1,,1|(176,216)| +1,23,8,3,0,0,0,0,0,64,0,-1--1--1,,1|(185,247)| +12,24,0,345,155,77,19,8,135,0,4,-1,0,0,0,-1--1--1,255-255-128,|12||0-0-0 +Underlined variables are subscripted by Region +///---\\\ +:GRAPH Allocation +:TITLE Allocation +:X-AXIS total supply available +:SCALE +:VAR Shipments[region] +:L<%^E!@ +1:ALLOCATE BY PRIORITY.vdf +1:SalesData.vdf +9:ALLOCATE BY PRIORITY +22:$,Dollar,Dollars,$s +22:Hour,Hours +22:Month,Months +22:Person,People,Persons +22:Unit,Units +22:Week,Weeks +22:Year,Years +22:Day,Days +31:1,SalesData +32:11,Boston +33:(0,0),(1,2),(2,0),(3,0),(4,1),(5,3),(6,7),(7,4),(8,0),(9,0),(10,0), +15:0,0,0,0,0,0 +19:100,0 +27:0, +34:0, +4:Time +5:shipments[region] +35:Date +36:YYYY-MM-DD +37:2000 +38:1 +39:1 +40:2 +41:0 +24:0 +25:12 +26:12 +6:Boston +6:Dayton +6:Fresno +6:ptype From 6a4869a22248aba5d3b7c8c03794fc71af61c2ae Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 20 Apr 2026 11:20:27 +0530 Subject: [PATCH 3/6] feat: Implemented algorithm for allocate by priority in C --- packages/cli/src/c/vensim.c | 227 ++++++++++++++++++++++++++++++++++++ packages/cli/src/c/vensim.h | 2 + 2 files changed, 229 insertions(+) diff --git a/packages/cli/src/c/vensim.c b/packages/cli/src/c/vensim.c index 31232ec2..ba8b8066 100644 --- a/packages/cli/src/c/vensim.c +++ b/packages/cli/src/c/vensim.c @@ -503,6 +503,233 @@ double* _ALLOCATE_AVAILABLE( return allocations; } +// +// Helper methods for allocate by priority +// +double __sum(double* arr, size_t n) { + double total = 0.0; + for (size_t i = 0; i < n; i++) { + total += arr[i]; + } + return total; +} + +// +// ALLOCATE BY PRIORITY +// +#define ALLOCATE_BY_PRIORITY_BUFSIZE 60 +#define PRINT_ALLOCATIONS_DEBUG_INFO + +double* _ALLOCATE_BY_PRIORITY( + double* request_quantities, double* priority_values, double size, double width, double supply, size_t num_requesters) { + + // request points to an array of length num_requesters. + // priority points to an array of length num_requesters. + // size is the number of elements across which allocation is being made. + // width specifies how big a gap in priority is required to have the allocation go first to + // higher priority with only leftovers going to lower priority. + // supply is the total supply available to fulfill all requests. + + // Allocate by priority allocates supply to requesters based on order of priority. The way in + // which the rationing works is determined by the relative priorities and the width parameter. + + static double allocations[ALLOCATE_BY_PRIORITY_BUFSIZE]; + if (num_requesters > ALLOCATE_BY_PRIORITY_BUFSIZE) { + fprintf(stderr, "_ALLOCATE_BY_PRIORITY num_requesters exceeds internal maximum size of %d\n", ALLOCATE_BY_PRIORITY_BUFSIZE); + return NULL; + } + + // Validate request values (must be non-negative) + for (size_t i = 0; i < num_requesters; i++) { + if (request_quantities[i] < -_epsilon) { + fprintf(stderr, + "_ALLOCATE_BY_PRIORITY encountered negative request value at index %zu: %f\n", + i, request_quantities[i]); + return NULL; + } + } + + // Validate width (must not be negative) + if (width < -_epsilon) { + fprintf(stderr, + "_ALLOCATE_BY_PRIORITY encountered invalid width value: %f\n" + "Width must not be negative.\n", + width); + return NULL; + } + + // Validate supply (must not be negative) + if (supply < -_epsilon) { + fprintf(stderr, + "_ALLOCATE_BY_PRIORITY encountered invalid supply value: %f\n" + "Supply must not be negative.\n", + supply); + return NULL; + } + + // If supply > sum(request), return request + if (supply > __sum(request_quantities, num_requesters)) { + return request_quantities; + } + + // If supply = 0, all targets get allocated 0 + if(fabs(supply) < _epsilon) { + return allocations; + } + + static double out_return[ALLOCATE_BY_PRIORITY_BUFSIZE]; + + fprintf(stderr, request_quantities); + + // Remove request 0 targets and order by priority + bool is_0[ALLOCATE_BY_PRIORITY_BUFSIZE]; + size_t idx[ALLOCATE_BY_PRIORITY_BUFSIZE]; + size_t m = 0; + + for (size_t i = 0; i < num_requesters; i++) { + is_0[i] = request_quantities[i] == 0.0; + if (!is_0[i]) { + idx[m++] = i; + } + } + + /* sort = (-priority[~is_0]).argsort() */ + for (size_t i = 0; i < m; i++) { + for (size_t j = i + 1; j < m; j++) { + if (priority_values[idx[j]] > priority_values[idx[i]]) { + size_t tmp = idx[i]; + idx[i] = idx[j]; + idx[j] = tmp; + } + } + } + + double request[ALLOCATE_BY_PRIORITY_BUFSIZE]; + double priority[ALLOCATE_BY_PRIORITY_BUFSIZE]; + + for (size_t i = 0; i < m; i++) { + request[i] = (double)request_quantities[idx[i]]; + priority[i] = priority_values[idx[i]]; + } + + // Create the outputs array + for (size_t i = 0; i < num_requesters; i++) out_return[i] = 0.0; + + double out[ALLOCATE_BY_PRIORITY_BUFSIZE] = {0.0}; + + // Compute the distances between target supply and next target start + double distances[ALLOCATE_BY_PRIORITY_BUFSIZE]; + + for (size_t i = 0; i < m; i++) distances[i] = NAN; + + // last target will have an numpy.nan as distances as there are no + // more targets after + for (size_t i = 0; i + 1 < m; i++) { + double d = -(priority[i + 1] - priority[i]) / width; + if (d > 1.0) d = 1.0; + distances[i] = d * request[i]; + } + + // Create a vector of the current active targets + bool active[ALLOCATE_BY_PRIORITY_BUFSIZE] = {false}; + active[0] = true; + + // Create a vector of the last activated target + size_t c_i = 0; + + while (supply > 0.0) { + + bool any_active = false; + for (size_t i = 0; i < m; i++) { + if (active[i]) { + any_active = true; + break; + } + } + if (!any_active) break; + + // Compute the slopes of the active targets of supply + double slopes[ALLOCATE_BY_PRIORITY_BUFSIZE]; + double slope_sum = 0.0; + + for (size_t i = 0; i < m; i++) { + if (active[i]) { + slopes[i] = request[i]; + slope_sum += slopes[i]; + } else { + slopes[i] = 0.0; + } + } + + for (size_t i = 0; i < m; i++) { + slopes[i] /= slope_sum; + } + + // Compute how much supply much be given to any target reach its request + double dx_next_top = NAN; + + for (size_t i = 0; i < m; i++) { + if (active[i]) { + double val = (request[i] - out[i]) / slopes[i]; + if (isnan(dx_next_top) || val < dx_next_top) { + dx_next_top = val; + } + } + } + + // Compute how much supply is needed to start next target + // (last target will return a numpy.nan) + double dx_next_start = (distances[c_i] - out[c_i]) / slopes[c_i]; + + // Compute where the next change in allocation function will change + // this will happen when a target reaches is request, or when + // the next target starts or when the supply is totally distributed + double dx = dx_next_top; + + if (!isnan(dx_next_start) && dx_next_start < dx) dx = dx_next_start; + if (supply < dx) dx = supply; + + // Assing the supply to the targets + for (size_t i = 0; i < m; i++) { + out[i] += slopes[i] * dx; + } + + if (fabs(dx - dx_next_start) <= (1e-10 * fabs(dx_next_start) + 1e-16)) { + // A new target will start in the next loop + c_i++; + + // Active the next targetif its request is different than 0 + if (c_i < m) active[c_i] = true; + } + + if (dx == dx_next_top) { + // One or more target have reached their request + for (size_t i = 0; i < m; i++) { + if (fabs(out[i] - request[i]) <= 1e-12) { + active[i] = false; + } + } + } + + supply -= dx; + + if (supply < 1e-12) { // tolerance threshold + supply = 0.0; + } + } + + // Return the distributed supply in the original order + // adding to it again the request 0 if the where removed + for (size_t i = 0; i < m; i++) { + out_return[idx[i]] = out[i]; + } + + fprintf(stderr, out_return); + return out_return; + + +} + // // DELAY FIXED // diff --git a/packages/cli/src/c/vensim.h b/packages/cli/src/c/vensim.h index d29f6097..59b47b25 100644 --- a/packages/cli/src/c/vensim.h +++ b/packages/cli/src/c/vensim.h @@ -39,6 +39,8 @@ extern "C" { double* _ALLOCATE_AVAILABLE(double* requested_quantities, double* priority_profiles, double available_resource, size_t num_requesters); +double* _ALLOCATE_BY_PRIORITY(double* request, double* priority, double size, double width, double supply, size_t num_requesters); +double* _ALLOCATE_BY_PRIORITY_1D(double* request_in, double* priority_in, double width, double supply, size_t n); double _PULSE(double start, double width); double _PULSE_TRAIN(double start, double width, double interval, double end); double _RAMP(double slope, double start_time, double end_time); From faaad832678ca1e930c6bd607aa092155505e281 Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 20 Apr 2026 12:13:25 +0530 Subject: [PATCH 4/6] feat: updated comments for allocate by priority --- packages/cli/src/c/vensim.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/packages/cli/src/c/vensim.c b/packages/cli/src/c/vensim.c index ba8b8066..44f8ccad 100644 --- a/packages/cli/src/c/vensim.c +++ b/packages/cli/src/c/vensim.c @@ -593,7 +593,7 @@ double* _ALLOCATE_BY_PRIORITY( } } - /* sort = (-priority[~is_0]).argsort() */ + // Sort indices in `idx` by descending `priority_values` (highest priority first) for (size_t i = 0; i < m; i++) { for (size_t j = i + 1; j < m; j++) { if (priority_values[idx[j]] > priority_values[idx[i]]) { @@ -604,6 +604,7 @@ double* _ALLOCATE_BY_PRIORITY( } } + // Populate local arrays with request and priority values reordered according to idx double request[ALLOCATE_BY_PRIORITY_BUFSIZE]; double priority[ALLOCATE_BY_PRIORITY_BUFSIZE]; @@ -622,23 +623,24 @@ double* _ALLOCATE_BY_PRIORITY( for (size_t i = 0; i < m; i++) distances[i] = NAN; - // last target will have an numpy.nan as distances as there are no - // more targets after + // Last target will have NaN as distances as there are no more targets after for (size_t i = 0; i + 1 < m; i++) { double d = -(priority[i + 1] - priority[i]) / width; if (d > 1.0) d = 1.0; distances[i] = d * request[i]; } - // Create a vector of the current active targets + // Index of the current activated target bool active[ALLOCATE_BY_PRIORITY_BUFSIZE] = {false}; active[0] = true; - // Create a vector of the last activated target + // Index of the last activated target size_t c_i = 0; - while (supply > 0.0) { + // Continue allocating until supply is exhausted + while (supply > _epsilon) { + // Check if there are any active targets left bool any_active = false; for (size_t i = 0; i < m; i++) { if (active[i]) { @@ -648,19 +650,20 @@ double* _ALLOCATE_BY_PRIORITY( } if (!any_active) break; - // Compute the slopes of the active targets of supply + // Compute proportional allocation weights ("slopes") for active targets double slopes[ALLOCATE_BY_PRIORITY_BUFSIZE]; double slope_sum = 0.0; for (size_t i = 0; i < m; i++) { if (active[i]) { - slopes[i] = request[i]; + slopes[i] = request[i]; // weight based on requested amount slope_sum += slopes[i]; } else { slopes[i] = 0.0; } } + // Normalize slopes so total allocation proportion sums to 1 for (size_t i = 0; i < m; i++) { slopes[i] /= slope_sum; } @@ -677,23 +680,23 @@ double* _ALLOCATE_BY_PRIORITY( } } - // Compute how much supply is needed to start next target - // (last target will return a numpy.nan) + // Compute how much supply is needed to activate the next target + // (last target will return nan) double dx_next_start = (distances[c_i] - out[c_i]) / slopes[c_i]; - // Compute where the next change in allocation function will change - // this will happen when a target reaches is request, or when - // the next target starts or when the supply is totally distributed + // Determine next allocation step size: + // 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; if (supply < dx) dx = supply; - // Assing the supply to the targets + // Distribute this increment of supply across active targets for (size_t i = 0; i < m; i++) { out[i] += slopes[i] * dx; } + // If we reached the threshold to activate the next target if (fabs(dx - dx_next_start) <= (1e-10 * fabs(dx_next_start) + 1e-16)) { // A new target will start in the next loop c_i++; @@ -702,8 +705,8 @@ double* _ALLOCATE_BY_PRIORITY( if (c_i < m) active[c_i] = true; } + // If any targets have reached their requested amount, deactivate them if (dx == dx_next_top) { - // One or more target have reached their request for (size_t i = 0; i < m; i++) { if (fabs(out[i] - request[i]) <= 1e-12) { active[i] = false; @@ -711,11 +714,9 @@ double* _ALLOCATE_BY_PRIORITY( } } + // Reduce remaining supply supply -= dx; - if (supply < 1e-12) { // tolerance threshold - supply = 0.0; - } } // Return the distributed supply in the original order From 196369e96e86a4c6df164f1da67fc7e7dbd0d1c3 Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 20 Apr 2026 12:15:49 +0530 Subject: [PATCH 5/6] test: Added spec and dat file to test allocate by priority --- .../allocate_by_priority.dat | 108 ++++++++++++++++++ .../allocate_by_priority_spec.json | 4 + 2 files changed, 112 insertions(+) create mode 100644 models/allocate_by_priority/allocate_by_priority.dat create mode 100644 models/allocate_by_priority/allocate_by_priority_spec.json diff --git a/models/allocate_by_priority/allocate_by_priority.dat b/models/allocate_by_priority/allocate_by_priority.dat new file mode 100644 index 00000000..74f32486 --- /dev/null +++ b/models/allocate_by_priority/allocate_by_priority.dat @@ -0,0 +1,108 @@ +demand[Boston] +0 3 +demand[Dayton] +0 2 +demand[Fresno] +0 4 +Final Supply +0 10 +FINAL TIME +0 12 +Initial Supply +0 0 +INITIAL TIME +0 0 +priority[Boston] +0 1 +priority[Dayton] +0 2 +priority[Fresno] +0 3 +priority width +0 1 +SAVEPER +0 1 +1 1 +2 1 +3 1 +4 1 +5 1 +6 1 +7 1 +8 1 +9 1 +10 1 +11 1 +12 1 +shipments[Boston] +0 0 +1 0 +2 0 +3 0 +4 0 +5 0 +6 0 +7 0 +8 0.666667 +9 1.5 +10 2.33333 +11 3 +12 3 +shipments[Dayton] +0 0 +1 0 +2 0 +3 0 +4 0 +5 0.166667 +6 1 +7 1.83333 +8 2 +9 2 +10 2 +11 2 +12 2 +shipments[Fresno] +0 0 +1 0.833333 +2 1.66667 +3 2.5 +4 3.33333 +5 4 +6 4 +7 4 +8 4 +9 4 +10 4 +11 4 +12 4 +TIME STEP +0 1 +total shipments +0 0 +1 0.833333 +2 1.66667 +3 2.5 +4 3.33333 +5 4.16667 +6 5 +7 5.83333 +8 6.66667 +9 7.5 +10 8.33333 +11 9 +12 9 +total supply available +0 0 +1 0.833333 +2 1.66667 +3 2.5 +4 3.33333 +5 4.16667 +6 5 +7 5.83333 +8 6.66667 +9 7.5 +10 8.33333 +11 9.16667 +12 10 diff --git a/models/allocate_by_priority/allocate_by_priority_spec.json b/models/allocate_by_priority/allocate_by_priority_spec.json new file mode 100644 index 00000000..331eae1a --- /dev/null +++ b/models/allocate_by_priority/allocate_by_priority_spec.json @@ -0,0 +1,4 @@ +{ + "name": "ALLOCATE BY PRIORITY test model", + "outputVarNames": ["Time", "shipments[Boston]", "shipments[Dayton]", "shipments[Fresno]", "total supply available"] +} From 0bbc3b5e55d10d7f3caa8abf68f08c29ceed257f Mon Sep 17 00:00:00 2001 From: Nico Date: Mon, 20 Apr 2026 12:44:11 +0530 Subject: [PATCH 6/6] cleanup of code --- packages/cli/src/c/vensim.h | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/cli/src/c/vensim.h b/packages/cli/src/c/vensim.h index 59b47b25..c5db0a2c 100644 --- a/packages/cli/src/c/vensim.h +++ b/packages/cli/src/c/vensim.h @@ -40,7 +40,6 @@ extern "C" { double* _ALLOCATE_AVAILABLE(double* requested_quantities, double* priority_profiles, double available_resource, size_t num_requesters); double* _ALLOCATE_BY_PRIORITY(double* request, double* priority, double size, double width, double supply, size_t num_requesters); -double* _ALLOCATE_BY_PRIORITY_1D(double* request_in, double* priority_in, double width, double supply, size_t n); double _PULSE(double start, double width); double _PULSE_TRAIN(double start, double width, double interval, double end); double _RAMP(double slope, double start_time, double end_time);