Matrix/Vector-Valued Linear Functions: Parents#
In Sage, matrices assume that the base is a ring. Hence, we cannot
construct matrices whose entries are linear functions in Sage. Really,
they should be thought of as the tensor product of the \(R\)-module of
linear functions and the \(R\)-vector/matrix space, with the latter viewed
as an \(R\)-module (\(R\) is usually QQ
or RDF
for our purposes).
You should not construct any tensor products by calling the parent directly. This is also why none of the classes are imported in the global namespace. The come into play whenever you have vector or matrix MIP linear expressions/constraints. The intended way to construct them is implicitly by acting with vectors or matrices on linear functions. For example:
sage: mip.<x> = MixedIntegerLinearProgram('ppl') # base ring is QQ
sage: 3 + x[0] + 2*x[1] # a linear function
3 + x_0 + 2*x_1
sage: x[0] * vector([3,4]) + 1 # vector linear function
(1, 1) + (3, 4)*x_0
sage: x[0] * matrix([[3,1],[4,0]]) + 1 # matrix linear function
[1 + 3*x_0 x_0]
[4*x_0 1 ]
>>> from sage.all import *
>>> mip = MixedIntegerLinearProgram('ppl', names=('x',)); (x,) = mip._first_ngens(1)# base ring is QQ
>>> Integer(3) + x[Integer(0)] + Integer(2)*x[Integer(1)] # a linear function
3 + x_0 + 2*x_1
>>> x[Integer(0)] * vector([Integer(3),Integer(4)]) + Integer(1) # vector linear function
(1, 1) + (3, 4)*x_0
>>> x[Integer(0)] * matrix([[Integer(3),Integer(1)],[Integer(4),Integer(0)]]) + Integer(1) # matrix linear function
[1 + 3*x_0 x_0]
[4*x_0 1 ]
Internally, all linear functions are stored as a dictionary whose
keys are the index of the linear variable (and -1 for the constant term)
values are the coefficient of that variable. That is, a number for linear functions, a vector for vector-valued functions, etc.
The entire dictionary can be accessed with the
dict()
method. For convenience, you can also retrieve a single coefficient
with
coefficient()
. For
example:
sage: mip.<b> = MixedIntegerLinearProgram()
sage: f_scalar = (3 + b[7] + 2*b[9]); f_scalar
3 + x_0 + 2*x_1
sage: f_scalar.dict()
{-1: 3.0, 0: 1.0, 1: 2.0}
sage: f_scalar.dict()[1]
2.0
sage: f_scalar.coefficient(b[9])
2.0
sage: f_scalar.coefficient(1)
2.0
sage: f_vector = b[7] * vector([3,4]) + 1; f_vector
(1.0, 1.0) + (3.0, 4.0)*x_0
sage: f_vector.coefficient(-1)
(1.0, 1.0)
sage: f_vector.coefficient(b[7])
(3.0, 4.0)
sage: f_vector.coefficient(0)
(3.0, 4.0)
sage: f_vector.coefficient(1)
(0.0, 0.0)
sage: f_matrix = b[7] * matrix([[0,1], [2,0]]) + b[9] - 3; f_matrix
[-3 + x_1 x_0 ]
[2*x_0 -3 + x_1]
sage: f_matrix.coefficient(-1)
[-3.0 0.0]
[ 0.0 -3.0]
sage: f_matrix.coefficient(0)
[0.0 1.0]
[2.0 0.0]
sage: f_matrix.coefficient(1)
[1.0 0.0]
[0.0 1.0]
>>> from sage.all import *
>>> mip = MixedIntegerLinearProgram(names=('b',)); (b,) = mip._first_ngens(1)
>>> f_scalar = (Integer(3) + b[Integer(7)] + Integer(2)*b[Integer(9)]); f_scalar
3 + x_0 + 2*x_1
>>> f_scalar.dict()
{-1: 3.0, 0: 1.0, 1: 2.0}
>>> f_scalar.dict()[Integer(1)]
2.0
>>> f_scalar.coefficient(b[Integer(9)])
2.0
>>> f_scalar.coefficient(Integer(1))
2.0
>>> f_vector = b[Integer(7)] * vector([Integer(3),Integer(4)]) + Integer(1); f_vector
(1.0, 1.0) + (3.0, 4.0)*x_0
>>> f_vector.coefficient(-Integer(1))
(1.0, 1.0)
>>> f_vector.coefficient(b[Integer(7)])
(3.0, 4.0)
>>> f_vector.coefficient(Integer(0))
(3.0, 4.0)
>>> f_vector.coefficient(Integer(1))
(0.0, 0.0)
>>> f_matrix = b[Integer(7)] * matrix([[Integer(0),Integer(1)], [Integer(2),Integer(0)]]) + b[Integer(9)] - Integer(3); f_matrix
[-3 + x_1 x_0 ]
[2*x_0 -3 + x_1]
>>> f_matrix.coefficient(-Integer(1))
[-3.0 0.0]
[ 0.0 -3.0]
>>> f_matrix.coefficient(Integer(0))
[0.0 1.0]
[2.0 0.0]
>>> f_matrix.coefficient(Integer(1))
[1.0 0.0]
[0.0 1.0]
Just like sage.numerical.linear_functions
, (in)equalities
become symbolic inequalities. See
linear_tensor_constraints
for details.
Note
For brevity, we just use LinearTensor
in class names. It is
understood that this refers to the above tensor product
construction.
- sage.numerical.linear_tensor.LinearTensorParent(linear_functions_parent)[source]#
Return the parent for the tensor product over the common
base_ring
.The output is cached, so only a single parent is ever constructed for a given base ring.
INPUT:
free_module_parent
– module. A free module, like vector or matrix space.linear_functions_parent
– linear functions. The linear functions parent.
OUTPUT:
The parent of the tensor product of a free module and linear functions over a common base ring.
EXAMPLES:
sage: from sage.numerical.linear_functions import LinearFunctionsParent sage: from sage.numerical.linear_tensor import LinearTensorParent sage: LinearTensorParent(QQ^3, LinearFunctionsParent(QQ)) Tensor product of Vector space of dimension 3 over Rational Field and Linear functions over Rational Field sage: LinearTensorParent(ZZ^3, LinearFunctionsParent(QQ)) Traceback (most recent call last): ... ValueError: base rings must match
>>> from sage.all import * >>> from sage.numerical.linear_functions import LinearFunctionsParent >>> from sage.numerical.linear_tensor import LinearTensorParent >>> LinearTensorParent(QQ**Integer(3), LinearFunctionsParent(QQ)) Tensor product of Vector space of dimension 3 over Rational Field and Linear functions over Rational Field >>> LinearTensorParent(ZZ**Integer(3), LinearFunctionsParent(QQ)) Traceback (most recent call last): ... ValueError: base rings must match
- class sage.numerical.linear_tensor.LinearTensorParent_class(free_module, linear_functions)[source]#
Bases:
Parent
The parent for all linear functions over a fixed base ring.
Warning
You should use
LinearTensorParent()
to construct instances of this class.INPUT/OUTPUT:
EXAMPLES:
sage: from sage.numerical.linear_tensor import LinearTensorParent_class sage: LinearTensorParent_class <class 'sage.numerical.linear_tensor.LinearTensorParent_class'>
>>> from sage.all import * >>> from sage.numerical.linear_tensor import LinearTensorParent_class >>> LinearTensorParent_class <class 'sage.numerical.linear_tensor.LinearTensorParent_class'>
- Element[source]#
alias of
LinearTensor
- free_module()[source]#
Return the linear functions.
See also
free_module()
.OUTPUT:
Parent of the linear functions, one of the factors in the tensor product construction.
EXAMPLES:
sage: mip.<x> = MixedIntegerLinearProgram() sage: lt = x[0] * vector(RDF, [1,2]) sage: lt.parent().free_module() Vector space of dimension 2 over Real Double Field sage: lt.parent().free_module() is vector(RDF, [1,2]).parent() True
>>> from sage.all import * >>> mip = MixedIntegerLinearProgram(names=('x',)); (x,) = mip._first_ngens(1) >>> lt = x[Integer(0)] * vector(RDF, [Integer(1),Integer(2)]) >>> lt.parent().free_module() Vector space of dimension 2 over Real Double Field >>> lt.parent().free_module() is vector(RDF, [Integer(1),Integer(2)]).parent() True
- is_matrix_space()[source]#
Return whether the free module is a matrix space.
OUTPUT:
Boolean. Whether the
free_module()
factor in the tensor product is a matrix space.EXAMPLES:
sage: mip = MixedIntegerLinearProgram() sage: LF = mip.linear_functions_parent() sage: LF.tensor(RDF^2).is_matrix_space() False sage: LF.tensor(RDF^(2,2)).is_matrix_space() True
>>> from sage.all import * >>> mip = MixedIntegerLinearProgram() >>> LF = mip.linear_functions_parent() >>> LF.tensor(RDF**Integer(2)).is_matrix_space() False >>> LF.tensor(RDF**(Integer(2),Integer(2))).is_matrix_space() True
- is_vector_space()[source]#
Return whether the free module is a vector space.
OUTPUT:
Boolean. Whether the
free_module()
factor in the tensor product is a vector space.EXAMPLES:
sage: mip = MixedIntegerLinearProgram() sage: LF = mip.linear_functions_parent() sage: LF.tensor(RDF^2).is_vector_space() True sage: LF.tensor(RDF^(2,2)).is_vector_space() False
>>> from sage.all import * >>> mip = MixedIntegerLinearProgram() >>> LF = mip.linear_functions_parent() >>> LF.tensor(RDF**Integer(2)).is_vector_space() True >>> LF.tensor(RDF**(Integer(2),Integer(2))).is_vector_space() False
- linear_functions()[source]#
Return the linear functions.
See also
free_module()
.OUTPUT:
Parent of the linear functions, one of the factors in the tensor product construction.
EXAMPLES:
sage: mip.<x> = MixedIntegerLinearProgram() sage: lt = x[0] * vector([1,2]) sage: lt.parent().linear_functions() Linear functions over Real Double Field sage: lt.parent().linear_functions() is mip.linear_functions_parent() True
>>> from sage.all import * >>> mip = MixedIntegerLinearProgram(names=('x',)); (x,) = mip._first_ngens(1) >>> lt = x[Integer(0)] * vector([Integer(1),Integer(2)]) >>> lt.parent().linear_functions() Linear functions over Real Double Field >>> lt.parent().linear_functions() is mip.linear_functions_parent() True
- sage.numerical.linear_tensor.is_LinearTensor(x)[source]#
Test whether
x
is a tensor product of linear functions with a free module.INPUT:
x
– anything.
OUTPUT:
Boolean.
EXAMPLES:
sage: p = MixedIntegerLinearProgram() sage: x = p.new_variable(nonnegative=False) sage: from sage.numerical.linear_tensor import is_LinearTensor sage: is_LinearTensor(x[0] - 2*x[2]) doctest:warning... DeprecationWarning: The function is_LinearTensor is deprecated; use 'isinstance(..., LinearTensor)' instead. See https://github.com/sagemath/sage/issues/38184 for details. False sage: is_LinearTensor('a string') False
>>> from sage.all import * >>> p = MixedIntegerLinearProgram() >>> x = p.new_variable(nonnegative=False) >>> from sage.numerical.linear_tensor import is_LinearTensor >>> is_LinearTensor(x[Integer(0)] - Integer(2)*x[Integer(2)]) doctest:warning... DeprecationWarning: The function is_LinearTensor is deprecated; use 'isinstance(..., LinearTensor)' instead. See https://github.com/sagemath/sage/issues/38184 for details. False >>> is_LinearTensor('a string') False