Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
Parameters
----------
lin_op : LinOp
The root linear operator.
Returns
-------
bool
Were all the expression's arguments pruned?
"""
if lin_op.type is lo.VARIABLE:
return False
elif lin_op.type in [lo.SCALAR_CONST,
lo.DENSE_CONST,
lo.SPARSE_CONST,
lo.PARAM]:
return True
pruned_args = []
is_constant = True
for arg in lin_op.args:
arg_constant = prune_expr(arg)
if not arg_constant:
is_constant = False
pruned_args.append(arg)
# Overwrite old args with only non-constant args.
lin_op.args[:] = pruned_args[:]
return is_constant
Parameters
----------
lin_op : LinOp
A linear operator.
args : list
The arguments to the operator.
Returns
-------
NumPy matrix or SciPy sparse matrix.
The result of applying the linear operator.
"""
# Constants convert directly to their absolute value.
if lin_op.type in [lo.SCALAR_CONST, lo.DENSE_CONST, lo.SPARSE_CONST]:
result = np.abs(lin_op.data)
elif lin_op.type is lo.NEG:
result = args[0]
# Absolute value of coefficient.
elif lin_op.type is lo.MUL:
coeff = mul(lin_op.data, {}, True)
result = coeff*args[0]
elif lin_op.type is lo.DIV:
divisor = mul(lin_op.data, {}, True)
result = args[0]/divisor
elif lin_op.type is lo.CONV:
result = conv_mul(lin_op, args[0], is_abs=True)
else:
result = op_mul(lin_op, args)
return result
coeff = sp.coo_matrix((val_arr, (row_arr, col_arr)), shape).tocsc()
coeffs.append(coeff)
offset += offset_incr
return coeffs
# A list of all the linear operator types for constants.
CONSTANT_TYPES = [lo.PARAM, lo.SCALAR_CONST, lo.DENSE_CONST, lo.SPARSE_CONST]
# A map of LinOp type to the coefficient matrix function.
TYPE_TO_FUNC = {
lo.PROMOTE: promote_mat,
lo.NEG: neg_mat,
lo.MUL: mul_mat,
lo.RMUL: rmul_mat,
lo.MUL_ELEM: mul_elemwise_mat,
lo.DIV: div_mat,
lo.SUM_ENTRIES: sum_entries_mat,
lo.TRACE: trace_mat,
lo.INDEX: index_mat,
lo.TRANSPOSE: transpose_mat,
lo.RESHAPE: lambda lin_op: [1],
lo.SUM: lambda lin_op: [1]*len(lin_op.args),
lo.DIAG_VEC: diag_vec_mat,
lo.DIAG_MAT: diag_mat_mat,
lo.UPPER_TRI: upper_tri_mat,
lo.CONV: conv_mat,
lo.KRON: kron_mat,
lo.HSTACK: lambda lin_op: stack_mats(lin_op, False),
lo.VSTACK: lambda lin_op: stack_mats(lin_op, True),
}
def prune_expr(lin_op):
"""Prunes constant branches from the expression.
Parameters
----------
lin_op : LinOp
The root linear operator.
Returns
-------
bool
Were all the expression's arguments pruned?
"""
if lin_op.type is lo.VARIABLE:
return False
elif lin_op.type in [lo.SCALAR_CONST,
lo.DENSE_CONST,
lo.SPARSE_CONST,
lo.PARAM]:
return True
pruned_args = []
is_constant = True
for arg in lin_op.args:
arg_constant = prune_expr(arg)
if not arg_constant:
is_constant = False
pruned_args.append(arg)
# Overwrite old args with only non-constant args.
lin_op.args[:] = pruned_args[:]
Returns
-------
LinOP
A LinOp wrapping the constant.
"""
# Check if scalar.
if shape == (1, 1):
op_type = lo.SCALAR_CONST
if not np.isscalar(value):
value = value[0, 0]
# Check if sparse.
elif sparse:
op_type = lo.SPARSE_CONST
else:
op_type = lo.DENSE_CONST
return lo.LinOp(op_type, shape, [], value)
val_arr.append(1)
shape = (lin_op.size[0]*lin_op.size[1],
arg.size[0]*arg.size[1])
coeff = sp.coo_matrix((val_arr, (row_arr, col_arr)), shape).tocsc()
coeffs.append(coeff)
offset += offset_incr
return coeffs
# A list of all the linear operator types for constants.
CONSTANT_TYPES = [lo.PARAM, lo.SCALAR_CONST, lo.DENSE_CONST, lo.SPARSE_CONST]
# A map of LinOp type to the coefficient matrix function.
TYPE_TO_FUNC = {
lo.PROMOTE: promote_mat,
lo.NEG: neg_mat,
lo.MUL: mul_mat,
lo.RMUL: rmul_mat,
lo.MUL_ELEM: mul_elemwise_mat,
lo.DIV: div_mat,
lo.SUM_ENTRIES: sum_entries_mat,
lo.TRACE: trace_mat,
lo.INDEX: index_mat,
lo.TRANSPOSE: transpose_mat,
lo.RESHAPE: lambda lin_op: [1],
lo.SUM: lambda lin_op: [1]*len(lin_op.args),
lo.DIAG_VEC: diag_vec_mat,
lo.DIAG_MAT: diag_mat_mat,
lo.UPPER_TRI: upper_tri_mat,
lo.CONV: conv_mat,
lo.KRON: kron_mat,
lo.HSTACK: lambda lin_op: stack_mats(lin_op, False),
def get_coefficients(lin_op):
"""Converts a linear op into coefficients.
Parameters
----------
lin_op : LinOp
The linear op to convert.
Returns
-------
list
A list of (id, coefficient) tuples.
"""
# VARIABLE converts to a giant identity matrix.
if lin_op.type == lo.VARIABLE:
coeffs = var_coeffs(lin_op)
# Constants convert directly to their value.
elif lin_op.type in CONSTANT_TYPES:
mat = const_mat(lin_op)
coeffs = [(lo.CONSTANT_ID, flatten(mat))]
elif lin_op.type in TYPE_TO_FUNC:
# A coefficient matrix for each argument.
coeff_mats = TYPE_TO_FUNC[lin_op.type](lin_op)
coeffs = []
for coeff_mat, arg in zip(coeff_mats, lin_op.args):
rh_coeffs = get_coefficients(arg)
coeffs += mul_by_const(coeff_mat, rh_coeffs)
else:
raise Exception("Unknown linear operator.")
return coeffs
"""Applies the linear operator to the arguments.
Parameters
----------
lin_op : LinOp
A linear operator.
args : list
The arguments to the operator.
Returns
-------
NumPy matrix or SciPy sparse matrix.
The result of applying the linear operator.
"""
# Constants convert directly to their value.
if lin_op.type in [lo.SCALAR_CONST, lo.DENSE_CONST, lo.SPARSE_CONST]:
result = lin_op.data
# No-op is not evaluated.
elif lin_op.type is lo.NO_OP:
return None
# For non-leaves, recurse on args.
elif lin_op.type is lo.SUM:
result = sum(args)
elif lin_op.type is lo.NEG:
result = -args[0]
elif lin_op.type is lo.MUL:
coeff = mul(lin_op.data, {})
result = coeff*args[0]
elif lin_op.type is lo.DIV:
divisor = mul(lin_op.data, {})
result = args[0]/divisor
elif lin_op.type is lo.SUM_ENTRIES:
else:
result = coeff.T*value
elif lin_op.type is lo.DIV:
divisor = mul(lin_op.data, {})
result = value/divisor
elif lin_op.type is lo.SUM_ENTRIES:
result = np.mat(np.ones(lin_op.args[0].shape))*value
elif lin_op.type is lo.INDEX:
row_slc, col_slc = lin_op.data
result = np.mat(np.zeros(lin_op.args[0].shape))
result[row_slc, col_slc] = value
elif lin_op.type is lo.TRANSPOSE:
result = value.T
elif lin_op.type is lo.PROMOTE:
result = np.ones(lin_op.shape[0]).dot(value)
elif lin_op.type is lo.DIAG_VEC:
# The return type in numpy versions < 1.10 was ndarray.
result = np.diag(value)
if isinstance(result, np.matrix):
result = result.A[0]
elif lin_op.type is lo.CONV:
result = conv_mul(lin_op, value, transpose=True)
else:
raise Exception("Unknown linear operator.")
return result