moptipy.utils package¶
Utilities used in other moptipy modules. Strings that carry format information. Bases: A subclass of str capable of holding formatting information. This is a version of string that also stores format information that can, for example, be used by a text format driver when typesetting text. Instances of this class can also be used as normal strings and be printed to the console without any issue. However, they also hold information about whether the text should be Furthermore, if a number or numerical string is represented as a formatted string, the field If the field Add the given format to the specified string. Create a formatted string representing a number. number ( the formatted string representing it Create a special string. A special string has mode SPECIAL set and notifies the text format that special formatting conversion, e.g., a translation from the character “alpha” (u03b1) to alpha is required. text ( the formatted string represents NaN, i.e., “not a number” the formatted string represents negative infinity the formatted string represents positive infinity Print a help screen. Create an argument parser with default settings. the argument parser The HTML text format driver. Bases: The HTML text driver. Begin an HTML table cell. Begin a row in an HTML table. End an HTML table cell. End a row in a HTML table. The The idea here is to have simply tools that provide locale-specific keywords, texts, and number formats. Bases: A language-based dictionary for locale-specific keywords. Get the current language. the current language Make a suitable filename by appending the language id. Get the default font for this language. the default font for this language Convert an integer to a string. Return a string based on the specified format. Translate the given key to a string in the current language. Get a callable that always returns the current translation of a key. The callable will ignore all of its parameters and just return the translation. This means that you can pass parameters to it and they will be ignored. key ( the callable doing the translation Create a lambda taking a dimensions and presenting a function thereof. The latex text format driver. Bases: The LaTeX text driver. Begin a LaTeX table cell. End a row in a LaTeX table. End a table section header. Classes for writing structured log files. A A The beginning and ending of section named XXX are BEGIN_XXX and END_XXX. This class is used by the Bases: A logger that is designed to output CSV data. The coma-separated-values log is actually a semicolon-separated-values log. This form of logging is used to store progress information or time series data, as captured by the optimization Bases: A logger logging to a string in memory. the YAML-conform separator between a key and a value Bases: A logger for key-value pairs. The key-values section XXX starts with the line BEGIN_XXX and ends with the line END_XXX. On every line in between, there is a key-value pair of the form key: value. Key-values sections support so-called scopes. Key-values pairs belong to a scope Y if the key starts with Y. followed by the actual key, e.g., a.g: 5 denotes that the key g of scope a has value 5. Such scopes can be arbitrarily nested: The key-value pair x.y.z: 2 denotes a key z in the scope y nested within scope x having the value 2. This system of nested scopes allows you to recursively invoke the method Write a key-value pair. Given key A and value B, the line A: B will be added to the log. If value (B) happens to be a floating point number, the value will also be stored in hexadecimal notation ( Create a new scope for key prefixes. prefix ( the new logger Bases: An internal base class for logger sections. Write a comment line. A comment starts with # and is followed by text. Bases: An abstract base class for logging data in a structured way. There are two implementations of this, Create a log section for CSV data with ; as column separator. The first line will be the headline with the column names. the new logger Create a log section for key-value pairs. The contents of such a section will be valid YAML mappings, i.w., conform to https://yaml.org/spec/1.2/spec.html#mapping. This means they can be parsed with a YAML parser (after removing the section start and end marker, of course). title ( the new logger Create a log section for unstructured text. title ( the new logger the indicator of the start of a log section the replacement for special characters Bases: A logger for raw, unprocessed text. Such a log section is used to capture the raw contents of the solutions discovered by the optimization Parse a the dictionary with the The markdown text format driver. Bases: The markdown text driver. Begin a Markdown table cell. Begin a row in a markdown table. End a row in a Markdown table. Simple routines for handling numbers and numerical stuff. The positive limit for doubles that can be represented exactly as ints. Try to divide two numbers at best precision. First, we will check if we can convert the numbers to integers without loss of precision via a/b, but always finite ValueError – if either one of the arguments or the final result would not be finite Attempt to convert a float to an integer. This method will convert a floating point number to an integer if the floating point number was representing an exact integer. This is the case if it has a) no fractional part and b) is in the range -9007199254740992…9007199254740992, i.e., the range where +1 and -1 work without loss of precision. val ( an int if val can be represented as int without loss of precision, val otherwise TypeError – if val is neither an instance of int nor of float ValueError – if val is a float, but not finite Try to divide two integers at best precision. Floating point divisions can incur some loss of precision. We try to avoid this here as much as possible. First, we check if a is divisible by b without any fractional part. If this is true, then we can do a pure integer division without loss of any precision. Otherwise, we would do a floating point division. This will lead the values be converted to floating point numbers, which can incur a loss of precision. In the past, we tried to divide both numbers by their gcd to make them smaller in order to avoid a loss of precision. But it seems that Python is already doing something like this internally when performing the a / b division anyway, so we don’t do this anymore. However, it is still attempted to convert the result back to an integer. a/b, either as int or as float but always a finite value OverflowError – if the division must be performed using floating point arithmetic, but the result would be too large to fit into a float ZeroDivisionError – if b==0 Compute value**(1/power) where value and power are both integers. value ( power ( none_on_overflow ( the root, or None if we encounter an overflow Utilities for interaction with numpy. The default floating point type. The default integer type: the signed 64-bit integer. The default numerical types. The default unsigned integer type: an unsigned 64-bit integer. The numpy integer data types. the character identifying the numpy data type backing the space Convert a numpy array to a string. This method represents a numpy array as a string. It makes sure to include all the information stored in the array and to represent it as compactly as possible. If the array has numerical values, it will use the default CSV separator. If the array contains Boolean values, it will use no separator at all. Obtain the most suitable numpy data type to represent the data. If the data is always integer, the smallest possible integer type will be sought using always_int ( lower_bound ( upper_bound ( ValueError – if the lower_bound > upper_bound or any bound is nan or the integer bounds exceed the largest int range TypeError – if, well, you provide parameters of the wrong types Fill the canonical permutation into an array. Convert an integer range to an appropriate numpy data type. The returned type is as compact as possible and signed types are preferred over unsigned types. The returned the numpy integer range TypeError – if the parameters are not integers ValueError – if the range is invalid, i.e., if min_value exceeds max_value or either of them exceeds the possible range of the largest numpy integers. Check if an array is all finite. a ( True if all elements in the array are finite, False otherwise Check whether a Check whether a Create an integer array of the given length filled with the maximum value. shape – the requested shape dtype ( the new array Convert a scalar number from numpy to a corresponding Python type. number ( an integer or float representing the number Convert a numpy data type to a string. Instantiate a random number generator from a seed. Make sure that a random seed is valid. rand_seed ( the rand seed TypeError – if the random seed is not an int ValueError – if the random seed is not valid Draw a (pseudo-random) random seed. This method either uses a provided random number generator random or a default generator. It draws 8 bytes from this generator and converts them to an unsigned (64 bit) integer big-endian style. random ( the random seed TypeError – if random is specified but is not an instance of Generator Reproducibly generate n_seeds unique random seeds from a string. This function will produce a sorted sequence of n_seeds random seeds, each of which being an unsigned 64-bit integer, from the string passed in. The same string will always yield the same sequence reproducibly. Running the function twice with different values of n_seeds will result in the two sets of random seeds, where the larger one (for the larger value of n_seeds) contains all elements of the smaller one. This works as follows: First, we encode the string to an array of bytes using the UTF-8 encoding (string.encode(“utf8”)). Then, we compute the SHA-512 digest of this byte array (using hashlib.sha512). From this digest, we then use two chunks of 32 bytes (256 bit) to seed two This procedure is used in Penny Pritzker and Willie E. May, editors, Secure Hash Standard (SHS), Federal Information Processing Standards Publication FIPS PUB 180-4, Gaithersburg, MD, USA: National Institute of Standards and Technology, Information Technology Laboratory, August 2015. doi: https://dx.doi.org/10.6028/NIST.FIPS.180-4 https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf Unicode Consortium, editors, The Unicode(R) Standard, Version 15.0 - Core Specification, Mountain View, CA, USA: Unicode, Inc., September 2022, ISBN:978-1-936213-32-0, https://www.unicode.org/versions/Unicode15.0.0/ NumPy Community, Permuted Congruential Generator (64-bit, PCG64), in NumPy Reference, Release 1.23.0, June 2022, Austin, TX, USA: NumFOCUS, Inc., https://numpy.org/doc/1.23/numpy-ref.pdf Melissa E. O’Neill: PCG: A Family of Simple Fast Space-Efficient Statistically Good Algorithms for Random Number Generation, Report HMC-CS-2014-0905, September 5, 2014, Claremont, CA, USA: Harvey Mudd College, Computer Science Department. https://www.cs.hmc.edu/tr/hmc-cs-2014-0905.pdf a list of random seeds TypeError – if the parameters do not follow the type contract ValueError – if the parameter values are invalid The numeric format definitions. the default shared singleton instance of the number group format Bases: A format description for a group of numbers. With instances of this class, you can convert a sequence of numbers to a sequence of strings with uniform, pleasant formatting. The idea is that such numbers can be written, e.g., into a column of a table and that this column will then have a nice and uniform appearance. In other words, we will avoid situations like the following: “1234938845, 1e-20, 0.002, 34757773, 1e30, 0.9998837467” which looks rather odd. While the numbers may be displayed correctly, the formatting of all numbers is different. If we want to present numbers that describe related quantities, we rather want them to all have the same format. This class here can achieve this in a customizable way. Derive a new number group format from this one. int_to_float_threshold ( get_int_renderer ( get_float_format ( a new number group format that differs from the current format only in terms of the non-None parameters specified the getter for the float format to be used to represent a range of values the function to be used to get the renderer for all integers and integer parts of floats the absolute threshold above which all integer numbers must be converted to floats to render them in the ‘E’ notation Convert a sequence of numbers to text with uniform shape. Often, we need to convert a set of numbers to strings as output for a table or another representative thext. In such a case, you want to present all numbers in the set in the same format. Imagine you have the number vector [1E-4, 1/7, 123456789012345678]. If you simply convert this list to a string directly, what you get is [0.0001, 0.14285714285714285, 123456789012345678]. Now this looks very ugly. First, we have one very big number 123456789012345678. If the numbers stem from an experiment, then we are hardly able to obtain any number at a very extreme precision. The 18 digits in 123456789012345678 sort of suggest a precision to 18 decimals, since the number ends in specific digits (as opposed to 123450000000000000 which a reader would naturally preceive as a rounded quantity). Additionally, we have the number 0.14285714285714285, which has a very long fractional part, which, too, suggests a very high precision. Writing both mentioned numbers next to each other, this suggests as if we could present a number as high as 10**18 at a precision of 10**-17. And it also looks ugly, because both numbers are not uniformly formatted. Instead, our function here renders the number list as [‘1.00*10^-4^’, ‘1.43*10^-1^’, ‘1.23*10^17^’]. It recognizes that we should present numbers as powers of ten and then limits the precision to three digits. This function is thus intended to produce some sort of uniform format with reasonable precision uniformly for a numerical vector, under the assumption that all numbers should be presented in the same numerical range and quantity. a list with the text representation Get the default float format for numbers in the given range. min_finite ( max_finite ( max_frac_len ( min_non_zero_abs ( int_to_float_threshold ( Get the default integer renderer. the default integer renderer, which uses the integer rendering of the currently active language setting. Default styles for plots. The internal color black. The internal color white. The default grid color Obtain the basic style for lines in diagrams. Create a sequence of distinct line dashes. Transform an importance value to an alpha value. Basically, an importance of 0 indicates a normal line in a normal plot that does not need to be emphasized. A positive importance means that the line should be emphasized. A negative importance means that the line should be de-emphasized. Transform an importance value to a font size. Transform an importance value to a line width. Basically, an importance of 0 indicates a normal line in a normal plot that does not need to be emphasized. A positive importance means that the line should be emphasized. A negative importance means that the line should be de-emphasized. Utilities for creating and storing figures. Create a matplotlib figure. Divide a figure into nrows*ncols sub-plots. items ( max_items_per_plot ( max_rows ( max_cols ( min_rows ( min_cols ( default_width_per_col ( default_height_per_row ( max_height ( max_width ( kwargs – a set of optional arguments plot_config ( a tuple with the figure, followed by a series of tuples with each sub-figure, the index of the first item assigned to it, the index of the last item assigned to it + 1, their row, their column, and their overall index Get a list with label colors from a set of artists. a list of label colors Get a renderer that can be used for determining figure element sizes. the renderer Put labels on a figure. axes ( x_label ( x_label_inside ( x_label_location ( y_label ( y_label_inside ( y_label_location ( font_size ( z_order ( Put a label text box near an axis. axes ( text ( x ( y ( font_size ( may_rotate_text ( z_order ( font ( Routines for handling strings. the replacement for “.” in a file name Beautify the string representation of a float. This function beautifies the string representation of a float by using unicode superscripts for exponents. s ( the beautified string representation Convert a string from a name to a number. This function is the inverse of s ( an integer or float, depending on the number represented by s Convert a float to a string for use in a component name. This function can be inverted by applying Sanitize a name in such a way that it can be used as path component. name ( the sanitized name ValueError – if the name is invalid or empty TypeError – if the name is None or not a string A tool for writing a section with system information into log files. Add a dependency so that its version can be stored in log files. Warning: You must add all dependencies before the first log file is written. As soon as the dependency ( ignore_if_make_build ( TypeError – if dependency is not a string ValueError – if dependency is an invalid string or the log information has already been accessed before and modifying it now is not permissible. Get the system information as string. the system information as string Write the system information section to a logger. The concept of this method is that we only construct the whole system configuration exactly once in memory and then always directly flush it as a string to the logger. This is much more efficient than querying it every single time. Classes for printing tables in a text format. Bases: A row class. Render the text of a cell. As parameter text, you can provide either a string or a sequence of strings. You can also provide an instance of Bases: A set of table rows. Bases: A table section is a group of rows, potentially with a header. Bases: The table context. This class provides a simple and hierarchically structured way to write tables in different formats. It only supports the most rudimentary formatting and nothing fancy (such as references, etc.). However, it may be totally enough to quickly produce tables with results of experiments. Every table must have a table header (see Infrastructure to created structured text, like Markdown and LaTeX. indicates a row or cell in the section header indicates a row or cell in the table header Bases: A base class for text format drivers. Table drivers allow us to render the structured text. It used, for example, by instances of Write the beginning of the table body. stream ( cols ( Begin a header cell, section header cell, or normal cell. stream ( cols ( section_index ( row_index ( col_index ( cell_mode ( Begin the header row of the table. stream ( cols ( Begin a table header row, section row, or normal row in a section. stream ( cols ( section_index ( row_index ( row_mode ( Begin a new section of the table. stream ( cols ( section_index ( Begin the header row of a section. stream ( cols ( section_index ( Write the ending of the table body. stream ( cols ( End a header cell, section header cell, or normal cell. stream ( cols ( section_index ( row_index ( col_index ( cell_mode ( End the header row of the table. stream ( cols ( End a table header row, section row, or normal row in a section. stream ( cols ( section_index ( row_index ( End a section of the table. stream ( cols ( section_index ( n_rows ( End the header row of a section. stream ( cols ( section_index ( Get the right filename for this text driver. Write a chunk of text. stream ( text ( bold ( italic ( code ( mode (Submodules¶
moptipy.utils.formatted_string module¶
str
bold
, italic
, or rendered in a monospace code
font.mode
will be non-zero. If it is TEXT=1, the string is a normal number, if it is NAN=2, the string is “nan”, if it is POSITIVE_INFINITY=3, then the string is inf, and if it is NEGATIVE_INFINITY=4, the string is -inf. These values permit a text driver, for example, to replace the special numeric values with unicode constants or certain commands. It may also choose to replace floating point number of the form 1.5E23 with something like 1.5*10^23. It can do so because a non-zero mode
indicates that the string is definitely representing a number and that numbers in the string did not just occur for whatever other reason.mode
has value SPECIAL=5, then the text contains a special sequence, e.g., a unicode character outside of the normal range. Then, the text format driver can render this character as a special entity.>>> from typing import cast
>>> st = "abc"
>>> type(st)
<class 'str'>
>>> fs = cast(FormattedStr, FormattedStr.add_format(st, bold=True))
>>> type(fs)
<class 'moptipy.utils.formatted_string.FormattedStr'>
>>> fs.bold
True
>>> fs.italic
False
>>> fs = cast(FormattedStr, FormattedStr.add_format(fs, italic=True))
>>> fs.bold
True
>>> fs.italic
True
>>> fs.mode
0
int
| float
| str
| None
) – the original number or numeric string>>> FormattedStr.number(inf)
'inf'
>>> FormattedStr.number(inf) is _PINF
True
>>> FormattedStr.number(inf).mode
3
>>> FormattedStr.number(-inf)
'-inf'
>>> FormattedStr.number(-inf) is _NINF
True
>>> FormattedStr.number(-inf).mode
4
>>> FormattedStr.number(nan)
'nan'
>>> FormattedStr.number(nan) is _NAN
True
>>> FormattedStr.number(nan).mode
2
>>> FormattedStr.number(123)
'123'
>>> FormattedStr.number(123e3)
'123000.0'
>>> FormattedStr.number(123e3).mode
1
str
) – the text>>> FormattedStr.special("bla")
'bla'
>>> FormattedStr.special("bla").mode
5
moptipy.utils.help module¶
>>> ap = moptipy_argparser(
... __file__, "This is a test program.", "This is a test.")
>>> isinstance(ap, argparse.ArgumentParser)
True
>>> "Copyright" in ap.epilog
True
moptipy.utils.html module¶
TextFormatDriver
moptipy.utils.lang module¶
Lang
class provides facilities for easy internationalization.object
>>> Lang.get("en").set_current()
>>> print(Lang.current().filename("b"))
b
>>> Lang.get("zh").set_current()
>>> print(Lang.current().filename("b"))
b_zh
>>> print(Lang.get("en").filename("test"))
test
>>> print(Lang.get("zh").filename("test"))
test_zh
>>> print(Lang.get("en").font())
DejaVu Sans
>>> print(Lang.get("zh").font())
Noto Sans SC
>>> print(Lang.get("en").format_int(100000))
100'000
>>> print(Lang.get("zh").format_int(100000))
10'0000
>>> l = Lang.get("en")
>>> l.extend({"z": "{a}: bla{b}"})
>>> print(l.format_str("z", a=5, b=6))
5: bla6
>>> EN.extend({'a': 'b'})
>>> EN.set_current()
>>> print(Lang.translate("a"))
b
>>> DE.extend({'a': 'c'})
>>> Lang.get("de").set_current()
>>> print(Lang.translate("a"))
c
str
) – the key to translate>>> cal = Lang.translate_call("a")
>>> EN.extend({'a': 'b'})
>>> EN.set_current()
>>> print(cal())
b
>>> print(cal(1, 2, 3))
b
>>> DE.extend({'a': 'c'})
>>> Lang.get("de").set_current()
>>> print(cal("x"))
c
>>> Lang.get("en").set_current()
>>> Lang.get("en").extend({"ERT": "ERT"})
>>> Lang.get("en").extend({"FEs": "time in FEs"})
>>> f = Lang.translate_func("ERT")
>>> print(f("FEs"))
ERT [time in FEs]
>>> Lang.get("de").set_current()
>>> Lang.get("de").extend({"ERT": "ERT"})
>>> Lang.get("de").extend({"FEs": "Zeit in FEs"})
>>> print(f("FEs"))
ERT [Zeit in FEs]
moptipy.utils.latex module¶
TextFormatDriver
>>> from io import StringIO
>>> from moptipy.utils.formatted_string import FormattedStr
>>> from moptipy.utils.table import Table
>>> s = StringIO()
>>> latex = LaTeX.instance()
>>> print(str(latex))
tex
>>> with Table(s, "lrc", latex) as t:
... with t.header() as header:
... with header.row() as h:
... h.cell(FormattedStr("1", bold=True))
... h.cell(FormattedStr("2", code=True))
... h.cell(FormattedStr("3", italic=True))
... with t.section() as g:
... with g.row() as r:
... r.cell("a")
... r.cell("b")
... r.cell("c")
... with g.row() as r:
... r.cell("d")
... r.cell("e")
... r.cell("f")
>>> print(f"'{s.getvalue()}'")
'\begin{tabular}{lrc}%
\hline%
{\textbf{1}}&{\texttt{2}}&{\textit{3}}\\%
\hline%
a&b&c\\%
d&e&f\\%
\hline%
\end{tabular}%
'
moptipy.utils.logger module¶
Logger
offers functionality to write structured, text-based log files that can hold a variety of information. It is implemented in two flavors, FileLogger
, which writes data to a file, and InMemoryLogger
, which writes data to a buffer in memory (which is mainly useful for testing).Logger
can produce output in three formats:csv()
creates a section of semicolon-separated-values data (CsvLogSection
), which we call csv because it structured basically exactly as the well-known comma-separated-values data, just using semicolons.key_values()
creates a key-values section (KeyValueLogSection
) in YAML format. The specialty of this section is that it permits hierarchically structuring of data by spawning out sub-sections that are signified by a key prefix via scope()
.text()
creates a raw text section (TextLogSection
), into which raw text can be written.Execution
and experiment-running facility (run_experiment()
) to produce log files complying with https://thomasweise.github.io/moptipy/#log-files. Such log files can be parsed via log_parser
.LogSection
Process
and activated by, e.g., the methods set_log_improvements()
and set_log_all_fes()
. It will look like this:>>> with InMemoryLogger() as logger:
... with logger.csv("CSV", ["A", "B", "C"]) as csv:
... csv.row((1, 2, 3))
... csv.row([1.5, 2.0, 3.5])
... print(logger.get_log())
['BEGIN_CSV', 'A;B;C', '1;2;3', '1.5;2;3.5', 'END_CSV']
Logger
LogSection
log_parameters_to()
without worrying of key clashes. Just wrap the call to the log_parameters_to method of a sub-component into a unique scope. At the same time, this avoids the need of any more complex hierarchical data structures in our log files.>>> with InMemoryLogger() as logger:
... with logger.key_values("A") as kv:
... kv.key_value("x", 1)
... with kv.scope("b") as sc1:
... sc1.key_value("i", "j")
... with sc1.scope("c") as sc2:
... sc2.key_value("l", 5)
... kv.key_value("y", True)
... print(logger.get_log())
['BEGIN_A', 'x: 1', 'b.i: j', 'b.c.l: 5', 'y: T', 'END_A']
float.hex()
).KeyValueLogSection
only allows you to store flat key-value pairs where each key must be unique. However, what do we do if we have two components of an algorithm that have parameters with the same name (key)? We can hierarchically nest KeyValueLogSection
sections via prefix scopes. The idea is as follows: If one component has sub-components, instead of invoking their log_parameters_to()
methods directly, which could lead to key-clashes, it will create a scope()
for each one and then pass these scopes to their log_parameters_to()
. Each scope basically appends a prefix and a “.” to the keys. If the prefixes are unique, this ensures that all prefix+”.”+keys are unique, too.>>> from moptipy.utils.logger import InMemoryLogger
>>> with InMemoryLogger() as l:
... with l.key_values("A") as kv:
... kv.key_value("x", "y")
... with kv.scope("b") as sc1:
... sc1.key_value("x", "y")
... with sc1.scope("c") as sc2:
... sc2.key_value("x", "y")
... with kv.scope("d") as sc3:
... sc3.key_value("x", "y")
... with sc3.scope("c") as sc4:
... sc4.key_value("x", "y")
... print(l.get_log())
['BEGIN_A', 'x: y', 'b.x: y', 'b.c.x: y', 'd.x: y', 'd.c.x: y', 'END_A']
str
) – the key prefixAbstractContextManager
>>> from moptipy.utils.logger import InMemoryLogger
>>> with InMemoryLogger() as l:
... with l.text("A") as tx:
... tx.write("aaaaaa")
... tx.comment("hello")
... print(l.get_log())
['BEGIN_A', 'aaaaaa', '# hello', 'END_A']
AbstractContextManager
InMemoryLogger
, which logs data in memory and is mainly there for testing and debugging, an FileLogger
which logs to a text file and is to be used in experiments with moptipy.>>> from moptipy.utils.logger import FileLogger
>>> from pycommons.io.temp import temp_file
>>> with temp_file() as t:
... with FileLogger(str(t)) as l:
... with l.csv("A", ["x", "y"]) as csv:
... csv.row([1,2])
... csv.row([3,4])
... csv.row([4, 12])
... text = open(str(t), "r").read().splitlines()
... print(text)
['BEGIN_A', 'x;y', '1;2', '3;4', '4;12', 'END_A']
>>> import csv
>>> for r in csv.reader(text[1:5], delimiter=";"):
... print(r)
['x', 'y']
['1', '2']
['3', '4']
['4', '12']
str
) – the title of the new section>>> from pycommons.io.temp import temp_file
>>> with temp_file() as t:
... with FileLogger(str(t)) as l:
... with l.key_values("B") as kv:
... kv.key_value("a", "b")
... with kv.scope("c") as kvc:
... kvc.key_value("d", 12)
... kvc.key_value("e", True)
... kv.key_value("f", 3)
... text = open(str(t), "r").read().splitlines()
>>> print(text)
['BEGIN_B', 'a: b', 'c.d: 12', 'c.e: T', 'f: 3', 'END_B']
>>> import yaml
>>> dic = yaml.safe_load("\n".join(text[1:5]))
>>> print(list(dic.keys()))
['a', 'c.d', 'c.e', 'f']
str
) – the title of the new section>>> from moptipy.utils.logger import InMemoryLogger
>>> with InMemoryLogger() as l:
... with l.text("C") as tx:
... tx.write("aaaaaa")
... tx.write("bbbbb")
... tx.write("\n")
... tx.write("ccccc")
... print(l.get_log())
['BEGIN_C', 'aaaaaa', 'bbbbb', '', 'ccccc', 'END_C']
LogSection
Process
. For this purpose, our system will use the method to_str()
of the search and/or solution Space
.>>> with InMemoryLogger() as logger:
... with logger.text("T") as txt:
... txt.write("Hello World!")
... print(logger.get_log())
['BEGIN_T', 'Hello World!', 'END_T']
key_values()
section’s text.>>> from moptipy.utils.logger import InMemoryLogger
>>> with InMemoryLogger() as l:
... with l.key_values("B") as kv:
... kv.key_value("a", "b")
... with kv.scope("c") as kvc:
... kvc.key_value("d", 12)
... kvc.key_value("e", True)
... kv.key_value("f", 3)
... txt = l.get_log()
>>> print(txt)
['BEGIN_B', 'a: b', 'c.d: 12', 'c.e: T', 'f: 3', 'END_B']
>>> dic = parse_key_values(txt[1:5])
>>> keys = list(dic.keys())
>>> keys.sort()
>>> print(keys)
['a', 'c.d', 'c.e', 'f']
moptipy.utils.markdown module¶
TextFormatDriver
>>> from io import StringIO
>>> from moptipy.utils.formatted_string import FormattedStr
>>> from moptipy.utils.table import Table
>>> s = StringIO()
>>> md = Markdown.instance()
>>> print(str(md))
md
>>> with Table(s, "lrc", md) as t:
... with t.header() as header:
... with header.row() as h:
... h.cell(FormattedStr("1", bold=True))
... h.cell(FormattedStr("2", code=True))
... h.cell(FormattedStr("3", italic=True))
... with t.section() as g:
... with g.row() as r:
... r.cell("a")
... r.cell("b")
... r.cell("c")
... with g.row() as r:
... r.cell("d")
... r.cell("e")
... r.cell("f")
>>> print(f"'{s.getvalue()}'")
'|**1**|`2`|*3*|
|:--|--:|:-:|
|a|b|c|
|d|e|f|
'
moptipy.utils.math module¶
try_int()
. If yes, then we go for the maximum-precision integer division via try_int_div()
. If no, then we do the normal floating point division and try to convert the result to an integer if that can be done without loss of precision.>>> try_float_div(1e180, 1e60)
1.0000000000000001e+120
>>> try_float_div(1e60, 1e-60)
1e+120
>>> try_float_div(1e14, 1e-1)
1000000000000000
>>> try_float_div(1e14, -1e-1)
-1000000000000000
>>> try_float_div(-1e14, 1e-1)
-1000000000000000
>>> try_float_div(-1e14, -1e-1)
1000000000000000
>>> try_float_div(1e15, 1e-1)
1e+16
>>> try_float_div(1e15, -1e-1)
-1e+16
>>> try_float_div(-1e15, 1e-1)
-1e+16
>>> try_float_div(-1e15, -1e-1)
1e+16
>>> try_float_div(1e15, 1e-15)
9.999999999999999e+29
>>> print(type(try_float_div(10, 2)))
<class 'int'>
>>> print(type(try_float_div(10, 3)))
<class 'float'>
>>> print(type(try_float_div(10, 0.5)))
<class 'int'>
>>> from math import inf, nan
>>> try:
... try_float_div(1.0, 0)
... except ZeroDivisionError as zde:
... print(zde)
integer division or modulo by zero
>>> try:
... try_float_div(1.0, -0.0)
... except ZeroDivisionError as zde:
... print(zde)
integer division or modulo by zero
>>> try:
... try_float_div(inf, 0)
... except ValueError as ve:
... print(ve)
Value must be finite, but is inf.
>>> try:
... try_float_div(-inf, 0)
... except ValueError as ve:
... print(ve)
Value must be finite, but is -inf.
>>> try:
... try_float_div(nan, 0)
... except ValueError as ve:
... print(ve)
Value must be finite, but is nan.
>>> try:
... try_float_div(1, inf)
... except ValueError as ve:
... print(ve)
Value must be finite, but is inf.
>>> try:
... try_float_div(1, -inf)
... except ValueError as ve:
... print(ve)
Value must be finite, but is -inf.
>>> try:
... try_float_div(1, nan)
... except ValueError as ve:
... print(ve)
Value must be finite, but is nan.
>>> try:
... try_float_div(1e300, 1e-60)
... except ValueError as ve:
... print(ve)
Result must be finite, but is 1e+300/1e-60=inf.
int
| float
) – the input value, which must either be int or float>>> print(type(try_int(10.5)))
<class 'float'>
>>> print(type(try_int(10)))
<class 'int'>
>>> from math import inf, nan, nextafter
>>> type(try_int(0.0))
<class 'int'>
>>> type(try_int(0.5))
<class 'float'>
>>> try:
... try_int(inf)
... except ValueError as ve:
... print(ve)
Value must be finite, but is inf.
>>> try:
... try_int(-inf)
... except ValueError as ve:
... print(ve)
Value must be finite, but is -inf.
>>> try:
... try_int(nan)
... except ValueError as ve:
... print(ve)
Value must be finite, but is nan.
>>> try:
... try_int("blab") # noqa # type: off
... except TypeError as te:
... print(te)
val should be an instance of any in {float, int} but is str, namely 'blab'.
>>> type(try_int(9007199254740992.0))
<class 'int'>
>>> try_int(9007199254740992.0)
9007199254740992
>>> too_big = nextafter(9007199254740992.0, inf)
>>> print(too_big)
9007199254740994.0
>>> type(try_int(too_big))
<class 'float'>
>>> type(try_int(-9007199254740992.0))
<class 'int'>
>>> try_int(-9007199254740992.0)
-9007199254740992
>>> type(try_int(-too_big))
<class 'float'>
>>> print(try_int_div(10, 2))
5
>>> print(try_int_div(10, -2))
-5
>>> print(try_int_div(-10, 2))
-5
>>> print(try_int_div(-10, -2))
5
>>> print(type(try_int_div(10, 2)))
<class 'int'>
>>> print(try_int_div(10, 3))
3.3333333333333335
>>> print(try_int_div(-10, 3))
-3.3333333333333335
>>> print(try_int_div(10, -3))
-3.3333333333333335
>>> print(try_int_div(-10, -3))
3.3333333333333335
>>> print(type(try_int_div(10, 3)))
<class 'float'>
>>> print(try_int_div(9007199254740992, 1))
9007199254740992
>>> print(try_int_div(2109792310235001520128, 234234))
9007199254740992
>>> print(try_int_div(2109792310235001520128, 234235))
9007160801054503
>>> print(try_int_div(2109792310235001520128, 234233))
9007237708755818.0
>>> large = 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
>>> try:
... large / 1
... except OverflowError as oe:
... print(oe)
integer division result too large for a float
>>> try_int_div(large, 1)
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
>>> try_int_div(large * 7, 1 * 7)
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
>>> try:
... try_int_div(large, 7)
... except OverflowError as oe:
... print(oe)
integer division result too large for a float
>>> try:
... try_int_div(0, 0)
... except ZeroDivisionError as zde:
... print(zde)
integer division or modulo by zero
>>> try:
... try_int_div(1, 0)
... except ZeroDivisionError as zde:
... print(zde)
integer division or modulo by zero
>>> try:
... try_int_div(-1, 0)
... except ZeroDivisionError as zde:
... print(zde)
integer division or modulo by zero
int
) – the integer value to compute the root ofint
) – the integer power of the rootbool
, default: True
) – True if None should be returned if we encounter an OverflowError
, False if we should simply re-raise it>>> try_int_root(100, 2)
10
>>> try_int_root(100, 3) - (100 ** (1/3))
0.0
>>> try_int_root(123100, 23) - (123100 ** (1/23))
0.0
>>> 123100**1000 - try_int_root(123100**1000, 1000)**1000
0
>>> 11**290 - try_int_root(11**290, 290)**290
0
>>> (abs(1.797E308 - try_int_root(int(1.797E308), 10) ** 10)
... < abs(1.797E308 - (int(1.797E308) ** 0.1) ** 10))
True
moptipy.utils.nputils module¶
>>> import numpy as npx
>>> array_to_str(npx.array([1, 2, 3]))
'1;2;3'
>>> array_to_str(npx.array([1, 2.2, 3]))
'1;2.2;3'
>>> array_to_str(npx.array([True, False, True]))
'TFT'
int_range_to_dtype()
. If always_int is True and one or both of the bounds are infinite, then the largest available integer type is returned. If the bounds are finite but exceed the integer range, a ValueError is thrown. If the data is not always integer, the float64 is returned.bool
) – is the data always integer?int
| float
) – the lower bound of the data, set to -inf if no lower bound is known and we should assume the full integer rangeint
| float
) – the upper bound of the data, set to -inf if no upper bound is known and we should assume the full integer range>>> print(dtype_for_data(True, 0, 127))
int8
>>> print(dtype_for_data(True, 0, 128))
uint8
>>> print(dtype_for_data(True, -1, 32767))
int16
>>> print(dtype_for_data(True, 0, 32768))
uint16
>>> print(dtype_for_data(True, -1, 32768))
int32
>>> print(dtype_for_data(True, 0, 65535))
uint16
>>> print(dtype_for_data(True, 0, 65536))
int32
>>> print(dtype_for_data(True, -1, 65535))
int32
>>> print(dtype_for_data(True, 0, (2 ** 31) - 1))
int32
>>> print(dtype_for_data(True, 0, 2 ** 31))
uint32
>>> print(dtype_for_data(True, -1, 2 ** 31))
int64
>>> print(dtype_for_data(True, 0, (2 ** 63) - 1))
int64
>>> print(dtype_for_data(True, 0, 2 ** 63))
uint64
>>> print(dtype_for_data(True, 0, (2 ** 63) + 1))
uint64
>>> print(dtype_for_data(True, 0, (2 ** 64) - 1))
uint64
>>> try:
... dtype_for_data(True, 0, 2 ** 64)
... except ValueError as v:
... print(v)
max_value for unsigned integers must be <=18446744073709551615, but is 18446744073709551616 for min_value=0.
>>> from math import inf, nan
>>> print(dtype_for_data(True, 0, inf))
uint64
>>> print(dtype_for_data(True, -1, inf))
int64
>>> print(dtype_for_data(True, -inf, inf))
int64
>>> print(dtype_for_data(True, -inf, inf))
int64
>>> try:
... dtype_for_data(True, 1, 0)
... except ValueError as v:
... print(v)
invalid bounds [1,0].
>>> try:
... dtype_for_data(False, 1, 0)
... except ValueError as v:
... print(v)
invalid bounds [1,0].
>>> try:
... dtype_for_data(True, 1, nan)
... except ValueError as v:
... print(v)
invalid bounds [1,nan].
>>> try:
... dtype_for_data(False, nan, 0)
... except ValueError as v:
... print(v)
invalid bounds [nan,0].
>>> print(dtype_for_data(False, 1, 2))
float64
>>> try:
... dtype_for_data(False, nan, '0')
... except TypeError as v:
... print(v)
upper_bound should be an instance of any in {float, int} but is str, namely '0'.
>>> try:
... dtype_for_data(True, 'x', 0)
... except TypeError as v:
... print(v)
lower_bound should be an instance of any in {float, int} but is str, namely 'x'.
>>> try:
... dtype_for_data(True, 1.0, 2.0)
... except TypeError as v:
... print(v)
finite lower_bound of always_int should be an instance of int but is float, namely 1.0.
>>> try:
... dtype_for_data(True, 0, 2.0)
... except TypeError as v:
... print(v)
finite upper_bound of always_int should be an instance of int but is float, namely 2.0.
>>> try:
... dtype_for_data(3, 0, 2)
... except TypeError as v:
... print(v)
always_int should be an instance of bool but is int, namely 3.
>>> import numpy
>>> arr = numpy.empty(10, int)
>>> fill_in_canonical_permutation(arr)
>>> print(arr)
[0 1 2 3 4 5 6 7 8 9]
numpy.dtype
will allow accommodating all values in the inclusive interval min_value..max_value.>>> from moptipy.utils.nputils import int_range_to_dtype
>>> print(int_range_to_dtype(0, 127))
int8
>>> print(int_range_to_dtype(0, 128))
uint8
>>> print(int_range_to_dtype(0, 128, True))
int16
>>> print(int_range_to_dtype(0, 32767))
int16
>>> print(int_range_to_dtype(0, 32768))
uint16
>>> print(int_range_to_dtype(0, 32768, True))
int32
>>> print(int_range_to_dtype(0, (2 ** 31) - 1))
int32
>>> print(int_range_to_dtype(0, 2 ** 31))
uint32
>>> print(int_range_to_dtype(0, 2 ** 31, True))
int64
>>> print(int_range_to_dtype(0, (2 ** 63) - 1))
int64
>>> print(int_range_to_dtype(0, 2 ** 63))
uint64
>>> print(int_range_to_dtype(0, (2 ** 64) - 1))
uint64
>>> try:
... int_range_to_dtype(0, (2 ** 64) - 1, True)
... except ValueError as e:
... print(e)
Signed integer range cannot exceed -9223372036854775808..9223372036854775807, but 0..18446744073709551615 was specified.
>>> try:
... int_range_to_dtype(0, (2 ** 64) + 1)
... except ValueError as e:
... print(e)
max_value for unsigned integers must be <=18446744073709551615, but is 18446744073709551617 for min_value=0.
>>> try:
... int_range_to_dtype(-1, (2 ** 64) - 1)
... except ValueError as e:
... print(e)
Signed integer range cannot exceed -9223372036854775808..9223372036854775807, but -1..18446744073709551615 was specified.
>>> try:
... int_range_to_dtype(-1.0, (2 ** 64) - 1)
... except TypeError as e:
... print(e)
min_value should be an instance of int but is float, namely -1.0.
>>> try:
... int_range_to_dtype(-1, 'a')
... except TypeError as e:
... print(e)
max_value should be an instance of int but is str, namely 'a'.
ndarray
) – the input array>>> import numpy as npx
>>> from moptipy.utils.nputils import is_all_finite
>>> print(is_all_finite(npx.array([1.1, 2.1, 3])))
True
>>> print(is_all_finite(npx.array([1, 2, 3])))
True
>>> print(is_all_finite(npx.array([1.1, npx.inf, 3])))
False
numpy.dtype
is a floating point type.>>> import numpy as npx
>>> from moptipy.utils.nputils import is_np_float
>>> print(is_np_float(npx.dtype(npx.int8)))
False
>>> print(is_np_float(npx.dtype(npx.uint16)))
False
>>> print(is_np_float(npx.dtype(npx.float64)))
True
numpy.dtype
is an integer type.>>> import numpy as npx
>>> from moptipy.utils.nputils import is_np_int
>>> print(is_np_int(npx.dtype(npx.int8)))
True
>>> print(is_np_int(npx.dtype(npx.uint16)))
True
>>> print(is_np_int(npx.dtype(npx.float64)))
False
dtype
, default: dtype('int64')
) – the data type (defaults to 64bit integers)>>> import numpy as npx
>>> from moptipy.utils.nputils import np_ints_max
>>> print(np_ints_max(4, npx.dtype("uint8")))
[255 255 255 255]
Any
) – the numpy number>>> type(np_to_py_number(1))
<class 'int'>
>>> type(np_to_py_number(1.0))
<class 'float'>
>>> type(np_to_py_number(np.int8(1)))
<class 'int'>
>>> type(np_to_py_number(np.float64(1)))
<class 'float'>
>>> try:
... np_to_py_number(np.complex64(1))
... except TypeError as te:
... print(te)
number should be an instance of any in {float, int, numpy.floating, numpy.integer} but is numpy.complex64.
>>> import numpy as npx
>>> numpy_type_to_str(npx.dtype(int))
'l'
>>> numpy_type_to_str(npx.dtype(float))
'd'
>>> type(rand_generator(1))
<class 'numpy.random._generator.Generator'>
>>> type(rand_generator(1).bit_generator)
<class 'numpy.random._pcg64.PCG64'>
>>> rand_generator(1).random() == rand_generator(1).random()
True
Any
) – the random seed to check>>> rand_seed_check(1)
1
>>> rand_seed_check(0)
0
>>> try:
... rand_seed_check(-1)
... except ValueError as ve:
... print(ve)
rand_seed=-1 is invalid, must be in 0..18446744073709551615.
>>> rand_seed_check(18446744073709551615)
18446744073709551615
>>> try:
... rand_seed_check(18446744073709551616)
... except ValueError as ve:
... print(ve)
rand_seed=18446744073709551616 is invalid, must be in 0..18446744073709551615.
>>> try:
... rand_seed_check(1.2)
... except TypeError as te:
... print(te)
rand_seed should be an instance of int but is float, namely 1.2.
Generator
, default: Generator(PCG64) at 0x7F66BC07B3E0
) – the random number generator to be used to generate the seed>>> from numpy.random import default_rng as drg
>>> rand_seed_generate(default_rng(100))
10991970318022328789
>>> rand_seed_generate(default_rng(100))
10991970318022328789
>>> rand_seed_generate(default_rng(10991970318022328789))
11139051376468819756
>>> rand_seed_generate(default_rng(10991970318022328789))
11139051376468819756
>>> rand_seed_generate(default_rng(11139051376468819756))
16592984639586750386
>>> rand_seed_generate(default_rng(11139051376468819756))
16592984639586750386
>>> rand_seed_generate(default_rng(16592984639586750386))
12064014979695949294
>>> rand_seed_generate(default_rng(16592984639586750386))
12064014979695949294
PCG64
random number generators. We then alternatingly draw seeds from these two generators using rand_seed_generate()
until we have n_seeds unique values.moptipy.api.experiment.run_experiment()
to draw the random seeds for the algorithm runs to be performed. As string input, that method uses the string representation of the problem instance. This guarantees that all algorithms start with the same seeds on the same problems. It also guarantees that an experiment is repeatable, i.e., will use the same seeds when executed twice. Finally, it ensures that cherry-picking is impossible, as all seeds are fairly pseudo-random.>>> rand_seeds_from_str("hello world!", 1)
[11688012229199056962]
>>> rand_seeds_from_str("hello world!", 2)
[3727742416375614079, 11688012229199056962]
>>> rand_seeds_from_str("hello world!", 3)
[3727742416375614079, 11688012229199056962, 17315292100125916507]
>>> rand_seeds_from_str("metaheuristic optimization", 1)
[12323230366215963648]
>>> rand_seeds_from_str("metaheuristic optimization", 2)
[12323230366215963648, 13673960948036381176]
>>> rand_seeds_from_str("metaheuristic optimization", 3)
[12323230366215963648, 13673960948036381176, 18426184104943646060]
moptipy.utils.number_renderer module¶
object
int
| float
| None
, default: None
) – the int-to-float thresholdOptional
[Callable
[[], Callable
[[int
], str
]]], default: None
) – the integer renderer getterOptional
[Callable
[[int
| float
, int
| float
, int
, int
| float
, int
| float
], str
]], default: None
) – the float format getter>>> d = DEFAULT_NUMBER_RENDERER
>>> d.derive() is d
True
>>> d.int_to_float_threshold
10000000000
>>> from moptipy.utils.lang import EN
>>> EN.set_current()
>>> d.get_int_renderer()(123456789)
"123'456'789"
>>> d.get_float_format(-10, 10, 2)
'{:.2f}'
>>> d = d.derive(int_to_float_threshold=22)
>>> d is DEFAULT_NUMBER_RENDERER
False
>>> d.int_to_float_threshold
22
>>> d = d.derive(get_int_renderer=lambda: lambda x: "bla")
>>> d.get_int_renderer()(112)
'bla'
Final
[Callable
[[int
| float
, int
| float
, int
, int
| float
, int
| float
], str
]]¶Final
[Callable
[[], Callable
[[int
], str
]]]¶Final
[int
| float
]¶list
[FormattedStr
| None
]>>> from moptipy.utils.lang import EN
>>> EN.set_current()
>>> ff = DEFAULT_NUMBER_RENDERER
>>> ff.render([1.75651, 212, 3234234])
['2', '212', "3'234'234"]
>>> ff.render([1.75651, 22, 34])
['1.757', '22.000', '34.000']
>>> ff.render([1.75651, 122, 34])
['1.76', '122.00', '34.00']
>>> ff.render([1.75651, 122, 3334])
['1.8', '122.0', "3'334.0"]
>>> ff.render([1.5, 212, 3234234])
['2', '212', "3'234'234"]
>>> ff.render([1.5, 2e12, 3234234])
['1.50e0', '2.00e12', '3.23e6']
>>> ff.render([233, 22139283482834, 3234234])
['2.33e2', '2.21e13', '3.23e6']
>>> ff.render([233, 22139283, 3234234])
['233', "22'139'283", "3'234'234"]
>>> from math import nan, inf
>>> ff.render([22139283, inf, -inf, nan, None])
["22'139'283", 'inf', '-inf', 'nan', None]
>>> ff.render([1E-4, 1/7, 123456789012345678])
['1.00e-4', '1.43e-1', '1.23e17']
>>> ff.render([0, 0.02, 0.1, 1e-3])
['0.000', '0.020', '0.100', '0.001']
>>> ff.render([-0.2, 1e-6, 0.9])
['-2.000e-1', '1.000e-6', '9.000e-1']
int
| float
, default: 0
) – the minimum finite value that may need to be formattedint
| float
, default: 0
) – the maximum finite value that may need to be formattedint
, default: 2
) – the length of the longest fractional part of any number encountered that can be converted to a string not in the “E” notationint
| float
, default: inf
) – the minimum non-zero absolute value; will be inf if all absolute values are zeroint
| float
, default: 10000000000
) – the threshold above which all integers are converted to floating point numbers with the ‘E’ notation>>> default_get_float_format(0, 0, 0)
'{:.0f}'
>>> default_get_float_format(0, 1e5, 10)
'{:.0f}'
>>> default_get_float_format(-1e7, 1e2, 10)
'{:.0f}'
>>> default_get_float_format(0, 0, 1)
'{:.1f}'
>>> default_get_float_format(0, 1e3, 11)
'{:.1f}'
>>> default_get_float_format(-1e3, 1e2, 11)
'{:.1f}'
>>> default_get_float_format(0, 0, 2)
'{:.2f}'
>>> default_get_float_format(0, 0, 3)
'{:.3f}'
>>> default_get_float_format(0, 0, 4)
'{:.3f}'
>>> default_get_float_format(0, 1e11, 4)
'{:.2e}'
>>> default_get_float_format(-1, 1, 4, 1e-3)
'{:.3f}'
>>> from moptipy.utils.lang import EN, ZH
>>> EN.set_current()
>>> f = default_get_int_renderer()
>>> f(1_000_000)
"1'000'000"
>>> ZH.set_current()
>>> f = default_get_int_renderer()
>>> f(1_000_000)
"100'0000"
moptipy.utils.plot_defaults module¶
moptipy.utils.plot_utils module¶
int
) – the number of items to divideint
, default: 3
) – the maximum number of items per plotint
, default: 3
) – the maximum number of rowsint
, default: 1
) – the maximum number of columnsint
, default: 1
) – the minimum number of rowsint
, default: 1
) – the minimum number of colsfloat
| int
| None
, default: 8.6
) – the optional default width of a columnfloat
| int
| None
, default: 5.315092303249095
) – the optional default height per rowfloat
| int
| None
, default: 9
) – the maximum heightfloat
| int
| None
, default: 8.6
) – the maximum widthdict
[str
, Any
] | None
, default: None
) – the configuration to be applied to all sub-plotstuple
[Figure
, tuple
[tuple
[Axes
| Figure
, int
, int
, int
, int
, int
], ...
]]Axes
) – the axes to add the label tostr
| None
, default: None
) – a callable returning the label for the x-axis, a label string, or None if no label should be putbool
, default: True
) – put the x-axis label inside the plot (so that it does not consume additional vertical space)float
, default: 0.5
) – the location of the x-axis label if it is placed inside the plot areastr
| None
, default: None
) – a callable returning the label for the y-axis, a label string, or None if no label should be putbool
, default: True
) – put the xyaxis label inside the plot (so that it does not consume additional horizontal space)nal vertical space)float
, default: 1
) – the location of the y-axis label if it is placed inside the plot areafloat
, default: 8.0
) – the font size to usefloat
| None
, default: None
) – an optional z-order valueAxes
) – the axes to add the label tostr
) – the text to placefloat
| None
, default: None
) – the location along the x-axis: 0 means left, 0.5 means centered, 1 means rightfloat
| None
, default: None
) – the location along the x-axis: 0 means bottom, 0.5 means centered, 1 means topfloat
, default: 8.0
) – the font sizebool
, default: False
) – should we rotate the text by 90° if that makes sense (True) or always keep it horizontally (False)float
| None
, default: None
) – an optional z-order valueUnion
[None
, str
, Callable
], default: <function <lambda> at 0x7f668579b9c0>
) – the font to usemoptipy.utils.strings module¶
str
| float
) – either a float or the string representation of a float>>> beautify_float_str('0.0')
'0.0'
>>> beautify_float_str('1e12')
'1×10¹²'
>>> beautify_float_str('1e-3')
'1×10⁻³'
>>> beautify_float_str('inf')
'∞'
>>> beautify_float_str('-inf')
'-∞'
>>> beautify_float_str('nan')
'∅'
num_to_str_for_name()
.str
) – the string from the name>>> name_str_to_num(num_to_str_for_name(1.1))
1.1
>>> name_str_to_num(num_to_str_for_name(1))
1
>>> name_str_to_num(num_to_str_for_name(-5e3))
-5000
>>> name_str_to_num(num_to_str_for_name(-6e-3))
-0.006
>>> name_str_to_num(num_to_str_for_name(100.0))
100
>>> name_str_to_num(num_to_str_for_name(-1e-4))
-0.0001
name_str_to_num()
.>>> num_to_str_for_name(1.3)
'1d3'
>>> num_to_str_for_name(1.0)
'1'
>>> num_to_str_for_name(-7)
'm7'
>>> num_to_str_for_name(-6.32)
'm6d32'
>>> num_to_str_for_name(-1e-5)
'm1em5'
>>> sanitize_name(" hello world ")
'hello_world'
>>> sanitize_name(" 56.6-455 ")
'56d6m455'
>>> sanitize_name(" _ i _ am _ funny --6 _ ")
'i_am_funny_m6'
str
) – the name that should be sanitizedmoptipy.utils.sys_info module¶
log_sys_info()
is invoked for the first time, adding new dependencies will cause an error. And writing a log file via the experiment
API or to a file specified in the execution
API will invoke this function.str
) – the basic name of the library, exactly as you would import it in a Python module. For example, to include the version of numpy in the log files, you would do add_dependency(“numpy”) (of course, the version of numpy is already automatically included anyway).bool
, default: False
) – should this dependency be ignored if this method is invoked during a make build? This makes sense if the dependency itself is a package which is uninstalled and then re-installed during a make build process. In such a situation, the dependency version may be unavailable and cause an exception.>>> raw_infos = get_sys_info()
>>> raw_infos is get_sys_info() # caching!
True
>>> for k in raw_infos.split("\n"):
... print(k[:k.find(": ")])
session.start
session.node
session.processId
session.cpuAffinity
session.commandLine
session.workingDirectory
session.ipAddress
version.cmaes
version.contourpy
version.cycler
version.fonttools
version.intelcmplrlibrt
version.joblib
version.kiwisolver
version.llvmlite
version.matplotlib
version.moptipy
version.numba
version.numpy
version.packaging
version.pdfo
version.pillow
version.psutil
version.pycommons
version.pyparsing
version.pythondateutil
version.scikitlearn
version.scipy
version.setuptools
version.six
version.threadpoolctl
hardware.machine
hardware.nPhysicalCpus
hardware.nLogicalCpus
hardware.cpuMhz
hardware.byteOrder
hardware.cpu
hardware.memSize
python.version
python.implementation
os.name
os.release
os.version
>>> from moptipy.utils.logger import InMemoryLogger
>>> with InMemoryLogger() as l:
... log_sys_info(l)
... log = l.get_log()
>>> print(log[0])
BEGIN_SYS_INFO
>>> print(log[-1])
END_SYS_INFO
>>> log[1:-1] == get_sys_info().split('\n')
True
moptipy.utils.table module¶
AbstractContextManager
moptipy.utils.formatted_string.FormattedStr
or a sequence thereof. This allows you to render formatted text in a natural fashion.AbstractContextManager
Rows
AbstractContextManager
header()
). Every table then consists of a sequence of one or multiple sections (see section()
and Section
). Each table section itself may or may not have a header (see Section.header()
) and must have at least one row (see Rows.row()
and Row
). Each row must have the exact right number of cells (see Row.cell()
).moptipy.utils.text_format module¶
object
Table
to write tabular data to a text format stream.TextIOBase
) – the stream to write tostr
) – the column definitionTextIOBase
) – the stream to write tostr
) – the column definitionsint
) – the index of the current section, -1 if this is a table header cellint
) – the row index in the section or headerint
) – the column index, 0 for the first columnint
) – the mode of the cell, will be one of MODE_NORMAL, MODE_TABLE_HEADER, or MODE_SECTION_HEADERTextIOBase
) – the stream to write tostr
) – the column definitionTextIOBase
) – the stream to write tostr
) – the column definitionint
) – the index of the current section, -1 if we are in the table headerint
) – the row index in the section or headerint
) – the mode of the row, will be one of MODE_NORMAL, MODE_TABLE_HEADER, or MODE_SECTION_HEADERTextIOBase
) – the stream to write tostr
) – the column definitionint
) – the index of the section, 0 for the first sectionTextIOBase
) – the stream to write tostr
) – the column definitionint
) – the index of the section, 0 for the first sectionTextIOBase
) – the stream to write tostr
) – the column definitionTextIOBase
) – the stream to write tostr
) – the column definitionsint
) – the index of the current section, -1 if this is a table header cellint
) – the row index in the section or headerint
) – the column index, 0 for the first columnint
) – the mode of the cell, will be one of MODE_NORMAL, MODE_TABLE_HEADER, or MODE_SECTION_HEADERTextIOBase
) – the stream to write tostr
) – the column definitionTextIOBase
) – the stream to write tostr
) – the column definitionint
) – the index of the current sectionint
) – the row index in the section or headerTextIOBase
) – the stream to write tostr
) – the column definitionint
) – the index of the section, 0 for the first sectionint
) – the number of rows that were written in the sectionTextIOBase
) – the stream to write tostr
) – the column definitionint
) – the index of the section, 0 for the first sectionTextIOBase
) – the stream to write tostr
) – the text to writebool
) – is the text in bold face?bool
) – is the text in italic face?bool
) – is the text in code face?int
) – the mode of a formatted text piece, see the attribute mode
of FormattedStr