Skip to content

quast_decisiontree.core.builder

quast_decisiontree.core.builder

HyperParam

Source code in src/quast_decisiontree/core/builder.py
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
class HyperParam:
    def __init__(
        self,
        name: str,
        hparam_type: Any,
        description: str | None = None,
        default: Any = "",
        test: Callable | None = None,
        allow_multiple: bool = False,
    ) -> None:
        """Each parameter needs to be initialized with a name, a type or list of types, and can
        optionally include a callable to check whether a parameter is valid

        Args:
            name (str): the name of the hyperparameter. It will be used in ansatz construction, so
                it needs to match the name of the argument in the initializer.
            type (Any): a single type to check against and attempt to convert user input into.
                If you want to avoid typechecking altogether, pass the object type (and use at
                your own risk)
            description (optional, str): A description string to be displayed when asking to
                set the hyperparameter.
            default: An optional default value for the parameter. It will bypass all typechecking
                and other checks.
            test (Optional[Callable], optional): A callable to check whether parameter values
                are valid. By default, no additional check is performed.
            allow_multiple (bool, optional): Whether the hyperparameter also accepts a list of
                compatible values (e.g. when either a single gate or a list of gates can be given)
        """
        self.name = name
        self.type = hparam_type
        if test is None:
            self.test = lambda input: True
        else:
            self.test = test
        if description is None:
            self.description = ""
        else:
            self.description = str(description)
        self.has_default = default != ""
        if not self.has_default:
            self.default = None
            self.value = None
        else:
            self.default = default
            self.value = self.default
        self.allow_multiple = allow_multiple

    def clear_value(self):
        self.value = self.default

    def _check_single_value(self, value: Any) -> bool:
        if self.has_default and value == self.default:
            return True

        # None means no type checking
        if self.type is None:
            return self.test(value)

        try:
            typed_value = self.type(value)
        except (ValueError, TypeError):
            return False

        return self.test(typed_value)

    def check_value(self, value: Any):
        single_value_check = self._check_single_value(value)
        if single_value_check:
            return True
        elif not self.allow_multiple:
            return False
        else:  # in this case, it might be a list of allowed values
            try:
                checks = [self._check_single_value(x) for x in value]
            except TypeError:
                return False
            else:
                return all(checks)

name instance-attribute

name = name

type instance-attribute

type = hparam_type

test instance-attribute

test = lambda input: True

description instance-attribute

description = ''

has_default instance-attribute

has_default = default != ''

default instance-attribute

default = None

value instance-attribute

value = None

allow_multiple instance-attribute

allow_multiple = allow_multiple

__init__

__init__(
    name,
    hparam_type,
    description=None,
    default="",
    test=None,
    allow_multiple=False,
)

Each parameter needs to be initialized with a name, a type or list of types, and can optionally include a callable to check whether a parameter is valid

Parameters:

Name Type Description Default
name str

the name of the hyperparameter. It will be used in ansatz construction, so it needs to match the name of the argument in the initializer.

required
type Any

a single type to check against and attempt to convert user input into. If you want to avoid typechecking altogether, pass the object type (and use at your own risk)

required
description (optional, str)

A description string to be displayed when asking to set the hyperparameter.

None
default Any

An optional default value for the parameter. It will bypass all typechecking and other checks.

''
test Optional[Callable]

A callable to check whether parameter values are valid. By default, no additional check is performed.

None
allow_multiple bool

Whether the hyperparameter also accepts a list of compatible values (e.g. when either a single gate or a list of gates can be given)

False
Source code in src/quast_decisiontree/core/builder.py
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
def __init__(
    self,
    name: str,
    hparam_type: Any,
    description: str | None = None,
    default: Any = "",
    test: Callable | None = None,
    allow_multiple: bool = False,
) -> None:
    """Each parameter needs to be initialized with a name, a type or list of types, and can
    optionally include a callable to check whether a parameter is valid

    Args:
        name (str): the name of the hyperparameter. It will be used in ansatz construction, so
            it needs to match the name of the argument in the initializer.
        type (Any): a single type to check against and attempt to convert user input into.
            If you want to avoid typechecking altogether, pass the object type (and use at
            your own risk)
        description (optional, str): A description string to be displayed when asking to
            set the hyperparameter.
        default: An optional default value for the parameter. It will bypass all typechecking
            and other checks.
        test (Optional[Callable], optional): A callable to check whether parameter values
            are valid. By default, no additional check is performed.
        allow_multiple (bool, optional): Whether the hyperparameter also accepts a list of
            compatible values (e.g. when either a single gate or a list of gates can be given)
    """
    self.name = name
    self.type = hparam_type
    if test is None:
        self.test = lambda input: True
    else:
        self.test = test
    if description is None:
        self.description = ""
    else:
        self.description = str(description)
    self.has_default = default != ""
    if not self.has_default:
        self.default = None
        self.value = None
    else:
        self.default = default
        self.value = self.default
    self.allow_multiple = allow_multiple

clear_value

clear_value()
Source code in src/quast_decisiontree/core/builder.py
60
61
def clear_value(self):
    self.value = self.default

check_value

check_value(value)
Source code in src/quast_decisiontree/core/builder.py
78
79
80
81
82
83
84
85
86
87
88
89
90
def check_value(self, value: Any):
    single_value_check = self._check_single_value(value)
    if single_value_check:
        return True
    elif not self.allow_multiple:
        return False
    else:  # in this case, it might be a list of allowed values
        try:
            checks = [self._check_single_value(x) for x in value]
        except TypeError:
            return False
        else:
            return all(checks)

AutoClassBuilder

class allowing to build other classes automatically by streamlining the hyperparameter selection process

The core added functionality is a storage for the hyperparameters for easier inspection.

Source code in src/quast_decisiontree/core/builder.py
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
class AutoClassBuilder:
    """class allowing to build other classes automatically by streamlining the hyperparameter
    selection process

    The core added functionality is a storage for the hyperparameters for easier inspection.
    """

    def __init__(
        self,
        superclass: Any,
        hyperparams: list,
        name: str | None = None,
        description: str | None = None,
    ) -> None:
        """Creates a variational ansatz builder.

        Args:
            superclass (BlueprintCircuit): The underlying circuit class with Qiskit-like signature
                Its constructors needs to match the hyperparameters
            hyperparams (list): A list of hyperparameters matching the superclass constructor.
            name (Optional[str]): an optional name to be shown to the user. Otherwise,
                superclass.__name__ will be used.
            description (Optional[str]): an optional description to be shown to the user when
                selecting an algorithm
        """
        self.constructor = superclass
        self.hyperparameters = hyperparams
        if name is None:
            self.name = superclass.__name__
        else:
            self.name = name

        if description is None:
            self.description = ""
        else:
            self.description = description
        self.ansatz = None

    def build(self, hyperparams=None):
        if hyperparams is not None:
            self.set_hyperparams(hyperparams)
        args = {param.name: param.value for param in self.hyperparameters}
        return self.constructor(**args)

    def _get_hp_ind(self, name: str):
        """gets the hyperparameter with the given name"""
        for ind, hp in enumerate(self.hyperparameters):
            if hp.name == name:
                return ind
        raise ValueError(f"No hyperparameter found for name {name}.")

    def set_hyperparam(self, name_or_ind: str | int, value: Any, check_valid=True) -> None:
        """sets the hyperparameter with the given name to the given value, optionally
        checking that it matches the hyperparameter's type and other set_conditions
        """
        if isinstance(name_or_ind, str):
            name = name_or_ind
            ind = self._get_hp_ind(name_or_ind)
        else:
            ind = name_or_ind
            name = self.hyperparameters[ind].name

        if check_valid and not self.hyperparameters[ind].check_value(value):
            raise ValueError(f"Value {value!r} for hyperparameter {name!r} isn't valid.")
        self.hyperparameters[ind].value = value

    def set_hyperparams(self, answers: list | Mapping, check_valid=True):
        """sets the hyperparameters. If provided as a list, one value must be submitted
        for each hyperparameter. If provided as dictionary, the keys must correspond to
        the names of existing hyperparameters

        If check_values = True, the type and other checks of the hyperparameter will be
        run for each value that's provided.
        """
        if isinstance(answers, list):
            if len(answers) != len(self.hyperparameters):
                raise ValueError(
                    f"Length of provided list is {len(answers)}, but there are"
                    f" {len(self.hyperparameters)} hyperparameters."
                )
            else:
                for ind, answer in enumerate(answers):
                    self.set_hyperparam(ind, answer, check_valid=check_valid)
        elif isinstance(answers, Mapping):
            for key, val in answers.items():
                self.set_hyperparam(key, val, check_valid=check_valid)

    def print_hyperparams(self, print_width=50):
        print(f"{'Hyperparameters for ' + self.name:=^{print_width}}")
        for hparam in self.hyperparameters:
            print(
                f"{hparam.name:20}: {hparam.type.__name__:15}: Value {str(hparam.value):15}"
                f" (Default: {str(hparam.default):15})"
            )
        print("=" * print_width)

constructor instance-attribute

constructor = superclass

hyperparameters instance-attribute

hyperparameters = hyperparams

name instance-attribute

name = superclass.__name__

description instance-attribute

description = ''

ansatz instance-attribute

ansatz = None

__init__

__init__(
    superclass, hyperparams, name=None, description=None
)

Creates a variational ansatz builder.

Parameters:

Name Type Description Default
superclass BlueprintCircuit

The underlying circuit class with Qiskit-like signature Its constructors needs to match the hyperparameters

required
hyperparams list

A list of hyperparameters matching the superclass constructor.

required
name Optional[str]

an optional name to be shown to the user. Otherwise, superclass.name will be used.

None
description Optional[str]

an optional description to be shown to the user when selecting an algorithm

None
Source code in src/quast_decisiontree/core/builder.py
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
def __init__(
    self,
    superclass: Any,
    hyperparams: list,
    name: str | None = None,
    description: str | None = None,
) -> None:
    """Creates a variational ansatz builder.

    Args:
        superclass (BlueprintCircuit): The underlying circuit class with Qiskit-like signature
            Its constructors needs to match the hyperparameters
        hyperparams (list): A list of hyperparameters matching the superclass constructor.
        name (Optional[str]): an optional name to be shown to the user. Otherwise,
            superclass.__name__ will be used.
        description (Optional[str]): an optional description to be shown to the user when
            selecting an algorithm
    """
    self.constructor = superclass
    self.hyperparameters = hyperparams
    if name is None:
        self.name = superclass.__name__
    else:
        self.name = name

    if description is None:
        self.description = ""
    else:
        self.description = description
    self.ansatz = None

build

build(hyperparams=None)
Source code in src/quast_decisiontree/core/builder.py
131
132
133
134
135
def build(self, hyperparams=None):
    if hyperparams is not None:
        self.set_hyperparams(hyperparams)
    args = {param.name: param.value for param in self.hyperparameters}
    return self.constructor(**args)

set_hyperparam

set_hyperparam(name_or_ind, value, check_valid=True)

sets the hyperparameter with the given name to the given value, optionally checking that it matches the hyperparameter's type and other set_conditions

Source code in src/quast_decisiontree/core/builder.py
144
145
146
147
148
149
150
151
152
153
154
155
156
157
def set_hyperparam(self, name_or_ind: str | int, value: Any, check_valid=True) -> None:
    """sets the hyperparameter with the given name to the given value, optionally
    checking that it matches the hyperparameter's type and other set_conditions
    """
    if isinstance(name_or_ind, str):
        name = name_or_ind
        ind = self._get_hp_ind(name_or_ind)
    else:
        ind = name_or_ind
        name = self.hyperparameters[ind].name

    if check_valid and not self.hyperparameters[ind].check_value(value):
        raise ValueError(f"Value {value!r} for hyperparameter {name!r} isn't valid.")
    self.hyperparameters[ind].value = value

set_hyperparams

set_hyperparams(answers, check_valid=True)

sets the hyperparameters. If provided as a list, one value must be submitted for each hyperparameter. If provided as dictionary, the keys must correspond to the names of existing hyperparameters

If check_values = True, the type and other checks of the hyperparameter will be run for each value that's provided.

Source code in src/quast_decisiontree/core/builder.py
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
def set_hyperparams(self, answers: list | Mapping, check_valid=True):
    """sets the hyperparameters. If provided as a list, one value must be submitted
    for each hyperparameter. If provided as dictionary, the keys must correspond to
    the names of existing hyperparameters

    If check_values = True, the type and other checks of the hyperparameter will be
    run for each value that's provided.
    """
    if isinstance(answers, list):
        if len(answers) != len(self.hyperparameters):
            raise ValueError(
                f"Length of provided list is {len(answers)}, but there are"
                f" {len(self.hyperparameters)} hyperparameters."
            )
        else:
            for ind, answer in enumerate(answers):
                self.set_hyperparam(ind, answer, check_valid=check_valid)
    elif isinstance(answers, Mapping):
        for key, val in answers.items():
            self.set_hyperparam(key, val, check_valid=check_valid)

print_hyperparams

print_hyperparams(print_width=50)
Source code in src/quast_decisiontree/core/builder.py
180
181
182
183
184
185
186
187
def print_hyperparams(self, print_width=50):
    print(f"{'Hyperparameters for ' + self.name:=^{print_width}}")
    for hparam in self.hyperparameters:
        print(
            f"{hparam.name:20}: {hparam.type.__name__:15}: Value {str(hparam.value):15}"
            f" (Default: {str(hparam.default):15})"
        )
    print("=" * print_width)