juliapolyhedra / qhull.jl Goto Github PK
View Code? Open in Web Editor NEWA Julia wrapper around a PyCall wrapper around the qhull Convex Hull library
License: Other
A Julia wrapper around a PyCall wrapper around the qhull Convex Hull library
License: Other
p = rand(10,3)
ch = chull(p)
Throws an error that dimensions do not match.
This package seems not upgraded to Julia 1.0, is there any plan to do it?
This Julia code consistently takes more than 5s for me:
using LinearAlgebra
using QHull
function gen_on_unit_sphere(n::Int)
x = randn(n, 3)
x ./ norm.(eachrow(x))
end
function benchmark(n::Int)
points = gen_on_unit_sphere(n)
@time hull = chull(points)
@assert length(hull.vertices) == n
end
for trial=1:3
benchmark(10000) # ~5-10s
end
#=
5.353007 seconds (655.40 k allocations: 22.665 MiB)
5.631815 seconds (655.37 k allocations: 22.665 MiB, 0.57% gc time)
6.718458 seconds (655.31 k allocations: 22.664 MiB)
=#
but this equivalent Python takes less than 0.5s:
#%%
import time
import numpy as np
from scipy.spatial import ConvexHull
def gen_on_unit_sphere(N):
points = np.random.randn(int(N), 3)
points /= np.linalg.norm(points, axis=1, keepdims=True)
return points
def benchmark(N):
for trial in range(10):
points = gen_on_unit_sphere(N)
start = time.time()
hull = ConvexHull(points)
end = time.time()
assert len(hull.vertices) == N
print(end - start) # ~ 0.1s
benchmark(10000)
"""
0.10167193412780762
0.10614609718322754
0.06934404373168945
0.132598876953125
0.4867589473724365
0.12485194206237793
0.07023811340332031
0.1384291648864746
0.1513369083404541
0.21898388862609863
"""
Any idea what could explain the difference? I'm running the Python code with the same conda env used to build the Julia package.
I am getting this error with Julia 0.6.4 under Windows 10:
julia> Pkg.add("QHull")
ERROR: unknown package QHull
macro expansion at .\pkg\entry.jl:53 [inlined]
(::Base.Pkg.Entry.##1#3{String,Base.Pkg.Types.VersionSet})() at .\task.jl:335
Stacktrace:
[1] sync_end() at .\task.jl:287
[2] macro expansion at .\task.jl:303 [inlined]
[3] add(::String, ::Base.Pkg.Types.VersionSet) at .\pkg\entry.jl:51
[4] (::Base.Pkg.Dir.##4#7{Array{Any,1},Base.Pkg.Entry.#add,Tuple{String}})() at .\pkg\dir.jl:36
[5] cd(::Base.Pkg.Dir.##4#7{Array{Any,1},Base.Pkg.Entry.#add,Tuple{String}}, ::String) at .\file.jl:59
[6] #cd#1(::Array{Any,1}, ::Function, ::Function, ::String, ::Vararg{String,N} where N) at .\pkg\dir.jl:36
Any ideas?
cc @cynddl
Running the package on Julia 1.1, I get a lot of deprecation warnings:
$ cat qhull-test.jl
using QHull
points = rand(10, 2)
hull = chull(points)
display(hull)
$ julia qhull-test.jl
┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.
│ caller = chull(::Array{Float64,2}) at QHull.jl:34
└ @ QHull ~/.julia/packages/QHull/yeRSS/src/QHull.jl:34
┌ Warning: `getindex(o::PyObject, s::AbstractString)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o."s"` instead of `o["s"]`.
│ caller = chull(::Array{Float64,2}) at QHull.jl:35
└ @ QHull ~/.julia/packages/QHull/yeRSS/src/QHull.jl:35
┌ Warning: `getindex(o::PyObject, s::AbstractString)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o."s"` instead of `o["s"]`.
│ caller = chull(::Array{Float64,2}) at QHull.jl:36
└ @ QHull ~/.julia/packages/QHull/yeRSS/src/QHull.jl:36
┌ Warning: `getindex(o::PyObject, s::AbstractString)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o."s"` instead of `o["s"]`.
│ caller = chull(::Array{Float64,2}) at QHull.jl:38
└ @ QHull ~/.julia/packages/QHull/yeRSS/src/QHull.jl:38
┌ Warning: `getindex(o::PyObject, s::AbstractString)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o."s"` instead of `o["s"]`.
│ caller = chull(::Array{Float64,2}) at QHull.jl:42
└ @ QHull ~/.julia/packages/QHull/yeRSS/src/QHull.jl:42
┌ Warning: `getindex(o::PyObject, s::AbstractString)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o."s"` instead of `o["s"]`.
│ caller = chull(::Array{Float64,2}) at QHull.jl:43
└ @ QHull ~/.julia/packages/QHull/yeRSS/src/QHull.jl:43
┌ Warning: `getindex(o::PyObject, s::AbstractString)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o."s"` instead of `o["s"]`.
│ caller = chull(::Array{Float64,2}) at QHull.jl:44
└ @ QHull ~/.julia/packages/QHull/yeRSS/src/QHull.jl:44
Convex Hull of 10 points in 2 dimensions
Hull segment vertex indices:
[4, 8, 6, 3, 9]
Points on convex hull in original order:
[0.14431 0.70416; 0.874876 0.0934001; 0.561833 0.871743; 0.842075 0.889761; 0.192936 0.0327743]
$ julia --version
julia version 1.1.0
I assume that getindex
methods with ::PyObject
come from the function calls to the python package.
#19 might therefore fix this indirectly.
After #40 is resolved, calling chull
on 1000 points on the unit sphere takes less than 0.02s, but doing the same using
p = polyhedron(v, QHull.Library())
# Removing redundant points, i.e. points which are in the interior of the convex hull
removevredundancy!(p)
# Show remaining points, i.e. the non-redundant ones
@show vrep(p)
# Show the H-representation, the facets describing the polytope
@show hrep(p)
takes more than 5s due to this line taking time quadratic in the number of half-spaces just to remove duplicate half-spaces:
Line 94 in 391da0c
Is there a version of removeduplicates
that runs in near-linear time?
Still concerning the notebook of the previous issue:
Originally posted by @ferrolho in #27 (comment)
The value computed and stored for p3
is incorrect:
julia> @show volume(p1) volume(p2) volume(p3);
volume(p1) = 1.0
volume(p2) = 1.0
volume(p3) = 85.33333333333336
This is still related to the H-rep, as demonstrated by the following snippets:
julia> volume(polyhedron(hrep(p3), lib))
85.33333333333336
Constructing a new polyhedron from the V-rep yields the correct volume of the convex set:
julia> volume(polyhedron(vrep(p3), lib))
0.125
I am not being able to:
vrep(intersect(p1, p2))
removehredundancy!(p1)
hchebyshevcenter(p1)
Apparently, all of the above are, at some point, calling hchebyshevcenter
, and thus failing.
Here is a notebook with a MWE:
And here is the output of the solver when calling vrep(p3)
with p1
and p2
having been built using QHull
with KNITRO (as opposed to GLPK, in the notebook above):
=======================================
Academic License
(NOT FOR COMMERCIAL USE)
Artelys Knitro 12.0.0
=======================================
Knitro presolve eliminated 0 variables and 0 constraints.
datacheck: 0
hessian_no_f: 1
The problem is identified as an LP.
Knitro changing algorithm from AUTO to 1.
Knitro changing bar_initpt from AUTO to 1.
Knitro changing bar_murule from AUTO to 4.
Knitro changing bar_penaltycons from AUTO to 0.
Knitro changing bar_penaltyrule from AUTO to 2.
Knitro changing bar_switchrule from AUTO to 2.
Knitro changing linesearch from AUTO to 1.
Knitro changing linsolver from AUTO to 2.
Problem Characteristics ( Presolved)
-----------------------
Objective goal: Maximize
Objective type: linear
Number of variables: 28 ( 28)
bounded below only: 25 ( 25)
bounded above only: 0 ( 0)
bounded below and above: 0 ( 0)
fixed: 0 ( 0)
free: 3 ( 3)
Number of constraints: 48 ( 48)
linear equalities: 0 ( 0)
quadratic equalities: 0 ( 0)
gen. nonlinear equalities: 0 ( 0)
linear one-sided inequalities: 48 ( 48)
quadratic one-sided inequalities: 0 ( 0)
gen. nonlinear one-sided inequalities: 0 ( 0)
linear two-sided inequalities: 0 ( 0)
quadratic two-sided inequalities: 0 ( 0)
gen. nonlinear two-sided inequalities: 0 ( 0)
Number of nonzeros in Jacobian: 96 ( 96)
Number of nonzeros in Hessian: 0 ( 0)
Iter Objective FeasError OptError ||Step|| CGits
-------- -------------- ---------- ---------- ---------- -------
0 0.000000e+00 1.500e+00
10 -2.956290e+00 2.956e+00 3.078e+00 5.167e+00 0
20 -1.208565e+04 1.209e+04 2.024e+04 2.745e+04 0
30 -3.333331e-01 3.889e-01 3.889e-01 2.167e-07 5
40 -2.558210e+00 2.558e+00 2.558e+00 1.051e-01 0
50 -1.891607e+02 1.892e+02 1.892e+02 1.928e+02 0
60 -3.691123e-01 4.060e-01 4.060e-01 2.731e-01 0
70 -3.339335e-01 3.887e-01 3.887e-01 3.753e-04 4
79 1.323388e-10 7.500e-01 7.500e-01 1.173e-04 0
EXIT: Convergence to an infeasible point. Problem appears to be locally
infeasible. If problem is believed to be feasible, try multistart
to search for feasible points, or decrease infeastol.
Final Statistics
----------------
Final objective value = 1.32338787650762e-10
Final feasibility error (abs / rel) = 7.50e-01 / 5.00e-01
Final optimality error (abs / rel) = 7.50e-01 / 7.50e-01
# of iterations = 79
# of CG iterations = 45
# of function evaluations = 0
# of gradient evaluations = 0
# of Hessian evaluations = 0
Total program time (secs) = 0.00757 ( 0.008 CPU time)
Time spent in evaluations (secs) = 0.00000
===============================================================================
Solver returned LOCALLY_INFEASIBLE when computing the H-Chebyshev center.
Stacktrace:
[1] error(::String) at ./error.jl:33
[2] hchebyshevcenter(::MixedMatHRep{Float64,Array{Float64,2}}, ::OptimizerFactory) at /home/henrique/.julia/dev/Polyhedra/src/center.jl:35
[3] chebyshevcenter at /home/henrique/.julia/dev/Polyhedra/src/center.jl:74 [inlined]
[4] qhull(::MixedMatHRep{Float64,Array{Float64,2}}, ::OptimizerFactory) at /home/henrique/.julia/packages/QHull/kgHQK/src/polyhedron.jl:101
[5] qhull(::QHull.Polyhedron, ::Symbol) at /home/henrique/.julia/packages/QHull/kgHQK/src/polyhedron.jl:70
[6] qhull(::QHull.Polyhedron) at /home/henrique/.julia/packages/QHull/kgHQK/src/polyhedron.jl:61
[7] getext at /home/henrique/.julia/packages/QHull/kgHQK/src/polyhedron.jl:165 [inlined]
[8] vrep(::QHull.Polyhedron) at /home/henrique/.julia/packages/QHull/kgHQK/src/polyhedron.jl:209
[9] top-level scope at In[36]:1
julia> using QHull, Polyhedra
julia> v = vrep([x y])
V-representation MixedMatVRep{Float64, Matrix{Float64}}:
4-element iterator of Vector{Float64}:
[0.0, 0.0]
[0.0, 1.0]
[1.0, 0.0]
[0.1, 0.1]
julia> p = polyhedron(v, QHull.Library())
Polyhedron QHull.Polyhedron:
4-element iterator of Vector{Float64}:
[0.0, 0.0]
[0.0, 1.0]
[1.0, 0.0]
[0.1, 0.1]
julia> removevredundancy!(p)
ERROR: ArgumentError: ref of NULL PyObject
Stacktrace:
[1] _getproperty
@ ~/.julia/packages/PyCall/BD546/src/PyCall.jl:299 [inlined]
[2] __getproperty(o::PyCall.PyObject, s::Symbol)
@ PyCall ~/.julia/packages/PyCall/BD546/src/PyCall.jl:306
[3] getproperty
@ ~/.julia/packages/PyCall/BD546/src/PyCall.jl:312 [inlined]
[4] chull(x::Matrix{Float64})
@ QHull ~/.julia/packages/QHull/iY1Yu/src/QHull.jl:34
[5] qhull(h::MixedMatVRep{Float64, Matrix{Float64}}, solver::Nothing)
@ QHull ~/.julia/packages/QHull/iY1Yu/src/polyhedron.jl:84
[6] qhull(p::QHull.Polyhedron, rep::Symbol)
@ QHull ~/.julia/packages/QHull/iY1Yu/src/polyhedron.jl:62
[7] removevredundancy!(p::QHull.Polyhedron)
@ QHull ~/.julia/packages/QHull/iY1Yu/src/polyhedron.jl:202
[8] top-level scope
@ REPL[34]:1
Start an clean enviroment with only QHull
(julia) pkg> st
Status `~/sandbox/julia/Project.toml`
[a8468747] QHull v0.2.1
Then try to add StaticArrays
(julia) pkg> add StaticArrays
Resolving package versions...
Updating `~/sandbox/julia/Project.toml`
[90137ffa] + StaticArrays v0.12.5
No Changes to `~/sandbox/julia/Manifest.toml`
It can be seen that StaticArrays version 0.12.5 is installed by default.
Try to add StaticArrays current version will fail as
(julia) pkg> add [email protected]
Resolving package versions...
ERROR: Unsatisfiable requirements detected for package StaticArrays [90137ffa]:
StaticArrays [90137ffa] log:
├─possible versions are: 0.8.0-1.2.13 or uninstalled
├─restricted to versions 1.2.13 by an explicit requirement, leaving only versions 1.2.13
└─restricted by compatibility requirements with QHull [a8468747] to versions: 0.8.0-0.12.5 — no versions left
└─QHull [a8468747] log:
├─possible versions are: 0.0.1-0.2.1 or uninstalled
└─restricted to versions * by an explicit requirement, leaving only versions 0.0.1-0.2.1
For a polyhedron p
using QHull.Library()
, the following line of code returns Nothing
:
julia> typeof(Polyhedra.default_solver(p))
Nothing
I am not entirely sure this is the root cause of the issue, but look at the following notebook showing MethodError: no method matching Model(::Nothing)
when a V-rep is requested from a H-rep:
Hey there,
I use this in one of my packages and this dependency makes a little bit trouble during the installation / first use. On two of my colleagues systems (both Linux) I had to update the scipy version to get this working since Julia choose their global Python toolchain.
To avoid these kinds of problems, maybe we should instead wrap qhull directly? Or do you have other ideas to get the installation process more stable?
I was just wondering, wouldn't the name Qhull.jl
be more helpful for this package since it is a wrapper for the Qhull library ?
@JuliaRegistrator register()
This issue is used to trigger TagBot; feel free to unsubscribe.
If you haven't already, you should update your TagBot.yml
to include issue comment triggers.
Please see this post on Discourse for instructions and more details.
If you'd like for me to do this for you, comment TagBot fix
on this issue.
I'll open a PR within a few hours, please be patient!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.