Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic implementation of optimal grouping of objects using dynamic programming #272

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

pravalikavis
Copy link

References to other Issues or PRs or Relevant literature

fixes #230

Brief description of what is fixed or changed

  1. Added a file which has an optimal_grouping method which groups the given objects based on the cost input function.
  2. This function uses dynamic programing which reduces the time complexity
  3. It can be used on problems like Matrix chain multiplication, optimal binary search tree and on any other problem that follows the two rules of dynamic programming along with divide and conquer.

Other comments

@czgdp1807
Copy link
Member

The algorithm will work on an array of objects if I am not wrong. So, the code should be shifted to pydatastructs/pydatastructs/linear_data_structures/algorithms.py.

@pravalikavis
Copy link
Author

I have moved the file to linear_data_structures.

@czgdp1807
Copy link
Member

Hi,
The code is having too many checks. Can you please simplify it? And the code should be appended to https://github.com/codezonediitj/pydatastructs/blob/master/pydatastructs/linear_data_structures/algorithms.py

@pravalikavis
Copy link
Author

Hi,
I moved the code to the specified file and removed some type checks.

@czgdp1807
Copy link
Member

Add some tests for your patch. See tests folder under linear_data_structures. The build is failing. Make it work.

Comment on lines 366 to 370





Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too many empty lines.

"""
gets a value
"""
return matrix[lookup_index[0]][lookup_index[1]]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One liner functions aren't recommended. They just slow down the code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my suggestions at https://github.com/codezonediitj/pydatastructs/pull/272/files#r426157438
You have to do something similar with every one liner function.

"""

# gets the present value at the present index
present_value = _get_value_opt_group(cost_storage, lookup_index)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
present_value = _get_value_opt_group(cost_storage, lookup_index)
present_value = cost_storage[lookup_index[0]][lookup_index[1]]

Comment on lines 469 to 476
def _test_lookup_function(lookup_index: List[int], input_index: List[int]):
if lookup_index is None:
raise TypeError(
'Check lookup_function: returning wrong type should return an array of start and end index')

if lookup_index.__len__() < 2:
raise ValueError(
'Check lookup_function:lookup index should at least have 2 integer items, first specifying the start and second specifying the last indices')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 478 to 480
if input_index == lookup_index:
raise RuntimeError(
'Check lookup_function:verify get_lookup_fn giving same output as input which will lead to infinite loop')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if input_index == lookup_index:
raise RuntimeError(
'Check lookup_function:verify get_lookup_fn giving same output as input which will lead to infinite loop')
assert input_index == lookup_index

Comment on lines 569 to 571
if get_lookup_fn is None or type(get_lookup_fn) is not FunctionType:
raise TypeError(
'get_lookup_fn cannot be none and should be a function with 3 arguments')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not worry about type checking. If user will give garbage, they will get garbage.

@@ -3,13 +3,16 @@
from pydatastructs.utils.misc_util import _check_type, _comp
from concurrent.futures import ThreadPoolExecutor
from math import log, floor
from types import *
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not do *, import only those things which you want to use. Avoid namespace pollution.

@codecov
Copy link

codecov bot commented May 27, 2020

Codecov Report

Merging #272 into master will decrease coverage by 0.180%.
The diff coverage is 89.583%.

@@              Coverage Diff              @@
##            master      #272       +/-   ##
=============================================
- Coverage   98.842%   98.662%   -0.181%     
=============================================
  Files           23        23               
  Lines         2420      2467       +47     
=============================================
+ Hits          2392      2434       +42     
- Misses          28        33        +5     
Impacted Files Coverage Δ
pydatastructs/linear_data_structures/__init__.py 100.000% <ø> (ø)
pydatastructs/linear_data_structures/algorithms.py 96.815% <89.583%> (-3.185%) ⬇️

Impacted file tree graph

@pravalikavis
Copy link
Author

Hi,
I have made the changes.

Copy link

@robotjellyzone robotjellyzone left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@Smit-create
Copy link
Member

@pravalikavis Please resolve merge conflicts.

@czgdp1807
Copy link
Member

My only concern with dynamic programming problems is that they aren't that abstract and generalized. Moreover, they are pseudo-polynomial solutions to optimisation problems (mostly discrete). So possibly, we can add a separate optimisation module and put the dynamic programming solutions there. In fact they can also contain parametrised approximation algorithm. Anyways, we should first check if there is already a python package for solving these kind of formulations.

@Smit-create
Copy link
Member

Agreed on this

@czgdp1807 czgdp1807 added the Please take over PRs that can be continued by anyone. label Oct 21, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
algorithms Please take over PRs that can be continued by anyone.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Matrix Chain Multiplication
4 participants