9x25dillon commited on
Commit
60a3e1e
·
verified ·
1 Parent(s): dd7c96a

Upload 19 files

Browse files

License

This dataset is licensed under a Creative Commons Attribution 4.0 International (CC BY 4.0) license.

This allows for the sharing and adaptation of the datasets for any purpose, provided that the appropriate credit is given.
Pawel Bielski

[email protected]

Karlsruhe Institute of Technology

Dustin Kottonau

Karlsruhe Institute of Technology
Additional Information

- staDynBenignLab.csv: 1086 features extracted from 595 files on MS Windows 7 and 8, obtained Program Files directory.

- staDynVxHeaven2698Lab.csv: 1087 features extracted from 2698 files of VxHeaven dataset.

- staDynVt2955Lab.csv: 1087 features extracted from 2955 provided by Virus Total in 2018.

Has Missing Values?

No
Variable Information

Static features: ASM, Hex dump and PE Header (discreate, continuous)

Dynamic features: extracted from a Cuckoo sandbox



Dataset Files
Reviews

There are no reviews for this dataset yet.
Write a Review
Comments


Install the ucimlrepo package

pip install ucimlrepo

Import the dataset into your code

from ucimlrepo import fetch_ucirepo

# fetch dataset
malware_static_and_dynamic_features_vxheaven_and_virus_total = fetch_ucirepo(id=541)

# data (as pandas dataframes)
X = malware_static_and_dynamic_features_vxheaven_and_virus_total.data.features
y = malware_static_and_dynamic_features_vxheaven_and_virus_total.data.targets

# metadata
print(malware_static_and_dynamic_features_vxheaven_and_virus_total.metadata)

# variable information
print(malware_static_and_dynamic_features_vxheaven_and_virus_total.variables)

View the full documentation
0 citations
4165 views
Citation

Malware static and dynamic features VxHeaven and Virus Total [Dataset]. (2019). UCI Machine Learning Repository. https://doi.org/10.24432/C58K6H.

Style:
DOI
10.24432/C58K6H
License

This dataset is licensed under a Creative Commons Attribution 4.0 International (CC BY 4.0) license.

This allows for the sharing and adaptation of the datasets for any purpose, provided that the appropriate credit is given.

Files changed (19) hide show
  1. DynamicPolynomials.jl +47 -0
  2. appveyor.yml +36 -0
  3. cmult.jl +65 -0
  4. comp.jl +162 -0
  5. diff.jl +28 -0
  6. div.jl +22 -0
  7. mono.jl +81 -0
  8. monovec.jl +241 -0
  9. mult.jl +101 -0
  10. ncmult.jl +123 -0
  11. operators.jl +66 -0
  12. poly.jl +230 -0
  13. promote.jl +27 -0
  14. staDynBenignLab.csv +0 -0
  15. staDynVt2955Lab.csv +0 -0
  16. staDynVxHeaven2698Lab.csv +0 -0
  17. subs.jl +106 -0
  18. term.jl +52 -0
  19. var.jl +101 -0
DynamicPolynomials.jl ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ module DynamicPolynomials
2
+
3
+ using Reexport
4
+ @reexport using MultivariatePolynomials
5
+ const MP = MultivariatePolynomials
6
+
7
+
8
+ include("var.jl")
9
+ include("mono.jl")
10
+ const DMonomialLike{C} = Union{Monomial{C}, PolyVar{C}}
11
+ include("term.jl")
12
+ include("monovec.jl")
13
+ include("poly.jl")
14
+ const TermPoly{C, T} = Union{Term{C, T}, Polynomial{C, T}}
15
+ const PolyType{C} = Union{Polynomial{C}, Term{C}, Monomial{C}, PolyVar{C}}
16
+ MP.constantmonomial(::Type{<:PolyType{C}}) where {C} = Monomial{C}()
17
+ MP.constantmonomial(p::PolyType) = Monomial(_vars(p), zeros(Int, nvariables(p)))
18
+ MP.monomialtype(::Type{<:PolyType{C}}) where C = Monomial{C}
19
+ MP.monomialtype(::PolyType{C}) where C = Monomial{C}
20
+ #function MP.constantmonomial(::Type{Monomial{C}}, vars=PolyVar{C}[]) where {C}
21
+ # return Monomial{C}(vars, zeros(Int, length(vars)))
22
+ #end
23
+ MP.termtype(::Union{TermPoly{C, T}, Type{<:TermPoly{C, T}}}) where {C, T} = Term{C, T}
24
+ MP.termtype(::Union{PolyType{C}, Type{<:PolyType{C}}}, ::Type{T}) where {C, T} = Term{C, T}
25
+ MP.polynomial(p::PolyType) = Polynomial(p)
26
+ function MP.polynomial(p::PolyType{C}, ::Type{T}) where {C, T}
27
+ return convert(Polynomial{C, T}, p)
28
+ end
29
+ MP.polynomialtype(::Type{Term{C, T}}) where {T, C} = Polynomial{C, T}
30
+ MP.polynomialtype(::Type{T}, ::Type{<:DMonomialLike{C}}) where {T, C} = Polynomial{C, T}
31
+ MP.polynomialtype(::Union{PolyType{C}, Type{<:PolyType{C}}}, ::Type{T}) where {C, T} = Polynomial{C, T}
32
+ _vars(p::AbstractArray{<:PolyType}) = mergevars(_vars.(p))[1]
33
+ MP.variables(p::Union{PolyType, MonomialVector, AbstractArray{<:PolyType}}) = _vars(p) # tuple(_vars(p))
34
+ MP.nvariables(p::Union{PolyType, MonomialVector, AbstractArray{<:PolyType}}) = length(_vars(p))
35
+ MP.similarvariable(p::Union{PolyType{C}, Type{<:PolyType{C}}}, ::Type{Val{V}}) where {C, V} = PolyVar{C}(string(V))
36
+ MP.similarvariable(p::Union{PolyType{C}, Type{<:PolyType{C}}}, V::Symbol) where {C} = PolyVar{C}(string(V))
37
+ include("promote.jl")
38
+
39
+ include("operators.jl")
40
+ include("comp.jl")
41
+
42
+ include("diff.jl")
43
+ include("subs.jl")
44
+
45
+ include("div.jl")
46
+
47
+ end # module
appveyor.yml ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ environment:
2
+ matrix:
3
+ - julia_version: 1.0
4
+ - julia_version: latest
5
+
6
+ platform:
7
+ - x86 # 32-bit
8
+ - x64 # 64-bit
9
+
10
+ ## uncomment the following lines to allow failures on nightly julia
11
+ ## (tests will run but not make your overall status red)
12
+ matrix:
13
+ allow_failures:
14
+ - julia_version: latest
15
+
16
+ branches:
17
+ only:
18
+ - master
19
+ - /release-.*/
20
+
21
+ notifications:
22
+ - provider: Email
23
+ on_build_success: false
24
+ on_build_failure: false
25
+ on_build_status_changed: false
26
+
27
+ install:
28
+ - ps: iex ((new-object net.webclient).DownloadString("https://raw.githubusercontent.com/JuliaCI/Appveyor.jl/version-1/bin/install.ps1"))
29
+
30
+ build_script:
31
+ - echo "%JL_BUILD_SCRIPT%"
32
+ - C:\julia\bin\julia -e "%JL_BUILD_SCRIPT%"
33
+
34
+ test_script:
35
+ - echo "%JL_TEST_SCRIPT%"
36
+ - C:\julia\bin\julia -e "%JL_TEST_SCRIPT%"
cmult.jl ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Product between PolyVar and Monomial -> Monomial
2
+ function Base.:(*)(x::PolyVar{true}, y::PolyVar{true})
3
+ if x === y
4
+ Monomial{true}([x], [2])
5
+ else
6
+ Monomial{true}(x > y ? [x,y] : [y,x], [1,1])
7
+ end
8
+ end
9
+ function multiplyvar(v::Vector{PolyVar{true}}, x::PolyVar{true})
10
+ i = findfirst(w->w <= x, v)
11
+ if (i != nothing && i > 0) && v[i] == x
12
+ multiplyexistingvar(v, x, i)
13
+ else
14
+ insertvar(v, x, (i == nothing || i == 0) ? length(v)+1 : i)
15
+ end
16
+ end
17
+ function Base.:(*)(x::PolyVar{true}, y::Monomial{true})
18
+ w, updatez = multiplyvar(y.vars, x)
19
+ Monomial{true}(w, updatez(y.z))
20
+ end
21
+ Base.:(*)(y::MonomialVector{true}, x::PolyVar{true}) = x * y
22
+ function Base.:(*)(x::PolyVar{true}, y::MonomialVector{true})
23
+ w, updatez = multiplyvar(y.vars, x)
24
+ MonomialVector{true}(w, updatez.(y.Z))
25
+ end
26
+ function multdivmono(v::Vector{PolyVar{true}}, x::Monomial{true}, op)
27
+ if v == x.vars
28
+ # /!\ no copy done here for efficiency, do not mess up with vars
29
+ w = v
30
+ updatez = z -> op.(z, x.z)
31
+ else
32
+ w, maps = mergevars([v, x.vars])
33
+ updatez = z -> begin
34
+ newz = zeros(Int, length(w))
35
+ I = maps[1]; i = 1; lI = length(I)
36
+ J = maps[2]; j = 1; lJ = length(J)
37
+ while i <= lI || j <= lJ
38
+ if i > lI || (j <= lJ && J[j] < I[i])
39
+ newz[J[j]] = op(0, x.z[j])
40
+ j += 1
41
+ elseif j > lJ || (i <= lI && I[i] < J[j])
42
+ newz[I[i]] = op(z[i], 0)
43
+ i += 1
44
+ else
45
+ @assert I[i] == J[j]
46
+ newz[I[i]] = op(z[i], x.z[j])
47
+ i += 1
48
+ j += 1
49
+ end
50
+ end
51
+ newz
52
+ end
53
+ end
54
+ w, updatez
55
+ end
56
+ function MP.mapexponents(f, x::Monomial{true}, y::Monomial{true})
57
+ w, updatez = multdivmono(x.vars, y, f)
58
+ Monomial{true}(w, updatez(x.z))
59
+ end
60
+ function Base.:(*)(x::Monomial{true}, y::MonomialVector{true})
61
+ w, updatez = multdivmono(y.vars, x, +)
62
+ MonomialVector{true}(w, updatez.(y.Z))
63
+ end
64
+ Base.:(*)(y::MonomialVector{true}, x::Monomial{true}) = x * y
65
+ Base.:(*)(x::Monomial{true}, y::PolyVar{true}) = y * x
comp.jl ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import Base.==
2
+
3
+ #Base.iszero(t::Term) = iszero(t.α)
4
+ Base.iszero(p::Polynomial) = isempty(p)
5
+
6
+ # TODO This should be in Base with T instead of PolyVar{C}.
7
+ # See https://github.com/blegat/MultivariatePolynomials.jl/issues/3
8
+ function (==)(x::Vector{PolyVar{C}}, y::Vector{PolyVar{C}}) where C
9
+ if length(x) != length(y)
10
+ false
11
+ else
12
+ #for (xi, yi) in zip(x, y)
13
+ for i in 1:length(x)
14
+ if x[i] != y[i]
15
+ return false
16
+ end
17
+ end
18
+ true
19
+ end
20
+ end
21
+
22
+ # Comparison of PolyVar
23
+
24
+ function (==)(x::PolyVar{C}, y::PolyVar{C}) where C
25
+ x.id == y.id
26
+ end
27
+
28
+ Base.isless(x::PolyVar{C}, y::PolyVar{C}) where C = isless(y.id, x.id)
29
+
30
+ # Comparison of Monomial
31
+
32
+ # graded lex ordering
33
+ function mycomp(x::Monomial{C}, y::Monomial{C}) where C
34
+ degx = degree(x)
35
+ degy = degree(y)
36
+ if degx != degy
37
+ degx - degy
38
+ else
39
+ i = j = 1
40
+ # since they have the same degree,
41
+ # if we get j > nvariables(y), the rest in x.z should be zeros
42
+ while i <= nvariables(x) && j <= nvariables(y)
43
+ if x.vars[i] > y.vars[j]
44
+ if x.z[i] == 0
45
+ i += 1
46
+ else
47
+ return 1
48
+ end
49
+ elseif x.vars[i] < y.vars[j]
50
+ if y.z[j] == 0
51
+ j += 1
52
+ else
53
+ return -1
54
+ end
55
+ elseif x.z[i] != y.z[j]
56
+ return x.z[i] - y.z[j]
57
+ else
58
+ i += 1
59
+ j += 1
60
+ end
61
+ end
62
+ 0
63
+ end
64
+ end
65
+
66
+ function (==)(x::Monomial{C}, y::Monomial{C}) where C
67
+ mycomp(x, y) == 0
68
+ end
69
+ (==)(x::PolyVar{C}, y::Monomial{C}) where C = convert(Monomial{C}, x) == y
70
+
71
+ # graded lex ordering
72
+ function Base.isless(x::Monomial{C}, y::Monomial{C}) where C
73
+ mycomp(x, y) < 0
74
+ end
75
+ Base.isless(x::Monomial{C}, y::PolyVar{C}) where C = isless(x, convert(Monomial{C}, y))
76
+ Base.isless(x::PolyVar{C}, y::Monomial{C}) where C = isless(convert(Monomial{C}, x), y)
77
+
78
+ # Comparison of MonomialVector
79
+ function (==)(x::MonomialVector{C}, y::MonomialVector{C}) where C
80
+ if length(x.Z) != length(y.Z)
81
+ return false
82
+ end
83
+ allvars, maps = mergevars([_vars(x), _vars(y)])
84
+ # Should be sorted in the same order since the non-common
85
+ # polyvar should have exponent 0
86
+ for (a, b) in zip(x.Z, y.Z)
87
+ A = zeros(length(allvars))
88
+ B = zeros(length(allvars))
89
+ A[maps[1]] = a
90
+ B[maps[2]] = b
91
+ if A != B
92
+ return false
93
+ end
94
+ end
95
+ return true
96
+ end
97
+ (==)(mv::AbstractVector, x::MonomialVector) = monovec(mv) == x
98
+ (==)(x::MonomialVector, mv::AbstractVector) = x == monovec(mv)
99
+
100
+ # Comparison of Term
101
+ function (==)(p::Polynomial{C}, q::Polynomial{C}) where {C}
102
+ # terms should be sorted and without zeros
103
+ if length(p) != length(q)
104
+ return false
105
+ end
106
+ for i in 1:length(p)
107
+ if p.x[i] != q.x[i]
108
+ # There should not be zero terms
109
+ @assert p.a[i] != 0
110
+ @assert q.a[i] != 0
111
+ return false
112
+ end
113
+ if p.a[i] != q.a[i]
114
+ return false
115
+ end
116
+ end
117
+ return true
118
+ end
119
+
120
+ function grlex(x::Vector{Int}, y::Vector{Int})
121
+ @assert length(x) == length(y)
122
+ degx = sum(x)
123
+ degy = sum(y)
124
+ if degx != degy
125
+ degx < degy
126
+ else
127
+ for (a, b) in zip(x, y)
128
+ if a < b
129
+ return true
130
+ elseif a > b
131
+ return false
132
+ end
133
+ end
134
+ false
135
+ end
136
+ end
137
+
138
+ function Base.isapprox(p::Polynomial{C, S}, q::Polynomial{C, T};
139
+ rtol::Real=Base.rtoldefault(S, T, 0), atol::Real=0,
140
+ ztol::Real=iszero(atol) ? Base.rtoldefault(S, T, 0) : atol) where {C, S, T}
141
+ i = j = 1
142
+ while i <= length(p.x) || j <= length(q.x)
143
+ if i > length(p.x) || (j <= length(q.x) && q.x[j] > p.x[i])
144
+ if !isapproxzero(q.a[j], ztol=ztol)
145
+ return false
146
+ end
147
+ j += 1
148
+ elseif j > length(q.x) || p.x[i] > q.x[j]
149
+ if !isapproxzero(p.a[i], ztol=ztol)
150
+ return false
151
+ end
152
+ i += 1
153
+ else
154
+ if !isapprox(p.a[i], q.a[j], rtol=rtol, atol=atol)
155
+ return false
156
+ end
157
+ i += 1
158
+ j += 1
159
+ end
160
+ end
161
+ true
162
+ end
diff.jl ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function MP.differentiate(m::Monomial{C}, x::PolyVar{C}) where C
2
+ i = findfirst(isequal(x), _vars(m))
3
+ if (i == nothing || i == 0) || m.z[i] == 0
4
+ zeroterm(m)
5
+ else
6
+ z = copy(m.z)
7
+ z[i] -= 1
8
+ m.z[i] * Monomial(_vars(m), z)
9
+ end
10
+ end
11
+
12
+ function MP.differentiate(p::Polynomial{C, T}, x::PolyVar{C}) where {C, T}
13
+ # grlex order preserved
14
+ i = something(findfirst(isequal(x), _vars(p)), 0)
15
+ S = typeof(zero(T) * 0)
16
+ if iszero(i)
17
+ zero(Polynomial{C, S})
18
+ else
19
+ keep = findall(z -> z[i] > 0, p.x.Z)
20
+ Z = copy.(p.x.Z[keep])
21
+ a = Vector{S}(undef, length(keep))
22
+ for j in 1:length(Z)
23
+ a[j] = p.a[keep[j]] * Z[j][i]
24
+ Z[j][i] -= 1
25
+ end
26
+ Polynomial(a, MonomialVector(_vars(p), Z))
27
+ end
28
+ end
div.jl ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function MP.divides(m1::Monomial, m2::Monomial)
2
+ e1 = exponents(m1)
3
+ v1 = variables(m1)
4
+ e2 = exponents(m2)
5
+ v2 = variables(m2)
6
+ i = 1; lI = length(e1)
7
+ j = 1; lJ = length(e2)
8
+ while i <= lI || j <= lJ
9
+ if i > lI || (j <= lJ && v2[j] > v1[i])
10
+ j += 1
11
+ elseif j > lJ || (i <= lI && v1[i] > v2[j])
12
+ iszero(e1[i]) || return false
13
+ i += 1
14
+ else
15
+ @assert v1[i] == v2[j]
16
+ e1[i] <= e2[j] || return false
17
+ i += 1
18
+ j += 1
19
+ end
20
+ end
21
+ return true
22
+ end
mono.jl ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export Monomial
2
+
3
+ const TupOrVec{T} = Union{AbstractVector{T}, Tuple{Vararg{T}}}
4
+
5
+ # Invariant:
6
+ # vars is increasing
7
+ # z may contain 0's (otherwise, getindex of MonomialVector would be inefficient)
8
+ struct Monomial{C} <: AbstractMonomial
9
+ vars::Vector{PolyVar{C}}
10
+ z::Vector{Int}
11
+
12
+ function Monomial{C}(vars::Vector{PolyVar{C}}, z::Vector{Int}) where {C}
13
+ if length(vars) != length(z)
14
+ throw(ArgumentError("There should be as many vars than exponents"))
15
+ end
16
+ new(vars, z)
17
+ end
18
+ end
19
+
20
+ Monomial{C}(vars::Tuple{Vararg{PolyVar{C}}}, z::Vector{Int}) where C = Monomial{C}([vars...], z)
21
+
22
+ iscomm(::Type{Monomial{C}}) where C = C
23
+ Monomial{C}() where C = Monomial{C}(PolyVar{C}[], Int[])
24
+ Monomial(vars::TupOrVec{PolyVar{C}}, z::Vector{Int}) where C = Monomial{C}(vars, z)
25
+ function Base.convert(::Type{Monomial{C}}, x::PolyVar{C}) where C
26
+ return Monomial{C}([x], [1])
27
+ end
28
+ Monomial(x::PolyVar{C}) where C = convert(Monomial{C}, x)
29
+ function MP.convertconstant(::Type{Monomial{C}}, α) where C
30
+ α == 1 || error("Cannot convert $α to a Monomial{$C} as it is not one")
31
+ Monomial{C}(PolyVar{C}[], Int[])
32
+ end
33
+
34
+ # defaults to commutative so that `Monomial(1)` is consistent with TypedPolynomials
35
+ Monomial(α::Number) = convert(Monomial{true}, α)
36
+
37
+ Base.broadcastable(m::Monomial) = Ref(m)
38
+ Base.copy(m::M) where {M<:Monomial} = M(m.vars, copy(m.z))
39
+
40
+ # Generate canonical reperesentation by removing variables that are not used
41
+ function canonical(m::Monomial)
42
+ list = m.z .> 0
43
+ Monomial(_vars(m)[list], m.z[list])
44
+ end
45
+ function Base.hash(x::Monomial, u::UInt)
46
+ cx = canonical(x)
47
+ if iszero(nvariables(cx))
48
+ hash(1, u)
49
+ elseif nvariables(cx) == 1 && cx.z[1] == 1
50
+ hash(cx.vars[1], u)
51
+ else # TODO reduce power in MP
52
+ hash(_vars(cx), hash(cx.z, u))
53
+ end
54
+ end
55
+
56
+ MP.exponents(m::Monomial) = m.z
57
+ # /!\ vars not copied, do not mess with vars
58
+ _vars(m::Union{Monomial}) = m.vars
59
+
60
+ MP.monomial(m::Monomial) = m
61
+ # Does m1 divides m2 ?
62
+ #function MP.divides(m1::Monomial, m2::Monomial)
63
+ # i = j = 1
64
+ # while i <= length(m1.z) && j <= length(m2.z)
65
+ # if m1.vars[i] == m2.vars[j]
66
+ # if m1.z[i] > m2.z[j]
67
+ # return false
68
+ # end
69
+ # i += 1
70
+ # j += 1
71
+ # elseif m1.vars[i] > m2.vars[j]
72
+ # if !iszero(m1.z[i])
73
+ # return false
74
+ # end
75
+ # i += 1
76
+ # else
77
+ # j += 1
78
+ # end
79
+ # end
80
+ # i > length(m1.z)
81
+ #end
monovec.jl ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export MonomialVector
2
+
3
+ # Invariant: Always sorted and no zero vector
4
+ struct MonomialVector{C} <: AbstractVector{Monomial{C}}
5
+ vars::Vector{PolyVar{C}}
6
+ Z::Vector{Vector{Int}}
7
+
8
+ function MonomialVector{C}(vars::Vector{PolyVar{C}}, Z::Vector{Vector{Int}}) where {C}
9
+ @assert !C || issorted(vars, rev=true)
10
+ @assert all(z -> length(z) == length(vars), Z)
11
+ @assert issorted(Z, rev=true, lt=grlex)
12
+ new(vars, Z)
13
+ end
14
+ end
15
+ MonomialVector(vars::Vector{PolyVar{C}}, Z::Vector{Vector{Int}}) where {C} = MonomialVector{C}(vars, Z)
16
+ MonomialVector{C}() where {C} = MonomialVector{C}(PolyVar{C}[], Vector{Int}[])
17
+
18
+ # Generate canonical reperesentation by removing variables that are not used
19
+ function canonical(m::MonomialVector)
20
+ v = zeros(Bool, nvariables(m))
21
+ for z in m.Z
22
+ v = [v[i] || z[i] > 0 for i in eachindex(v)]
23
+ end
24
+ MonomialVector(_vars(m)[v], Vector{Int}[z[v] for z in m.Z])
25
+ end
26
+
27
+ function Base.hash(m::MonomialVector, u::UInt)
28
+ cm = canonical(m)
29
+ if length(cm.Z) == 0
30
+ hash([], u)
31
+ elseif length(cm.Z) == 1
32
+ hash(Monomial(_vars(cm), cm.Z[1]), u)
33
+ else
34
+ hash(_vars(cm), hash(cm.Z, hash(u)))
35
+ end
36
+ end
37
+
38
+ # /!\ vars not copied, do not mess with vars
39
+ Base.copy(m::MV) where {MV<:MonomialVector} = MV(m.vars, copy(m.Z))
40
+ function Base.getindex(x::MV, I) where {MV<:MonomialVector}
41
+ MV(x.vars, x.Z[sort(I)])
42
+ end
43
+ Base.getindex(x::MonomialVector, i::Integer) = Monomial(x.vars, x.Z[i])
44
+
45
+ Base.firstindex(x::MonomialVector) = firstindex(x.Z)
46
+ Base.lastindex(x::MonomialVector) = lastindex(x.Z)
47
+ Base.size(x::MonomialVector) = (length(x),)
48
+ Base.length(x::MonomialVector) = length(x.Z)
49
+ Base.isempty(x::MonomialVector) = length(x) == 0
50
+ Base.iterate(x::MonomialVector) = isempty(x) ? nothing : (x[1], 1)
51
+ function Base.iterate(x::MonomialVector, state::Int)
52
+ state < length(x) ? (x[state+1], state+1) : nothing
53
+ end
54
+
55
+ MultivariatePolynomials.extdegree(x::MonomialVector) = isempty(x) ? (0, 0) : extrema(sum.(x.Z))
56
+ MultivariatePolynomials.mindegree(x::MonomialVector) = isempty(x) ? 0 : minimum(sum.(x.Z))
57
+ MultivariatePolynomials.maxdegree(x::MonomialVector) = isempty(x) ? 0 : maximum(sum.(x.Z))
58
+
59
+ _vars(m::Union{Monomial, MonomialVector}) = m.vars
60
+
61
+ # Recognize arrays of monomials of this module
62
+ # [x, y] -> Vector{PolyVar}
63
+ # [x, x*y] -> Vector{Monomial}
64
+ # [1, x] -> Vector{Term{Int}}
65
+ const DMonoVecElemNonConstant{C} = Union{PolyVar{C}, Monomial{C}, Term{C}}
66
+ # [1] -> Vector{Int}
67
+ const DMonoVecElem{C} = Union{Int, DMonoVecElemNonConstant{C}}
68
+ const DMonoVec{C} = AbstractVector{<:DMonoVecElem{C}}
69
+
70
+ MP.emptymonovec(vars::AbstractVector{PolyVar{C}}) where {C} = MonomialVector{C}(vars, Vector{Int}[])
71
+ MP.emptymonovec(t::DMonoVecElemNonConstant) = emptymonovec(_vars(t))
72
+ MP.emptymonovec(::Type{<:DMonoVecElemNonConstant{C}}) where {C} = MonomialVector{C}()
73
+
74
+ function fillZfordeg!(Z, n, deg, ::Type{Val{true}}, filter::Function)
75
+ z = zeros(Int, n)
76
+ z[1] = deg
77
+ while true
78
+ if filter(z)
79
+ push!(Z, z)
80
+ z = copy(z)
81
+ end
82
+ if z[end] == deg
83
+ break
84
+ end
85
+ sum = 1
86
+ for j in (n-1):-1:1
87
+ if z[j] != 0
88
+ z[j] -= 1
89
+ z[j+1] += sum
90
+ break
91
+ else
92
+ sum += z[j+1]
93
+ z[j+1] = 0
94
+ end
95
+ end
96
+ end
97
+ end
98
+ function fillZrec!(Z, z, i, n, deg, filter::Function)
99
+ if deg == 0
100
+ if filter(z)
101
+ push!(Z, copy(z))
102
+ end
103
+ else
104
+ for i in i:i+n-1
105
+ z[i] += 1
106
+ fillZrec!(Z, z, i, n, deg-1, filter)
107
+ z[i] -= 1
108
+ end
109
+ end
110
+ end
111
+ function fillZfordeg!(Z, n, deg, ::Type{Val{false}}, filter::Function)
112
+ z = zeros(Int, deg * n - deg + 1)
113
+ fillZrec!(Z, z, 1, n, deg, filter)
114
+ end
115
+ # List exponents in decreasing Graded Lexicographic Order
116
+ function getZfordegs(n, degs::AbstractVector{Int}, ::Type{Val{C}}, filter::Function) where C
117
+ Z = Vector{Vector{Int}}()
118
+ for deg in sort(degs, rev=true)
119
+ fillZfordeg!(Z, n, deg, Val{C}, filter)
120
+ end
121
+ @assert issorted(Z, rev=true, lt=grlex)
122
+ Z
123
+ end
124
+
125
+ function MonomialVector(vars::Vector{PolyVar{true}}, degs::AbstractVector{Int}, filter::Function = x->true)
126
+ MonomialVector{true}(vars, getZfordegs(length(vars), degs, Val{true}, z -> filter(Monomial(vars, z))))
127
+ end
128
+
129
+ function getvarsforlength(vars::Vector{PolyVar{false}}, len::Int)
130
+ n = length(vars)
131
+ map(i -> vars[((i-1) % n) + 1], 1:len)
132
+ end
133
+ function MonomialVector(vars::Vector{PolyVar{false}}, degs::AbstractVector{Int}, filter::Function = x->true)
134
+ Z = getZfordegs(length(vars), degs, Val{false}, z -> filter(Monomial(getvarsforlength(vars, length(z)), z)))
135
+ v = isempty(Z) ? vars : getvarsforlength(vars, length(first(Z)))
136
+ MonomialVector{false}(v, Z)
137
+ end
138
+ MonomialVector(vars::Vector{<:PolyVar}, degs::Int, filter::Function = x->true) = MonomialVector(vars, [degs], filter)
139
+
140
+ MP.monomials(vars::AbstractVector{<:PolyVar}, args...) = MonomialVector(vars, args...)
141
+ MP.monomials(vars::Tuple{Vararg{PolyVar}}, args...) = monomials([vars...], args...)
142
+
143
+ #function MP.monomials(vars::TupOrVec{PolyVar{true}}, degs::AbstractVector{Int}, filter::Function = x->true)
144
+ # Z = getZfordegs(length(vars), degs, true, z -> filter(Monomial(vars, z)))
145
+ # [Monomial{true}(vars, z) for z in Z]
146
+ #end
147
+ #function MP.monomials(vars::TupOrVec{PolyVar{false}}, degs::AbstractVector{Int}, filter::Function = x->true)
148
+ # Z = getZfordegs(length(vars), degs, false, z -> filter(Monomial(vars, z)))
149
+ # v = isempty(Z) ? vars : getvarsforlength(vars, length(first(Z)))
150
+ # [Monomial{false}(v, z) for z in Z]
151
+ #end
152
+ #MP.monomials(vars::TupOrVec{PV}, degs::Int, filter::Function = x->true) where {PV<:PolyVar} = monomials(vars, [degs], filter)
153
+
154
+ function buildZvarsvec(::Type{PV}, X::DMonoVec) where {PV<:PolyVar}
155
+ varsvec = Vector{PV}[ (isa(x, DMonoVecElemNonConstant) ? _vars(x) : PolyVar[]) for x in X ]
156
+ allvars, maps = mergevars(varsvec)
157
+ nvars = length(allvars)
158
+ Z = [zeros(Int, nvars) for i in 1:length(X)]
159
+ offset = 0
160
+ for (i, x) in enumerate(X)
161
+ if isa(x, PolyVar)
162
+ @assert length(maps[i]) == 1
163
+ z = [1]
164
+ elseif isa(x, Monomial)
165
+ z = x.z
166
+ elseif isa(x, Term)
167
+ z = x.x.z
168
+ else
169
+ @assert isa(x, Int)
170
+ z = Int[]
171
+ end
172
+ Z[i][maps[i]] = z
173
+ end
174
+ allvars, Z
175
+ end
176
+
177
+ MP.sortmonovec(X::MonomialVector) = (1:length(X), X)
178
+ function _sortmonovec(X::DMonoVec{C}) where {C}
179
+ allvars, Z = buildZvarsvec(PolyVar{C}, X)
180
+ σ = sortperm(Z, rev=true, lt=grlex)
181
+ allvars, Z, σ
182
+ end
183
+ function _removedups!(Z::Vector{Vector{Int}}, σ::Vector{Int})
184
+ dups = findall(i -> Z[σ[i]] == Z[σ[i-1]], 2:length(σ))
185
+ deleteat!(σ, dups)
186
+ end
187
+ function MP.sortmonovec(X::DMonoVec{C}) where {C}
188
+ if isempty(X)
189
+ Int[], MonomialVector{C}()
190
+ else
191
+ allvars, Z, σ = _sortmonovec(X)
192
+ _removedups!(Z, σ)
193
+ σ, MonomialVector{C}(allvars, Z[σ])
194
+ end
195
+ end
196
+
197
+ function MonomialVector{C}(X::DMonoVec{C}) where C
198
+ allvars, Z = buildZvarsvec(PolyVar{C}, X)
199
+ sort!(Z, rev=true, lt=grlex)
200
+ dups = findall(i -> Z[i] == Z[i-1], 2:length(Z))
201
+ deleteat!(Z, dups)
202
+ MonomialVector{C}(allvars, Z)
203
+ end
204
+ function MonomialVector(X)
205
+ monovectype(X)(X)
206
+ end
207
+
208
+ MP.monovectype(X::Union{DMonoVecElemNonConstant{C}, Type{<:DMonoVecElemNonConstant{C}}, DMonoVec{C}, Type{<:DMonoVec{C}}}) where {C} = MonomialVector{C}
209
+ function MP.monovec(X::DMonoVec)
210
+ MonomialVector(X)
211
+ end
212
+ MP.monovec(a, mv::MonomialVector) = (a, mv)
213
+
214
+ function MP.mergemonovec(ms::Vector{MonomialVector{C}}) where {C}
215
+ m = length(ms)
216
+ I = ones(Int, length(ms))
217
+ L = length.(ms)
218
+ X = Vector{Monomial{C}}()
219
+ while any(I .<= L)
220
+ max = nothing
221
+ for i in 1:m
222
+ if I[i] <= L[i]
223
+ x = ms[i][I[i]]
224
+ if max === nothing || max < x
225
+ max = x
226
+ end
227
+ end
228
+ end
229
+ @assert max !== nothing
230
+ # to ensure that max is no more a union
231
+ max === nothing && return X
232
+ push!(X, max)
233
+ for i in 1:m
234
+ if I[i] <= L[i] && max == ms[i][I[i]]
235
+ I[i] += 1
236
+ end
237
+ end
238
+ end
239
+ # There is no duplicate by construction
240
+ return MonomialVector{C}(buildZvarsvec(PolyVar{C}, X)...)
241
+ end
mult.jl ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function multiplyexistingvar(v::Vector{PolyVar{C}}, x::PolyVar{C}, i::Int) where {C}
2
+ updatez = z -> begin
3
+ newz = copy(z)
4
+ newz[i] += 1
5
+ newz
6
+ end
7
+ # /!\ v not copied for efficiency, do not mess up with vars
8
+ v, updatez
9
+ end
10
+ function insertvar(v::Vector{PolyVar{C}}, x::PolyVar{C}, i::Int) where {C}
11
+ n = length(v)
12
+ I = 1:i-1
13
+ J = i:n
14
+ K = J.+1
15
+ w = Vector{PolyVar{C}}(undef, n+1)
16
+ w[I] = v[I]
17
+ w[i] = x
18
+ w[K] = v[J]
19
+ updatez = z -> begin
20
+ newz = Vector{Int}(undef, n+1)
21
+ newz[I] = z[I]
22
+ newz[i] = 1
23
+ newz[K] = z[J]
24
+ newz
25
+ end
26
+ w, updatez
27
+ end
28
+
29
+ include("cmult.jl")
30
+ include("ncmult.jl")
31
+
32
+ MP.multconstant(α, x::Monomial) = Term(α, x)
33
+ MP.mapcoefficientsnz(f::Function, p::Polynomial) = Polynomial(f.(p.a), p.x)
34
+
35
+ # I do not want to cast x to TermContainer because that would force the promotion of eltype(q) with Int
36
+ function Base.:(*)(x::DMonomialLike, p::Polynomial)
37
+ # /!\ No copy of a is done
38
+ Polynomial(p.a, x*p.x)
39
+ end
40
+ function Base.:(*)(x::DMonomialLike{false}, p::Polynomial)
41
+ # /!\ No copy of a is done
42
+ # Order may change, e.g. y * (x + y) = y^2 + yx
43
+ Polynomial(monovec(p.a, [x*m for m in p.x])...)
44
+ end
45
+ function Base.:(*)(p::Polynomial, x::DMonomialLike)
46
+ # /!\ No copy of a is done
47
+ Polynomial(p.a, p.x*x)
48
+ end
49
+
50
+ function _term_poly_mult(t::Term{C, S}, p::Polynomial{C, T}, op::Function) where {C, S, T}
51
+ U = Base.promote_op(op, S, T)
52
+ if iszero(t)
53
+ zero(Polynomial{C, U})
54
+ else
55
+ n = nterms(p)
56
+ allvars, maps = mergevars([t.x.vars, p.x.vars])
57
+ nv = length(allvars)
58
+ # Necessary to annotate the type in case it is empty
59
+ Z = Vector{Int}[zeros(Int, nv) for i in 1:n]
60
+ for i in 1:n
61
+ Z[i][maps[1]] = t.x.z
62
+ Z[i][maps[2]] += p.x.Z[i]
63
+ end
64
+ Polynomial(op.(t.α, p.a), MonomialVector(allvars, Z))
65
+ end
66
+ end
67
+ Base.:(*)(p::Polynomial, t::Term) = _term_poly_mult(t, p, (α, β) -> β * α)
68
+ Base.:(*)(t::Term, p::Polynomial) = _term_poly_mult(t, p, *)
69
+ _sumprod(a, b) = a * b + a * b
70
+ function Base.:(*)(p::Polynomial{C, S}, q::Polynomial{C, T}) where {C, S, T}
71
+ U = Base.promote_op(_sumprod, S, T)
72
+ if iszero(p) || iszero(q)
73
+ zero(Polynomial{C, U})
74
+ else
75
+ samevars = _vars(p) == _vars(q)
76
+ if samevars
77
+ allvars = _vars(p)
78
+ else
79
+ allvars, maps = mergevars([_vars(p), _vars(q)])
80
+ end
81
+ N = length(p)*length(q)
82
+ Z = Vector{Vector{Int}}(undef, N)
83
+ a = Vector{U}(undef, N)
84
+ i = 0
85
+ for u in p
86
+ for v in q
87
+ if samevars
88
+ z = u.x.z + v.x.z
89
+ else
90
+ z = zeros(Int, length(allvars))
91
+ z[maps[1]] += u.x.z
92
+ z[maps[2]] += v.x.z
93
+ end
94
+ i += 1
95
+ Z[i] = z
96
+ a[i] = u.α * v.α
97
+ end
98
+ end
99
+ polynomialclean(allvars, a, Z)
100
+ end
101
+ end
ncmult.jl ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function Base.:(*)(x::PolyVar{false}, y::PolyVar{false})
2
+ if x === y
3
+ Monomial{false}([x], [2])
4
+ else
5
+ Monomial{false}([x, y], [1, 1])
6
+ end
7
+ end
8
+
9
+ function multiplyvar(v::Vector{PolyVar{false}}, z::Vector{Int}, x::PolyVar{false})
10
+ i = length(v)
11
+ while i > 0 && z[i] == 0
12
+ i -= 1
13
+ end
14
+ if v[i] == x
15
+ multiplyexistingvar(v, x, i)
16
+ else
17
+ # ---->
18
+ # \ |\ |\
19
+ # \ | \ | \
20
+ # \| \| \
21
+ # If z[i] > x, we wait either for a rise (v[i] > v[i-1]) or v[i] < x
22
+ # Otherwise, we first wait for a drop and then wait for the same thing
23
+ ndrop = 0
24
+ if v[i] > x
25
+ droplim1 = 0
26
+ droplim2 = 1
27
+ else
28
+ droplim1 = 1
29
+ droplim2 = 2
30
+ end
31
+ i += 1
32
+ while i <= length(v) && v[i] != x
33
+ if v[i] > v[i-1]
34
+ ndrop += 1
35
+ end
36
+ if ndrop >= droplim2 || (ndrop >= droplim1 && v[i] < x)
37
+ break
38
+ end
39
+ i += 1
40
+ end
41
+
42
+ if i <= length(v) && v[i] == x
43
+ multiplyexistingvar(v, x, i)
44
+ else
45
+ insertvar(v, x, i)
46
+ end
47
+ end
48
+ end
49
+ function multiplyvar(x::PolyVar{false}, v::Vector{PolyVar{false}}, z::Vector{Int})
50
+ i = 1
51
+ while i <= length(v) && z[i] == 0
52
+ i += 1
53
+ end
54
+ if v[i] == x
55
+ multiplyexistingvar(v, x, i)
56
+ else
57
+ # <----
58
+ # \ |\ |\
59
+ # \ | \ | \
60
+ # \| \| \
61
+ # If z[i] < x, we wait either for a drop (v[i] < v[i+1]) or v[i] > x
62
+ # Otherwise, we first wait for a drop and then wait for the same thing
63
+ ndrop = 0
64
+ if v[i] < x
65
+ droplim1 = 0
66
+ droplim2 = 1
67
+ else
68
+ droplim1 = 1
69
+ droplim2 = 2
70
+ end
71
+ i -= 1
72
+ while i > 0 && v[i] != x
73
+ if v[i] < v[i+1]
74
+ ndrop += 1
75
+ end
76
+ if ndrop >= droplim2 || (ndrop >= droplim1 && v[i] > x)
77
+ break
78
+ end
79
+ i -= 1
80
+ end
81
+ if i > 0 && v[i] == x
82
+ multiplyexistingvar(v, x, i)
83
+ else
84
+ insertvar(v, x, i+1)
85
+ end
86
+ end
87
+ end
88
+ function Base.:(*)(x::PolyVar{false}, y::Monomial{false})
89
+ w, updatez = multiplyvar(x, y.vars, y.z)
90
+ Monomial{false}(w, updatez(y.z))
91
+ end
92
+ function Base.:(*)(y::Monomial{false}, x::PolyVar{false})
93
+ w, updatez = multiplyvar(y.vars, y.z, x)
94
+ Monomial{false}(w, updatez(y.z))
95
+ end
96
+
97
+ function Base.:(*)(x::Monomial{false}, y::Monomial{false})
98
+ i = findlast(z -> z > 0, x.z)
99
+ if i == nothing || i == 0
100
+ return y
101
+ end
102
+ j = findfirst(z -> z > 0, y.z)
103
+ if j == nothing || j == 0
104
+ return x
105
+ end
106
+ if x.vars[i] == y.vars[j]
107
+ w = [x.vars[1:i]; y.vars[j+1:end]]
108
+ z = [x.z[1:i-1]; x.z[i] + y.z[j]; y.z[j+1:end]]
109
+ else
110
+ w = [x.vars[1:i]; y.vars[j:end]]
111
+ z = [x.z[1:i]; y.z[j:end]]
112
+ end
113
+ return Monomial{false}(w, z)
114
+ end
115
+
116
+ function Base.:(*)(y::MonomialVector{false}, x::DMonomialLike{false})
117
+ MonomialVector{false}([yi * x for yi in y])
118
+ end
119
+ function Base.:(*)(x::DMonomialLike{false}, y::MonomialVector{false})
120
+ # The order may change
121
+ # Example: y * [x^2, y^2] == [y^3, yx^2]
122
+ MonomialVector{false}([x * yi for yi in y])
123
+ end
operators.jl ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # In Base/intfuncs.jl, x^p returns zero(x) when p == 0
2
+ # Since one(PolyVar) and one(Monomial) do not return
3
+ # a PolyVar and a Monomial, this results in type instability
4
+ # Defining the specific methods solve this problem and also make
5
+ # them a lot faster
6
+ Base.:(^)(x::PolyVar{C}, i::Int) where {C} = Monomial{C}([x], [i])
7
+ Base.:(^)(x::Monomial{true}, i::Int) = Monomial{true}(x.vars, i*x.z)
8
+
9
+ myminivect(x::T, y::T) where {T} = [x, y]
10
+ function myminivect(x::S, y::T) where {S,T}
11
+ U = promote_type(S, T)
12
+ [U(x), U(y)]
13
+ end
14
+
15
+ Base.:(+)(x::DMonomialLike, y::DMonomialLike) = Term(x) + Term(y)
16
+ Base.:(-)(x::DMonomialLike, y::DMonomialLike) = Term(x) - Term(y)
17
+
18
+ _getindex(p::Polynomial, i) = p[i]
19
+ _getindex(t::Term, i) = t
20
+ function plusorminus(p::TermPoly{C, S}, q::TermPoly{C, T}, op) where {C, S, T}
21
+ varsvec = [_vars(p), _vars(q)]
22
+ allvars, maps = mergevars(varsvec)
23
+ nvars = length(allvars)
24
+ U = Base.promote_op(op, S, T)
25
+ a = Vector{U}()
26
+ Z = Vector{Vector{Int}}()
27
+ i = j = 1
28
+ while i <= nterms(p) || j <= nterms(q)
29
+ z = zeros(Int, nvars)
30
+ if j > nterms(q) || (i <= nterms(p) && _getindex(p, i).x > _getindex(q, j).x)
31
+ t = _getindex(p, i)
32
+ z[maps[1]] = t.x.z
33
+ α = convert(U, t.α)
34
+ i += 1
35
+ elseif i > nterms(p) || _getindex(q, j).x > _getindex(p, i).x
36
+ t = _getindex(q, j)
37
+ z[maps[2]] = t.x.z
38
+ α = convert(U, op(t.α))
39
+ j += 1
40
+ else
41
+ t = _getindex(p, i)
42
+ z[maps[1]] = t.x.z
43
+ s = _getindex(q, j)
44
+ α = op(t.α, s.α)
45
+ i += 1
46
+ j += 1
47
+ end
48
+ push!(a, α)
49
+ push!(Z, z)
50
+ end
51
+
52
+ Polynomial(a, MonomialVector{C}(allvars, Z))
53
+ end
54
+
55
+
56
+ Base.:(+)(x::TermPoly{C}, y::TermPoly{C}) where C = plusorminus(x, y, +)
57
+ Base.:(-)(x::TermPoly{C}, y::TermPoly{C}) where C = plusorminus(x, y, -)
58
+ Base.:(+)(x::TermPoly{C}, y::Union{Monomial,PolyVar}) where C = x + Term{C}(y)
59
+ Base.:(+)(x::Union{Monomial,PolyVar}, y::TermPoly{C}) where C = Term{C}(x) + y
60
+
61
+ Base.:(-)(x::TermPoly{T}, y::DMonomialLike) where T = x - Term{T}(y)
62
+ Base.:(-)(x::DMonomialLike, y::TermPoly{T}) where T = Term{T}(x) - y
63
+
64
+ Base.:(-)(p::Polynomial) = Polynomial(-p.a, p.x)
65
+
66
+ include("mult.jl")
poly.jl ADDED
@@ -0,0 +1,230 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export Polynomial
2
+
3
+ # Invariant:
4
+ # a and x might be empty: meaning it is the zero polynomial
5
+ # a does not contain any zeros
6
+ # x is increasing in the monomial order (i.e. grlex)
7
+ struct Polynomial{C, T} <: AbstractPolynomial{T}
8
+ a::Vector{T}
9
+ x::MonomialVector{C}
10
+
11
+ function Polynomial{C, T}(a::Vector{T}, x::MonomialVector{C}) where {C, T}
12
+ length(a) == length(x) || throw(ArgumentError("There should be as many coefficient than monomials"))
13
+ zeroidx = Int[]
14
+ for (i,α) in enumerate(a)
15
+ if iszero(α)
16
+ push!(zeroidx, i)
17
+ end
18
+ end
19
+ if !isempty(zeroidx)
20
+ isnz = ones(Bool, length(a))
21
+ isnz[zeroidx] .= false
22
+ nzidx = findall(isnz)
23
+ a = a[nzidx]
24
+ x = x[nzidx]
25
+ end
26
+ new{C, T}(a, x)
27
+ end
28
+ end
29
+
30
+ iscomm(::Type{Polynomial{C, T}}) where {C, T} = C
31
+
32
+ Base.broadcastable(p::Polynomial) = Ref(p)
33
+ Base.copy(p::Polynomial{C, T}) where {C, T} = Polynomial{C, T}(copy(p.a), copy(p.x))
34
+ Base.zero(::Type{Polynomial{C, T}}) where {C, T} = Polynomial(T[], MonomialVector{C}())
35
+ Base.one(::Type{Polynomial{C, T}}) where {C, T} = Polynomial([one(T)], MonomialVector{C}(PolyVar{C}[], [Int[]]))
36
+ Base.zero(p::Polynomial{C, T}) where {C, T} = Polynomial(T[], emptymonovec(_vars(p)))
37
+ Base.one(p::Polynomial{C, T}) where {C, T} = Polynomial([one(T)], MonomialVector(_vars(p), [zeros(Int, nvariables(p))]))
38
+
39
+ Polynomial{C, T}(a::AbstractVector, x::MonomialVector) where {C, T} = Polynomial{C, T}(Vector{T}(a), x)
40
+ Polynomial{C, T}(a::AbstractVector, X::DMonoVec) where {C, T} = Polynomial{C, T}(monovec(a, X)...)
41
+ Polynomial{C}(a::Vector{T}, x) where {C, T} = Polynomial{C, T}(a, x)
42
+ Polynomial(af::Union{Function, Vector}, x::DMonoVec{C}) where {C} = Polynomial{C}(af, x)
43
+
44
+ # TODO Remove with MP v0.2.8
45
+ Polynomial{C, T}(p::Polynomial{C, T}) where {C, T} = p
46
+
47
+ Base.convert(::Type{Polynomial{C, T}}, p::Polynomial{C, T}) where {C, T} = p
48
+ function Base.convert(::Type{Polynomial{C, T}},
49
+ p::Polynomial{C, S}) where {C, S, T}
50
+ return Polynomial{C}(convert(Vector{T}, p.a), p.x)
51
+ end
52
+ #function convert(::Type{Polynomial{C, T}},
53
+ # p::AbstractPolynomialLike) where {C, T}
54
+ # return convert(Polynomial{C, T}, polynomial(p, T))
55
+ #end
56
+ function Base.convert(::Type{Polynomial{C, T}}, t::Term{C}) where {C, T}
57
+ return Polynomial{C, T}(T[t.α], [t.x])
58
+ end
59
+ function Base.convert(::Type{Polynomial{C, T}}, m::DMonomialLike{C}) where {C, T}
60
+ return Polynomial(convert(Term{C, T}, m))
61
+ end
62
+ function MP.convertconstant(::Type{Polynomial{C, T}}, α) where {C, T}
63
+ return Polynomial(convert(Term{C, T}, α))
64
+ end
65
+
66
+ Polynomial{C}(p::Union{Polynomial{C}, Term{C}, Monomial{C}, PolyVar{C}}) where {C} = Polynomial(p)
67
+ Polynomial{C}(α) where {C} = Polynomial(Term{C}(α))
68
+
69
+ Polynomial(p::Polynomial) = p
70
+ Polynomial(t::Term{C, T}) where {C, T} = Polynomial{C, T}([t.α], [t.x])
71
+ Polynomial(x::Union{PolyVar{C}, Monomial{C}}) where {C} = Polynomial(Term{C}(x))
72
+
73
+ #Base.convert(::Type{TermContainer{C, T}}, p::Polynomial{C}) where {C, T} = Polynomial{C, T}(p)
74
+
75
+ function Polynomial{C, T}(f::Function, x::MonomialVector{C}) where {C, T}
76
+ a = T[f(i) for i in 1:length(x)]
77
+ Polynomial{C, T}(a, x)
78
+ end
79
+ function Polynomial{C, T}(f::Function, x::AbstractVector) where {C, T}
80
+ σ, X = sortmonovec(x)
81
+ a = T[f(i) for i in σ]
82
+ Polynomial{C, T}(a, X)
83
+ end
84
+ Polynomial{C}(f::Function, x) where {C} = Polynomial{C, Base.promote_op(f, Int)}(f, x)
85
+
86
+ #Base.convert(::Type{PolyType{C}}, p::TermContainer{C}) where {C} = p
87
+
88
+ # needed to build [p Q; Q p] where p is a polynomial and Q is a matpolynomial in Julia v0.5
89
+ #Base.convert(::Type{TermType{C}}, p::TermContainer{C}) where {C} = p
90
+ #Base.convert(::Type{TermType{C, T}}, p::TermContainer{C, T}) where {C, T} = p
91
+
92
+ Base.length(p::Polynomial) = length(p.a)
93
+ Base.isempty(p::Polynomial) = isempty(p.a)
94
+ Base.iterate(p::Polynomial) = isempty(p) ? nothing : (p[1], 1)
95
+ function Base.iterate(p::Polynomial, state::Int)
96
+ state < length(p) ? (p[state+1], state+1) : nothing
97
+ end
98
+ #eltype(::Type{Polynomial{C, T}}) where {C, T} = T
99
+ Base.getindex(p::Polynomial, I::Int) = Term(p.a[I[1]], p.x[I[1]])
100
+
101
+ #Base.transpose(p::Polynomial) = Polynomial(map(transpose, p.a), p.x) # FIXME invalid age range update
102
+
103
+ struct TermIterator{C, T} <: AbstractVector{Term{C, T}}
104
+ p::Polynomial{C, T}
105
+ end
106
+ Base.firstindex(p::TermIterator) = firstindex(p.p.a)
107
+ Base.lastindex(p::TermIterator) = lastindex(p.p.a)
108
+ Base.length(p::TermIterator) = length(p.p.a)
109
+ Base.size(p::TermIterator) = (length(p),)
110
+ Base.isempty(p::TermIterator) = isempty(p.p.a)
111
+ Base.iterate(p::TermIterator) = isempty(p) ? nothing : (p[1], 1)
112
+ function Base.iterate(p::TermIterator, state::Int)
113
+ state < length(p) ? (p[state+1], state+1) : nothing
114
+ end
115
+
116
+ Base.getindex(p::TermIterator, I::Int) = Term(p.p.a[I[1]], p.p.x[I[1]])
117
+
118
+ MP.terms(p::Polynomial) = TermIterator(p)
119
+ MP.coefficients(p::Polynomial) = p.a
120
+ MP.monomials(p::Polynomial) = p.x
121
+ _vars(p::Polynomial) = _vars(p.x)
122
+
123
+ MP.extdegree(p::Polynomial) = extdegree(p.x)
124
+ MP.mindegree(p::Polynomial) = mindegree(p.x)
125
+ MP.maxdegree(p::Polynomial) = maxdegree(p.x)
126
+
127
+ MP.leadingcoefficient(p::Polynomial{C, T}) where {C, T} = iszero(p) ? zero(T) : first(p.a)
128
+ MP.leadingmonomial(p::Polynomial) = iszero(p) ? constantmonomial(p) : first(p.x)
129
+ MP.leadingterm(p::Polynomial) = iszero(p) ? zeroterm(p) : first(terms(p))
130
+
131
+ function MP.removeleadingterm(p::Polynomial)
132
+ Polynomial(p.a[2:end], p.x[2:end])
133
+ end
134
+ function MP.removemonomials(p::Polynomial, x::MonomialVector)
135
+ # use the fact that monomials are sorted to do this O(n) instead of O(n^2)
136
+ j = 1
137
+ I = Int[]
138
+ for (i,t) in enumerate(p)
139
+ while j <= length(x) && x[j] > t.x
140
+ j += 1
141
+ end
142
+ if j > length(x) || x[j] != t.x
143
+ push!(I, i)
144
+ end
145
+ end
146
+ Polynomial(p.a[I], p.x[I])
147
+ end
148
+ MP.removemonomials(p::Polynomial, x::Vector) = removemonomials(p, MonomialVector(x))
149
+
150
+ function removedups(adup::Vector{T}, Zdup::Vector{Vector{Int}}) where {T}
151
+ σ = sortperm(Zdup, rev=true, lt=grlex)
152
+ Z = Vector{Vector{Int}}()
153
+ a = Vector{T}()
154
+ i = 0
155
+ j = 1
156
+ while j <= length(adup)
157
+ k = σ[j]
158
+ if j == 1 || Zdup[k] != Zdup[σ[j-1]]
159
+ push!(Z, Zdup[k])
160
+ push!(a, adup[k])
161
+ i += 1
162
+ else
163
+ a[i] += adup[k]
164
+ end
165
+ j += 1
166
+ end
167
+ a, Z
168
+ end
169
+ function polynomialclean(vars::Vector{PolyVar{C}}, adup::Vector{T}, Zdup::Vector{Vector{Int}}) where {C, T}
170
+ a, Z = removedups(adup, Zdup)
171
+ Polynomial{C, T}(a, MonomialVector{C}(vars, Z))
172
+ end
173
+
174
+ MP.polynomial(a::AbstractVector, x::DMonoVec, s::MP.ListState) = Polynomial(collect(a), x)
175
+
176
+ #MP.polynomial(f::Function, x::AbstractVector) = Polynomial(f, x)
177
+ #MP.polynomial(ts::AbstractVector{Term{C, T}}) where {C, T} = Polynomial(coefficient.(ts), monomial.(ts)) # FIXME invalid age range update
178
+
179
+ # i < j
180
+ function trimap(i, j, n)
181
+ div(n*(n+1), 2) - div((n-i+1)*(n-i+2), 2) + j-i+1
182
+ end
183
+ MP.polynomial(Q::AbstractMatrix{T}, mv::MonomialVector) where T = MP.polynomial(Q, mv, Base.promote_op(+, T, T))
184
+ function MP.polynomial(Q::AbstractMatrix, mv::MonomialVector{C}, ::Type{T}) where {C, T}
185
+ if isempty(Q)
186
+ zero(Polynomial{C, T})
187
+ else
188
+ n = length(mv)
189
+ if C
190
+ N = trimap(n, n, n)
191
+ Z = Vector{Vector{Int}}(undef, N)
192
+ a = Vector{T}(undef, N)
193
+ for i in 1:n
194
+ for j in i:n
195
+ k = trimap(i, j, n)
196
+ Z[k] = mv.Z[i] + mv.Z[j]
197
+ if i == j
198
+ a[k] = Q[i, j]
199
+ else
200
+ a[k] = Q[i, j] + Q[j, i]
201
+ end
202
+ end
203
+ end
204
+ v = _vars(mv)
205
+ else
206
+ N = n^2
207
+ x = Vector{Monomial{C}}(undef, N)
208
+ a = Vector{T}(undef, N)
209
+ offset = 0
210
+ for i in 1:n
211
+ # for j in 1:n wouldn't be cache friendly for Q
212
+ for j in i:n
213
+ k = trimap(i, j, n)
214
+ q = Q[i, j]
215
+ x[offset+k] = mv[i] * mv[j]
216
+ a[offset+k] = q
217
+ if i != j
218
+ offset += 1
219
+ x[offset+k] = mv[j] * mv[i]
220
+ a[offset+k] = q
221
+ end
222
+ end
223
+ end
224
+ a, X = monovec(a, x)
225
+ v = _vars(X)
226
+ Z = X.Z
227
+ end
228
+ polynomialclean(v, a, Z)
229
+ end
230
+ end
promote.jl ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Promotion with PolyVar and Monomial
2
+ Base.promote_rule(::Type{PolyVar{C}}, ::Type{PolyVar{C}}) where {C} = PolyVar{C}
3
+ Base.promote_rule(::Type{<:DMonomialLike{C}}, ::Type{<:DMonomialLike{C}}) where {C} = Monomial{C}
4
+ #promote_rule{S<:Union{Monomial, PolyVar}, T<:Union{Monomial, PolyVar}}(::Type{S}, ::Type{T}) = Monomial{iscomm{S}}
5
+
6
+ Base.promote_rule(::Type{Polynomial{C, S}}, ::Type{Polynomial{C, T}}) where {S, C, T} = Polynomial{C, promote_type(S, T)}
7
+ Base.promote_rule(::Type{<:AbstractPolynomialLike{S}}, ::Type{Polynomial{C, T}}) where {S, C, T} = Polynomial{C, promote_type(S, T)}
8
+ Base.promote_rule(::Type{Polynomial{C, T}}, ::Type{<:AbstractPolynomialLike{S}}) where {S, C, T} = Polynomial{C, promote_type(S, T)}
9
+ Base.promote_rule(::Type{<:DMonomialLike{S}}, ::Type{Polynomial{C, T}}) where {S, C, T} = Polynomial{C, promote_type(T, Int)}
10
+ Base.promote_rule(::Type{Polynomial{C, T}}, ::Type{<:DMonomialLike{S}}) where {S, C, T} = Polynomial{C, promote_type(T, Int)}
11
+
12
+ MP.promote_rule_constant(::Type{T}, ::Type{<:DMonomialLike{C}}) where {C, T} = Term{C, promote_type(T, Int)}
13
+ MP.promote_rule_constant(::Type{S}, ::Type{Term{C, T}}) where {S, C, T} = Term{C, promote_type(S, T)}
14
+ MP.promote_rule_constant(::Type{S}, ::Type{<:TermPoly{C, T}}) where {S, C, T} = Polynomial{C, promote_type(S, T)}
15
+
16
+ # Promotion with Term
17
+ Base.promote_rule(::Type{Term{C, S}}, ::Type{Term{C, T}}) where {C,S,T} = Term{C, promote_type(S, T)}
18
+ Base.promote_rule(::Type{<:DMonomialLike{C}}, ::Type{Term{C, T}}) where {C,T} = Term{C, promote_type(T, Int)}
19
+ Base.promote_rule(::Type{Term{C, T}}, ::Type{<:DMonomialLike{C}}) where {C,T} = Term{C, promote_type(T, Int)}
20
+
21
+ # Promotion with Polynomial
22
+ #Base.promote_rule(::Type{Polynomial{C, S}}, ::Type{Term{C, T}}) where {C, S, T} = Polynomial{C, promote_type(S, T)}
23
+ #Base.promote_rule(::Type{Term{C, T}}, ::Type{Polynomial{C, S}}) where {C, S, T} = Polynomial{C, promote_type(S, T)}
24
+
25
+ #Base.promote_rule(::Type{<:TermPoly{C, S}}, ::Type{<:TermPoly{C, T}}) where {C, S, T} = Polynomial{C, promote_type(S, T)}
26
+ #Base.promote_rule(::Type{<:TermPoly{C, T}}, ::Type{<:DMonomialLike{C}}) where {C, T} = Polynomial{C, promote_type(T, Int)}
27
+ #Base.promote_rule(::Type{<:DMonomialLike{C}}, ::Type{<:TermPoly{C, T}}) where {C, T} = Polynomial{C, promote_type(T, Int)}
staDynBenignLab.csv ADDED
The diff for this file is too large to render. See raw diff
 
staDynVt2955Lab.csv ADDED
The diff for this file is too large to render. See raw diff
 
staDynVxHeaven2698Lab.csv ADDED
The diff for this file is too large to render. See raw diff
 
subs.jl ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function fillmap!(vals, vars, s::MP.Substitution)
2
+ j = findfirst(isequal(s.first), vars)
3
+ if j !== nothing
4
+ vals[j] = s.second
5
+ end
6
+ end
7
+ function fillmap!(vals, vars, s::MP.AbstractMultiSubstitution)
8
+ for (v, x) in zip(s.first, s.second)
9
+ fillmap!(vals, vars, v => x)
10
+ end
11
+ end
12
+
13
+ function fillmap!(vals, vars, s1::MP.AbstractSubstitution, s2::MP.AbstractSubstitution...)
14
+ fillmap!(vals, vars, s1)
15
+ fillmap!(vals, vars, s2...)
16
+ end
17
+
18
+ _eltype(::T) where {T} = T
19
+ _eltype(t::Tuple) = Base.promote_typeof(t...)
20
+ _eltype(::Tuple{Vararg{T}}) where {T} = T
21
+ _eltype(::AbstractVector{T}) where {T} = T
22
+ _substype(s::MP.AbstractSubstitution) = _eltype(s.second)
23
+ _substype(s1::MP.AbstractSubstitution, s2::MP.AbstractSubstitution...) = promote_type(_substype(s1), _substype(s2...))
24
+ _substype(s::MP.Substitutions) = _substype(s...)
25
+
26
+ function _subsmap(::MP.Eval, vars, s::MP.Substitutions)
27
+ # Every variable will be replaced by some value of type T
28
+ vals = Vector{_substype(s)}(undef, length(vars))
29
+ fillmap!(vals, vars, s...)
30
+ for i in 1:length(vals)
31
+ @assert isassigned(vals, i) "Variable $(vars[i]) was not assigned a value"
32
+ end
33
+ vals
34
+ end
35
+ function _subsmap(::MP.Subs, vars::Vector{PolyVar{C}}, s::MP.Substitutions) where {C}
36
+ # Some variable may not be replaced
37
+ vals = Vector{promote_type(_substype(s), PolyVar{C})}(undef, length(vars))
38
+ copyto!(vals, vars)
39
+ fillmap!(vals, vars, s...)
40
+ vals
41
+ end
42
+
43
+ subsmap(st, vars, s::MP.Substitutions) = _subsmap(st, vars, s)
44
+ _vec(a::AbstractVector) = a
45
+ _vec(a::Tuple) = [a...]
46
+ function subsmap(st, vars, s::Tuple{MP.VectorMultiSubstitution})
47
+ if vars === s[1].first || vars == s[1].first # shortcut, === happens when the user do p(variables(p) => ...)
48
+ _vec(s[1].second)
49
+ else
50
+ _subsmap(st, vars, s)
51
+ end
52
+ end
53
+
54
+ function monoeval(z::Vector{Int}, vals::AbstractVector)
55
+ @assert length(z) == length(vals)
56
+ @assert !isempty(z)
57
+ val = vals[1]^z[1]
58
+ for i in 2:length(vals)
59
+ if z[i] > 0
60
+ val *= vals[i]^z[i]
61
+ end
62
+ end
63
+ val
64
+ end
65
+
66
+ _subs(st, ::PolyVar, vals) = monoeval([1], vals::AbstractVector)
67
+ _subs(st, m::Monomial, vals) = monoeval(m.z, vals::AbstractVector)
68
+ _subs(st, t::Term, vals) = t.α * monoeval(t.x.z, vals::AbstractVector)
69
+ function _subs(::MP.Eval, p::Polynomial{C, T}, vals::AbstractVector{S}) where {C, T, S}
70
+ # I need to check for iszero otherwise I get : ArgumentError: reducing over an empty collection is not allowed
71
+ if iszero(p)
72
+ zero(Base.promote_op(*, S, T))
73
+ else
74
+ sum(i -> p.a[i] * monoeval(p.x.Z[i], vals), 1:length(p))
75
+ end
76
+ end
77
+ function _subs(::MP.Subs, p::Polynomial{C, T}, vals::AbstractVector{S}) where {C, T, S}
78
+ Tout = Base.promote_op(*, T, MP.coefficienttype(S))
79
+ # I need to check for iszero otherwise I get : ArgumentError: reducing over an empty collection is not allowed
80
+ if iszero(p)
81
+ zero(Polynomial{C, Tout})
82
+ else
83
+ convert(Polynomial{C, Tout}, sum(i -> p.a[i] * monoeval(p.x.Z[i], vals), 1:length(p)))
84
+ end
85
+
86
+ end
87
+
88
+ function MP.substitute(st::MP.AbstractSubstitutionType, p::PolyType, s::MP.Substitutions)
89
+ _subs(st, p, subsmap(st, _vars(p), s))
90
+ end
91
+
92
+ (v::PolyVar)(s::MP.AbstractSubstitution...) = MP.substitute(MP.Eval(), v, s)
93
+ (m::Monomial)(s::MP.AbstractSubstitution...) = MP.substitute(MP.Eval(), m, s)
94
+ (t::Term)(s::MP.AbstractSubstitution...) = MP.substitute(MP.Eval(), t, s)
95
+ (p::Polynomial)(s::MP.AbstractSubstitution...) = MP.substitute(MP.Eval(), p, s)
96
+
97
+ (p::PolyVar)(x::Number) = x
98
+ (p::Monomial)(x::NTuple{N, <:Number}) where N = MP.substitute(MP.Eval(), p, variables(p)=>x)
99
+ (p::Monomial)(x::AbstractVector{<:Number}) = MP.substitute(MP.Eval(), p, variables(p)=>x)
100
+ (p::Monomial)(x::Number...) = MP.substitute(MP.Eval(), p, variables(p)=>x)
101
+ (p::Term)(x::NTuple{N, <:Number}) where N = MP.substitute(MP.Eval(), p, variables(p)=>x)
102
+ (p::Term)(x::AbstractVector{<:Number}) = MP.substitute(MP.Eval(), p, variables(p)=>x)
103
+ (p::Term)(x::Number...) = MP.substitute(MP.Eval(), p, variables(p)=>x)
104
+ (p::Polynomial)(x::NTuple{N, <:Number}) where N = MP.substitute(MP.Eval(), p, variables(p)=>x)
105
+ (p::Polynomial)(x::AbstractVector{<:Number}) = MP.substitute(MP.Eval(), p, variables(p)=>x)
106
+ (p::Polynomial)(x::Number...) = MP.substitute(MP.Eval(), p, variables(p)=>x)
term.jl ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export Term
2
+
3
+ struct Term{C, T} <: AbstractTerm{T}
4
+ α::T
5
+ x::Monomial{C}
6
+ end
7
+
8
+ iscomm(::Type{Term{C, T}}) where {C, T} = C
9
+
10
+ Base.convert(::Type{Term{C, T}}, t::Term{C, T}) where {C, T} = t
11
+ function Base.convert(::Type{Term{C, T}}, t::Term{C}) where {C, T}
12
+ return Term{C, T}(T(t.α), t.x)
13
+ end
14
+ Term(t::Term) = t
15
+
16
+ function Base.convert(::Type{Term{C, T}}, x::Monomial{C}) where {C, T}
17
+ return Term{C, T}(one(T), x)
18
+ end
19
+ Term{C}(x::Monomial{C}) where C = convert(Term{C, Int}, x)
20
+ Term(x::Monomial{C}) where C = Term{C}(x)
21
+
22
+ function Base.convert(::Type{Term{C, T}}, x::PolyVar{C}) where {C, T}
23
+ return convert(Term{C, T}, convert(Monomial{C}, x))
24
+ end
25
+ Term{C}(x::PolyVar{C}) where C = Term{C}(convert(Monomial{C}, x))
26
+ Term(x::PolyVar{C}) where C = Term{C}(x)
27
+
28
+ function MP.convertconstant(::Type{Term{C, T}}, α) where {C, T}
29
+ return Term{C}(convert(T, α))
30
+ end
31
+ Term{C}(α::T) where {C, T} = Term{C, T}(α, Monomial{C}())
32
+
33
+ Base.broadcastable(t::Term) = Ref(t)
34
+ #(::Type{TermContainer{C}}){C}(x::PolyVar{C}) = Term(x)
35
+ #(::Type{TermContainer{C}}){C}(x::Monomial{C}) = Term(x)
36
+ #(::Type{TermContainer{C}}){C}(t::TermContainer{C}) = t
37
+ #TermContainer(x::PolyVar) = Term(x)
38
+ #TermContainer(x::Monomial) = Term(x)
39
+ #TermContainer(t::TermContainer) = t
40
+
41
+ #Base.convert{C, T}(::Type{TermContainer{C, T}}, x::Union{Monomial{C},PolyVar{C}}) = Term{C, T}(x)
42
+ #Base.convert{C, T}(::Type{TermContainer{C, T}}, α::T) = Term{C, T}(α, Monomial{C}())
43
+ #Base.convert{C, S, T}(::Type{TermContainer{C, T}}, α::S) = TermContainer{C, T}(T(α))
44
+ #(::Type{TermContainer{C}}){C, T}(α::T) = TermContainer{C, T}(α)
45
+
46
+ #Base.convert{C, T}(::Type{TermContainer{C, T}}, t::Term{C}) = Term{C, T}(t)
47
+
48
+ Base.copy(t::T) where {T<:Term} = T(copy(t.α), copy(t.x))
49
+
50
+ MP.coefficient(t::Term) = t.α
51
+ MP.monomial(t::Term) = t.x
52
+ _vars(t) = _vars(t.x)
var.jl ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export PolyVar, @polyvar, @ncpolyvar
2
+ export polyvecvar
3
+
4
+
5
+ function polyarrayvar(::Type{PV}, prefix, indices...) where {PV}
6
+ map(i -> PV("$(prefix)[$(join(i, ","))]"), Iterators.product(indices...))
7
+ end
8
+
9
+ function buildpolyvar(::Type{PV}, var) where {PV}
10
+ if isa(var, Symbol)
11
+ var, :($(esc(var)) = $PV($"$var"))
12
+ else
13
+ isa(var, Expr) || error("Expected $var to be a variable name")
14
+ Base.Meta.isexpr(var, :ref) || error("Expected $var to be of the form varname[idxset]")
15
+ (2 ≤ length(var.args)) || error("Expected $var to have at least one index set")
16
+ varname = var.args[1]
17
+ prefix = string(varname)
18
+ varname, :($(esc(varname)) = polyarrayvar($PV, $prefix, $(esc.(var.args[2:end])...)))
19
+ end
20
+ end
21
+
22
+ function buildpolyvars(::Type{PV}, args) where {PV}
23
+ vars = Symbol[]
24
+ exprs = []
25
+ for arg in args
26
+ var, expr = buildpolyvar(PV, arg)
27
+ push!(vars, var)
28
+ push!(exprs, expr)
29
+ end
30
+ vars, exprs
31
+ end
32
+
33
+ # Variable vector x returned garanteed to be sorted so that if p is built with x then vars(p) == x
34
+ macro polyvar(args...)
35
+ vars, exprs = buildpolyvars(PolyVar{true}, args)
36
+ :($(foldl((x,y) -> :($x; $y), exprs, init=:())); $(Expr(:tuple, esc.(vars)...)))
37
+ end
38
+
39
+ macro ncpolyvar(args...)
40
+ vars, exprs = buildpolyvars(PolyVar{false}, args)
41
+ :($(foldl((x,y) -> :($x; $y), exprs, init=:())); $(Expr(:tuple, esc.(vars)...)))
42
+ end
43
+
44
+ struct PolyVar{C} <: AbstractVariable
45
+ id::Int
46
+ name::String
47
+
48
+ function PolyVar{C}(name::AbstractString) where {C}
49
+ # gensym returns something like Symbol("##42")
50
+ # we first remove "##" and then parse it into an Int
51
+ id = parse(Int, string(gensym())[3:end])
52
+ new(id, convert(String, name))
53
+ end
54
+ end
55
+
56
+ Base.hash(x::PolyVar, u::UInt) = hash(x.id, u)
57
+ Base.broadcastable(x::PolyVar) = Ref(x)
58
+
59
+ MP.name(v::PolyVar) = v.name
60
+ function MP.name_base_indices(v::PolyVar)
61
+ splits = split(v.name, r"[\[,\]]\s*", keepempty=false)
62
+ if length(splits) == 1
63
+ return v.name, Int[]
64
+ else
65
+ return splits[1], parse.(Int, splits[2:end])
66
+ end
67
+ end
68
+
69
+ MP.monomial(v::PolyVar) = Monomial(v)
70
+ _vars(v::PolyVar) = [v]
71
+
72
+ iscomm(::Type{PolyVar{C}}) where {C} = C
73
+
74
+ function mergevars(varsvec::Vector{Vector{PV}}) where {PV<:PolyVar}
75
+ n = length(varsvec)
76
+ is = ones(Int, n)
77
+ maps = zeros.(Int, length.(varsvec))
78
+ nonempty = BitSet(findall(!isempty, varsvec))
79
+ vars = Vector{PV}()
80
+ while !isempty(nonempty)
81
+ imin = 0
82
+ for i in nonempty
83
+ if imin == 0 || varsvec[i][is[i]] > varsvec[imin][is[imin]]
84
+ imin = i
85
+ end
86
+ end
87
+ var = varsvec[imin][is[imin]]
88
+ push!(vars, var)
89
+ for i in nonempty
90
+ if var == varsvec[i][is[i]]
91
+ maps[i][is[i]] = length(vars)
92
+ if is[i] == length(varsvec[i])
93
+ pop!(nonempty, i)
94
+ else
95
+ is[i] += 1
96
+ end
97
+ end
98
+ end
99
+ end
100
+ vars, maps
101
+ end