lebrice/SimpleParsing

Reaching `ConflictResolutionError` on too big/nested and shared configs with more than 50 parameters.

manu418 opened this issue · 3 comments

Describe the bug
Making usage of this neat package, we created a configuration-structure kind of big. It has several layers of sub-configs and one config in particular is used repeatedly within an upper layer (see code example below for clarification). It turns out that now the config has grown to big (with over 50 parameters in the sub-config), leading to a simple_parsing.conflicts.ConflictResolutionError although there is no real conflict present.

To Reproduce

import dataclasses

from simple_parsing import ArgumentParser, DashVariant, NestedMode

SubConfig = dataclasses.make_dataclass(
    'SubConfig',
    fields=[
        (arg, int, dataclasses.field(default=1))
        for arg in list('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
    ]
)


@dataclasses.dataclass
class MainConfig:
    config_1: SubConfig
    config_2: SubConfig


if __name__ == "__main__":
    # parse commandline and load default config-file
    parser = ArgumentParser(
        add_option_string_dash_variants=DashVariant.DASH,
        nested_mode=NestedMode.WITHOUT_ROOT,
    )
    parser.add_arguments(MainConfig, "args")
    parsed_args = parser.parse_args()
    config: MainConfig = parsed_args.args
    print(config)

Expected behavior
Print out the config aka MainConfig(config_1=SubConfig(a=1, b=1, c=1, d=1, e=1, ..., Z=1).

Actual behavior
Raises simple_parsing.conflicts.ConflictResolutionError.

Desktop (please complete the following information):

  • Version 0.1.5
  • Python version: 3.10

Hey there, interesting bug!

I think what's happening is that you're reaching the limit of 50 attempts of resolving collisions:
https://github.com/lebrice/SimpleParsing/blob/master/simple_parsing/conflicts.py#L63

Can you try and check if increasing this limit fixes the issue locally?

Hi,
that is True. In the meantime, I did exactly this by doing

parser = ArgumentParser()
parser._conflict_resolver.max_attempts = 200

This is not a nice solution of course, but working. Is there another option that I have overlooked?

Not currently no. Perhaps the conflict resolution could be made smarter eventually.