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

Generation for memoized calls does not work for inherited methods and does not support dynamic binding #1013

Closed
lars-reimann opened this issue Apr 8, 2024 · 2 comments · Fixed by #1015
Labels
bug 🪲 Something isn't working released Included in a release
Milestone

Comments

@lars-reimann
Copy link
Member

lars-reimann commented Apr 8, 2024

Describe the bug

Running the pipeline below produces the following logs:

2024-04-08 20:12:18.772 [info] Launching Pipeline (653341ab-09b7-438d-950b-935b2ca7d4ad): file:///c%3A/Users/Lars/OneDrive/Desktop/test/test.sdstest - myPipeline
2024-04-08 20:12:18.773 [info] [Runner] Sending message to python server: {"type":"program","id":"653341ab-09b7-438d-950b-935b2ca7d4ad","data":{"code":{"test":{"gen_test":"# Imports ----------------------------------------------------------------------\r\n\r\nimport safeds_runner\r\nfrom safeds.data.tabular.containers import Table\r\nfrom safeds.data.tabular.transformation import OneHotEncoder, TableTransformer\r\n\r\n# Pipelines --------------------------------------------------------------------\r\n\r\ndef myPipeline():\r\n    titanic = safeds_runner.memoized_call(\"safeds.data.tabular.containers.Table.from_csv_file\", Table.from_csv_file, ['C:/Users/Lars/OneDrive/Desktop/test/titanic.csv'], [safeds_runner.file_mtime('C:/Users/Lars/OneDrive/Desktop/test/titanic.csv')])\r\n    safeds_runner.save_placeholder('titanic', titanic)\r\n    encoder = safeds_runner.memoized_call(\"safeds.data.tabular.transformation.OneHotEncoder.fit\", OneHotEncoder.fit, [safeds_runner.memoized_call(\"safeds.data.tabular.transformation.OneHotEncoder\", OneHotEncoder, [], []), titanic, ['sex']], [])\r\n    safeds_runner.save_placeholder('encoder', encoder)\r\n    transformedTable = safeds_runner.memoized_call(\"safeds.data.tabular.transformation.TableTransformer.transform\", TableTransformer.transform, [encoder, titanic], [])\r\n    safeds_runner.save_placeholder('transformedTable', transformedTable)\r\n","gen_test_myPipeline":"from .gen_test import myPipeline\r\n\r\nif __name__ == '__main__':\r\n    myPipeline()\r\n"}},"main":{"modulepath":"test","module":"test","pipeline":"myPipeline"}}}
2024-04-08 20:12:21.994 [info] [Runner] Message received: '{"type": "placeholder_type", "id": "653341ab-09b7-438d-950b-935b2ca7d4ad", "data": {"name": "titanic", "type": "Table"}}'
2024-04-08 20:12:21.994 [info] [Runner] Placeholder was calculated (653341ab-09b7-438d-950b-935b2ca7d4ad): titanic of type Table
2024-04-08 20:12:21.994 [info] Placeholder was calculated (653341ab-09b7-438d-950b-935b2ca7d4ad): titanic of type Table
2024-04-08 20:12:21.994 [info] Placeholder was calculated (653341ab-09b7-438d-950b-935b2ca7d4ad): titanic of type Table
2024-04-08 20:12:21.999 [info] [Runner] Message received: '{"type": "placeholder_type", "id": "653341ab-09b7-438d-950b-935b2ca7d4ad", "data": {"name": "encoder", "type": "OneHotEncoder"}}'
2024-04-08 20:12:21.999 [info] [Runner] Placeholder was calculated (653341ab-09b7-438d-950b-935b2ca7d4ad): encoder of type OneHotEncoder
2024-04-08 20:12:21.999 [info] Placeholder was calculated (653341ab-09b7-438d-950b-935b2ca7d4ad): encoder of type OneHotEncoder
2024-04-08 20:12:21.999 [info] Placeholder was calculated (653341ab-09b7-438d-950b-935b2ca7d4ad): encoder of type OneHotEncoder
2024-04-08 20:12:22.002 [info] [Runner] Message received: '{"type": "placeholder_type", "id": "653341ab-09b7-438d-950b-935b2ca7d4ad", "data": {"name": "transformedTable", "type": "Null"}}'
2024-04-08 20:12:22.002 [info] [Runner] Placeholder was calculated (653341ab-09b7-438d-950b-935b2ca7d4ad): transformedTable of type Null
2024-04-08 20:12:22.002 [info] Placeholder was calculated (653341ab-09b7-438d-950b-935b2ca7d4ad): transformedTable of type Null
2024-04-08 20:12:22.002 [info] Placeholder was calculated (653341ab-09b7-438d-950b-935b2ca7d4ad): transformedTable of type Null
2024-04-08 20:12:22.005 [info] [Runner] Message received: '{"type": "runtime_progress", "id": "653341ab-09b7-438d-950b-935b2ca7d4ad", "data": "done"}'
2024-04-08 20:12:22.005 [info] [Runner] Runner-Progress (653341ab-09b7-438d-950b-935b2ca7d4ad): done
2024-04-08 20:12:22.005 [info] Runner-Progress (653341ab-09b7-438d-950b-935b2ca7d4ad): done
2024-04-08 20:12:22.005 [info] Runner-Progress (653341ab-09b7-438d-950b-935b2ca7d4ad): done

Particularly note the part {"name": "transformedTable", "type": "Null"}. transformedTable should instead be a Table. This happens because the assignment of the placeholder is translated to

transformedTable = safeds_runner.memoized_call("safeds.data.tabular.transformation.TableTransformer.transform", TableTransformer.transform, [encoder, titanic], [])

There are two issues with this:

  1. The memoization key is wrong. Because of this, any invocation of transform on any subclass of TableTransformer is treated the same.
  2. The callable TableTransformer.transform is taken from the abstract superclass. It returns None since it has no implementation.

To Reproduce

Run this code (replace the path to the CSV file):

package test

pipeline myPipeline {
    val titanic = Table.fromCsvFile("C:/Users/Lars/OneDrive/Desktop/test/titanic.csv");
    val encoder = OneHotEncoder().fit(titanic, ["sex"]);
    val transformedTable = encoder.transform(titanic);
}

Expected behavior

In the DSL, we only know the static types of objects. We, thus, cannot compute memoization keys for instance methods at this point. This must be deferred to the runtime when memoized_call is evaluated. Likewise, we should let Python handle the dynamic binding.

For global functions and static methods, we can compute the memoization keys in the DSL, but it seems like we should fully move this responsibility to the runner if possible.

We could, for example, introduce a new runner method memoized_dynamic_call, which gets

  1. the receiver,
  2. the name of the method to call,
  3. the parameters,
  4. the hidden parameter.

Based on the dynamic type of the receiver and the method name, it can then derive its memoization key.

We could then rename memoized_call to memoized_static_call to be explicit.

Screenshots (optional)

No response

Additional Context (optional)

No response

@lars-reimann lars-reimann added the bug 🪲 Something isn't working label Apr 8, 2024
@lars-reimann
Copy link
Member Author

@WinPlay02 I'd say this one has a little higher priority than #1012, since there is no workaround. But it also seems more involved than #1012.

@lars-reimann lars-reimann added this to the v0.11.0 milestone Apr 8, 2024
lars-reimann pushed a commit to Safe-DS/Runner that referenced this issue Apr 9, 2024
Related to Safe-DS/DSL#1013

- introduces a new `memoized_dynamic_call` function, that fetches the
callable from the provided instance (receiver), calculates a new fully
qualified function name for the dynamic call and forwards everything to
the memoization map

---------

Co-authored-by: megalinter-bot <[email protected]>
lars-reimann pushed a commit to Safe-DS/Runner that referenced this issue Apr 9, 2024
Related to Safe-DS/DSL#1013

- introduces a new `memoized_dynamic_call` function, that fetches the
callable from the provided instance (receiver), calculates a new fully
qualified function name for the dynamic call and forwards everything to
the memoization map

---------

Co-authored-by: megalinter-bot <[email protected]>
lars-reimann pushed a commit that referenced this issue Apr 10, 2024
## [0.11.0](v0.10.0...v0.11.0) (2024-04-10)

### Features

* add `toFloat` methods for `Int` and `String` ([#1018](#1018)) ([55a2050](55a2050))
* fine-grained control over inlay hints for parameter names ([#1016](#1016)) ([2667caf](2667caf))
* messaging service ([#1004](#1004)) ([dcf4ecf](dcf4ecf))
* semantic highlighting of block lambda results ([#1011](#1011)) ([228733c](228733c))
* start runner in language server ([#1006](#1006)) ([ef4bb6f](ef4bb6f))
* stubs for int conversions ([#1008](#1008)) ([b635f5a](b635f5a))
* support relative paths ([#1019](#1019)) ([3d3f28d](3d3f28d))
* trigger EDA tool via code lenses ([#1010](#1010)) ([eb6e4b6](eb6e4b6))

### Bug Fixes

* consumption of source maps ([#1005](#1005)) ([ea3da87](ea3da87))
* disable global EDA panel cache ([#1014](#1014)) ([f888027](f888027)), closes [/github.com//issues/986#issuecomment-2042731653](https://github.com/Safe-DS//github.com/Safe-DS/DSL/issues/986/issues/issuecomment-2042731653)
* generation of dynamic member function calls with memoization + propagating of impurity information across chained calls ([#1015](#1015)) ([19015c3](19015c3)), closes [#1012](#1012) [#1013](#1013)
* only spawn one runner process and shut it down properly ([#1009](#1009)) ([2c72cee](2c72cee))
* show EDA tool for `TaggedTable` and `TimeSeries` ([#1017](#1017)) ([ffae98a](ffae98a))
@lars-reimann
Copy link
Member Author

🎉 This issue has been resolved in version 0.11.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@lars-reimann lars-reimann added the released Included in a release label Apr 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🪲 Something isn't working released Included in a release
Projects
Archived in project
1 participant