-
-
Notifications
You must be signed in to change notification settings - Fork 408
Make things work for general AbstractArray
s
#980
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
b87c015
6306e2c
ae06063
722fd26
553981a
035cfe9
5776b09
5c300c4
a8e0ab9
46b5548
2254e20
bded621
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -276,8 +276,8 @@ Base.sum(j::JuMPArray) = sum(j.innerArray) | |
Base.sum(j::JuMPDict) = sum(values(j.tupledict)) | ||
Base.sum(j::JuMPArray{Variable}) = AffExpr(vec(j.innerArray), ones(length(j.innerArray)), 0.0) | ||
Base.sum(j::JuMPDict{Variable}) = AffExpr(collect(values(j.tupledict)), ones(length(j.tupledict)), 0.0) | ||
Base.sum(j::Array{Variable}) = AffExpr(vec(j), ones(length(j)), 0.0) | ||
function Base.sum{T<:GenericAffExpr}(affs::Array{T}) | ||
Base.sum(j::AbstractArray{Variable}) = AffExpr(vec(j), ones(length(j)), 0.0) | ||
function Base.sum{T<:GenericAffExpr}(affs::AbstractArray{T}) | ||
new_aff = zero(T) | ||
for aff in affs | ||
append!(new_aff, aff) | ||
|
@@ -339,7 +339,7 @@ Base.ctranspose(x::JuMPArray) = _throw_transpose_error() | |
|
||
# Can remove the following code once == overloading is removed | ||
|
||
function Base.issymmetric{T<:JuMPTypes}(x::Matrix{T}) | ||
function Base.issymmetric{T<:JuMPTypes}(x::AbstractMatrix{T}) | ||
(n = size(x,1)) == size(x,2) || return false | ||
for i in 1:n, j in (i+1):n | ||
isequal(x[i,j], x[j,i]) || return false | ||
|
@@ -348,14 +348,14 @@ function Base.issymmetric{T<:JuMPTypes}(x::Matrix{T}) | |
end | ||
|
||
# Special-case because the the base version wants to do fill!(::Array{Variable}, zero(AffExpr)) | ||
Base.diagm(x::Vector{Variable}) = diagm(convert(Vector{AffExpr}, x)) | ||
Base.diagm(x::AbstractVector{Variable}) = diagm(convert(Vector{AffExpr}, x)) | ||
|
||
############### | ||
# The _multiply!(buf,y,z) adds the results of y*z into the buffer buf. No bounds/size | ||
# checks are performed; it is expected that the caller has done this, has ensured | ||
# that the eltype of buf is appropriate, and has zeroed the elements of buf (if desired). | ||
|
||
function _multiply!{T<:JuMPTypes}(ret::Array{T}, lhs::Array, rhs::Array) | ||
function _multiply!{T<:JuMPTypes}(ret::AbstractArray{T}, lhs::Array, rhs::Array) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @joehuchette should comment but I don't think this method was designed for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I don't think this part of the code will work with generic abstract arrays as-is. |
||
m, n = size(lhs,1), size(lhs,2) | ||
r, s = size(rhs,1), size(rhs,2) | ||
for i ∈ 1:m, j ∈ 1:s | ||
|
@@ -370,7 +370,7 @@ function _multiply!{T<:JuMPTypes}(ret::Array{T}, lhs::Array, rhs::Array) | |
end | ||
|
||
# this computes lhs.'*rhs and places it in ret | ||
function _multiplyt!{T<:JuMPTypes}(ret::Array{T}, lhs::Array, rhs::Array) | ||
function _multiplyt!{T<:JuMPTypes}(ret::AbstractArray{T}, lhs::Array, rhs::Array) | ||
m, n = size(lhs,2), size(lhs,1) # transpose | ||
r, s = size(rhs,1), size(rhs,2) | ||
for i ∈ 1:m, j ∈ 1:s | ||
|
@@ -384,7 +384,7 @@ function _multiplyt!{T<:JuMPTypes}(ret::Array{T}, lhs::Array, rhs::Array) | |
ret | ||
end | ||
|
||
function _multiply!{T<:Union{GenericAffExpr,GenericQuadExpr}}(ret::Array{T}, lhs::SparseMatrixCSC, rhs::Array) | ||
function _multiply!{T<:Union{GenericAffExpr,GenericQuadExpr}}(ret::AbstractArray{T}, lhs::SparseMatrixCSC, rhs::Array) | ||
nzv = nonzeros(lhs) | ||
rv = rowvals(lhs) | ||
for col ∈ 1:lhs.n | ||
|
@@ -398,11 +398,11 @@ function _multiply!{T<:Union{GenericAffExpr,GenericQuadExpr}}(ret::Array{T}, lhs | |
end | ||
|
||
# this computes lhs.'*rhs and places it in ret | ||
function _multiplyt!{T<:Union{GenericAffExpr,GenericQuadExpr}}(ret::Array{T}, lhs::SparseMatrixCSC, rhs::Array) | ||
function _multiplyt!{T<:Union{GenericAffExpr,GenericQuadExpr}}(ret::AbstractArray{T}, lhs::SparseMatrixCSC, rhs::Array) | ||
_multiply!(ret, transpose(lhs), rhs) # TODO fully implement | ||
end | ||
|
||
function _multiply!{T<:Union{GenericAffExpr,GenericQuadExpr}}(ret::Array{T}, lhs::Matrix, rhs::SparseMatrixCSC) | ||
function _multiply!{T<:Union{GenericAffExpr,GenericQuadExpr}}(ret::AbstractArray{T}, lhs::Matrix, rhs::SparseMatrixCSC) | ||
rowval = rowvals(rhs) | ||
nzval = nonzeros(rhs) | ||
for multivec_row in 1:size(lhs,1) | ||
|
@@ -419,7 +419,7 @@ function _multiply!{T<:Union{GenericAffExpr,GenericQuadExpr}}(ret::Array{T}, lhs | |
end | ||
|
||
# this computes lhs.'*rhs and places it in ret | ||
function _multiplyt!{T<:Union{GenericAffExpr,GenericQuadExpr}}(ret::Array{T}, lhs::Matrix, rhs::SparseMatrixCSC) | ||
function _multiplyt!{T<:Union{GenericAffExpr,GenericQuadExpr}}(ret::AbstractArray{T}, lhs::Matrix, rhs::SparseMatrixCSC) | ||
rowval = rowvals(rhs) | ||
nzval = nonzeros(rhs) | ||
for multivec_row ∈ 1:size(lhs,2) # transpose | ||
|
@@ -448,7 +448,7 @@ _multiply!(ret, lhs, rhs) = A_mul_B!(ret, lhs, ret) | |
|
||
import Base.At_mul_B | ||
import Base.Ac_mul_B | ||
# these methods are called when one does A.'*v or A'*v respectively | ||
# these methods are called when one does A.'*v or A'*v respectively | ||
At_mul_B{T<:JuMPTypes}(A::Union{Matrix{T},SparseMatrixCSC{T}}, x::Union{Matrix, Vector, SparseMatrixCSC}) = _matmult(A, x) | ||
At_mul_B{T<:JuMPTypes,R<:JuMPTypes}(A::Union{Matrix{T},SparseMatrixCSC{T}}, x::Union{Matrix{R}, Vector{R}, SparseMatrixCSC{R}}) = _matmult(A, x) | ||
At_mul_B{T<:JuMPTypes}(A::Union{Matrix,SparseMatrixCSC}, x::Union{Matrix{T}, Vector{T}, SparseMatrixCSC{T}}) = _matmult(A, x) | ||
|
@@ -485,7 +485,7 @@ _return_arrayt{R,S}(A::AbstractMatrix{R}, x::AbstractVector{S}) = _fillwithzeros | |
_return_arrayt{R,S}(A::AbstractMatrix{R}, x::AbstractMatrix{S}) = _fillwithzeros(Array{_multiply_type(R,S)}(size(A,2), size(x, 2))) | ||
|
||
# helper so we don't fill the buffer array with the same object | ||
function _fillwithzeros{T}(arr::Array{T}) | ||
function _fillwithzeros{T}(arr::AbstractArray{T}) | ||
for I in eachindex(arr) | ||
arr[I] = zero(T) | ||
end | ||
|
@@ -527,28 +527,28 @@ for op in [:+, :-]; @eval begin | |
end; end | ||
|
||
for op in [:*, :/]; @eval begin | ||
function $op{T<:JuMPTypes}(lhs::Number,rhs::Array{T}) | ||
function $op{T<:JuMPTypes}(lhs::Number,rhs::AbstractArray{T}) | ||
ret = Array{typeof($op(lhs, zero(T)))}(size(rhs)) | ||
for I in eachindex(ret) | ||
ret[I] = $op(lhs, rhs[I]) | ||
end | ||
ret | ||
end | ||
function $op{T<:JuMPTypes}(lhs::Array{T},rhs::Number) | ||
function $op{T<:JuMPTypes}(lhs::AbstractArray{T},rhs::Number) | ||
ret = Array{typeof($op(zero(T), rhs))}(size(lhs)) | ||
for I in eachindex(ret) | ||
ret[I] = $op(lhs[I], rhs) | ||
end | ||
ret | ||
end | ||
function $op{T<:JuMPTypes,S}(lhs::T,rhs::Array{S}) | ||
function $op{T<:JuMPTypes,S}(lhs::T,rhs::AbstractArray{S}) | ||
ret = Array{typeof($op(lhs, zero(S)))}(size(rhs)) | ||
for I in eachindex(ret) | ||
ret[I] = $op(lhs, rhs[I]) | ||
end | ||
ret | ||
end | ||
function $op{T<:JuMPTypes,S}(lhs::Array{S},rhs::T) | ||
function $op{T<:JuMPTypes,S}(lhs::AbstractArray{S},rhs::T) | ||
ret = Array{typeof($op(zero(S), rhs))}(size(lhs)) | ||
for I in eachindex(ret) | ||
ret[I] = $op(lhs[I], rhs) | ||
|
@@ -571,7 +571,7 @@ end; end | |
|
||
# The following are primarily there for internal use in the macro code for @constraint | ||
for op in [:(+), :(-)]; @eval begin | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are these methods now covered by built-ins in Julia? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, thanks for checking |
||
function $op(lhs::Array{Variable},rhs::Array{Variable}) | ||
function $op(lhs::AbstractArray{Variable},rhs::AbstractArray{Variable}) | ||
(sz = size(lhs)) == size(rhs) || error("Incompatible sizes for $op: $sz $op $(size(rhs))") | ||
ret = Array{AffExpr}(sz) | ||
for I in eachindex(ret) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm concerned about the validity of using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oops, forgot this one. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed (here and in a number of other locations). |
||
|
@@ -611,15 +611,15 @@ for (dotop,op) in [(:.+,:+), (:.-,:-), (:.*,:*), (:./,:/)] | |
end | ||
|
||
|
||
(+){T<:JuMPTypes}(x::Array{T}) = x | ||
function (-){T<:JuMPTypes}(x::Array{T}) | ||
(+){T<:JuMPTypes}(x::AbstractArray{T}) = x | ||
function (-){T<:JuMPTypes}(x::AbstractArray{T}) | ||
ret = similar(x, typeof(-one(T))) | ||
for I in eachindex(ret) | ||
ret[I] = -x[I] | ||
end | ||
ret | ||
end | ||
(*){T<:JuMPTypes}(x::Array{T}) = x | ||
(*){T<:JuMPTypes}(x::AbstractArray{T}) = x | ||
|
||
############################################################################### | ||
# Add nonlinear function fallbacks for JuMP built-in types | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,7 +44,7 @@ end | |
|
||
# TODO: get rid of this! This is only a helper, and should be Base.values | ||
# (and probably live there, as well) | ||
_values(x::Array) = x | ||
_values(x::AbstractArray) = x | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where is this used and why does it need to change? |
||
_values(x) = Base.values(x) | ||
|
||
# REPL-specific symbols | ||
|
@@ -103,7 +103,7 @@ math(s,mathmode) = mathmode ? s : "\$\$ $s \$\$" | |
# helper to look up corresponding JuMPContainerData | ||
printdata(v::JuMPContainer) = _getmodel(v).varData[v] | ||
getname(x::JuMPContainer) = hasmeta(x, :model) ? printdata(x).name : "__anon__" | ||
function printdata(v::Array{Variable}) | ||
function printdata(v::AbstractArray{Variable}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you redefining printing for |
||
if isempty(v) | ||
error("Cannot locate printing data for an empty array") | ||
end | ||
|
@@ -344,7 +344,7 @@ function fill_var_names(mode, colNames, v::JuMPDict{Variable}) | |
end | ||
end | ||
end | ||
function fill_var_names(mode, colNames, v::Array{Variable}) | ||
function fill_var_names(mode, colNames, v::AbstractArray{Variable}) | ||
isempty(v) && return | ||
sizes = size(v) | ||
m = first(v).m | ||
|
@@ -400,7 +400,7 @@ Base.show(io::IO, ::MIME"text/latex", j::Union{JuMPContainer{Variable},Array{Var | |
# Generic string converter, called by mode-specific handlers | ||
|
||
# Assumes that !isempty(j) | ||
_getmodel(j::Array{Variable}) = first(j).m | ||
_getmodel(j::AbstractArray{Variable}) = first(j).m | ||
_getmodel(j::JuMPContainer) = getmeta(j, :model) | ||
|
||
function cont_str(mode, j, sym::PrintSymbols) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -149,10 +149,10 @@ function addconstraint(m::Model, c::QuadConstraint) | |
end | ||
return ConstraintRef{Model,QuadConstraint}(m,length(m.quadconstr)) | ||
end | ||
addconstraint(m::Model, c::Array{QuadConstraint}) = | ||
addconstraint(m::Model, c::AbstractArray{QuadConstraint}) = | ||
error("Vectorized constraint added without elementwise comparisons. Try using one of (.<=,.>=,.==).") | ||
|
||
function addVectorizedConstraint(m::Model, v::Array{QuadConstraint}) | ||
function addVectorizedConstraint(m::Model, v::AbstractArray{QuadConstraint}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change is not covered by tests. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wasn't able to construct a test case involving nonstandard arrays of |
||
ret = Array{ConstraintRef{Model,QuadConstraint}}(size(v)) | ||
for I in eachindex(v) | ||
ret[I] = addconstraint(m, v[I]) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,7 +43,7 @@ end | |
|
||
addSOS1(m::Model, coll) = addSOS1(m, convert(Vector{AffExpr}, coll)) | ||
|
||
function addSOS1(m::Model, coll::Vector{AffExpr}) | ||
function addSOS1(m::Model, coll::AbstractVector{AffExpr}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not covered by tests. This method calls There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also doesn't seem necessary for your use case |
||
vars, weight = constructSOS(m,coll) | ||
push!(m.sosconstr, SOSConstraint(vars, weight, :SOS1)) | ||
if m.internalModelLoaded | ||
|
@@ -59,7 +59,7 @@ end | |
|
||
addSOS2(m::Model, coll) = addSOS2(m, convert(Vector{AffExpr}, coll)) | ||
|
||
function addSOS2(m::Model, coll::Vector{AffExpr}) | ||
function addSOS2(m::Model, coll::AbstractVector{AffExpr}) | ||
vars, weight = constructSOS(m,coll) | ||
push!(m.sosconstr, SOSConstraint(vars, weight, :SOS2)) | ||
if m.internalModelLoaded | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is not covered by tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.