From a6c23ed4b806db80b731fdec891c8ac934704d5e Mon Sep 17 00:00:00 2001 From: wsenafranca Date: Wed, 6 Dec 2017 11:57:40 -0200 Subject: [PATCH 01/11] Close #164 - Fix multiple runs to enable the model to read files in current directory and save output in another directory. --- lua/MultipleRuns.lua | 46 ++++++++++++++++++++++---------------------- lua/Utils.lua | 9 +++++++-- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/lua/MultipleRuns.lua b/lua/MultipleRuns.lua index 7f5b18c..c3fa267 100644 --- a/lua/MultipleRuns.lua +++ b/lua/MultipleRuns.lua @@ -245,7 +245,7 @@ end -- a: the parameter that the function is currently variating. In the Example: [a] = [1] => x, [a] = [2]=> y. -- Variables: The value that a parameter is being tested. Example: Variables = {x = -100, y = 1} -- resultTable Table returned by multipleRuns as result -local function factorialRecursive(data, params, a, variables, resultTable, addFunctions, s, repeated, numSimulation, maxSimulations, elapsedTimes, initialTime, summaryTable) +local function factorialRecursive(data, params, a, variables, resultTable, addFunctions, s, repeated, numSimulation, maxSimulations, elapsedTimes, initialTime, summaryTable, firstDir, folderDir) if params[a].ranged then -- if the parameter uses a range of values for parameter = params[a].min, (params[a].max + sessionInfo().round), params[a].step do -- Testing the parameter with each value in it's range. -- Giving the variables table the current parameter and value being tested. @@ -299,17 +299,18 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu end end) - local testDir = currentDir() + local testDir = folderDir + firstDir:setCurrentDir() + local simulationTime = sessionInfo().time + local m = data.model(mVariables) + testDir:setCurrentDir() if data.folderName then local dir = Directory(stringSimulations) dir:create() -- SKIP Directory(testDir..s..stringSimulations):setCurrentDir() -- SKIP end - local m if data.showProgress then - local simulationTime = sessionInfo().time - m = data.model(mVariables) -- SKIP local title = m:title() if repeated then title = table.concat({title, string.format("repetition %d/%d", case, data.repetition)}, ", ") @@ -332,7 +333,6 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu local timeString = os.date("%H:%M", round(initialTime + estimatedTime)) print(string.format("Estimated time to finish all simulations: %s (%s)", timeString, timeToString(timeLeft))) -- SKIP else - m = data.model(mVariables) --testing the model with it's current parameter values. m:run() end @@ -354,7 +354,7 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu end) end else -- else, go to the next parameter to test it with it's range of values. - resultTable, numSimulation, elapsedTimes, summaryTable = factorialRecursive(data, params, a + 1, variables, resultTable, addFunctions, s, repeated, numSimulation, maxSimulations, elapsedTimes, initialTime, summaryTable) + resultTable, numSimulation, elapsedTimes, summaryTable = factorialRecursive(data, params, a + 1, variables, resultTable, addFunctions, s, repeated, numSimulation, maxSimulations, elapsedTimes, initialTime, summaryTable, firstDir, folderDir) end end else -- if the parameter uses a table of multiple values @@ -409,17 +409,18 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu end end) - local testDir = currentDir() + local testDir = folderDir + firstDir:setCurrentDir() + local simulationTime = sessionInfo().time + local m = data.model(mVariables) + testDir:setCurrentDir() if data.folderName then local dir = Directory(stringSimulations) dir:create() Directory(testDir..s..stringSimulations):setCurrentDir() end - local m if data.showProgress then - local simulationTime = sessionInfo().time - m = data.model(mVariables) -- SKIP local title = m:title() if repeated then title = table.concat({title, string.format("repetition %d/%d", case, data.repetition)}, ", ") @@ -442,7 +443,6 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu local timeString = os.date("%H:%M", round(initialTime + estimatedTime)) print(string.format("Estimated time to finish all simulations: %s (%s)", timeString, timeToString(timeLeft))) -- SKIP else - m = data.model(mVariables) --testing the model with it's current parameter values. m:run() end @@ -464,7 +464,7 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu end) end else -- else, go to the next parameter to test it with each of it possible values. - resultTable, numSimulation, elapsedTimes, summaryTable = factorialRecursive(data, params, a + 1, variables, resultTable, addFunctions, s, repeated, numSimulation, maxSimulations, elapsedTimes, initialTime, summaryTable) -- SKIP + resultTable, numSimulation, elapsedTimes, summaryTable = factorialRecursive(data, params, a + 1, variables, resultTable, addFunctions, s, repeated, numSimulation, maxSimulations, elapsedTimes, initialTime, summaryTable, firstDir, folderDir) -- SKIP end end) end @@ -779,7 +779,7 @@ function MultipleRuns(data) local maxSimulations = countSimulations(params, 1) * data.repetition local initialTime = os.time() - resultTable = factorialRecursive(data, params, 1, variables, resultTable, addFunctions, s, repeated, 0, maxSimulations, {}, initialTime, summaryTable) + resultTable = factorialRecursive(data, params, 1, variables, resultTable, addFunctions, s, repeated, 0, maxSimulations, {}, initialTime, summaryTable, firstDir, folderDir) if data.folderName then firstDir:setCurrentDir() end @@ -814,6 +814,9 @@ function MultipleRuns(data) local sampleparams = {} table.insert(resultTable.simulations, stringSimulations..quantity) + local simulationTime = sessionInfo().time + firstDir:setCurrentDir() + local m = randomModel(data.model, data.parameters, true) if data.folderName then folderDir:setCurrentDir() local dir = Directory(stringSimulations..quantity) @@ -821,17 +824,15 @@ function MultipleRuns(data) Directory(folderDir..s..stringSimulations..quantity):setCurrentDir() end - local m if data.showProgress then - local simulationTime = sessionInfo().time - m = randomModel(data.model, data.parameters) -- SKIP - simulationTime = round(sessionInfo().time - simulationTime) -- SKIP local title = m:title() if repetition > 1 then -- SKIP title = table.concat({title, string.format("repetition %d/%d", case, data.repetition)}, ", ") end print(string.format("Running simulation %d/%d (%s)", numSimulation, maxSimulations, title)) -- SKIP + m:run() -- SKIP + simulationTime = round(sessionInfo().time - simulationTime) -- SKIP print(string.format("Simulation finished in %s", timeToString(simulationTime))) -- SKIP iterationTime = sessionInfo().time - iterationTime -- SKIP table.insert(elapsedTimes, iterationTime) -- SKIP @@ -846,7 +847,7 @@ function MultipleRuns(data) local timeString = os.date("%H:%M", round(initialTime + estimatedTime)) print(string.format("Estimated time to finish all simulations: %s (%s)", timeString, timeToString(timeLeft))) -- SKIP else - m = randomModel(data.model, data.parameters) + m:run() end clean() @@ -922,6 +923,9 @@ function MultipleRuns(data) local iterationTime = sessionInfo().time -- time to compute a single interation numSimulation = numSimulation + 1 table.insert(resultTable.simulations, stringSimulations..idx) + local simulationTime = sessionInfo().time + firstDir:setCurrentDir() + local m = data.model(clone(att)) if data.folderName then folderDir:setCurrentDir() local dir = Directory(stringSimulations..idx) @@ -929,10 +933,7 @@ function MultipleRuns(data) Directory(folderDir..s..stringSimulations..idx):setCurrentDir() end - local m if data.showProgress then - local simulationTime = sessionInfo().time - m = data.model(clone(att)) -- SKIP local title = m:title() if repetition > 1 then -- SKIP title = table.concat({title, string.format("repetition %d/%d", case, data.repetition)}, ", ") @@ -955,7 +956,6 @@ function MultipleRuns(data) local timeString = os.date("%H:%M", round(initialTime + estimatedTime)) print(string.format("Estimated time to finish all simulations: %s (%s)", timeString, timeToString(timeLeft))) -- SKIP else - m = data.model(clone(att)) m:run() end diff --git a/lua/Utils.lua b/lua/Utils.lua index b41236e..8ca5f6f 100644 --- a/lua/Utils.lua +++ b/lua/Utils.lua @@ -190,6 +190,8 @@ end -- This function can be used by SaMDE as well as by MultipleRuns. -- @arg tModel The Model to be instantiated. -- @arg tParameters A table of possible parameters for the model. +-- @arg skipRun An optional argument to determine whether the model will skip his execution or not after being created. +-- The default value is false meaning that the model will be executed internally by runModel. -- Multiple Runs or Calibration instance . -- @usage -- import("calibration") @@ -207,7 +209,7 @@ end -- } -- local parameters = {x = Choice{-100,- 1, 0, 1, 2, 100}, y = Choice{min = 1, max = 8, step = 1}} -- randomModel(myModel, parameters) -function randomModel(tModel, tParameters) +function randomModel(tModel, tParameters, skipRun) mandatoryArgument(1, "Model", tModel) mandatoryArgument(1, "table", tParameters) local sampleParams = {} @@ -231,7 +233,10 @@ function randomModel(tModel, tParameters) end end) local m = tModel(sampleParams) - m:run() + if not skipRun then -- needed to run models in the correct directory and to save their outputs correctly + m:run() + end + return m end From 90fddab565b2a5b4613b15f3047386c76cd33435 Mon Sep 17 00:00:00 2001 From: wsenafranca Date: Wed, 6 Dec 2017 15:32:15 -0200 Subject: [PATCH 02/11] Close #172 - Remove MultipleRuns:output. --- examples/daisy.lua | 3 +- examples/sir-mr-campaign.lua | 3 +- examples/sir-mr-probability.lua | 1 - lua/MultipleRuns.lua | 70 ++++++++++------------- tests/core/alternative/MultipleRuns.lua | 74 +++---------------------- tests/core/alternative/Utils.lua | 39 +++++-------- tests/core/basic/MultipleRuns.lua | 63 ++++++++------------- tests/core/basic/Utils.lua | 9 +-- 8 files changed, 80 insertions(+), 182 deletions(-) diff --git a/examples/daisy.lua b/examples/daisy.lua index 59008cb..37ebb75 100644 --- a/examples/daisy.lua +++ b/examples/daisy.lua @@ -12,8 +12,7 @@ local m = MultipleRuns{ model = Daisyworld, parameters = { sunLuminosity = Choice{min = 0.4, max = 1.6, step = 0.01}, - }, - output = {"blackArea", "whiteArea", "emptyArea"} + } } chart = Chart{ diff --git a/examples/sir-mr-campaign.lua b/examples/sir-mr-campaign.lua index 9af6335..8fc3421 100644 --- a/examples/sir-mr-campaign.lua +++ b/examples/sir-mr-campaign.lua @@ -10,8 +10,7 @@ runs = MultipleRuns{ model = SIR, parameters = { maximum = Choice{min = 100, max = 4000, step = 10} - }, - output = {"maxInfected", "susceptible"} + } } chart = Chart{ diff --git a/examples/sir-mr-probability.lua b/examples/sir-mr-probability.lua index 4acfc5f..7b2096a 100644 --- a/examples/sir-mr-probability.lua +++ b/examples/sir-mr-probability.lua @@ -12,7 +12,6 @@ runs = MultipleRuns{ probability = Choice{min = 0.05, max = 0.3, step = 0.001} }, --output = {"infected", "probability"} -- error! - output = {"susceptible", "maxInfected"} } chart = Chart{ diff --git a/lua/MultipleRuns.lua b/lua/MultipleRuns.lua index c3fa267..54723d1 100644 --- a/lua/MultipleRuns.lua +++ b/lua/MultipleRuns.lua @@ -142,6 +142,34 @@ local function checkParameters(origModel, origParameters) end local function testAddFunctions(resultTable, addFunctions, data, m, summaryResult) + forEachElement(m, function(attr, value, typ) + if addFunctions[attr] ~= nil then + customError("Values in model parameters or additional functions should not be repeated or have the same name.") + end + + if typ == "number" then + if not resultTable[attr] then + resultTable[attr] = {} + end + + local foundOnParameters = false + if data.strategy == "selected" then + forEachOrderedElement(data.parameters, function (_, pat, pty) + if pty == "table" then + if pat[attr] then + foundOnParameters = true + return + end + end + end) + end + + if not data.parameters[attr] and not foundOnParameters then + table.insert(resultTable[attr], value) + end + end + end) + if addFunctions == nil then return end forEachOrderedElement(addFunctions, function(idxF) @@ -149,10 +177,6 @@ local function testAddFunctions(resultTable, addFunctions, data, m, summaryResul resultTable[idxF] = {} end - if m[idxF] == nil and data.outputVariables[idxF] then - customError('Output value "'..idxF..'" is not present in the model.') - end - local returnValueF = data[idxF](m) table.insert(resultTable[idxF], returnValueF) if data.summary then @@ -619,11 +643,6 @@ function MultipleRuns(data) mandatoryTableArgument(data, "model", "Model") mandatoryTableArgument(data, "parameters", "table") - if type(data.output) == "string" then - data.output = {data.output} - end - - optionalTableArgument(data, "output", "table") optionalTableArgument(data, "strategy", "string") defaultTableValue(data, "repetition", 1) optionalTableArgument(data, "folderName", "string") @@ -663,37 +682,8 @@ function MultipleRuns(data) local resultTable = {simulations = {}} -- addFunctions: Parameter that organizes the additional functions choosen to be executed after the model. local addFunctions = {} - data.outputVariables = {} local summaryTable = {} - if data.output ~= nil then - forEachOrderedElement(data.output, function(_, att) - if data[att] ~= nil then - customError("Values in output parameters or additional functions should not be repeated or have the same name.") - end - - if data.strategy ~= "selected" then - if data.parameters[att] ~= nil then - customError("MultipleRuns already saves the output of all parameters inputed for testing, it's not necessary to select them in the 'output' table.") - end - else - forEachOrderedElement(data.parameters, function (_, pat, pty) - if pty == "table" then - if pat[att] ~= nil then - customError("MultipleRuns already saves the output of all parameters inputed for testing, it's not necessary to select them in the 'output' table.") - end - end - end) - end - - data[att] = function(model) - return model[att] - end - - data.outputVariables[att] = true - end) - end - forEachOrderedElement(data, function(idx, att) if type(att) == "function" then if addFunctions[idx] ~= nil then @@ -707,12 +697,11 @@ function MultipleRuns(data) local checkingArgument = {} checkingArgument[idx] = idx verifyUnnecessaryArguments(checkingArgument, { - "model", "output", "strategy", "parameters", "repetition", "folderName", "hideGraphics", "showProgress", "repeat", "quantity", "outputVariables"}) + "model", "strategy", "parameters", "repetition", "folderName", "hideGraphics", "showProgress", "repeat", "quantity", "outputVariables"}) end end) checkParameters(data.model, data) - data.output = nil if data.hideGraphics then sessionInfo().graphics = false @@ -803,6 +792,7 @@ function MultipleRuns(data) table.insert(summaryTable[variable], value) -- SKIP end) end + for case = 1, repetition do local stringSimulations = "" if repetition > 1 then diff --git a/tests/core/alternative/MultipleRuns.lua b/tests/core/alternative/MultipleRuns.lua index 67ae4fa..b5420fb 100644 --- a/tests/core/alternative/MultipleRuns.lua +++ b/tests/core/alternative/MultipleRuns.lua @@ -61,8 +61,7 @@ return{ showProgress = false, model = MyModel, parameters = {scenario1 ={x = 2, y = 5}}, - repetition = 3, - output = {"value"} + repetition = 3 } end @@ -72,8 +71,7 @@ return{ model = MyModel, showProgress = false, parameters = {scenario1 ={x = 2, y = 5, p = "extra"}}, - repetition = 3, - output = {"value"} + repetition = 3 } end @@ -85,8 +83,7 @@ return{ parameters = {x = Choice{1, 2}, y =Choice{1,5}, p = "extra"}, - repetition = 3, - output = {"value"} + repetition = 3 } end @@ -96,65 +93,28 @@ return{ model = MyModel, showProgress = false, parameters = {x = Choice{-100, 2}, y = Choice{1, 5}}, - repetition = 3, - output = {"x", "y", "value"} + repetition = 3 } end - unitTest:assertError(error_func, "MultipleRuns already saves the output of all parameters inputed for testing, it's not necessary to select them in the 'output' table.") error_func = function() m = MultipleRuns{ model = MyModel, showProgress = false, parameters = {scenario1 ={x = 2, y = 5}}, repetition = 3, - output = {"x", "y", "value"} - } - end - - unitTest:assertError(error_func, "MultipleRuns already saves the output of all parameters inputed for testing, it's not necessary to select them in the 'output' table.") - error_func = function() - m = MultipleRuns{ - model = MyModel, - showProgress = false, - parameters = {scenario1 ={x = 2, y = 5}}, - repetition = 3, - output = {"fake"} - } - end - - unitTest:assertError(error_func, 'Output value "fake" is not present in the model.') - error_func = function() - m = MultipleRuns{ - model = MyModel, - showProgress = false, - parameters = {scenario1 ={x = 2, y = 5}}, - repetition = 3, - output = {"value", "value"} - } - end - - unitTest:assertError(error_func, "Values in output parameters or additional functions should not be repeated or have the same name.") - error_func = function() - m = MultipleRuns{ - model = MyModel, - showProgress = false, - parameters = {scenario1 ={x = 2, y = 5}}, - repetition = 3, - output = {"value"}, value = function(model) return model.value end } end - unitTest:assertError(error_func, "Values in output parameters or additional functions should not be repeated or have the same name.") + unitTest:assertError(error_func, "Values in model parameters or additional functions should not be repeated or have the same name.") error_func = function() m = MultipleRuns{ model = MyModel, showProgress = false, repetition = 3, - output = {"value"} } end @@ -164,7 +124,6 @@ return{ showProgress = false, parameters = {scenario1 = {x = 2, y = 5, seed = 1001}}, repetition = 3, - output = {"value"} } end @@ -175,8 +134,7 @@ return{ model = MyModel2, showProgress = false, strategy = "factorial", - parameters = {x = Choice{min = 1, max = 5}, y = Choice{1, 2}}, - output = {"value"} + parameters = {x = Choice{min = 1, max = 5}, y = Choice{1, 2}} } end @@ -187,7 +145,6 @@ return{ showProgress = false, strategy = "sample", parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = 5}, - output = {"value"} } end @@ -198,7 +155,6 @@ return{ showProgress = false, strategy = "factorial", parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 1, max = 10}}, - output = {"value"} } end @@ -209,7 +165,6 @@ return{ strategy = "factorial", showProgress = false, parameters = {x = {-100, -1, 0, 1, 2, 100}, y = Choice{min = 1, max = 10, step = 1}}, - output = {"value"} } end @@ -222,7 +177,6 @@ return{ showProgress = false, parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 1, max = 10, step = 1}}, test = "test", - output = {"value"} } end @@ -234,7 +188,6 @@ return{ strategy = "factorial", showProgress = false, parameters = {x = Choice{-100, -1, 0, 1, 2, 99}, y = Choice{min = 1, max = 10, step = 1}}, - output = {"value"} } end @@ -245,7 +198,6 @@ return{ strategy = "factorial", showProgress = false, parameters = {x = Choice{1,2,3}}, - output = {"value"} } end @@ -256,7 +208,6 @@ return{ strategy = "factorial", showProgress = false, parameters = {x = Choice{min = 1, max = 5}, y = Choice{1, 2}}, - output = {"value"} } end @@ -266,8 +217,7 @@ return{ model = MyModel, strategy = "selected", showProgress = false, - parameters = {x = -100, y = 10}, - output = {"value"} + parameters = {x = -100, y = 10} } end @@ -277,8 +227,8 @@ return{ model = MyModel, strategy = "selected", showProgress = false, - parameters = {scenario1 = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 1, max = 10, step = 1}}}, - output = {"value"}} + parameters = {scenario1 = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 1, max = 10, step = 1}}} + } end unitTest:assertError(error_func, "Parameters used in strategy 'selected' cannot be 'Choice'.") @@ -291,7 +241,6 @@ return{ scenario1 = {x = Choice{2,3,4}, y = 5}, scenario2 = {x = 1, y = 3} }, - output = {"value"}, additionalF = function(_) return "test" end @@ -307,7 +256,6 @@ return{ scenario1 = {parameters3 = {x = Choice{2,3}, y = 5}}, scenario2 = {parameters3 = {x = 1, y = 3}} }, - output = {"value"}, additionalF = function(_) return "test" end @@ -322,7 +270,6 @@ return{ parameters = { parameters3 = {x = Choice{1,2,3}, y = 5} }, - output = {"value"}, additionalF = function(_) return "test" end @@ -337,7 +284,6 @@ return{ parameters = { parameters3 = {x = 2, y = 5} }, - output = {"value"}, additionalF = function(_) return "test" end @@ -352,7 +298,6 @@ return{ parameters = { parameters3 = {x = 2, y = 5} }, - output = {"value"}, additionalF = function(_) return "test" end @@ -367,7 +312,6 @@ return{ parameters = { parameters3 = {x = {0,1,2}, y = 5} }, - output = {"value"}, additionalF = function(_) return "test" end diff --git a/tests/core/alternative/Utils.lua b/tests/core/alternative/Utils.lua index fb20850..6639d26 100644 --- a/tests/core/alternative/Utils.lua +++ b/tests/core/alternative/Utils.lua @@ -57,8 +57,7 @@ return{ m = MultipleRuns{ model = MyModel, parameters = {x = Choice{min=1, max=10, step=1}, y = 5}, - repetition = 3, - output = {"value"} + repetition = 3 } end @@ -67,8 +66,7 @@ return{ m = MultipleRuns{ model = MyModel, parameters = {x = 1, y = Choice{min = 5, step = 1}}, - repetition = 3, - output = {"value"} + repetition = 3 } end @@ -76,8 +74,7 @@ return{ m = MultipleRuns{ model = MyModel, strategy = "factorial", - parameters = {x = Choice{min = 2, max = 5, step = 1}, y = Choice{min = 2, max = 5, step = 1}}, - output = {"value"} + parameters = {x = Choice{min = 2, max = 5, step = 1}, y = Choice{min = 2, max = 5, step = 1}} } end @@ -86,8 +83,7 @@ return{ m = MultipleRuns{ model = MyModel, strategy = "factorial", - parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 1}}, - output = {"value"} + parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 1}} } end @@ -96,8 +92,7 @@ return{ m = MultipleRuns{ model = MyModel, strategy = "factorial", - parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 0, max = 10, step = 1}}, - output = {"value"} + parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 0, max = 10, step = 1}} } end @@ -106,8 +101,7 @@ return{ m = MultipleRuns{ model = MyModel, strategy = "factorial", - parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 1, max = 11, step = 1}}, - output = {"value"} + parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 1, max = 11, step = 1}} } end @@ -116,8 +110,7 @@ return{ m = MultipleRuns{ model = MyModel, strategy = "factorial", - parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 1, max = 10, step = 0.5}}, - output = {"value"} + parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 1, max = 10, step = 0.5}} } end @@ -126,8 +119,7 @@ return{ m = MultipleRuns{ model = MyModel, strategy = "factorial", - parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 1.5, max = 9.5, step = 1}}, - output = {"value"} + parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 1.5, max = 9.5, step = 1}} } end @@ -136,8 +128,7 @@ return{ m = MultipleRuns{ model = MyModel, strategy = "factorial", - parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{1, 100}}, - output = {"value"} + parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{1, 100}} } end @@ -146,8 +137,7 @@ return{ m = MultipleRuns{ model = MyModel2, strategy = "factorial", - parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 1, max = 10, step = 1}}, - output = {"value"} + parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 1, max = 10, step = 1}} } end @@ -156,8 +146,7 @@ return{ m = MultipleRuns{ model = MyModel, strategy = "factorial", - parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{1, 1.5}}, - output = {"value"} + parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{1, 1.5}} } end @@ -166,8 +155,7 @@ return{ m = MultipleRuns{ model = MyModel, strategy = "factorial", - parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{2.5, 3}}, - output = {"value"} + parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{2.5, 3}} } end @@ -176,8 +164,7 @@ return{ m = MultipleRuns{ model = MyModel, strategy = "factorial", - parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 1, max = 10}}, - output = {"value"} + parameters = {x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 1, max = 10}} } end diff --git a/tests/core/basic/MultipleRuns.lua b/tests/core/basic/MultipleRuns.lua index 85a29ed..59edac6 100644 --- a/tests/core/basic/MultipleRuns.lua +++ b/tests/core/basic/MultipleRuns.lua @@ -141,11 +141,10 @@ return{ x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 1, max = 10, step = 1}, finalTime = 1 - }, + }, additionalF = function(_) return "test" - end, - output = {"value"} + end } unitTest:assertEquals(m.output.x[1], -100) @@ -161,11 +160,10 @@ return{ y = Choice{min = 1, max = 10, step = 1} }, finalTime = 1 - }, + }, additionalF = function(_) return "test" - end, - output = {"value"} + end } unitTest:assertEquals(mPosition.output[1].position_x, -100) @@ -181,11 +179,10 @@ return{ x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 1, max = 10, step = 1}, finalTime = 1 - }, + }, additionalF = function(_) return "test" - end, - output = {"value"} + end } unitTest:assertEquals(mQuant.output[1].simulations, '1_execution_finalTime_1_x_-100_y_1_') @@ -200,11 +197,10 @@ return{ x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{1,2,3,4,5}, finalTime = 1 - }, + }, additionalF = function(_) return "test" - end, - output = {"value"} + end } unitTest:assertEquals(mQuant2.output[1].simulations, '1_execution_finalTime_1_x_-100_y_1_') @@ -217,11 +213,10 @@ return{ x = Choice{-100, -1, 0, 1, 2, 100}, y2 = Choice{min = 1, max = 10, step = 1}, finalTime = 1 - }, + }, additionalF = function(_) return "test" - end, - output = {"value"} + end } unitTest:assertEquals(mMan.output[1].x, -100) @@ -233,14 +228,13 @@ return{ strategy = "factorial", showProgress = false, parameters = { - x = Choice{-100, -1, 0, 1, 2, 100}, - y2 = Choice{1,2,3,4,5}, + x = Choice{-100, -1, 0, 1, 2, 100}, + y2 = Choice{1,2,3,4,5}, finalTime = 1 - }, + }, additionalF = function(_) return "test" - end, - output = {"value"} + end } unitTest:assertEquals(mMandChoiceTable.output[1].x, -100) @@ -260,8 +254,7 @@ return{ }, additionalF = function(model) return (model.value) - end, - output = {"value"} + end } unitTest:assertEquals(mTab.output[1].parameters3_x, -100) @@ -296,11 +289,10 @@ return{ y = Choice{min = 1, max = 10, step = 1}, z = 1, finalTime = 1 - }, + }, additionalF = function(_) return "test" - end, - output = {"value"} + end } unitTest:assertEquals(mSingle.output[1].x, -100) @@ -314,8 +306,7 @@ return{ parameters = { scenario1 = {x = 2, y = 5}, scenario2 = {x = 1, y = 3} - }, - output = {"value"}, + }, additionalF = function(_) return "test" end @@ -333,8 +324,7 @@ return{ parameters = { scenario1 = {parameters3 = {x = 2, y = 5, z = 1}}, scenario2 = {parameters3 = {x = 1, y = 3, z = 1}} - }, - output = {"value"} + } } unitTest:assertEquals(m2Tab.output[1].parameters3.x, 2) @@ -348,7 +338,6 @@ return{ showProgress = false, parameters = {scenario1 = {x = 2, y = 5}}, repetition = 3, - output = {"value"}, additionalF = function(_) return "test" end @@ -366,8 +355,7 @@ return{ model = MyModel3, showProgress = false, parameters = {scenario1 = {parameters3 = {x = 2, y = 5, z = 1}}}, - repetition = 3, - output = {"value"} + repetition = 3 } -- CHECK HERE!! It should be parameters3_x @@ -386,9 +374,8 @@ return{ parameters = { x = Choice{-100, -1, 0, 1, 2, 100}, y = Choice{min = 1, max = 10, step = 1} - }, + }, quantity = 5, - output = {"value"}, additionalF = function(_) return "test" end @@ -407,8 +394,7 @@ return{ z = 1, finalTime = 1 }, - quantity = 5, - output = {"value"} + quantity = 5 } unitTest:assertEquals(m4Single.output[5].simulations, "5") @@ -426,8 +412,7 @@ return{ }, }, quantity = 5, - repetition = 2, - output = {"value"} + repetition = 2 } unitTest:assertEquals(m4Tab.output[5].simulations, "1_execution_3") @@ -441,7 +426,6 @@ return{ x = Choice{-1, 0, 1}, }, repetition = 2, - output = {"value"}, additionalF = function(model) return model.x end, @@ -517,7 +501,6 @@ return{ scenario2 = {x = 1, y = 3} }, repetition = 2, - output = {"value"}, additionalF = function() return 1 end, diff --git a/tests/core/basic/Utils.lua b/tests/core/basic/Utils.lua index 820513c..255b153 100644 --- a/tests/core/basic/Utils.lua +++ b/tests/core/basic/Utils.lua @@ -79,8 +79,7 @@ return{ }, additionalF = function() return "test" - end, - output = {"value"} + end } unitTest:assertEquals(mPosition.output.position_x[1], -100) @@ -109,8 +108,7 @@ return{ }, additionalF = function(_) return "test" - end, - output = {"value"} + end } unitTest:assertEquals(mPosition2.output[1].position.x, -100) @@ -128,8 +126,7 @@ return{ }, }, quantity = 5, - repetition = 2, - output = {"value"} + repetition = 2 } unitTest:assertEquals(m4Tab.output.simulations[5], "1_execution_3") From 18f3b0310a41de956357e45b6a135b2faeed418a Mon Sep 17 00:00:00 2001 From: wsenafranca Date: Wed, 6 Dec 2017 16:26:33 -0200 Subject: [PATCH 03/11] Fix to remove MultipleRuns:output for sample strategy. --- lua/MultipleRuns.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/MultipleRuns.lua b/lua/MultipleRuns.lua index 54723d1..ce12230 100644 --- a/lua/MultipleRuns.lua +++ b/lua/MultipleRuns.lua @@ -164,7 +164,7 @@ local function testAddFunctions(resultTable, addFunctions, data, m, summaryResul end) end - if not data.parameters[attr] and not foundOnParameters then + if not data.parameters[attr] and not foundOnParameters or data.strategy == "sample" then table.insert(resultTable[attr], value) end end From fafdb8f023c398235ae88e2699ef3848953d14c8 Mon Sep 17 00:00:00 2001 From: wsenafranca Date: Thu, 7 Dec 2017 14:52:11 -0200 Subject: [PATCH 04/11] Close #48 - Redirect every print from models to log files in Multiple Runs --- lua/MultipleRuns.lua | 95 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 12 deletions(-) diff --git a/lua/MultipleRuns.lua b/lua/MultipleRuns.lua index ce12230..3d6b844 100644 --- a/lua/MultipleRuns.lua +++ b/lua/MultipleRuns.lua @@ -262,6 +262,24 @@ local function countSimulations(params, i) return count end +local function redirectPrint(f) + local log = "" + local oldPrint = print + print = function(...) + local str = "" + for _, v in ipairs({...}) do + str = str .. v .. "\t" -- SKIP + end + + log = log .. str .. "\n" -- SKIP + end + + f() + + print = oldPrint + return log +end + -- function used in run() to test the model with all the possible combinations of parameters. -- params: Table with all the parameters and it's ranges or values indexed by number. -- Example: params = {{id = "x", min = 1, max = 10, elements = nil, ranged = true, step = 2}, @@ -326,7 +344,12 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu local testDir = folderDir firstDir:setCurrentDir() local simulationTime = sessionInfo().time - local m = data.model(mVariables) + local logs = "" + local m + logs = logs..redirectPrint(function() + m = data.model(mVariables) + end) + testDir:setCurrentDir() if data.folderName then local dir = Directory(stringSimulations) @@ -341,7 +364,10 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu end print(string.format("Running simulation %d/%d (%s)", numSimulation, maxSimulations, title)) -- SKIP - m:run() -- SKIP + logs = logs..redirectPrint(function() + m:run() -- SKIP + end) + simulationTime = round(sessionInfo().time - simulationTime) -- SKIP print(string.format("Simulation finished in %s", timeToString(simulationTime))) -- SKIP iterationTime = sessionInfo().time - iterationTime -- SKIP @@ -357,9 +383,15 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu local timeString = os.date("%H:%M", round(initialTime + estimatedTime)) print(string.format("Estimated time to finish all simulations: %s (%s)", timeString, timeToString(timeLeft))) -- SKIP else - m:run() + logs = logs..redirectPrint(function() + m:run() + end) + end + local logfile = File("output.log") + logfile:writeLine(logs) + logfile:close() clean() testAddFunctions(resultTable, addFunctions, data, m, summaryResult) testDir:setCurrentDir() @@ -436,7 +468,12 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu local testDir = folderDir firstDir:setCurrentDir() local simulationTime = sessionInfo().time - local m = data.model(mVariables) + local logs = "" + local m + logs = logs..redirectPrint(function() + m = data.model(mVariables) + end) + testDir:setCurrentDir() if data.folderName then local dir = Directory(stringSimulations) @@ -451,7 +488,10 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu end print(string.format("Running simulation %d/%d (%s)", numSimulation, maxSimulations, title)) -- SKIP - m:run() -- SKIP + logs = logs..redirectPrint(function() + m:run() -- SKIP + end) + simulationTime = round(sessionInfo().time - simulationTime) -- SKIP print(string.format("Simulation finished in %s", timeToString(simulationTime))) -- SKIP iterationTime = sessionInfo().time - iterationTime -- SKIP @@ -467,9 +507,14 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu local timeString = os.date("%H:%M", round(initialTime + estimatedTime)) print(string.format("Estimated time to finish all simulations: %s (%s)", timeString, timeToString(timeLeft))) -- SKIP else - m:run() + logs = logs..redirectPrint(function() + m:run() + end) end + local logfile = File("output.log") + logfile:writeLine(logs) + logfile:close() clean() testAddFunctions(resultTable, addFunctions, data, m, summaryResult) testDir:setCurrentDir() @@ -806,7 +851,12 @@ function MultipleRuns(data) local simulationTime = sessionInfo().time firstDir:setCurrentDir() - local m = randomModel(data.model, data.parameters, true) + local logs = "" + local m + logs = logs..redirectPrint(function() + m = randomModel(data.model, data.parameters, true) + end) + if data.folderName then folderDir:setCurrentDir() local dir = Directory(stringSimulations..quantity) @@ -821,7 +871,10 @@ function MultipleRuns(data) end print(string.format("Running simulation %d/%d (%s)", numSimulation, maxSimulations, title)) -- SKIP - m:run() -- SKIP + logs = logs..redirectPrint(function() + m:run() -- SKIP + end) + simulationTime = round(sessionInfo().time - simulationTime) -- SKIP print(string.format("Simulation finished in %s", timeToString(simulationTime))) -- SKIP iterationTime = sessionInfo().time - iterationTime -- SKIP @@ -837,9 +890,14 @@ function MultipleRuns(data) local timeString = os.date("%H:%M", round(initialTime + estimatedTime)) print(string.format("Estimated time to finish all simulations: %s (%s)", timeString, timeToString(timeLeft))) -- SKIP else - m:run() + logs = logs..redirectPrint(function() + m:run() + end) end + local logfile = File("output.log") + logfile:writeLine(logs) + logfile:close() clean() testAddFunctions(resultTable, addFunctions, data, m, summaryResult) forEachOrderedElement(data.parameters, function(idx2, att2, typ2) @@ -915,7 +973,12 @@ function MultipleRuns(data) table.insert(resultTable.simulations, stringSimulations..idx) local simulationTime = sessionInfo().time firstDir:setCurrentDir() - local m = data.model(clone(att)) + local logs = "" + local m + logs = logs..redirectPrint(function() + m = data.model(clone(att)) + end) + if data.folderName then folderDir:setCurrentDir() local dir = Directory(stringSimulations..idx) @@ -930,7 +993,10 @@ function MultipleRuns(data) end print(string.format("Running simulation %d/%d (%s)", numSimulation, maxSimulations, title)) -- SKIP - m:run() -- SKIP + logs = logs..redirectPrint(function() + m:run() -- SKIP + end) + simulationTime = round(sessionInfo().time - simulationTime) -- SKIP print(string.format("Simulation finished in %s", timeToString(simulationTime))) -- SKIP iterationTime = sessionInfo().time - iterationTime -- SKIP @@ -946,9 +1012,14 @@ function MultipleRuns(data) local timeString = os.date("%H:%M", round(initialTime + estimatedTime)) print(string.format("Estimated time to finish all simulations: %s (%s)", timeString, timeToString(timeLeft))) -- SKIP else - m:run() + logs = logs..redirectPrint(function() + m:run() + end) end + local logfile = File("output.log") + logfile:writeLine(logs) + logfile:close() clean() testAddFunctions(resultTable, addFunctions, data, m, summaryResult) forEachOrderedElement(data.parameters[idx], function(idx2, att2) From 082407e6165c87a580d192efa98b6416005cd2d0 Mon Sep 17 00:00:00 2001 From: wsenafranca Date: Tue, 12 Dec 2017 09:15:22 -0200 Subject: [PATCH 05/11] Close #189 - Add MultipleRuns:free to remove unnecessary memory --- lua/MultipleRuns.lua | 39 +++++++++++-- tests/core/basic/MultipleRuns.lua | 97 +++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 4 deletions(-) diff --git a/lua/MultipleRuns.lua b/lua/MultipleRuns.lua index 3d6b844..9afa700 100644 --- a/lua/MultipleRuns.lua +++ b/lua/MultipleRuns.lua @@ -280,6 +280,12 @@ local function redirectPrint(f) return log end +local function freeModel(model) + forEachElement(model, function(member) + model[member] = nil + end) +end + -- function used in run() to test the model with all the possible combinations of parameters. -- params: Table with all the parameters and it's ranges or values indexed by number. -- Example: params = {{id = "x", min = 1, max = 10, elements = nil, ranged = true, step = 2}, @@ -396,6 +402,11 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu testAddFunctions(resultTable, addFunctions, data, m, summaryResult) testDir:setCurrentDir() table.insert(resultTable.simulations, stringSimulations) + if data.free then + freeModel(m) + m = nil + collectgarbage() + end end if data.summary and type(data.summary) == "function" then @@ -519,6 +530,11 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu testAddFunctions(resultTable, addFunctions, data, m, summaryResult) testDir:setCurrentDir() table.insert(resultTable.simulations, stringSimulations) + if data.free then + freeModel(m) + m = nil + collectgarbage() + end end if data.summary then @@ -666,6 +682,8 @@ metaTableMultipleRuns_ = { -- @arg data.folderName Name or file path of the folder where the simulations output will be saved. -- Whenever the Model saves one or more files along its simulation, it is necessary to use this -- argument to guarantee that the files of each simulation will be saved in a different directory. +-- @arg data.free If true, then the memory used by Model instances will be removed after their simulations. Only the observed +-- properties of the model will be stored within MultipleRuns, (Default is false). -- @arg data.hideGraphics If true (default), then sessionInfo().graphics will disable all charts and observers during models execution. -- @arg data.showProgress If true, a message is printed on screen to show the models executions progress on repeated strategy, -- (Default is false). @@ -677,13 +695,13 @@ metaTableMultipleRuns_ = { -- @tabular strategy -- Strategy & Description & Mandatory arguments & Optional arguments \ -- "factorial" & Simulate the Model with all combinations of the argument parameters. --- & parameters, model & repetition, output, hideGraphics, quantity, folderName, showProgress, ... \ +-- & parameters, model & repetition, output, hideGraphics, quantity, folderName, free, showProgress, ... \ -- "sample" & Run the model with a random combination of the possible parameters & parameters, --- repetition, model & output, folderName, hideGraphics, quantity, showProgress, ... \ +-- repetition, model & output, folderName, free, hideGraphics, quantity, showProgress, ... \ -- "selected" & This should test the Model with a given set of parameters values. In this case, -- the argument parameters must be a named table, where each position is another table describing -- the parameters to be used in such simulation. & --- model, parameters & output, folderName, hideGraphics, repetition, showProgress, quantity, ... +-- model, parameters & output, folderName, free, hideGraphics, repetition, showProgress, quantity, ... function MultipleRuns(data) mandatoryTableArgument(data, "model", "Model") mandatoryTableArgument(data, "parameters", "table") @@ -695,6 +713,7 @@ function MultipleRuns(data) defaultTableValue(data, "hideGraphics", true) defaultTableValue(data, "showProgress", true) optionalTableArgument(data, "summary", "function") + defaultTableValue(data, "free", false) if data.strategy == nil then local choiceStrg = false @@ -742,7 +761,7 @@ function MultipleRuns(data) local checkingArgument = {} checkingArgument[idx] = idx verifyUnnecessaryArguments(checkingArgument, { - "model", "strategy", "parameters", "repetition", "folderName", "hideGraphics", "showProgress", "repeat", "quantity", "outputVariables"}) + "model", "strategy", "parameters", "repetition", "folderName", "hideGraphics", "showProgress", "repeat", "quantity", "outputVariables", "free"}) end end) @@ -921,6 +940,12 @@ function MultipleRuns(data) table.insert(resultTable[idx2], att2) end) + + if data.free then + freeModel(m) + m = nil + collectgarbage() + end end if data.summary then @@ -1029,6 +1054,12 @@ function MultipleRuns(data) table.insert(resultTable[idx2], att2) end) + + if data.free then + freeModel(m) + m = nil + collectgarbage() + end end if data.summary then diff --git a/tests/core/basic/MultipleRuns.lua b/tests/core/basic/MultipleRuns.lua index 59edac6..f47a543 100644 --- a/tests/core/basic/MultipleRuns.lua +++ b/tests/core/basic/MultipleRuns.lua @@ -126,6 +126,46 @@ local MyModel6 = Model{ end } +local MyModel7 = Model{ + x = 1, + y = 1, + finalTime = 1, + init = function(self) + self.timer = Timer{ + Event{action = function() + self.iniMem = collectgarbage("count") / 1024 -- in megabytes + self.z = {} + for i = 1, 100000 do + self.z[i] = i + end + + self.finMem = collectgarbage("count") / 1024 + end} + } + end +} + +local MyModel8 = Model{ + p = { + x = Choice{-1, 0, 1}, + y = Choice{min= - 1, max = 1, step = 1}, + }, + finalTime = 1, + init = function(self) + self.timer = Timer{ + Event{action = function() + self.iniMem = collectgarbage("count") / 1024 -- in megabytes + self.z = {} + for i = 1, 100000 do + self.z[i] = i + end + + self.finMem = collectgarbage("count") / 1024 + end} + } + end +} + local function fileExists(name) local sep = sessionInfo().separator return File(currentDir().."results"..sep..name..sep.."data.csv"):exists() @@ -659,5 +699,62 @@ return{ unitTest:assert(fileExists("1_execution_3")) unitTest:assert(fileExists("2_execution_3")) unitTest:assert(Directory(currentDir().."results"):delete()) + + local free1 = MultipleRuns{ + model = MyModel7, + showProgress = false, + free = true, + parameters = { + x = Choice{-1, 0, 1}, + y = Choice{-1, 0, 1} + } + } + + unitTest:assertEquals(free1.output.iniMem[3], free1.output.iniMem[6], 1) + unitTest:assertEquals(free1.output.finMem[3], free1.output.finMem[6], 1) + + local free2 = MultipleRuns{ + model = MyModel7, + showProgress = false, + free = true, + strategy = "sample", + parameters = { + x = Choice{-1, 0, 1}, + y = Choice{-1, 0, 1} + }, + quantity = 9 + } + + unitTest:assertEquals(free2.output.iniMem[3], free2.output.iniMem[6], 1) + unitTest:assertEquals(free2.output.finMem[3], free2.output.finMem[6], 1) + + local free3 = MultipleRuns{ + model = MyModel7, + showProgress = false, + free = true, + strategy = "selected", + parameters = { + scenario1 = {x = -1, y = -1}, + scenario2 = {x = 0, y = 0}, + scenario3 = {x = 1, y = 1} + }, + repetition = 3 + } + + unitTest:assertEquals(free3.output.iniMem[3], free3.output.iniMem[6], 1) + unitTest:assertEquals(free3.output.finMem[3], free3.output.finMem[6], 1) + + local free4 = MultipleRuns{ + model = MyModel8, + showProgress = false, + free = true, + parameters = {p = { + x = Choice{-1, 0, 1}, + y = Choice{min= - 1, max = 1, step = 1} + }}, + } + + unitTest:assertEquals(free4.output.iniMem[3], free4.output.iniMem[6], 1) + unitTest:assertEquals(free4.output.finMem[3], free4.output.finMem[6], 1) end } From c80cf0205dcd45c5a55002b61b815f6badf01de1 Mon Sep 17 00:00:00 2001 From: wsenafranca Date: Wed, 13 Dec 2017 14:36:24 -0200 Subject: [PATCH 06/11] Review the message shown for output function error #172 --- lua/MultipleRuns.lua | 11 +++++++---- tests/core/alternative/MultipleRuns.lua | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lua/MultipleRuns.lua b/lua/MultipleRuns.lua index 9afa700..2849546 100644 --- a/lua/MultipleRuns.lua +++ b/lua/MultipleRuns.lua @@ -144,7 +144,7 @@ end local function testAddFunctions(resultTable, addFunctions, data, m, summaryResult) forEachElement(m, function(attr, value, typ) if addFunctions[attr] ~= nil then - customError("Values in model parameters or additional functions should not be repeated or have the same name.") + customError("It is not possible to use function '"..attr.."' as output because this name is already an output value of the model.") end if typ == "number" then @@ -687,6 +687,9 @@ metaTableMultipleRuns_ = { -- @arg data.hideGraphics If true (default), then sessionInfo().graphics will disable all charts and observers during models execution. -- @arg data.showProgress If true, a message is printed on screen to show the models executions progress on repeated strategy, -- (Default is false). +-- @arg data.summary A function can be defined by the user to summarize results after executing all repetitions of a set of parameters. +-- This function gets as a parameter a table containing the values of each variable, the results of each simulation and results of each +-- user-defined functions. -- @arg data.strategy Strategy to be used when testing the model. See the table below: -- @arg data.... Additional functions can be defined by the user. Such functions are -- executed each time a simulation of a Model ends and get as parameter the model instance @@ -695,13 +698,13 @@ metaTableMultipleRuns_ = { -- @tabular strategy -- Strategy & Description & Mandatory arguments & Optional arguments \ -- "factorial" & Simulate the Model with all combinations of the argument parameters. --- & parameters, model & repetition, output, hideGraphics, quantity, folderName, free, showProgress, ... \ +-- & parameters, model & repetition, output, hideGraphics, quantity, folderName, free, showProgress, summary, ... \ -- "sample" & Run the model with a random combination of the possible parameters & parameters, --- repetition, model & output, folderName, free, hideGraphics, quantity, showProgress, ... \ +-- repetition, model & output, folderName, free, hideGraphics, quantity, showProgress, summary, ... \ -- "selected" & This should test the Model with a given set of parameters values. In this case, -- the argument parameters must be a named table, where each position is another table describing -- the parameters to be used in such simulation. & --- model, parameters & output, folderName, free, hideGraphics, repetition, showProgress, quantity, ... +-- model, parameters & output, folderName, free, hideGraphics, quantity, repetition, showProgress, summary, ... function MultipleRuns(data) mandatoryTableArgument(data, "model", "Model") mandatoryTableArgument(data, "parameters", "table") diff --git a/tests/core/alternative/MultipleRuns.lua b/tests/core/alternative/MultipleRuns.lua index b5420fb..f8776e5 100644 --- a/tests/core/alternative/MultipleRuns.lua +++ b/tests/core/alternative/MultipleRuns.lua @@ -109,7 +109,7 @@ return{ } end - unitTest:assertError(error_func, "Values in model parameters or additional functions should not be repeated or have the same name.") + unitTest:assertError(error_func, "It is not possible to use function 'value' as output because this name is already an output value of the model.") error_func = function() m = MultipleRuns{ model = MyModel, From 674db420a87cf4888709fcc0c493ac92b6659fea Mon Sep 17 00:00:00 2001 From: wsenafranca Date: Wed, 13 Dec 2017 16:05:37 -0200 Subject: [PATCH 07/11] Review the function to redirect output #48 --- lua/MultipleRuns.lua | 50 +++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/lua/MultipleRuns.lua b/lua/MultipleRuns.lua index 2849546..4d23429 100644 --- a/lua/MultipleRuns.lua +++ b/lua/MultipleRuns.lua @@ -262,22 +262,20 @@ local function countSimulations(params, i) return count end -local function redirectPrint(f) - local log = "" +local function redirectPrint(log, f) local oldPrint = print print = function(...) - local str = "" + local line = {} for _, v in ipairs({...}) do - str = str .. v .. "\t" -- SKIP + table.insert(line, v) -- SKIP end - log = log .. str .. "\n" -- SKIP + table.insert(log, table.concat(line, "\t")) -- SKIP end f() print = oldPrint - return log end local function freeModel(model) @@ -350,9 +348,9 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu local testDir = folderDir firstDir:setCurrentDir() local simulationTime = sessionInfo().time - local logs = "" + local log = {} local m - logs = logs..redirectPrint(function() + redirectPrint(log, function() m = data.model(mVariables) end) @@ -370,7 +368,7 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu end print(string.format("Running simulation %d/%d (%s)", numSimulation, maxSimulations, title)) -- SKIP - logs = logs..redirectPrint(function() + redirectPrint(log, function() m:run() -- SKIP end) @@ -389,14 +387,14 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu local timeString = os.date("%H:%M", round(initialTime + estimatedTime)) print(string.format("Estimated time to finish all simulations: %s (%s)", timeString, timeToString(timeLeft))) -- SKIP else - logs = logs..redirectPrint(function() + redirectPrint(log, function() m:run() end) end local logfile = File("output.log") - logfile:writeLine(logs) + logfile:writeLine(table.concat(log, "\n")) logfile:close() clean() testAddFunctions(resultTable, addFunctions, data, m, summaryResult) @@ -479,9 +477,9 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu local testDir = folderDir firstDir:setCurrentDir() local simulationTime = sessionInfo().time - local logs = "" + local log = {} local m - logs = logs..redirectPrint(function() + redirectPrint(log, function() m = data.model(mVariables) end) @@ -499,7 +497,7 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu end print(string.format("Running simulation %d/%d (%s)", numSimulation, maxSimulations, title)) -- SKIP - logs = logs..redirectPrint(function() + redirectPrint(log, function() m:run() -- SKIP end) @@ -518,13 +516,13 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu local timeString = os.date("%H:%M", round(initialTime + estimatedTime)) print(string.format("Estimated time to finish all simulations: %s (%s)", timeString, timeToString(timeLeft))) -- SKIP else - logs = logs..redirectPrint(function() + redirectPrint(log, function() m:run() end) end local logfile = File("output.log") - logfile:writeLine(logs) + logfile:writeLine(table.concat(log, "\n")) logfile:close() clean() testAddFunctions(resultTable, addFunctions, data, m, summaryResult) @@ -873,9 +871,9 @@ function MultipleRuns(data) local simulationTime = sessionInfo().time firstDir:setCurrentDir() - local logs = "" + local log = {} local m - logs = logs..redirectPrint(function() + redirectPrint(log, function() m = randomModel(data.model, data.parameters, true) end) @@ -893,7 +891,7 @@ function MultipleRuns(data) end print(string.format("Running simulation %d/%d (%s)", numSimulation, maxSimulations, title)) -- SKIP - logs = logs..redirectPrint(function() + redirectPrint(log, function() m:run() -- SKIP end) @@ -912,13 +910,13 @@ function MultipleRuns(data) local timeString = os.date("%H:%M", round(initialTime + estimatedTime)) print(string.format("Estimated time to finish all simulations: %s (%s)", timeString, timeToString(timeLeft))) -- SKIP else - logs = logs..redirectPrint(function() + redirectPrint(log, function() m:run() end) end local logfile = File("output.log") - logfile:writeLine(logs) + logfile:writeLine(table.concat(log, "\n")) logfile:close() clean() testAddFunctions(resultTable, addFunctions, data, m, summaryResult) @@ -1001,9 +999,9 @@ function MultipleRuns(data) table.insert(resultTable.simulations, stringSimulations..idx) local simulationTime = sessionInfo().time firstDir:setCurrentDir() - local logs = "" + local log = {} local m - logs = logs..redirectPrint(function() + redirectPrint(log, function() m = data.model(clone(att)) end) @@ -1021,7 +1019,7 @@ function MultipleRuns(data) end print(string.format("Running simulation %d/%d (%s)", numSimulation, maxSimulations, title)) -- SKIP - logs = logs..redirectPrint(function() + redirectPrint(log, function() m:run() -- SKIP end) @@ -1040,13 +1038,13 @@ function MultipleRuns(data) local timeString = os.date("%H:%M", round(initialTime + estimatedTime)) print(string.format("Estimated time to finish all simulations: %s (%s)", timeString, timeToString(timeLeft))) -- SKIP else - logs = logs..redirectPrint(function() + redirectPrint(log, function() m:run() end) end local logfile = File("output.log") - logfile:writeLine(logs) + logfile:writeLine(table.concat(log, "\n")) logfile:close() clean() testAddFunctions(resultTable, addFunctions, data, m, summaryResult) From 66430530df1dfd20d0e007f05a46860c2fc3e84e Mon Sep 17 00:00:00 2001 From: wsenafranca Date: Wed, 13 Dec 2017 16:24:10 -0200 Subject: [PATCH 08/11] Remove internal call to run model in randomModel #164 --- lua/MultipleRuns.lua | 2 +- lua/Utils.lua | 8 ++------ tests/core/alternative/Utils.lua | 6 ++++-- tests/core/basic/Utils.lua | 16 ++++++++++------ 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/lua/MultipleRuns.lua b/lua/MultipleRuns.lua index 4d23429..f0502e5 100644 --- a/lua/MultipleRuns.lua +++ b/lua/MultipleRuns.lua @@ -874,7 +874,7 @@ function MultipleRuns(data) local log = {} local m redirectPrint(log, function() - m = randomModel(data.model, data.parameters, true) + m = randomModel(data.model, data.parameters) end) if data.folderName then diff --git a/lua/Utils.lua b/lua/Utils.lua index 8ca5f6f..c972f60 100644 --- a/lua/Utils.lua +++ b/lua/Utils.lua @@ -209,7 +209,7 @@ end -- } -- local parameters = {x = Choice{-100,- 1, 0, 1, 2, 100}, y = Choice{min = 1, max = 8, step = 1}} -- randomModel(myModel, parameters) -function randomModel(tModel, tParameters, skipRun) +function randomModel(tModel, tParameters) mandatoryArgument(1, "Model", tModel) mandatoryArgument(1, "table", tParameters) local sampleParams = {} @@ -232,12 +232,8 @@ function randomModel(tModel, tParameters, skipRun) sampleParams[idx] = attribute end end) - local m = tModel(sampleParams) - if not skipRun then -- needed to run models in the correct directory and to save their outputs correctly - m:run() - end - return m + return tModel(sampleParams) end --- Function that returns the time in a higher-level representation. diff --git a/tests/core/alternative/Utils.lua b/tests/core/alternative/Utils.lua index 6639d26..e31dd9c 100644 --- a/tests/core/alternative/Utils.lua +++ b/tests/core/alternative/Utils.lua @@ -29,12 +29,14 @@ local error_func return{ randomModel = function(unitTest) error_func = function() - randomModel("test", {x = Choice{1, 2, 3}, y = Choice{3, 4, 5}}) + local m = randomModel("test", {x = Choice{1, 2, 3}, y = Choice{3, 4, 5}}) + m:run() end unitTest:assertError(error_func, "Incompatible types. Argument '#1' expected Model, got string.") error_func = function() - randomModel(MyModel, "test") + local m = randomModel(MyModel, "test") + m:run() end unitTest:assertError(error_func, "Incompatible types. Argument '#1' expected table, got string.") diff --git a/tests/core/basic/Utils.lua b/tests/core/basic/Utils.lua index 255b153..7dcb0bd 100644 --- a/tests/core/basic/Utils.lua +++ b/tests/core/basic/Utils.lua @@ -42,16 +42,20 @@ local MyModelPosition = Model{ return{ randomModel = function(unitTest) local rParam = { - x = Choice{-100, -1, 0, 1, 2, 100}, - y = Choice{min = 1, max = 10, step = 1} - } + x = Choice{-100, -1, 0, 1, 2, 100}, + y = Choice{min = 1, max = 10, step = 1} + } + local rs = randomModel(MyModel, rParam) + rs:run() unitTest:assertEquals(type(rs.value), "number") rParam = { - x = Choice{-100, -1, 0, 1, 2, 100}, - y = 5 - } + x = Choice{-100, -1, 0, 1, 2, 100}, + y = 5 + } + rs = randomModel(MyModel, rParam) + rs:run() unitTest:assertEquals(type(rs.value), "number") end, -- These are error verification functions so it's impossible to properly test them without veryfing the errors, From b6dd657866c76c937e823961f64881951f6639e4 Mon Sep 17 00:00:00 2001 From: wsenafranca Date: Wed, 13 Dec 2017 16:32:58 -0200 Subject: [PATCH 09/11] Remove freeModel function #164 --- lua/MultipleRuns.lua | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/lua/MultipleRuns.lua b/lua/MultipleRuns.lua index f0502e5..67abf01 100644 --- a/lua/MultipleRuns.lua +++ b/lua/MultipleRuns.lua @@ -278,12 +278,6 @@ local function redirectPrint(log, f) print = oldPrint end -local function freeModel(model) - forEachElement(model, function(member) - model[member] = nil - end) -end - -- function used in run() to test the model with all the possible combinations of parameters. -- params: Table with all the parameters and it's ranges or values indexed by number. -- Example: params = {{id = "x", min = 1, max = 10, elements = nil, ranged = true, step = 2}, @@ -401,7 +395,6 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu testDir:setCurrentDir() table.insert(resultTable.simulations, stringSimulations) if data.free then - freeModel(m) m = nil collectgarbage() end @@ -529,7 +522,6 @@ local function factorialRecursive(data, params, a, variables, resultTable, addFu testDir:setCurrentDir() table.insert(resultTable.simulations, stringSimulations) if data.free then - freeModel(m) m = nil collectgarbage() end @@ -680,8 +672,8 @@ metaTableMultipleRuns_ = { -- @arg data.folderName Name or file path of the folder where the simulations output will be saved. -- Whenever the Model saves one or more files along its simulation, it is necessary to use this -- argument to guarantee that the files of each simulation will be saved in a different directory. --- @arg data.free If true, then the memory used by Model instances will be removed after their simulations. Only the observed --- properties of the model will be stored within MultipleRuns, (Default is false). +-- @arg data.free If true, then the memory used by Model instances will be removed after each simulation. Only the observed +-- properties of the model will be stored within MultipleRuns. Default is false. -- @arg data.hideGraphics If true (default), then sessionInfo().graphics will disable all charts and observers during models execution. -- @arg data.showProgress If true, a message is printed on screen to show the models executions progress on repeated strategy, -- (Default is false). @@ -943,7 +935,6 @@ function MultipleRuns(data) end) if data.free then - freeModel(m) m = nil collectgarbage() end @@ -1057,7 +1048,6 @@ function MultipleRuns(data) end) if data.free then - freeModel(m) m = nil collectgarbage() end From 7ee24fbf00b27197d29155cbc72cfedfd9277b5d Mon Sep 17 00:00:00 2001 From: wsenafranca Date: Wed, 13 Dec 2017 16:34:15 -0200 Subject: [PATCH 10/11] Close #159 - Remove graphics from multiLevel --- lua/GoodnessOfFit.lua | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/lua/GoodnessOfFit.lua b/lua/GoodnessOfFit.lua index 80ca1ae..e0df305 100644 --- a/lua/GoodnessOfFit.lua +++ b/lua/GoodnessOfFit.lua @@ -259,41 +259,28 @@ multiLevel = function(data) end local fitnessSum = pixelByPixel(data.cs1, data.cs2, data.attribute, data.attribute, data.continuous) - local fitChart = Cell{sqrFit = fitnessSum} - if data.graphics == true then - Chart{ --SKIP - title = "MultiLevel Results", --SKIP - target = fitChart, --SKIP - select = {"sqrFit"} --SKIP - } --SKIP - fitChart:notify(0) --SKIP - end - + local fitSquareTable = {} + local resolutionTable = {} + table.insert(fitSquareTable, fitnessSum) + table.insert(resolutionTable, 0) if data.continuous == true then for i = 1, (largerSquare) do -- increase the square size and calculate fitness for each square. local fitSquare = continuousSquareBySquare(i, data.cs1, data.cs2, data.attribute) if fitSquare ~= -1 then - if data.graphics == true then - fitChart.sqrFit = fitSquare --SKIP - fitChart:notify(i) --SKIP - end - + table.insert(fitSquareTable, fitSquare) + table.insert(resolutionTable, i) fitnessSum = fitnessSum + (fitSquare * math.exp(-k * 2 ^ (i - 1))) exp = exp + math.exp(-k * 2 ^ (i - 1)) end end - else for i = 1, (largerSquare) do -- increase the square size and calculate fitness for each square. local fitSquare = newDiscreteSquareBySquare(i, data.cs1, data.cs2, data.attribute) if fitSquare ~= -1 then - if data.graphics == true then - fitChart.sqrFit = fitSquare --SKIP - fitChart:notify(i) --SKIP - end - + table.insert(fitSquareTable, fitSquare) + table.insert(resolutionTable, i) fitnessSum = fitnessSum + (fitSquare * math.exp(-k * 2 ^ (i - 1))) exp = exp + math.exp(-k * 2 ^ (i - 1)) end @@ -301,5 +288,6 @@ multiLevel = function(data) end local fitness = fitnessSum / exp - return fitness + local df = DataFrame{fit = fitSquareTable, resolution = resolutionTable} + return fitness, df end From eb72097c8f54986ef7df3f2231ac1d0aa5de1cba Mon Sep 17 00:00:00 2001 From: wsenafranca Date: Wed, 13 Dec 2017 16:41:40 -0200 Subject: [PATCH 11/11] Remove skipRun from doc --- lua/Utils.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lua/Utils.lua b/lua/Utils.lua index c972f60..0286b8b 100644 --- a/lua/Utils.lua +++ b/lua/Utils.lua @@ -190,9 +190,7 @@ end -- This function can be used by SaMDE as well as by MultipleRuns. -- @arg tModel The Model to be instantiated. -- @arg tParameters A table of possible parameters for the model. --- @arg skipRun An optional argument to determine whether the model will skip his execution or not after being created. --- The default value is false meaning that the model will be executed internally by runModel. --- Multiple Runs or Calibration instance . +-- Multiple Runs or Calibration instance. -- @usage -- import("calibration") -- local myModel = Model{