Skip to content

Commit

Permalink
Add support for ALLOCATE AVAILABLE
Browse files Browse the repository at this point in the history
Add support for Vensim's ALLOCATE AVAILABLE
  • Loading branch information
enekomartinmartinez committed Jul 4, 2022
1 parent 1167289 commit a22979f
Show file tree
Hide file tree
Showing 17 changed files with 997 additions and 33 deletions.
3 changes: 2 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
'numpy', 'scipy', 'matplotlib', 'matplotlib.pyplot', 'scipy.stats',
'scipy.integrate', 'pandas', 'parsimonious', 'parsimonious.nodes',
'xarray', 'autopep8', 'scipy.linalg', 'parsimonious.exceptions',
'scipy.stats.distributions', 'progressbar', 'black'
'scipy.stats.distributions', 'progressbar', 'black', 'scipy.optimize'
]

for mod_name in MOCK_MODULES:
Expand Down Expand Up @@ -152,6 +152,7 @@
'pandas': ('https://pandas.pydata.org/docs/', None),
'xarray': ('https://docs.xarray.dev/en/stable/', None),
'numpy': ('https://numpy.org/doc/stable/', None),
'scipy': ('https://docs.scipy.org/doc/scipy/', None),
'pytest': ('https://docs.pytest.org/en/7.1.x/', None)
}

Expand Down
1 change: 1 addition & 0 deletions docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ PySD builds on the core Python data analytics stack, and the following third par
* black
* openpyxl
* progressbar2
* portion

These modules should build automatically if you are installing via `pip`. If you are building from
source, or if pip fails to load them, they can be loaded with the same `pip` syntax as
Expand Down
1 change: 1 addition & 0 deletions docs/tables/functions.tab
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ VECTOR RANK VECTOR RANK(vec, direction) "CallStructure('vector_rank', (vec, di
VECTOR REORDER VECTOR REORDER(vec, svec) "CallStructure('vector_reorder', (vec, svec))" vector_reorder(vec, svec)
VECTOR SORT ORDER VECTOR SORT ORDER(vec, direction) "CallStructure('vector_sort_order', (vec, direction))" vector_sort_order(vec, direction)
GAME GAME(A) GameStructure(A) A
ALLOCATE AVAILABLE "ALLOCATE AVAILABLE(request, pp, avail)" "AllocateAvailableStructure(request, pp, avail)" allocate_available(request, pp, avail) Not all the priority profiles are included.
ALLOCATE BY PRIORITY "ALLOCATE BY PRIORITY(request, priority, size, width, supply)" "AllocateByPriorityStructure(request, priority, size, width, supply)" allocate_by_priority(request, priority, width, supply)
INITIAL INITIAL(value) init init(value) InitialStructure(value) pysd.statefuls.Initial
SAMPLE IF TRUE "SAMPLE IF TRUE(condition, input, initial_value)" "SampleIfTrueStructure(condition, input, initial_value)" pysd.statefuls.SampleIfTrue(...)
39 changes: 33 additions & 6 deletions docs/whats_new.rst
Original file line number Diff line number Diff line change
@@ -1,12 +1,39 @@
What's New
==========
v3.4.0 (2022/06/29)
-------------------

New Features
~~~~~~~~~~~~
- Add support for Vensim's `ALLOCATE AVAILABLE <https://www.vensim.com/documentation/fn_allocate_available.html>`_ (:py:func:`pysd.py_backend.allocation.allocate_available`) function (:issue:`339`). Integer allocation cases have not been implemented neither the fixed quantity and constant elasticity curve priority functions.

Breaking changes
~~~~~~~~~~~~~~~~

Deprecations
~~~~~~~~~~~~

Bug fixes
~~~~~~~~~

Documentation
~~~~~~~~~~~~~
- Improve the documentation of the :py:mod:`pysd.py_backend.allocation` module.

Performance
~~~~~~~~~~~

Internal Changes
~~~~~~~~~~~~~~~~
- Add a class to manage priority profiles so it can be also used by the `many-to-many allocation <https://www.vensim.com/documentation/24340.html>`_.


v3.3.0 (2022/06/22)
-------------------

New Features
~~~~~~~~~~~~
- Add support for Vensim's `ALLOCATE BY PRIORITY <https://www.vensim.com/documentation/fn_allocate_by_priority.html>`_ (:func:`pysd.py_backend.allocation.allocate_by_priority`) function (:issue:`263`).
- Add support for Vensim's `ALLOCATE BY PRIORITY <https://www.vensim.com/documentation/fn_allocate_by_priority.html>`_ (:py:func:`pysd.py_backend.allocation.allocate_by_priority`) function (:issue:`263`).

Breaking changes
~~~~~~~~~~~~~~~~
Expand All @@ -33,8 +60,8 @@ v3.2.0 (2022/06/10)

New Features
~~~~~~~~~~~~
- Add support for Vensim's `GET TIME VALUE <https://www.vensim.com/documentation/fn_get_time_value.html>`_ (:func:`pysd.py_backend.functions.get_time_value`) function (:issue:`332`). Not all cases have been implemented.
- Add support for Vensim's `VECTOR SELECT <http://vensim.com/documentation/fn_vector_select.html>`_ (:func:`pysd.py_backend.functions.vector_select`) function (:issue:`266`).
- Add support for Vensim's `GET TIME VALUE <https://www.vensim.com/documentation/fn_get_time_value.html>`_ (:py:func:`pysd.py_backend.functions.get_time_value`) function (:issue:`332`). Not all cases have been implemented.
- Add support for Vensim's `VECTOR SELECT <http://vensim.com/documentation/fn_vector_select.html>`_ (:py:func:`pysd.py_backend.functions.vector_select`) function (:issue:`266`).

Breaking changes
~~~~~~~~~~~~~~~~
Expand All @@ -61,9 +88,9 @@ v3.1.0 (2022/06/02)

New Features
~~~~~~~~~~~~
- Add support for Vensim's `VECTOR SORT ORDER <https://www.vensim.com/documentation/fn_vector_sort_order.html>`_ (:func:`pysd.py_backend.functions.vector_sort_order`) function (:issue:`326`).
- Add support for Vensim's `VECTOR RANK <https://www.vensim.com/documentation/fn_vector_rank.html>`_ (:func:`pysd.py_backend.functions.vector_rank`) function (:issue:`326`).
- Add support for Vensim's `VECTOR REORDER <https://www.vensim.com/documentation/fn_vector_reorder.html>`_ (:func:`pysd.py_backend.functions.vector_reorder`) function (:issue:`326`).
- Add support for Vensim's `VECTOR SORT ORDER <https://www.vensim.com/documentation/fn_vector_sort_order.html>`_ (:py:func:`pysd.py_backend.functions.vector_sort_order`) function (:issue:`326`).
- Add support for Vensim's `VECTOR RANK <https://www.vensim.com/documentation/fn_vector_rank.html>`_ (:py:func:`pysd.py_backend.functions.vector_rank`) function (:issue:`326`).
- Add support for Vensim's `VECTOR REORDER <https://www.vensim.com/documentation/fn_vector_reorder.html>`_ (:py:func:`pysd.py_backend.functions.vector_reorder`) function (:issue:`326`).

Breaking changes
~~~~~~~~~~~~~~~~
Expand Down
2 changes: 1 addition & 1 deletion pysd/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "3.3.0"
__version__ = "3.4.0"
7 changes: 4 additions & 3 deletions pysd/builders/python/namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
# used to create Python safe names with the variable reserved_words
from keyword import kwlist
from builtins import __dir__ as bidir
from pysd.py_backend.allocation import __dir__ as adir
from pysd.py_backend.cache import __dir__ as cadir
from pysd.py_backend.components import __dir__ as cdir
from pysd.py_backend.data import __dir__ as ddir
from pysd.py_backend.cache import __dir__ as cadir
from pysd.py_backend.external import __dir__ as edir
from pysd.py_backend.functions import __dir__ as fdir
from pysd.py_backend.statefuls import __dir__ as sdir
Expand All @@ -29,8 +30,8 @@ class NamespaceManager:
"""
_reserved_words = set(
dir() + bidir() + cdir() + ddir() + cadir() + edir() + fdir()
+ sdir() + udir()).union(kwlist)
dir() + adir() + bidir() + cadir() + cdir() + ddir() + edir()
+ fdir() + sdir() + udir()).union(kwlist)

def __init__(self, parameters: List[str] = []):
self._used_words = self._reserved_words.copy()
Expand Down
94 changes: 87 additions & 7 deletions pysd/builders/python/python_expressions_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@
from pysd.py_backend.utils import compute_shape

from pysd.translators.structures.abstract_expressions import\
AbstractSyntax, AllocateByPriorityStructure, ArithmeticStructure,\
CallStructure, DataStructure, DelayFixedStructure, DelayStructure,\
DelayNStructure, ForecastStructure, GameStructure, GetConstantsStructure,\
GetDataStructure, GetLookupsStructure, InitialStructure,\
InlineLookupsStructure, IntegStructure, LogicStructure, LookupsStructure,\
ReferenceStructure, SampleIfTrueStructure, SmoothNStructure,\
SmoothStructure, SubscriptsReferenceStructure, TrendStructure
AbstractSyntax, AllocateAvailableStructure, AllocateByPriorityStructure,\
ArithmeticStructure, CallStructure, DataStructure, DelayFixedStructure,\
DelayStructure, DelayNStructure, ForecastStructure, GameStructure,\
GetConstantsStructure, GetDataStructure, GetLookupsStructure,\
InitialStructure, InlineLookupsStructure, IntegStructure,\
LogicStructure, LookupsStructure, ReferenceStructure,\
SampleIfTrueStructure, SmoothNStructure, SmoothStructure,\
SubscriptsReferenceStructure, TrendStructure

from .python_functions import functionspace
from .subscripts import SubscriptManager
Expand Down Expand Up @@ -750,6 +751,75 @@ def _compute_axis(self, subscripts: dict) -> tuple:
return coords, axis


class AllocateAvailableBuilder(StructureBuilder):
"""Builder for allocate_available function."""

def __init__(self, allocate_str: AllocateAvailableStructure,
component: object):
super().__init__(None, component)

pp = allocate_str.pp
pp_sub = self.section.subscripts.elements[pp.reference][-1:]
pp.subscripts.subscripts = pp.subscripts.subscripts[:-1] + pp_sub
self.arguments = {
"request": allocate_str.request,
"pp": pp,
"avail": allocate_str.avail
}

def build(self, arguments: dict) -> BuildAST:
"""
Build method.
Parameters
----------
arguments: dict
The dictionary of builded arguments.
Returns
-------
built_ast: BuildAST
The built object.
"""
self.section.imports.add("allocation", "allocate_available")

calls = self.join_calls(arguments)

# the last sub of the request must be keep last sub of request and
# priority
last_sub = list(arguments["request"].subscripts)[-1]
pp_sub = list(arguments["pp"].subscripts)[-1]
# compute the merged subscripts
final_subscripts = self.get_final_subscripts(arguments)
# remove last sub from request
last_sub_value = final_subscripts[last_sub]
pp_sub_value = final_subscripts[pp_sub]
del final_subscripts[last_sub], final_subscripts[pp_sub]

# Update the susbcripts of avail
arguments["avail"].reshape(
self.section.subscripts, final_subscripts, True)

# Include last sub of request in the last position and update
# the subscripts of request
final_subscripts[last_sub] = last_sub_value
arguments["request"].reshape(
self.section.subscripts, final_subscripts, True)

# Include priority subscripts and update the subscripts of pp
final_subscripts[pp_sub] = pp_sub_value
arguments["pp"].reshape(
self.section.subscripts, final_subscripts, True)

expression = "allocate_available(%(request)s, %(pp)s, %(avail)s)"
return BuildAST(
expression=expression % arguments,
calls=calls,
subscripts=arguments["request"].subscripts,
order=0)


class AllocateByPriorityBuilder(StructureBuilder):
"""Builder for allocate_by_priority function."""

Expand Down Expand Up @@ -1731,6 +1801,7 @@ def subscripts(self, subscripts: SubscriptsReferenceStructure):
# the reference has a subscripts which is it not
# applied (!) and does not appear in the definition
# of the variable
not_mapped = True
for mapped in self.section.subscripts.mapping[dim]:
# check the mapped subscripts
# TODO update this and the parser to make it
Expand All @@ -1741,7 +1812,15 @@ def subscripts(self, subscripts: SubscriptsReferenceStructure):
# and it is not already in the variable
self.mapping_subscripts[mapped] =\
self.section.subscripts.subscripts[mapped]
not_mapped = False
break
if not_mapped:
# manage other not mapped subscripts
# this is necessary for Allocate Available
# where we must force the expression in the
# right to have more subscripts thant the
# expression in the left
self.mapping_subscripts[dim] = coordinates
else:
# the subscript is in the variable definition,
# do not change it
Expand Down Expand Up @@ -2089,6 +2168,7 @@ class ASTVisitor:
ReferenceStructure: ReferenceBuilder,
CallStructure: CallBuilder,
GameStructure: GameBuilder,
AllocateAvailableStructure: AllocateAvailableBuilder,
AllocateByPriorityStructure: AllocateByPriorityBuilder,
LogicStructure: OperationBuilder,
ArithmeticStructure: OperationBuilder,
Expand Down

0 comments on commit a22979f

Please sign in to comment.