Skip to content

Commit

Permalink
Split sma & adam_profile
Browse files Browse the repository at this point in the history
  • Loading branch information
FilTheo committed Aug 31, 2024
1 parent 6d9570d commit b084ce0
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 85 deletions.
48 changes: 34 additions & 14 deletions python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,45 @@ if(SKBUILD)

# Pybind11
find_package(pybind11 REQUIRED)
# Armadillo
find_package(armadillo REQUIRED)

# CARMA
ADD_SUBDIRECTORY(../src/libs/carma carma)

# BLAS and LAPACK. Needed by Armadillo
find_package(BLAS)
find_package(LAPACK)
if(LAPACK_FOUND AND BLAS_FOUND)
set(lapackblas_libraries ${BLAS_LIBRARIES} ${LAPACK_LIBRARIES})
else()
# IS: This is where they are on my system. This might change from one OS to another
set(lapackblas_libraries "/usr/lib/x86_64-linux-gnu/")
endif()

# Armadillo
find_package(armadillo)
IF(NOT ARMADILLO_FOUND)
set(ARMADILLO_INCLUDE_DIRS "/usr/lib/")
ENDIF()
include_directories(${ARMADILLO_INCLUDE_DIRS})

# Adam General
pybind11_add_module(_adam_general ../src/python_examples/adamGeneral.cpp)
target_include_directories(_adam_general PRIVATE ../src/python_examples/.)
target_link_libraries(_adam_general PRIVATE carma::carma ${ARMADILLO_LIBRARIES} ${lapackblas_libraries})
install(TARGETS _adam_general DESTINATION smooth/adam_general)


# Old experimental stuff by Leo
# code to add the pybind11 cpp module, look at demo project
# (https://github.com/ltsaprounis/python-cpp-experiments/tree/main) for details.
pybind11_add_module(_my_linalg ../src/python_examples/my_linalg.cpp)
#pybind11_add_module(_my_linalg ../src/python_examples/my_linalg.cpp)

# add CARMA as a subdirectory
add_subdirectory(../src/libs/carma build)
target_link_libraries(_my_linalg
PRIVATE carma::carma
${ARMADILLO_LIBRARIES}
)
#add_subdirectory(../src/libs/carma build)
#target_link_libraries(_my_linalg
# PRIVATE carma::carma
# ${ARMADILLO_LIBRARIES}
#)

install(TARGETS _my_linalg DESTINATION smooth/my_linalg)
# install(TARGETS _my_linalg DESTINATION smooth/my_linalg)

# Adam General
pybind11_add_module(_adam_general ../src/python_examples/adamGeneral.cpp)
target_link_libraries(_adam_general PRIVATE carma::carma ${ARMADILLO_LIBRARIES})
target_include_directories(_adam_general PRIVATE ../src/python_examples/.)
install(TARGETS _adam_general DESTINATION smooth/adam_general)
63 changes: 63 additions & 0 deletions python/smooth/adam_general/adam_profile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import numpy as np


def adamProfileCreator(
lagsModelAll, lagsModelMax, obsAll, lags=None, yIndex=None, yClasses=None
):
"""
Creates recent profile and the lookup table for adam.
Parameters:
lagsModelAll (list): All lags used in the model for ETS + ARIMA + xreg.
lagsModelMax (int): The maximum lag used in the model.
obsAll (int): Number of observations to create.
lags (list): The original lags provided by user (optional).
yIndex (list): The indices needed to get the specific dates (optional).
yClasses (list): The class used for the actual data (optional).
Returns:
dict: A dictionary with 'recent' (profilesRecentTable) and 'lookup' (indexLookupTable) as keys.
"""
# Initialize matrices
profilesRecentTable = np.zeros((len(lagsModelAll), lagsModelMax))
indexLookupTable = np.ones((len(lagsModelAll), obsAll + lagsModelMax))
profileIndices = (
np.arange(1, lagsModelMax * len(lagsModelAll) + 1)
.reshape(-1, len(lagsModelAll))
.T
)

# Update matrices based on lagsModelAll
for i, lag in enumerate(lagsModelAll):
# Create the matrix with profiles based on the provided lags.
# For every row, fill the first 'lag' elements from 1 to lag
profilesRecentTable[i, : lag[0]] = np.arange(1, lag[0] + 1)

# For the i-th row in indexLookupTable, fill with a repeated sequence starting from lagsModelMax to the end of the row.
# The repeated sequence is the i-th row of profileIndices, repeated enough times to cover 'obsAll' observations.
# '- 1' at the end adjusts these values to Python's zero-based indexing.
indexLookupTable[i, lagsModelMax : (lagsModelMax + obsAll)] = ( # noqa
np.tile(
profileIndices[i, : lagsModelAll[i][0]],
int(np.ceil(obsAll / lagsModelAll[i][0])),
)[0:obsAll]
- 1
)

# Extract unique values from from lagsModelMax to lagsModelMax + obsAll of indexLookupTable
unique_values = np.unique(
indexLookupTable[i, lagsModelMax : lagsModelMax + obsAll] # noqa
)

# fix the head of teh data before the sample starts
# Repeat the unique values lagsModelMax times and then trim the sequence to only keep the first lagsModelMax elements
indexLookupTable[i, :lagsModelMax] = np.tile(unique_values, lagsModelMax)[
-lagsModelMax:
]

# Convert to int!
indexLookupTable = indexLookupTable.astype(int)

# Note: I skip andling of special cases (e.g., daylight saving time, leap years)
return {
"recent": np.array(profilesRecentTable, dtype="float64"),
"lookup": np.array(indexLookupTable, dtype="int64"),
}
86 changes: 15 additions & 71 deletions python/smooth/adam_general/sma.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import numpy as np
from smooth.adam_general._adam_general import adam_fitter
from smooth.adam_general.adam_profile import adamProfileCreator


def sma(y, order=1, h=10, holdout=False):
Expand All @@ -24,21 +25,25 @@ def sma(y, order=1, h=10, holdout=False):
def creator_sma(order):
# lags_model_all = np.ones(shape=(order, 1))
# This needs to be a vector of values
lags_model_all = np.arange(1, order + 1).reshape(order, 1)
lags_model_max = max(lags_model_all)
lags_model_all = np.arange(1, order+1, dtype="int32").reshape(order, 1)
lags_model_max = int(max(lags_model_all))
obs_states = obs_in_sample + lags_model_max

# profiles_recent_table = np.zeros(
profiles_recent_table, index_lookup_table = adamProfileCreator(
lagsModelAll=lags_model_all,
lagsModelMax=lags_model_max,
obsAll=obs_all
).values()

# # This needs to be generated by a profileCreator() function
# profiles_recent_table = np.mean(y_in_sample[0 : (order - 1)]) * np.ones(
# shape=(order, lags_model_max), dtype=np.float64
# )

# This needs to be generated by a profileCreator() function
profiles_recent_table = np.mean(y_in_sample[0 : (order - 1)]) * np.ones(
shape=(order, lags_model_max), dtype=np.float64
)

# This as well...
index_lookup_table = np.tile(np.arange(order), (obs_all + lags_model_max, 1)).T
# # This as well...
# index_lookup_table = np.tile(
# np.arange(order), (obs_all + lags_model_max, 1)
# ).T

matF = np.ones((order, order)) / order
matWt = np.ones((obs_in_sample, order))
Expand Down Expand Up @@ -72,64 +77,3 @@ def creator_sma(order):
return adam_fitted

return creator_sma(order=order)


def adamProfileCreator(
lagsModelAll, lagsModelMax, obsAll, lags=None, yIndex=None, yClasses=None
):
"""
Creates recent profile and the lookup table for adam.
Parameters:
lagsModelAll (list): All lags used in the model for ETS + ARIMA + xreg.
lagsModelMax (int): The maximum lag used in the model.
obsAll (int): Number of observations to create.
lags (list): The original lags provided by user (optional).
yIndex (list): The indices needed to get the specific dates (optional).
yClasses (list): The class used for the actual data (optional).
Returns:
dict: A dictionary with 'recent' (profilesRecentTable) and 'lookup' (indexLookupTable) as keys.
"""
# Initialize matrices
profilesRecentTable = np.zeros((len(lagsModelAll), lagsModelMax))
indexLookupTable = np.ones((len(lagsModelAll), obsAll + lagsModelMax))
profileIndices = (
np.arange(1, lagsModelMax * len(lagsModelAll) + 1)
.reshape(-1, len(lagsModelAll))
.T
)

# Update matrices based on lagsModelAll
for i, lag in enumerate(lagsModelAll):
# Create the matrix with profiles based on the provided lags.
# For every row, fill the first 'lag' elements from 1 to lag
profilesRecentTable[i, :lag] = np.arange(1, lag + 1)

# For the i-th row in indexLookupTable, fill with a repeated sequence starting from lagsModelMax to the end of the row.
# The repeated sequence is the i-th row of profileIndices, repeated enough times to cover 'obsAll' observations.
# '- 1' at the end adjusts these values to Python's zero-based indexing.
indexLookupTable[i, lagsModelMax : (lagsModelMax + obsAll)] = ( # noqa
np.tile(
profileIndices[i, : lagsModelAll[i]],
int(np.ceil(obsAll / lagsModelAll[i])),
)[0:obsAll]
- 1
)

# Extract unique values from from lagsModelMax to lagsModelMax + obsAll of indexLookupTable
unique_values = np.unique(
indexLookupTable[i, lagsModelMax : lagsModelMax + obsAll] # noqa
)

# fix the head of teh data before the sample starts
# Repeat the unique values lagsModelMax times and then trim the sequence to only keep the first lagsModelMax elements
indexLookupTable[i, :lagsModelMax] = np.tile(unique_values, lagsModelMax)[
-lagsModelMax:
]

# Convert to int!
indexLookupTable = indexLookupTable.astype(int)

# Note: I skip andling of special cases (e.g., daylight saving time, leap years)
return {"recent": profilesRecentTable, "lookup": indexLookupTable}
7 changes: 7 additions & 0 deletions python/smooth/adam_general/test_script.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import numpy as np
from smooth.adam_general.sma import sma

if __name__ == "__main__":
y = np.arange(0, 100)
results = sma(y, order=5)
print(results["yFitted"])
Empty file added python/test/skeleton.py
Empty file.

0 comments on commit b084ce0

Please sign in to comment.