Exemple #1
0
    def set_section_property(self, section_name, property_name, value):
        section_name = InputParser._format_section_name(section_name)
        property_name = InputParser._format_property_name(property_name)
        types = self.get_property_types(section_name, property_name)
        value = InputParser._get_value(value, types)
        if len(types) > 0:
            validator = jsonschema.Draft4Validator(self._schema)
            valid = False
            for type in types:
                valid = validator.is_type(value, type)
                if valid:
                    break

            if not valid:
                raise AlgorithmError(
                    "{}.{}: Value '{}' is not of types: '{}'".format(
                        section_name, property_name, value, types))

        sections_temp = copy.deepcopy(self._sections)
        InputParser._set_section_property(sections_temp, section_name,
                                          property_name, value, types)
        msg = self._validate(sections_temp, section_name, property_name)
        if msg is not None:
            raise AlgorithmError("{}.{}: Value '{}': '{}'".format(
                section_name, property_name, value, msg))

        InputParser._set_section_property(self._sections, section_name,
                                          property_name, value, types)
        if property_name == InputParser.NAME:
            if InputParser.INPUT == section_name:
                self._update_algorithm_input_schema()
                # remove properties that are not valid for this section
                default_properties = self.get_section_default_properties(
                    section_name)
                if isinstance(default_properties, dict):
                    properties = self.get_section_properties(section_name)
                    for property_name in list(properties.keys()):
                        if property_name != InputParser.NAME and property_name not in default_properties:
                            self.delete_section_property(
                                section_name, property_name)
            elif InputParser.PROBLEM == section_name:
                self._update_algorithm_problem()
                self._update_input_problem()
            elif InputParser.is_pluggable_section(section_name):
                self._update_pluggable_input_schemas()
                # remove properties that are not valid for this section
                default_properties = self.get_section_default_properties(
                    section_name)
                if isinstance(default_properties, dict):
                    properties = self.get_section_properties(section_name)
                    for property_name in list(properties.keys()):
                        if property_name != InputParser.NAME and property_name not in default_properties:
                            self.delete_section_property(
                                section_name, property_name)

                if section_name == InputParser.ALGORITHM:
                    self._update_dependency_sections()

        self._sections = self._order_sections(self._sections)
Exemple #2
0
    def save_to_file(self, file_name):
        if file_name is None:
            raise AlgorithmError('Missing file path')

        file_name = file_name.strip()
        if len(file_name) == 0:
            raise AlgorithmError('Missing file path')

        with open(file_name, 'w') as f:
            print(json.dumps(self.get_sections(), sort_keys=True, indent=4),
                  file=f)
Exemple #3
0
def get_algorithm_ck(params, algo_input=None, json_output=False):
    """
    Retrieve algorithm as named in params, using params and algo_input as input data
    and returning a result dictionary
    Args:
        params (dict): Dictionary of params for algo and dependent objects
        algo_input(algorithminput): Main input data for algorithm. Optional, an algo may run entirely from params
        json_output(bool): False for regular python dictionary return, True for json conversion
    Returns:
        Result dictionary containing result of algorithm computation
    """
    _discover_on_demand()

    inputparser = InputParser(params)
    inputparser.parse()
    inputparser.validate_merge_defaults()
    logger.debug('Algorithm Input: {}'.format(json.dumps(inputparser.get_sections(), sort_keys=True, indent=4)))

    algo_name = inputparser.get_section_property(InputParser.ALGORITHM, InputParser.NAME)
    if algo_name is None:
        raise AlgorithmError('Missing algorithm name')

    if algo_name not in local_algorithms():
        raise AlgorithmError('Algorithm "{0}" missing in local algorithms'.format(algo_name))

    backend_cfg = None
    backend = inputparser.get_section_property(InputParser.BACKEND, InputParser.NAME)
    if backend is not None:
        backend_cfg = {k: v for k, v in inputparser.get_section(InputParser.BACKEND).items() if k != 'name'}
        backend_cfg['backend'] = backend

    algorithm = get_algorithm_instance(algo_name)
    algorithm.random_seed = inputparser.get_section_property(InputParser.PROBLEM, 'random_seed')
    if backend_cfg is not None:
        algorithm.setup_quantum_backend(**backend_cfg)

    algo_params = copy.deepcopy(inputparser.get_sections())

    if algo_input is None:
        input_name = inputparser.get_section_property('input', InputParser.NAME)
        if input_name is not None:
            algo_input = get_input_instance(input_name)
            input_params = copy.deepcopy(inputparser.get_section_properties('input'))
            del input_params[InputParser.NAME]
            convert_json_to_dict(input_params)
            algo_input.from_params(input_params)

    algorithm.init_params(algo_params, algo_input)

    return algorithm
Exemple #4
0
    def _update_input_problem(self):
        problem_name = self.get_section_property(InputParser.PROBLEM,
                                                 InputParser.NAME)
        if problem_name is None:
            problem_name = self.get_property_default_value(
                InputParser.PROBLEM, InputParser.NAME)

        if problem_name is None:
            raise AlgorithmError(
                "No algorithm 'problem' section found on input.")

        input_name = self.get_section_property(InputParser.INPUT,
                                               InputParser.NAME)
        if input_name is not None and problem_name in InputParser.get_input_problems(
                input_name):
            return

        for input_name in local_inputs():
            if problem_name in self.get_input_problems(input_name):
                # set to the first input to solve the problem
                self.set_section_property(InputParser.INPUT, InputParser.NAME,
                                          input_name)
                return

        # no input solve this problem, remove section
        self.delete_section(InputParser.INPUT)
Exemple #5
0
    def _update_algorithm_problem(self):
        problem_name = self.get_section_property(InputParser.PROBLEM,
                                                 InputParser.NAME)
        if problem_name is None:
            problem_name = self.get_property_default_value(
                InputParser.PROBLEM, InputParser.NAME)

        if problem_name is None:
            raise AlgorithmError(
                "No algorithm 'problem' section found on input.")

        algo_name = self.get_section_property(InputParser.ALGORITHM,
                                              InputParser.NAME)
        if algo_name is not None and problem_name in InputParser.get_algorithm_problems(
                algo_name):
            return

        for algo_name in local_algorithms():
            if problem_name in self.get_algorithm_problems(algo_name):
                # set to the first algorithm to solve the problem
                self.set_section_property(InputParser.ALGORITHM,
                                          InputParser.NAME, algo_name)
                return

        # no algorithm solve this problem, remove section
        self.delete_section(InputParser.ALGORITHM)
Exemple #6
0
    def __init__(self, input=None):
        """Create InputParser object."""
        self._original_sections = None
        self._filename = None
        self._sections = None
        if input is not None:
            if isinstance(input, dict):
                self._sections = input
            elif isinstance(input, str):
                self._filename = input
            else:
                raise AlgorithmError("Invalid parser input type.")

        self._section_order = [
            InputParser.PROBLEM, InputParser.INPUT, InputParser.ALGORITHM
        ]
        for pluggable_type in local_pluggables_types():
            if pluggable_type != InputParser.ALGORITHM:
                self._section_order.append(pluggable_type)

        self._section_order.extend([InputParser.BACKEND, InputParser._UNKNOWN])

        problems_dict = OrderedDict()
        for algo_name in local_algorithms():
            problems = InputParser.get_algorithm_problems(algo_name)
            for problem in problems:
                problems_dict[problem] = None

        problems_enum = {'enum': list(problems_dict.keys())}
        jsonfile = os.path.join(os.path.dirname(__file__), 'input_schema.json')
        with open(jsonfile) as json_file:
            self._schema = json.load(json_file)
            self._schema['definitions'][InputParser.PROBLEM]['properties'][
                InputParser.NAME]['oneOf'] = [problems_enum]
            self._original_schema = copy.deepcopy(self._schema)
Exemple #7
0
    def _format_property_name(property_name):
        if property_name is None:
            property_name = ''
        property_name = property_name.strip()
        if len(property_name) == 0:
            raise AlgorithmError("Empty property name.")

        return property_name
Exemple #8
0
    def _format_section_name(section_name):
        if section_name is None:
            section_name = ''
        section_name = section_name.strip()
        if len(section_name) == 0:
            raise AlgorithmError("Empty section name.")

        return section_name
Exemple #9
0
    def _validate_input_problem(self):
        input_name = self.get_section_property(InputParser.INPUT,
                                               InputParser.NAME)
        if input_name is None:
            return

        problem_name = self.get_section_property(InputParser.PROBLEM,
                                                 InputParser.NAME)
        if problem_name is None:
            problem_name = self.get_property_default_value(
                InputParser.PROBLEM, InputParser.NAME)

        if problem_name is None:
            raise AlgorithmError(
                "No algorithm 'problem' section found on input.")

        problems = InputParser.get_input_problems(input_name)
        if problem_name not in problems:
            raise AlgorithmError(
                "Problem: {} not in the list of problems: {} for input: {}.".
                format(problem_name, problems, input_name))
Exemple #10
0
    def parse(self):
        """Parse the data."""
        if self._sections is None:
            if self._filename is None:
                raise AlgorithmError("Missing input file")

            with open(self._filename) as json_file:
                self._sections = json.load(json_file)

        self._update_pluggable_input_schemas()
        self._update_algorithm_input_schema()
        self._sections = self._order_sections(self._sections)
        self._original_sections = copy.deepcopy(self._sections)
Exemple #11
0
 def get_section(self, section_name):
     """Return a Section by name.
     Args:
         section_name (str): the name of the section, case insensitive
     Returns:
         Section: The section with this name
     Raises:
         AlgorithmError: if the section does not exist.
     """
     section_name = InputParser._format_section_name(section_name)
     try:
         return self._sections[section_name]
     except KeyError:
         raise AlgorithmError('No section "{0}"'.format(section_name))
Exemple #12
0
    def validate_merge_defaults(self):
        try:
            self._merge_default_values()
            json_dict = self.get_sections()
            logger.debug('Algorithm Input: {}'.format(
                json.dumps(json_dict, sort_keys=True, indent=4)))
            logger.debug('Algorithm Input Schema: {}'.format(
                json.dumps(self._schema, sort_keys=True, indent=4)))
            jsonschema.validate(json_dict, self._schema)
        except jsonschema.exceptions.ValidationError as ve:
            logger.info('JSON Validation error: {}'.format(str(ve)))
            raise AlgorithmError(ve.message)

        self._validate_algorithm_problem()
        self._validate_input_problem()
Exemple #13
0
    def set_section_data(self, section_name, value):
        """
        Sets a section data.
        Args:
            section_name (str): the name of the section, case insensitive
            value : value to set
        """
        section_name = InputParser._format_section_name(section_name)
        types = self.get_section_types(section_name)
        value = InputParser._get_value(value, types)
        if len(types) > 0:
            validator = jsonschema.Draft4Validator(self._schema)
            valid = False
            for type in types:
                valid = validator.is_type(value, type)
                if valid:
                    break

            if not valid:
                raise AlgorithmError(
                    "{}: Value '{}' is not of types: '{}'".format(
                        section_name, value, types))

        self._sections[section_name] = value
Exemple #14
0
    def _update_algorithm_input_schema(self):
        # find alogorithm input
        default_name = self.get_property_default_value(InputParser.INPUT,
                                                       InputParser.NAME)
        input_name = self.get_section_property(InputParser.INPUT,
                                               InputParser.NAME, default_name)
        if input_name is None:
            # find the first valid input for the problem
            problem_name = self.get_section_property(InputParser.PROBLEM,
                                                     InputParser.NAME)
            if problem_name is None:
                problem_name = self.get_property_default_value(
                    InputParser.PROBLEM, InputParser.NAME)

            if problem_name is None:
                raise AlgorithmError(
                    "No algorithm 'problem' section found on input.")

            for name in local_inputs():
                if problem_name in self.get_input_problems(name):
                    # set to the first input to solve the problem
                    input_name = name
                    break

        if input_name is None:
            # just remove fromm schema if none solves the problem
            if InputParser.INPUT in self._schema['definitions']:
                del self._schema['definitions'][InputParser.INPUT]
            if InputParser.INPUT in self._schema['properties']:
                del self._schema['properties'][InputParser.INPUT]
            return

        if default_name is None:
            default_name = input_name

        config = {}
        try:
            config = get_input_configuration(input_name)
        except:
            pass

        input_schema = config[
            'input_schema'] if 'input_schema' in config else {}
        properties = input_schema[
            'properties'] if 'properties' in input_schema else {}
        properties[InputParser.NAME] = {'type': 'string'}
        required = input_schema[
            'required'] if 'required' in input_schema else []
        additionalProperties = input_schema[
            'additionalProperties'] if 'additionalProperties' in input_schema else True
        if default_name is not None:
            properties[InputParser.NAME]['default'] = default_name
            required.append(InputParser.NAME)

        if InputParser.INPUT not in self._schema['definitions']:
            self._schema['definitions'][InputParser.INPUT] = {'type': 'object'}

        if InputParser.INPUT not in self._schema['properties']:
            self._schema['properties'][InputParser.INPUT] = {
                '$ref': "#/definitions/{}".format(InputParser.INPUT)
            }

        self._schema['definitions'][
            InputParser.INPUT]['properties'] = properties
        self._schema['definitions'][InputParser.INPUT]['required'] = required
        self._schema['definitions'][
            InputParser.INPUT]['additionalProperties'] = additionalProperties