Skip to main content
Version: Next

Extended Override syntax​

Hydra Overrides supports functions. When calling a function, one can optionally name parameters. This is following the Python convention of naming parameters.

Example function
def func(a:int, b:str) -> bool:
...


Calling function
func(10,foo)     # Positional only
func(a=10,b=foo) # Named only
func(10,b=foo) # Mixed
func(a=10,foo) # Error

Note the lack of quotes in the examples above. Despite some similarities, this is not Python.

important

Hydra supports very specific functions. If you would like to have another function added, please file an issue and explain the use case.

Sweeps​

Sweep overrides are used by Sweepers to determine what to do. For example, one can instruct the Basic Sweeper to sweep over all combinations of the ranges num1=range(0,3) and num2=range(0,3) - resulting in 9 jobs, each getting a different pair of numbers from 0, 1 and 2.

Choice sweep​

Signature
def choice(
*args: Union[str, int, float, bool, Dict[Any, Any], List[Any], ChoiceSweep]
) -> ChoiceSweep:
"""
A choice sweep over the specified values
"""

Choice sweeps are the most common sweeps. A choice sweep is described in one of two equivalent forms.

Examples
db=mysql,postgresql          # a comma separated list of two or more elements. 
db=choice(mysql,postgresql) # choice

Glob choice sweep​

Signature
def glob(
include: Union[List[str], str], exclude: Optional[Union[List[str], str]] = None
) -> Glob:
"""
A glob selects from all options in the config group.
inputs are in glob format. e.g: *, foo*, *foo.
:param include: a string or a list of strings to use as include globs
:param exclude: a string or a list of strings to use as exclude globs
:return: A Glob object
"""

Assuming the config group schema with the options school, support and warehouse:

Examples
schema=glob(*)                                # school,support,warehouse
schema=glob(*,exclude=support) # school,warehouse
schema=glob([s*,w*],exclude=school) # support,warehouse

Range sweep​

Unlike Python, Hydra's range can be used with both integer and floating-point numbers. In both cases, the range represents a discrete list of values.

Signature
def range(
start: Union[int, float], stop: Optional[Union[int, float]] = None, step: Union[int, float] = 1
) -> RangeSweep:
"""
Range is defines a sweeep over a range of integer or floating-point values.
For a positive step, the contents of a range r are determined by the formula
r[i] = start + step*i where i >= 0 and r[i] < stop.
For a negative step, the contents of the range are still determined by the formula
r[i] = start + step*i, but the constraints are i >= 0 and r[i] > stop.
"""
Examples
num=range(5)                          # 0,1,2,3,4
num=range(0,5) # 0,1,2,3,4
num=range(0,5,2) # 0,2,4
num=range(0,10,3.3) # 0.0,3.3,6.6,9.9
num=range(-5,step=-1) # 0,-1,-2,-3,-4

Interval sweep​

An interval sweep represents all the floating point value between two values. This is used by optimizing sweepers like Ax and Nevergrad. The basic sweeper does not support interval.

Signature
def interval(start: Union[int, float], end: Union[int, float]) -> IntervalSweep:
"""
A continuous interval between two floating point values.
value=interval(x,y) is interpreted as x <= value < y
"""
Examples
interval(1.0,5.0)  # 1.0 <= x < 5.0
interval(1,5) # 1.0 <= x < 5.0, auto-cast to floats

Tag​

With tags you can add arbitrary metadata to a sweep. The metadata can be used by advanced sweepers.

Signature
def tag(*args: Union[str, Union[Sweep]], sweep: Optional[Sweep] = None) -> Sweep:
"""
Tags the sweep with a list of string tags.
"""
Examples
tag(log,interval(0,1))          # 1.0 <= x < 1.0, tags=[log]
tag(foo,bar,interval(0,1)) # 1.0 <= x < 1.0, tags=[foo,bar]

Reordering lists and sweeps​

sort​

Signature
def sort(
*args: Union[ElementType, ChoiceSweep, RangeSweep],
sweep: Optional[Union[ChoiceSweep, RangeSweep]] = None,
list: Optional[List[Any]] = None,
reverse: bool = False,
) -> Any:
"""
Sort an input list or sweep.
reverse=True reverses the order
"""
Examples
# sweep
sort(1,3,2) # ChoiceSweep(1,2,3)
sort(1,3,2,reverse=true) # ChoiceSweep(3,2,1)
sort(choice(1,2,3)) # ChoiceSweep(1,2,3)
sort(sweep=choice(1,2,3)) # ChoiceSweep(1,2,3)
sort(choice(1,2,3),reverse=true) # ChoiceSweep(3,2,1)
sort(range(10,1)) # range in ascending order
sort(range(1,10),reverse=true) # range in descending order

# lists
sort([1,3,2]) # [1,2,3]
sort(list=[1,3,2]) # [1,2,3]
sort(list=[1,3,2], reverse=true) # [3,2,1]

# single value returned as is
sort(1) # 1

shuffle​

Signature
def shuffle(
*args: Union[ElementType, ChoiceSweep, RangeSweep],
sweep: Optional[Union[ChoiceSweep, RangeSweep]] = None,
list: Optional[List[Any]] = None,
) -> Union[List[Any], ChoiceSweep, RangeSweep]:
"""
Shuffle input list or sweep (does not support interval)
"""
Examples
shuffle(a,b,c)                                       # shuffled a,b,c
shuffle(choice(a,b,c)), shuffle(sweep=choice(a,b,c)) # shuffled choice(a,b,c)
shuffle(range(1,10)) # shuffled range(1,10)
shuffle([a,b,c]), shuffle(list=[a,b,c]) # shuffled list [a,b,c]

Type casting​

You can cast values and sweeps to int, float, bool, str or json_str. Note that unlike the others, json_str will affect the whole container rather than just the values.

Example
int(3.14)                  # 3 (int)
int(value=3.14) # 3 (int)
float(10) # 10.0 (float)
str(10) # "10" (str)
bool(1) # true (bool)
float(range(1,10)) # range(1.0,10.0)
str([1,2,3]) # ['1','2','3']
str({a:10}) # {a:'10'}
json_str({a:10}) # '{"a":10}'

Below are pseudo code snippets that illustrates the differences between Python's casting and Hydra's casting.

Casting string to bool​

Python
def bool(value: Any) -> bool:
if isinstance(value, str):
return len(value) > 0
else:
return bool(value)




Hydra
def bool(s: str) -> bool:
if isinstance(value, str):
if value.lower() == "false":
return False
elif value.lower() == "true":
return True
else:
raise ValueError()
return bool(value)

Casting lists​

Casting lists results in a list where each element is recursively cast. Failure to cast an element in the list fails the cast of the list.

Python
def cast_int(value: Any):
if isinstance(value, list):
raise TypeError()
else:
return int(v)


Hydra
def cast_int(value: Any):
if isinstance(v, list):
return list(map(cast_int, v))
else:
return int(v)


Casting dicts​

Casting dicts results in a dict where values are recursively cast, but keys are unchanged. Failure to cast a value in the dict fails the cast of the entire dict.

Python
def cast_int(value: Any):
if isinstance(value, dict):
raise TypeError()
else:
return int(v)


Hydra
def cast_int(value: Any):
if isinstance(value, dict):
return apply_to_values(
value, cast_int
)
else:
return int(v)

Casting ranges​

Ranges can be cast to float or int, resulting in start, stop and step being cast and thus the range elements being cast.

Python
def cast_int(value: Any):
if isinstance(value, RangeSweep):
raise TypeError()
else:
return int(v)




Hydra
def cast_int(value: Any):
if isinstance(value, RangeSweep):
return RangeSweep(
start=cast_int(value.start),
stop=cast_int(value.stop),
step=cast_int(value.step),
)
else:
return int(v)

Conversion matrix​

Below is the conversion matrix from various inputs to all supported types. Input are grouped by type.

int()float()str()bool()json()
101010.0β€œ10”trueβ€œ10”
000.0β€œ0”falseβ€œ0”
10.01010.0β€œ10.0”trueβ€œ10.0”
0.000.0β€œ0.0”falseβ€œ0.0”
inferrorinfβ€˜inf’trueβ€œInfinity”
nanerrornanβ€˜nan’trueβ€œNaN”
1e61,000,0001e6β€˜1000000.0’trueβ€œ1000000.0”
fooerrorerrorfooerror'β€œfoo”'
β€œβ€ (empty string)errorerrorβ€œβ€error'β€œβ€'
β€œ10”1010.0β€œ10”error'β€œ10”'
β€œ10.0”error10.0β€œ10.0”error'β€œ10.0”'
β€œtrue”errorerrorβ€œtrue”true'β€œtrue”'
β€œfalse”errorerrorβ€œfalse”false'β€œfalse”'
β€œ[1,2,3]”errorerrorβ€œ[1,2,3]”error'β€œ[1,2,3]”'
β€œ{a:10}”errorerrorβ€œ{a:10}”error'β€œ{a:10}”'
true11.0β€œtrue”trueβ€œtrue”
false00.0β€œfalse”falseβ€œfalse”
[][][][][]β€œ[]”
[0,1,2][0,1,2][0.0,1.0,2.0][β€œ0”,”1”,”2”][false,true,true]β€œ[1, 2, 3]”
[1,[2]][1,[2]][1.0,[2.0]][β€œ1”,[β€œ2”]][true,[true]]β€œ[1, [2]]”
[a,1]errorerror[β€œa”,”1”]error'[β€œa”, 1]'
{}{}{}{}{}β€œ{}”
{a:10}{a:10}{a:10.0}{a:”10”}{a: true}'{β€œa”: 10}'
{a:[0,1,2]}{a:[0,1,2]}{a:[0.0,1.0,2.-]}{a:[β€œ0”,”1”,”2”]}{a:[false,true,true]}'{β€œa”: [1, 2, 3]}'
{a:10,b:xyz}errorerror{a:”10”,b:”xyz”}error'{β€œa”: 10, β€œb”: β€œxyz”}'
choice(0,1)choice(0,1)choice(0.0,1.0)choice(β€œ0”,β€œ1”)choice(false,true)choice(β€œ0”, β€œ1”)
choice(a,b)errorerrorchoice(β€œa”,”b”)errorchoice('β€œa”', 'β€œb”')
choice(1,a)errorerrorchoice(β€œ1”,”a”)errorchoice(β€œ1”, 'β€œa”')
interval(1.0, 2.0)interval(1, 2)interval(1.0, 2.0)errorerrorinterval(β€œ1.0”, β€œ2.0”)
interval(1, 2)interval(1, 2)interval(1.0, 2.0)errorerrorinterval(β€œ1”, β€œ2”)
range(1,10)range(1,10)range(1.0,10.0)errorerrorerror
range(1.0, 10.0)range(1,10)range(1.0,10.0)errorerrorerror