Add compare_lists.py

This commit is contained in:
afik.cohen 2024-05-13 20:18:57 -07:00
parent b4df42b235
commit 68fa504b3e
4 changed files with 107 additions and 1 deletions

View file

@ -8,7 +8,7 @@
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="SDK_NAME" value="codeflash311" />
<option name="SDK_NAME" value="$USER_HOME$/miniforge3/envs/codeflash311" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/cli" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />

View file

@ -0,0 +1,37 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="compare_lists" type="PythonConfigurationType" factoryName="Python">
<module name="codeflash" />
<option name="ENV_FILES" value="$PROJECT_DIR$/cli/codeflash/.env" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="SDK_NAME" value="$USER_HOME$/miniforge3/envs/codeflash311" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/cli" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<EXTENSION ID="net.ashald.envfile">
<option name="IS_ENABLED" value="false" />
<option name="IS_SUBST" value="false" />
<option name="IS_PATH_MACRO_SUPPORTED" value="false" />
<option name="IS_IGNORE_MISSING_FILES" value="false" />
<option name="IS_ENABLE_EXPERIMENTAL_INTEGRATIONS" value="false" />
<ENTRIES>
<ENTRY IS_ENABLED="true" PARSER="runconfig" IS_EXECUTABLE="false" />
<ENTRY IS_ENABLED="true" PARSER="env" IS_EXECUTABLE="false" PATH="cli/codeflash/.env" />
</ENTRIES>
</EXTENSION>
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/cli/codeflash/main.py" />
<option name="PARAMETERS" value="--file code_to_optimize/compare_lists.py --module-root $PROJECT_DIR$/cli --function compare_lists --test-framework pytest --tests-root code_to_optimize/tests/pytest" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
</component>

View file

@ -0,0 +1,65 @@
import itertools
from functools import reduce
from typing import List, Set, Tuple
def compare_lists(
li1: List[int],
li2: List[int],
value_func1=None,
value_func2=None,
) -> Tuple[Set[int], Set[int], Set[int]]:
"""Compare *li1* and *li2*, return the results as a list in the following form:
[[data seen in both lists], [data only seen in li1], [data only seen in li2]]
and [data seen in both lists] contains 2 tuple: [(actual items in li1), (actual items in li2)]
* *value_func1* callback function to li1, applied to each item in the list, returning the **logical** value for comparison
* *value_func2* callback function to li2, similarly
If not supplied, lists will be compared as it is.
Usage::
>>> compare_lists([1, 2, 3], [1, 3, 5])
>>> ([(1, 3), (1, 3)], [2], [5])
Or with callback functions specified::
>>> f = lambda x: x['v']
>>>
>>> li1 = [{'v': 1}, {'v': 2}, {'v': 3}]
>>> li2 = [1, 3, 5]
>>>
>>> compare_lists(li1, li2, value_func1=f)
>>> ([({'v': 1}, {'v': 3}), (1, 3)], [{'v': 2}], [5])
"""
if not value_func1:
value_func1 = lambda x: x
if not value_func2:
value_func2 = lambda x: x
def to_dict(li, vfunc):
return {k: list(g) for k, g in itertools.groupby(li, vfunc)}
def flatten(li):
return reduce(list.__add__, li) if li else []
d1 = to_dict(li1, value_func1)
d2 = to_dict(li2, value_func2)
if d1 == d2:
return set(li1), set(), set()
k1 = set(d1.keys())
k2 = set(d2.keys())
elems_left = flatten([d1[k] for k in k1 - k2])
elems_right = flatten([d2[k] for k in k2 - k1])
common_keys = k1 & k2
elems_both = flatten([d2[k] for k in common_keys])
return set(elems_both), set(elems_left), set(elems_right)

View file

@ -837,6 +837,7 @@ class Optimizer:
generated_tests_elapsed_time = 0.0
# For the original function - run the tests and get the runtime
logging.info(f"Establishing original code baseline runtime for {function_name}.")
# TODO: Compare the function return values over the multiple runs and check if they are any different,
# if they are different, then we can't optimize this function because it is a non-deterministic function
test_env = os.environ.copy()
@ -850,6 +851,9 @@ class Optimizer:
cumulative_test_runs = 0
first_run = True
do_break = False
logging.info(
f"Running {len(instrumented_unittests_created_for_function)} tests for {function_name} ..."
)
while (
cumulative_test_runtime < MAX_CUMULATIVE_TEST_RUNTIME_NANOSECONDS
and cumulative_test_runs < MAX_TEST_FUNCTION_RUNS