179 lines
5.8 KiB
Lua
179 lines
5.8 KiB
Lua
-------------------------------------------------------------------------------
|
|
---Description of the module.
|
|
---@class SolverAlgebra
|
|
SolverAlgebra = newclass(Solver,function(base, object)
|
|
Solver.init(base, object)
|
|
end)
|
|
|
|
-------------------------------------------------------------------------------
|
|
---Retourne la colonne
|
|
---@param M table
|
|
---@param xrow number
|
|
---@param invert boolean
|
|
---@return table
|
|
function SolverAlgebra:getCol(M, xrow, invert)
|
|
local row = M[xrow]
|
|
local zrow = M[#M]
|
|
local xcol = 0
|
|
local max = 0
|
|
local col_master = 0
|
|
local col_exclude = 0
|
|
if row[self.col_Cn] > 0 then
|
|
col_master = row[self.col_Cn]
|
|
end
|
|
if row[self.col_Cn] < 0 then
|
|
col_exclude = -row[self.col_Cn]
|
|
end
|
|
---on cherche la plus grande demande
|
|
for icol,cell_value in pairs(row) do
|
|
if icol > self.col_start and ((invert ~= true and cell_value > 0) or (invert == true and cell_value < 0)) then
|
|
local zvalue = M[#M][icol]
|
|
local Z = zvalue-M[self.row_input][icol] ---valeur demandee (Z-input)
|
|
local C = -Z/cell_value
|
|
-- if zvalue = 0 the choose is already use
|
|
if (C > max and zvalue ~= 0 and col_master == 0 and col_exclude == 0)
|
|
or (col_master ~= 0 and col_master == icol)
|
|
or (C > max and col_exclude ~= 0 and col_exclude ~= icol) then
|
|
max = C
|
|
xcol = icol
|
|
end
|
|
end
|
|
end
|
|
---cas des voider
|
|
if xcol == 0 then
|
|
for icol,cell_value in pairs(row) do
|
|
if icol > self.col_start and ((invert ~= true and cell_value > 0) or (invert == true and cell_value < 0)) then
|
|
local Z = M[#M][icol]-M[self.row_input][icol] ---valeur demandee (input - Z)
|
|
local C = -Z/cell_value
|
|
if C > max then
|
|
max = C
|
|
xcol = icol
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return xcol
|
|
end
|
|
|
|
-------------------------------------------------------------------------------
|
|
---Calcul de la ligne
|
|
---@param M table
|
|
---@param xrow number
|
|
---@param xcol number
|
|
---@return table
|
|
function SolverAlgebra:lineCompute(M, xrow, xcol)
|
|
if M == nil or xrow == 0 or xcol == 0 then return M end
|
|
local row = M[xrow]
|
|
local P = M[xrow][self.col_P]
|
|
local E = M[xrow][self.col_E] ---energy
|
|
local Z = M[#M][xcol] ---valeur demandee Z
|
|
local V = M[xrow][xcol] ---valeur produite
|
|
local C = -Z/V ---coefficient
|
|
if Z < 0 then
|
|
M[xrow][self.col_C] = C
|
|
M[xrow][self.col_R] = P * C
|
|
for icol, cell_value in pairs(row) do
|
|
if icol > self.col_start then
|
|
local X = M[xrow][icol]
|
|
M[#M][icol] = M[#M][icol] + X * P * C
|
|
end
|
|
end
|
|
end
|
|
return M
|
|
end
|
|
|
|
-------------------------------------------------------------------------------
|
|
---Calcul de la ligne par factory
|
|
---@param M table
|
|
---@param xrow number
|
|
---@param time number
|
|
---@return table
|
|
function SolverAlgebra:lineComputeByFactory(M, xrow, time)
|
|
if M == nil or xrow == 0 then return M end
|
|
local row = M[xrow]
|
|
local F = M[xrow][self.col_F]
|
|
local S = M[xrow][self.col_S]
|
|
local P = M[xrow][self.col_P]
|
|
local E = M[xrow][self.col_E] ---energy
|
|
local C = 1 ---coefficient
|
|
local R = time*F*S/E ---nombre de recette/seconde
|
|
M[xrow][self.col_C] = C
|
|
M[xrow][self.col_R] = R
|
|
for icol,cell_value in pairs(row) do
|
|
if icol > self.col_start then
|
|
local X = M[xrow][icol]
|
|
---calcul Z
|
|
M[#M][icol] = M[#M][icol] + X * R
|
|
end
|
|
end
|
|
return M
|
|
end
|
|
|
|
-------------------------------------------------------------------------------
|
|
---Check factory column
|
|
---@param Mx table
|
|
---@return number
|
|
function SolverAlgebra:checkFactoryColumn(Mx)
|
|
for irow, row in pairs(Mx) do
|
|
if row[self.col_F] > 0 then return row[self.col_F] end
|
|
end
|
|
end
|
|
|
|
-------------------------------------------------------------------------------
|
|
---Resoud la matrice
|
|
---@param Mbase table
|
|
---@param debug boolean
|
|
---@param by_factory boolean
|
|
---@param time number
|
|
---@return table, table
|
|
function SolverAlgebra:solveMatrix(Mbase, debug, by_factory, time)
|
|
if Mbase ~= nil then
|
|
local num_loop = 0
|
|
local icol = 0
|
|
local runtime = {}
|
|
self:addRuntime(debug, runtime, "Initial", Mbase)
|
|
local Mstep = self:prepare(Mbase)
|
|
self:addRuntime(debug, runtime, "Prepare", Mstep)
|
|
if by_factory == true then
|
|
local start_row = 0
|
|
for irow, row in pairs(Mstep) do
|
|
if irow > self.row_input and irow < #Mstep then
|
|
if row[self.col_F] > 0 then
|
|
if start_row == 0 then start_row = irow end
|
|
self:addRuntime(debug, runtime, "Step "..num_loop, Mstep, {x=self.col_F,y=irow})
|
|
Mstep = self:lineComputeByFactory(Mstep, irow, time)
|
|
num_loop = num_loop + 1
|
|
if start_row > self.row_input + 1 then
|
|
for xrow = start_row, self.row_input + 1, -1 do
|
|
if Mstep[xrow][self.col_R] == 0 then
|
|
icol = self:getCol(Mstep, xrow, true)
|
|
self:addRuntime(debug, runtime, "Step "..num_loop, Mstep, {x=icol,y=xrow})
|
|
Mstep = self:lineCompute(Mstep, xrow, icol)
|
|
num_loop = num_loop + 1
|
|
end
|
|
end
|
|
end
|
|
elseif start_row ~= 0 then
|
|
icol = self:getCol(Mstep, irow, false)
|
|
self:addRuntime(debug, runtime, "Step "..num_loop, Mstep, {x=icol,y=irow})
|
|
Mstep = self:lineCompute(Mstep, irow, icol)
|
|
num_loop = num_loop + 1
|
|
end
|
|
end
|
|
end
|
|
else
|
|
for irow, row in pairs(Mstep) do
|
|
if irow > self.row_input and irow < #Mstep then
|
|
icol = self:getCol(Mstep, irow, false)
|
|
self:addRuntime(debug, runtime, "Step "..num_loop, Mstep, {x=icol,y=irow})
|
|
Mstep = self:lineCompute(Mstep, irow, icol)
|
|
num_loop = num_loop + 1
|
|
end
|
|
end
|
|
end
|
|
local Mr = self:finalize(Mstep)
|
|
Mr = self:appendState(Mr)
|
|
self:addRuntime(debug, runtime, "final", Mr)
|
|
return Mr, runtime
|
|
end
|
|
end |