Skip to content

Commit c567b82

Browse files
committed
google-styled docstrings
1 parent e7ae54f commit c567b82

File tree

17 files changed

+402
-155
lines changed

17 files changed

+402
-155
lines changed

src/wmipa/core/assignmentconverter.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,30 @@
1111

1212

1313
class AssignmentConverter:
14-
"""
15-
This class is responsible of converting the pysmt assignments
16-
returned by an enumerator into pairs <Polytope, Polynomial>.
17-
"""
14+
"""This class is responsible of converting the pysmt assignments returned by an enumerator into pairs <Polytope, Polynomial>."""
1815

1916
def __init__(self, enumerator: "Enumerator") -> None:
17+
"""Default constructor.
18+
19+
Args:
20+
enumerator: the enumerator instance
21+
"""
2022
self.enumerator = enumerator
2123

2224
def convert(
2325
self, truth_assignment: dict[FNode, bool], domain: Collection[FNode]
2426
) -> tuple[Polytope, Polynomial]:
27+
"""Converts a truth assignment (as returned by an Enumerator)
28+
into a <Polytope, Polynomial> pair.
29+
30+
Args:
31+
truth_assignment: mapping pysmt atoms to bool
32+
domain: list of real variables in pysmt format
33+
34+
Returns:
35+
A convex integration problem as a pair of instances of Polytope and Polynomial.
36+
The two represent the convex integration bounds and integrand respectively.
37+
"""
2538

2639
mgr = self.enumerator.env.formula_manager
2740

src/wmipa/core/inequality.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,26 @@
77

88

99
class Inequality:
10-
"""Internal representations of inequalities in canonical form:
10+
"""Internal class for inequalities in the canonical form:
1111
12-
Polynomial {<,<=} 0
12+
P {<,<=} 0
1313
14-
where Polynomial is also in canonical form.
14+
where P is a degree 1 polynomial.
1515
16+
Attributes:
17+
strict: boolean flag, true when the inequality is <
18+
mgr: pysmt formula manager
19+
polynomial: the Polynomial P
1620
"""
1721

1822
def __init__(self, expr: FNode, variables: Collection[FNode], env: Environment):
23+
"""Default constructor.
24+
25+
Args:
26+
expr: the inequality in pysmt format
27+
variables: the continuous integration domain
28+
env: the pysmt environment
29+
"""
1930
if expr.is_le() or expr.is_lt():
2031
self.strict = expr.is_lt()
2132
else:
@@ -33,6 +44,11 @@ def __init__(self, expr: FNode, variables: Collection[FNode], env: Environment):
3344
assert self.polynomial.degree == 1
3445

3546
def to_pysmt(self) -> FNode:
47+
"""Converts the inequality in pysmt format.
48+
49+
Returns:
50+
Either a LT (less-than) or LE (less-or-equal-than) atom.
51+
"""
3652
op = self.mgr.LT if self.strict else self.mgr.LE
3753
return op(self.polynomial.to_pysmt(), self.mgr.Real(0))
3854

src/wmipa/core/polynomial.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,27 @@
1212

1313

1414
class Polynomial:
15-
"""Internal representation of a canonical polynomial.
15+
"""Internal class representing canonical polynomials.
1616
Implemented as a dict, having for each monomial: {key : coefficient}
1717
where key is a tuple encoding exponents of the ordered variables.
1818
1919
E.g. {(2,0,1): 3} = "3 * x^2 * y^0 * z^1"
20+
21+
Attributes:
22+
monomials: the monomial dictionary
23+
variables: the continuous integration domain
24+
ordered_keys: sorted list of monomial keys
25+
mgr: the pysmt formula manager
2026
"""
2127

2228
def __init__(self, expr: FNode, variables: Collection[FNode], env: Environment):
29+
"""Default constructor.
30+
31+
Args:
32+
expr: the polynomial in pysmt format
33+
variables: the continuous integration domain
34+
env: the pysmt environment
35+
"""
2336
self.monomials = PolynomialParser(variables).parse(expr)
2437
const_key = tuple(0 for _ in range(len(variables)))
2538
if const_key in self.monomials and self.monomials[const_key] == 0:
@@ -30,12 +43,17 @@ def __init__(self, expr: FNode, variables: Collection[FNode], env: Environment):
3043

3144
@property
3245
def degree(self) -> int:
46+
"""Returns the degree of the polynomial."""
3347
if len(self.monomials) == 0:
3448
return 0
3549
else:
3650
return max(sum(exponents) for exponents in self.monomials)
3751

3852
def to_numpy(self) -> Callable[[np.ndarray], np.ndarray]:
53+
"""Returns the polynomial as a callable function.
54+
55+
This function can be used to evaluate a numpy array.
56+
"""
3957
return lambda x: np.sum(
4058
np.array(
4159
[k * np.prod(np.pow(x, e), axis=1) for e, k in self.monomials.items()]
@@ -44,7 +62,7 @@ def to_numpy(self) -> Callable[[np.ndarray], np.ndarray]:
4462
)
4563

4664
def to_pysmt(self) -> FNode:
47-
65+
"""Returns the polynomial in pysmt format."""
4866
if len(self.monomials) == 0:
4967
return self.mgr.Real(0)
5068

@@ -156,7 +174,7 @@ def _sum_polys(mono_first: Monomials, mono_second: Monomials) -> Monomials:
156174

157175
@staticmethod
158176
def _multiply_polys(mono_first: Monomials, mono_second: Monomials) -> Monomials:
159-
"""Multiply two polynomials represented as monomial dictionaries."""
177+
"""Multiplies two polynomials represented as monomial dictionaries."""
160178
result = {}
161179
n = (
162180
len(next(iter(mono_first.keys())))
@@ -178,7 +196,7 @@ def _multiply_polys(mono_first: Monomials, mono_second: Monomials) -> Monomials:
178196

179197
@classmethod
180198
def _expand_power(cls, base_poly: Monomials, exp_val: int) -> Monomials:
181-
"""Expand (polynomial)^n by repeated multiplication."""
199+
"""Expands (polynomial)^n by repeated multiplication."""
182200
if exp_val == 0:
183201
n = len(next(iter(base_poly.keys())))
184202
return {tuple(0 for _ in range(n)): 1}

src/wmipa/core/polytope.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,28 @@
88

99

1010
class Polytope:
11-
"""Internal data structure for H-polytopes."""
11+
"""Internal class for convex H-polytopes.
12+
13+
Attributes:
14+
inequalities: list of wmipa.core.Inequality
15+
N: the number of variables
16+
"""
1217

1318
def __init__(
1419
self,
1520
expressions: Collection[FNode],
1621
variables: Collection[FNode],
1722
env: Environment,
1823
):
24+
"""Default constructor for a H-polytope defined on an ordered list of variables (the continuous integration domain).
25+
26+
Args:
27+
expressions: list of linear inequalities in pysmt format
28+
variables: the continuous integration domain
29+
env: the pysmt environment
30+
"""
1931
self.inequalities = [Inequality(e, variables, env) for e in expressions]
2032
self.N = len(variables)
21-
self.H = len(expressions)
2233
self.mgr = env.formula_manager
2334

2435
def to_pysmt(self) -> FNode:
@@ -28,8 +39,15 @@ def to_pysmt(self) -> FNode:
2839
return self.mgr.And(*map(lambda x: x.to_pysmt(), self.inequalities))
2940

3041
def to_numpy(self) -> tuple[np.ndarray, np.ndarray]:
31-
"""Returns two numpy arrays A, b encoding the polytope.
32-
(Non-)Strictness information is discarded."""
42+
"""Converts the polytope to a pair of numpy arrays.
43+
44+
Note: information on the strictness of each inequality is discarded.
45+
46+
Returns:
47+
Two numpy arrays A, b encoding the polytope
48+
49+
A x {<=/<} b
50+
"""
3351
A, b = [], []
3452
const_key = tuple(0 for _ in range(self.N))
3553
key = lambda i: tuple(1 if j == i else 0 for j in range(self.N))

src/wmipa/core/utils.py

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
"""This module implements some useful methods used throughout the code.
2-
3-
Credits: least common multiple code by J.F. Sebastian
4-
(http://stackoverflow.com/a/147539)
5-
6-
"""
1+
"""This module implements some useful methods used throughout the code."""
72

83
from collections import defaultdict
94
from typing import Any
@@ -17,20 +12,24 @@
1712

1813

1914
def is_atom(node: FNode) -> bool:
15+
"""Returns true iff node is a propositional or theory atom."""
2016
return node.is_symbol(BOOL) or node.is_theory_relation()
2117

2218

2319
def is_literal(node: FNode) -> bool:
20+
"""Returns true iff node is an atom or its negation."""
2421
return is_atom(node) or (node.is_not() and is_atom(node.arg(0)))
2522

2623

2724
def is_clause(formula: FNode) -> bool:
25+
"""Returns true iff formula is a disjuction of literals."""
2826
return is_literal(formula) or (
2927
formula.is_or() and all(is_literal(lit) for lit in formula.args())
3028
)
3129

3230

3331
def is_cnf(formula: FNode) -> bool:
32+
"""Returns true iff formula is in Conjunctive Normal Form."""
3433
return is_clause(formula) or (
3534
formula.is_and() and all(is_clause(c) for c in formula.args())
3635
)
@@ -40,7 +39,6 @@ class LiteralNormalizer:
4039
"""A helper class for normalizing literals. This class is useful
4140
whenever literals involving algebraic atoms are manipulated by an
4241
external procedure, such as an SMT-based enumerator.
43-
4442
"""
4543

4644
def __init__(self, env: Environment):
@@ -60,35 +58,34 @@ def _normalize(self, literal: FNode) -> FNode:
6058
self._cache[literal] = normalized_literal
6159
return self._cache[literal]
6260

63-
def normalize(self, phi: FNode, remember_alias: bool = False) -> tuple[FNode, bool]:
64-
"""Return a normalized representation of a literal.
61+
def normalize(self, literal: FNode, remember_alias: bool = False) -> tuple[FNode, bool]:
62+
"""Normalizes 'literal', possibly storing original formula in the alias dictionary.
6563
6664
Args:
67-
phi (FNode): The formula to normalize.
68-
remember_alias (bool): If True, the original formula is remembered to be an alias of its normalized version.
65+
literal: the literal in pysmt format
66+
remember_alias: store 'literal' as an alias (def: False)
6967
7068
Returns:
71-
FNode: The normalized formula.
72-
bool: True if the formula was negated, False otherwise.
69+
A normalized atom plus a Boolean that indicates if the normalized literal was negative.
7370
"""
74-
normalized_phi = self._normalize(phi)
75-
negated = False
76-
if normalized_phi.is_not():
77-
normalized_phi = normalized_phi.arg(0)
78-
negated = True
71+
normalized_literal = self._normalize(literal)
72+
negative = False
73+
if normalized_literal.is_not():
74+
normalized_literal = normalized_literal.arg(0)
75+
negative = True
7976
if remember_alias:
80-
self._known_aliases[normalized_phi].add((phi, negated))
81-
return normalized_phi, negated
77+
self._known_aliases[normalized_literal].add((literal, negative))
78+
return normalized_literal, negative
8279

8380
def known_aliases(self, literal: FNode) -> set[tuple[FNode, bool]]:
84-
"""Return the set of known aliases of the literal.
85-
86-
Args:
87-
literal (FNode): The literal to check.
81+
"""Maps back a normalized atom into the original ones (multiple literals might map into the same normalized literal).
8882
8983
Returns:
90-
set(tuple(FNode, bool)): The set of known aliases of the literal. Each alias is a tuple containing the
91-
normalized literal and a boolean indicating whether the alias is negated.
84+
The set of known aliases for a normalized (positive) 'literal'.
85+
86+
Each alias is a tuple containing:
87+
- the original literal
88+
- the Boolean flag 'negative'
9289
"""
9390
if literal not in self._known_aliases:
9491
known_aliases_str = "\n".join(str(x) for x in self._known_aliases.keys())

0 commit comments

Comments
 (0)