Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 47 additions & 17 deletions packages/compile/src/model/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -525,24 +525,28 @@ function allVars() {
return R.filter(isNotPlaceholderVar, variables)
}
function constVars() {
// Return an array of vars of type `const`, sorted by LHS variable name.
return vsort(varsOfType('const'))
}
function lookupVars() {
// Return an array of vars of type `lookup`, sorted by LHS variable name.
return vsort(varsOfType('lookup'))
}
function dataVars() {
// Return an array of vars of type `data`, sorted by LHS variable name.
return vsort(varsOfType('data'))
}
function auxVars() {
// console.error('AUX VARS');
// Return an array of vars of type `aux`, sorted according to the dependency graph.
return sortVarsOfType('aux')
}
function levelVars() {
// console.error('LEVEL VARS');
// Return an array of vars of type `level`, sorted according to the dependency graph.
return sortVarsOfType('level')
}
function initVars() {
// console.error('INIT VARS');
// Return an array of all vars that have the `hasInitValue` flag set to true,
// sorted according to the dependency graph.
return sortInitVars()
}
function varWithRefId(refId) {
Expand Down Expand Up @@ -1055,26 +1059,52 @@ function printDepsGraph(graph, varType) {

function allListedVars() {
// Put variables into the order that they are evaluated by SDE in the generated model
let vars = []
vars.push(...constVars())
vars.push(...lookupVars())
vars.push(...dataVars())
const listedVars = []
const visitedRefIds = new Set()
function addUnique(vars) {
for (const v of vars) {
// Skip variables that have already been visited
if (visitedRefIds.has(v.refId)) {
continue
}
visitedRefIds.add(v.refId)

// Filter out variables that are generated/used internally
if (v.includeInOutput === false) {
continue
}

// Include the variable
listedVars.push(v)
}
}

// The order of execution/evaluation in the generated model is:
// initConstants (vars of type `const` only)
// initLookups (vars of type `lookup` only)
// initData (vars of type `data` only)
// initLevels (vars returned by `initVars`, a mix of initial, aux, and level vars)
// evalAux (vars of type `aux` only)
// evalLevels (vars of type `level` only)
// So to make the ordering in the listing better match the order of evaluation,
// we emit variables in the above order, but filter to avoid having duplicates.
addUnique(constVars())
addUnique(lookupVars())
addUnique(dataVars())
// The special exogenous `Time` variable may have already been removed by
// `removeUnusedVariables` if it is not referenced explicitly in the model,
// so we will only include it in the listing if it is defined here
// so we will only include it in the listing if it is defined here. Note
// that `_time` is set to `_initial_time` as the first step in the
// `initLevels` function, which is why it is included here.
const timeVar = varWithName('_time')
if (timeVar) {
vars.push(timeVar)
}
vars.push(...auxVars())
vars.push(...levelVars())

// Filter out variables that are generated/used internally
const isInternal = v => {
return v.includeInOutput === false
addUnique([timeVar])
}
addUnique(initVars())
addUnique(auxVars())
addUnique(levelVars())

return R.filter(v => !isInternal(v), vars)
return listedVars
}

function filteredListedVars() {
Expand Down
92 changes: 53 additions & 39 deletions packages/compile/src/model/model.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function readInlineModel(

describe('Model', () => {
describe('jsonList', () => {
it('should expose accessible variables', () => {
it('should expose accessible variables sorted in order of execution', () => {
const listing = readInlineModel(`
DimA: A1, A2 ~~|
DimB: B1, B2 ~~|
Expand All @@ -84,6 +84,7 @@ describe('Model', () => {
c data ~~|
c = c data ~~|
d[DimA] = 10, 11 ~~|
e = INITIAL(c) ~~|
level init = 5 ~~|
level = INTEG(x, level init) ~~|
w = WITH LOOKUP(x, ( [(0,0)-(2,2)], (0,0),(0.1,0.01),(0.5,0.7),(1,1),(1.5,1.2),(2,1.3) )) ~~|
Expand All @@ -92,7 +93,6 @@ describe('Model', () => {
TIME STEP = 1 ~~|
SAVEPER = 1 ~~|
`)

expect(listing.full).toEqual({
dimensions: [
{
Expand Down Expand Up @@ -235,6 +235,37 @@ describe('Model', () => {
modelFormula: '',
varIndex: 11
},
{
refId: '_c',
varName: '_c',
references: ['_c_data'],
hasInitValue: false,
varType: 'aux',
modelLHS: 'c',
modelFormula: 'c data',
varIndex: 12
},
{
refId: '_e',
varName: '_e',
hasInitValue: true,
initReferences: ['_c'],
varType: 'initial',
modelLHS: 'e',
modelFormula: 'INITIAL(c)',
varIndex: 13
},
{
refId: '_level',
varName: '_level',
references: ['_x'],
hasInitValue: true,
initReferences: ['_level_init'],
varType: 'level',
modelLHS: 'level',
modelFormula: 'INTEG(x,level init)',
varIndex: 14
},
{
refId: '_a',
varName: '_a',
Expand All @@ -245,7 +276,7 @@ describe('Model', () => {
varType: 'aux',
modelLHS: 'a[DimA]',
modelFormula: 'a data[DimA]',
varIndex: 12
varIndex: 15
},
{
refId: '_b',
Expand All @@ -257,17 +288,7 @@ describe('Model', () => {
varType: 'aux',
modelLHS: 'b[DimA,DimB]',
modelFormula: 'b data[DimA,DimB]',
varIndex: 13
},
{
refId: '_c',
varName: '_c',
references: ['_c_data'],
hasInitValue: false,
varType: 'aux',
modelLHS: 'c',
modelFormula: 'c data',
varIndex: 14
varIndex: 16
},
{
refId: '_x',
Expand All @@ -277,7 +298,7 @@ describe('Model', () => {
varType: 'aux',
modelLHS: 'x',
modelFormula: 'input',
varIndex: 15
varIndex: 17
},
{
refId: '_w',
Expand All @@ -287,7 +308,7 @@ describe('Model', () => {
varType: 'aux',
modelLHS: 'w',
modelFormula: 'WITH LOOKUP(x,([(0,0)-(2,2)],(0,0),(0.1,0.01),(0.5,0.7),(1,1),(1.5,1.2),(2,1.3)))',
varIndex: 16
varIndex: 18
},
{
refId: '_y',
Expand All @@ -297,7 +318,7 @@ describe('Model', () => {
varType: 'aux',
modelLHS: 'y',
modelFormula: ':NOT: x',
varIndex: 17
varIndex: 19
},
{
refId: '_z',
Expand All @@ -307,18 +328,7 @@ describe('Model', () => {
varType: 'aux',
modelLHS: 'z',
modelFormula: 'ABS(y)',
varIndex: 18
},
{
refId: '_level',
varName: '_level',
references: ['_x'],
hasInitValue: true,
initReferences: ['_level_init'],
varType: 'level',
modelLHS: 'level',
modelFormula: 'INTEG(x,level init)',
varIndex: 19
varIndex: 20
}
]
})
Expand Down Expand Up @@ -383,38 +393,42 @@ describe('Model', () => {
index: 11
},
{
id: '_a',
dimIds: ['_dima'],
id: '_c',
index: 12
},
{
id: '_b',
dimIds: ['_dima', '_dimb'],
id: '_e',
index: 13
},
{
id: '_c',
id: '_level',
index: 14
},
{
id: '_x',
id: '_a',
dimIds: ['_dima'],
index: 15
},
{
id: '_w',
id: '_b',
dimIds: ['_dima', '_dimb'],
index: 16
},
{
id: '_y',
id: '_x',
index: 17
},
{
id: '_z',
id: '_w',
index: 18
},
{
id: '_level',
id: '_y',
index: 19
},
{
id: '_z',
index: 20
}
]
})
Expand Down