import types
import operator
import functools
import numpy as np
from flopt.container import FloptNdarray
from flopt.variable import VarElement
from flopt.expression import (
ExpressionElement,
Expression,
CustomExpression,
Reduction,
MathOperation,
Const,
)
import flopt.expression
from flopt.solution import Solution
from flopt.constants import number_classes, array_classes
[docs]def Sum(x):
"""
Parameters
----------
x : iterator of varElement
Returns
-------
all sum of x
"""
if isinstance(x, types.GeneratorType):
return Sum(list(x))
if all(isinstance(_x, number_classes) for _x in x):
return sum(x)
elif isinstance(x, np.ndarray):
return flopt.expression.Sum(x.ravel())
return flopt.expression.Sum(x)
[docs]def Prod(x):
"""
Parameters
----------
x : iterator of varElement
Returns
-------
all product of x
"""
if isinstance(x, types.GeneratorType):
return Prod(list(x))
if all(isinstance(_x, number_classes) for _x in x):
return functools.reduce(operator.mul, x)
elif isinstance(x, np.ndarray):
return flopt.expression.Prod(x.ravel())
return flopt.expression.Prod(x)
def Dot(x, y):
"""
Parameters
----------
x : iterator of varElement or number
y : iterator of varElement or number
Returns
-------
inner product of x and y
"""
return Sum(_x * _y for _x, _y in zip(x, y))
def Norm(x):
return Dot(x, x) ** 0.5
def Sqnorm(x):
return Dot(x, x)
def operation(operator, x):
"""
Parameters
----------
operator : function of x
x : VarElement or array of VarElement
"""
if isinstance(x, types.GeneratorType):
return operation(operator, list(x))
if isinstance(x, (VarElement, ExpressionElement)):
return operator(x)
elif isinstance(x, (list, tuple, set)):
cls = x.__class__
return cls(operation(operator, var) for var in x)
elif isinstance(x, dict):
return {k: operation(operator, v) for k, v in x.items()}
elif isinstance(x, FloptNdarray):
return np.frompyfunc(lambda var: operator(var), 1, 1)(x)
return x
def Value(x):
"""Convert operation to number from variable and expression
Parameters
----------
x : array or generator of expressions or variables
"""
return operation(lambda v: v.value(), x)
def sqrt(x):
"""squared root operation
Parameters
----------
x : array or generator of expressions or variables
"""
return operation(lambda v: v**0.5, x)
[docs]def exp(x):
"""exponential operation
Parameters
----------
x : array or generator of expressions or variables
"""
return operation(flopt.expression.Exp, x)
[docs]def cos(x):
"""cosine operation
Parameters
----------
x : array or generator of expressions or variables
"""
return operation(flopt.expression.Cos, x)
[docs]def sin(x):
"""sine operation
Parameters
----------
x : array or generator of expressions or variables
"""
return operation(flopt.expression.Sin, x)
[docs]def tan(x):
"""tangent operation
Parameters
----------
x : array or generator of expressions or variables
"""
return operation(flopt.expression.Tan, x)
[docs]def log(x):
"""logarithmic operation
Parameters
----------
x : array or generator of expressions or variables
"""
return operation(flopt.expression.Log, x)
[docs]def abs(x):
"""absolute operation
Parameters
----------
x : array or generator of expressions or variables
"""
return operation(flopt.expression.Abs, x)
[docs]def floor(x):
"""floor operation
Parameters
----------
x : array or generator of expressions or variables
"""
return operation(flopt.expression.Floor, x)
[docs]def ceil(x):
"""ceil operation
Parameters
----------
x : array or generator of expressions or variables
"""
return operation(flopt.expression.Ceil, x)
def get_dot_graph(expression, save_file, rankdir=None):
with open(save_file, "w") as writer:
print("digraph g {", file=writer)
if rankdir is not None:
print(f"rankdir = {rankdir};", file=writer)
_get_dot_graph(expression, writer)
print("}", file=writer)
def _get_dot_graph(expression, writer):
node_self = id(expression)
node_str = '{} [label="{}", color=orange, style=filled]'
operation_str = '{} [label="{}", color=lightblue, style=filled]'
edge_str = "{} -> {}"
print(node_str.format(node_self, expression.getName()), file=writer)
if isinstance(expression, ExpressionElement):
if isinstance(expression, Const):
return node_self
node_operator = hash(expression)
operator_str = expression.operator
if isinstance(expression, CustomExpression):
elms = expression.args
elif isinstance(expression, Expression):
elms = [expression.elmA, expression.elmB]
elif isinstance(expression, Reduction):
elms = expression.elms
elif isinstance(expression, MathOperation):
elms = [expression.elm]
print(operation_str.format(node_operator, operator_str), file=writer)
print(edge_str.format(node_operator, node_self), file=writer)
for elm in elms:
node = _get_dot_graph(elm, writer)
print(edge_str.format(node, node_operator), file=writer)
else:
# VarElement or Const
pass
return node_self