Skip to content

Commit

Permalink
Refactor common utilities to resolve matrix coefficients [breaking]
Browse files Browse the repository at this point in the history
This is an attempt to simplify the workflow, by avoiding having python
calling lua, calling python, calling lua, etc..

The motivation is also to work around this bug:
scoder/lupa#243

With such purpose in mind, I now use Lua for the generation of the
assignments of the matrix coefficients, rather than Python.

This change breaks the existing code generation backends.
  • Loading branch information
Marco F committed Sep 19, 2023
1 parent 19b3b92 commit f5f536c
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 30 deletions.
54 changes: 54 additions & 0 deletions src/ctgen/assignments.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
-- This module contains common functions to generate the code for the
-- assignments of matrix coefficients.

local common = common


--- Factory for the functions that generate the assignments of the matrix
--- coefficients.
--
--
local getMatrixSpecificGenerators = function(lang, matrixMetadata, resolvedMatrix)
-- resolvedMatrix must have all reference to symbols resolved
local ret = {}
local coefficient = common.py_matrix_coeff(resolvedMatrix)

ret.constantCoefficientsAssignments = function(matrixVarName)
local it, inv, ctrl = python.iter(matrixMetadata.constantCoefficients)
return function()
local r,c = it(inv, ctrl) -- run the iterator once
ctrl = r
if r ~= nil then
local value = coefficient(r, c)
if value ~= 0.0 then
-- we do not generate assignments of zeros, assuming the matrix is initialized
return lang.matrixAssignment(matrixVarName,r,c,tostring(value))
end
end
return nil
end, inv, ctrl
end

ret.variableCoefficientsAssignments = function(matrixVarName)
local it, inv, ctrl = python.iter(matrixMetadata.variableCoefficients)
return function()
local r,c = it(inv, ctrl) -- run the iterator once
ctrl = r
if r ~= nil then
local value = tostring( coefficient(r,c) )
return lang.matrixAssignment(matrixVarName,r,c, value)
end
return nil
end, inv, ctrl
end

return ret
end


-- The global table with the functions of this module
ctgen__matrix_coeff_assignments = {
getMatrixSpecificGenerators = getMatrixSpecificGenerators,
}

return ctgen__matrix_coeff_assignments
45 changes: 15 additions & 30 deletions src/ctgen/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,44 +90,29 @@ def floatLiteralsAsConstants(transform):
return transform


class StatementsGenerator:
class SymbolicCoefficientsResolver:
'''
Helper class to generate some common code statements related to a model and
individual transforms (i.e. matrices).
Helper class to transform the symbolic matrix coefficients into some
text expressions suitable for code generation.
Of course the specifities of such transformation will depend on the
language backend provided to the constructor.
'''

def __init__(self, aCodeGenerator):
def __init__(self, backendSpecifics):
'''
The argument `aCodeGenerator` is a configuration object. Its fields
The argument `backendSpecifics` is a configuration object. Its fields
`langSpecifics`, `variableAccess`, `parameterAccess`, `constantAccess`
encapsulate the details of a specific code-generation backend.
TODO document the expected API of these objects
'''
self.lang = aCodeGenerator.langSpecifics
self.varAccess = aCodeGenerator.variableAccess
self.parAccess = aCodeGenerator.parameterAccess
self.cnstAccess= aCodeGenerator.constantAccess

def getMatrixSpecificGenerators(self, matrixMetadata):
resolved = self._resolveSymbols(matrixMetadata)
def constantCoefficientsAssignments( indexableVariable):
for row, col in matrixMetadata.constantCoefficients :
value = resolved[row, col]
if value != 0.0 : # we do not generate assignments of zeros, assuming the matrix is initialized
yield self.lang.matrixAssignment(indexableVariable, row, col, value.__str__())

def variableCoefficientsAssignments(indexableVariable):
for r,c in matrixMetadata.variableCoefficients :
yield self.lang.matrixAssignment(indexableVariable, r,c, resolved[r,c].__str__())

return {
'constantCoefficientsAssignments' : constantCoefficientsAssignments,
'variableCoefficientsAssignments' : variableCoefficientsAssignments
}


def _resolveSymbols(self, matrixMetadata):
self.lang = backendSpecifics.langSpecifics
self.varAccess = backendSpecifics.variableAccess
self.parAccess = backendSpecifics.parameterAccess
self.cnstAccess= backendSpecifics.constantAccess

def resolveSymbols(self, matrixMetadata):
# A slightly hacky way of replacing expressions with code
# that would resolve to the value.
# We replace the sine/cosine of any symbol representing a rotation, and
Expand Down Expand Up @@ -170,7 +155,7 @@ def _resolveSymbols(self, matrixMetadata):

return matrixMetadata.mx.subs( replacements ) # Sympy replacement


# @unused?
def constantsDefinitions(self, constantsDict):
'''
A helper function to generate code that defines a list of variables
Expand Down

0 comments on commit f5f536c

Please sign in to comment.