quicksum
The behavior of the quicksum function is
similar to the builtin sum() function, but this function often
generates a more compact Pyomo expression. Its main argument is a
variable length argument list, args, which represents
expressions that are summed together. For example:
M = pyo.ConcreteModel()
M.x = pyo.Var(range(5))
# Summation using the Python sum() function
e1 = sum(M.x[i] ** 2 for i in M.x)
# Summation using the Pyomo quicksum function
e2 = pyo.quicksum(M.x[i] ** 2 for i in M.x)
The summation is customized based on the start and
linear arguments. The start defines the initial
value for summation, which defaults to zero. If start is
a numeric value, then the linear argument determines how
the sum is processed:
If linear is False, then the terms in args are assumed to be nonlinear.
If linear is True, then the terms in args are assumed to be linear.
If linear is None, the first term in args is analyze to determine whether the terms are linear or nonlinear.
This argument allows the quicksum
function to customize the expression representation used, and
specifically a more compact representation is used for linear
polynomials. The quicksum
function can be slower than the builtin sum() function,
but this compact representation can generate problem representations
more quickly.
Consider the following example:
M = pyo.ConcreteModel()
M.A = pyo.RangeSet(100000)
M.p = pyo.Param(M.A, mutable=True, initialize=1)
M.x = pyo.Var(M.A)
start = time.time()
e = sum((M.x[i] - 1) ** M.p[i] for i in M.A)
print("sum: %f" % (time.time() - start))
start = time.time()
generate_standard_repn(e)
print("repn: %f" % (time.time() - start))
start = time.time()
e = pyo.quicksum((M.x[i] - 1) ** M.p[i] for i in M.A)
print("quicksum: %f" % (time.time() - start))
start = time.time()
generate_standard_repn(e)
print("repn: %f" % (time.time() - start))
The sum consists of linear terms because the exponents are one.
The following output illustrates that quicksum can identify this
linear structure to generate expressions more quickly:
sum: 1.447861
repn: 0.870225
quicksum: 1.388344
repn: 0.864316
If start is not a numeric value, then the quicksum sets the initial value to start
and executes a simple loop to sum the terms. This allows the sum
to be stored in an object that is passed into the function (e.g. the linear context manager
linear_expression).
Warning
By default, linear is None. While this allows
for efficient expression generation in normal cases, there are
circumstances where the inspection of the first
term in args is misleading. Consider the following
example:
M = pyo.ConcreteModel()
M.x = pyo.Var(range(5))
e = pyo.quicksum(M.x[i] ** 2 if i > 0 else M.x[i] for i in range(5))
The first term created by the generator is linear, but the
subsequent terms are nonlinear. Pyomo gracefully transitions
to a nonlinear sum, but in this case quicksum
is doing additional work that is not useful.
sum_product
The sum_product function supports
a generalized dot product. The args argument contains one
or more components that are used to create terms in the summation.
If the args argument contains a single components, then its
sequence of terms are summed together; the sum is equivalent to
calling quicksum. If two or more components are
provided, then the result is the summation of their terms multiplied
together. For example:
M = pyo.ConcreteModel()
M.z = pyo.RangeSet(5)
M.x = pyo.Var(range(10))
M.y = pyo.Var(range(10))
# Sum the elements of x
e1 = pyo.sum_product(M.x)
# Sum the product of elements in x and y
e2 = pyo.sum_product(M.x, M.y)
# Sum the product of elements in x and y, over the index set z
e3 = pyo.sum_product(M.x, M.y, index=M.z)
The denom argument specifies components whose terms are in
the denominator. For example:
# Sum the product of x_i/y_i
e1 = pyo.sum_product(M.x, denom=M.y)
# Sum the product of 1/(x_i*y_i)
e2 = pyo.sum_product(denom=(M.x, M.y))
The terms summed by this function are explicitly specified, so
sum_product can identify
whether the resulting expression is linear, quadratic or nonlinear.
Consequently, this function is typically faster than simple loops,
and it generates compact representations of expressions..
Finally, note that the dot_product
function is an alias for sum_product.