Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
language: julia

os:
- linux
- osx

notifications:
email: false

julia:
- 0.6
- 0.7
- 1.0
- nightly

matrix:
allow_failures:
- julia: nightly
#script:
# - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
# - julia -e 'Pkg.init(); Pkg.clone(pwd()); Pkg.test("ImplicitEquations")'

script:
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
- julia -e 'using Pkg; Pkg.clone(pwd()); Pkg.test("ImplicitEquations")'
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The ImplicitEquations.jl package is licensed under the MIT "Expat" License:

> Copyright (c) 2014-16: jverzani.
> Copyright (c) 2014-18: jverzani.
>
> Permission is hereby granted, free of charge, to any person obtaining
> a copy of this software and associated documentation files (the
Expand Down
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
[![ImplicitEquations](http://pkg.julialang.org/badges/ImplicitEquations_0.6.svg)](http://pkg.julialang.org/?pkg=ImplicitEquations&ver=0.6)
 
Linux: [![Build Status](https://travis-ci.org/jverzani/ImplicitEquations.jl.svg?branch=master)](https://travis-ci.org/jverzani/ImplicitEquations.jl)
 
Windows: [![Build Status](https://ci.appveyor.com/api/projects/status/github/jverzani/ImplicitEquations.jl?branch=master&svg=true)](https://ci.appveyor.com/project/jverzani/implicitequations-jl)
Expand Down Expand Up @@ -32,5 +30,3 @@ plot(f ⩵ 0) # \Equal[tab]
```

![DevilsCurve](http://i.imgur.com/LChTzC1.png)


8 changes: 3 additions & 5 deletions REQUIRE
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
julia 0.6
ForwardDiff 0.3.0
ValidatedNumerics 0.5.0
RecipesBase 0.0.6
Compat 0.8.6
julia 0.7
IntervalArithmetic 0.15.0
RecipesBase 0.5.0
35 changes: 17 additions & 18 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
environment:
matrix:
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.6/julia-0.6-latest-win32.exe"
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.6/julia-0.6-latest-win64.exe"
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe"
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe"
- julia_version: 0.7
- julia_version: 1.0
- julia_version: latest

platform:
- x86 # 32-bit
- x64 # 64-bit

## uncomment the following lines to allow failures on nightly julia
## (tests will run but not make your overall status red)
matrix:
allow_failures:
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe"
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe"
- julia_version: latest


branches:
only:
Expand All @@ -21,19 +27,12 @@ notifications:
on_build_status_changed: false

install:
- ps: "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12"
# Download most recent Julia Windows binary
- ps: (new-object net.webclient).DownloadFile(
$env:JULIA_URL,
"C:\projects\julia-binary.exe")
# Run installer silently, output to C:\projects\julia
- C:\projects\julia-binary.exe /S /D=C:\projects\julia
- ps: iex ((new-object net.webclient).DownloadString("https://raw.githubusercontent.com/JuliaCI/Appveyor.jl/version-1/bin/install.ps1"))

build_script:
# Need to convert from shallow to complete for Pkg.clone to work
- IF EXIST .git\shallow (git fetch --unshallow)
- C:\projects\julia\bin\julia -e "versioninfo();
Pkg.clone(pwd(), \"ImplicitEquations\"); Pkg.build(\"ImplicitEquations\")"
- echo "%JL_BUILD_SCRIPT%"
- C:\julia\bin\julia -e "%JL_BUILD_SCRIPT%"

test_script:
- C:\projects\julia\bin\julia --check-bounds=yes -e "Pkg.test(\"ImplicitEquations\")"
- echo "%JL_TEST_SCRIPT%"
- C:\julia\bin\julia -e "%JL_TEST_SCRIPT%"
32 changes: 20 additions & 12 deletions docs/examples.ipynb

Large diffs are not rendered by default.

10 changes: 4 additions & 6 deletions docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ is graphed over the default region as follows:

```
using Plots, ImplicitEquations
pyplot()

a,b = -1,2
f(x,y) = y^4 - x^4 + a*y^2 + b*x^2
Expand Down Expand Up @@ -121,11 +120,11 @@ Uses a few new things: the `screen` function is used to restrict
ranges and logical operators to combine predicates.

```
f0(x,y) = ((x/7)^2 + (y/3)^2 - 1) * screen(abs(x)>3) * screen(y > -3*sqrt(33)/7)
f0(x,y) = ((x/7)^2 + (y/3)^2 - 1) * screen(abs(x)>3) * screen(y > -3*sqrt(33)/7)
f1(x,y) = ( abs(x/2)-(3 * sqrt(33)-7) * x^2/112 -3 +sqrt(1-(abs((abs(x)-2))-1)^2)-y)
f2(x,y) = y - (9 - 8*abs(x)) * screen((abs(x)>= 3/4) & (abs(x) <= 1) )
f3(x,y) = y - (3*abs(x) + 3/4) * I_((1/2 < abs(x)) & (abs(x) < 3/4)) # alternate name for screen
f4(x,y) = y - 2.25 * I_(abs(x) <= 1/2)
f4(x,y) = y - 2.25 * I_(abs(x) <= 1/2)
f5(x,y) = (6 * sqrt(10)/7 + (1.5-.5 * abs(x)) - 6 * sqrt(10)/14 * sqrt(4-(abs(x)-1)^2) -y) * screen(abs(x) >= 1)

r = (f0 ⩵ 0) | (f1 ⩵ 0) | (f2 ⩵ 0) | (f3 ⩵ 0) | (f4 ⩵ 0) | (f5 ⩵ 0)
Expand Down Expand Up @@ -186,7 +185,7 @@ plot(f ⩵ 2*3^2)
## now add tangent at (3,3)
a,b = 3,3
dydx(a,b) = -b/a # implicit differentiate to get dy/dx =-y/x
tl(x) = b + dydx(a,b)*(x-a)
tl(x) = b + dydx(a,b)*(x-a)
plot!(tl, linewidth=3, -5, 5)
```

Expand All @@ -204,7 +203,7 @@ interval arithmetic, as possible.

The package
[IntervalConstraintProgramming ](https://github.com/dpsanders/IntervalConstraintProgramming.jl)
also allows for this type of graphing, and momre.
also allows for this type of graphing, and more.

## TODO

Expand All @@ -221,4 +220,3 @@ also allows for this type of graphing, and momre.
* Tupper sketches out how to be more rigorous with computing whether a region is black or white.

* increase speed (could color 1-pixel regions better if so, perhaps; division checks; type stability).

6 changes: 1 addition & 5 deletions src/ImplicitEquations.jl
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
__precompile__(true)

module ImplicitEquations


using ForwardDiff
import ValidatedNumerics: Interval, diam, isempty
import IntervalArithmetic: Interval, diam, isempty
using RecipesBase
using Compat

include("predicates.jl")
include("intervals.jl")
Expand Down
43 changes: 18 additions & 25 deletions src/intervals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Base: <, <=, ==, !==, >=, >,
+, -, *, /, ^

## a few definitionsn for ValidatedNumerics that don't fit in there:
## Validated numerics doesn't define these, as the order ins't a total order
## Validated numerics doesn't define these, as the order ins't a total order
Base.isless(i::Interval{T}, j::Interval{S}) where {T<:Real, S<:Real} = isless(i.hi, j.lo)
#<=(i::Interval{T}, j::Interval{S}) where {T<:Real, S<:Real} = <=(i.hi, j.lo)

Expand All @@ -14,7 +14,7 @@ Base.isless(i::Interval{T}, j::Interval{S}) where {T<:Real, S<:Real} = isless(i.


## BInterval represents TRUE (true, true), FALSE (false, false) and MAYBE (false, true)
immutable BInterval <: Integer
struct BInterval <: Integer
lo :: Bool
hi :: Bool

Expand Down Expand Up @@ -50,13 +50,13 @@ function negate_op(op)
end

## OIinterval includes interval, if defined on interval and if continuous on interval
immutable OInterval <: Real
struct OInterval <: Real
val::Interval
def::BInterval
cont::BInterval
OInterval(val, def, cont) = new(val, def, cont)
end

(O::OInterval)(o::OInterval) = o
Base.show(io::IO, o::OInterval) = print(io, "OInterval: ", o.val, " def=", o.def, " cont=",o.cont)

## some outer constructors...
Expand All @@ -66,22 +66,16 @@ OInterval(a) = OInterval(a,a) # thin one...
OInterval(i::Interval) = OInterval(i.lo, i.hi)

Base.convert(::Type{OInterval}, i::Interval) = OInterval(i.lo, i.hi)
Base.convert(::Type{OInterval}, x::S) where {S<:Real}= OInterval(x)
Base.promote_rule(::Type{OInterval}, ::Type{ForwardDiff.Dual{N,B}}) where {N,B<:Real} = warn("defined to remove ambiguity")

Base.promote_rule(::Type{OInterval}, ::Type{A}) where {A<:Real} = OInterval

## A region is two OIntervals.
immutable Region
struct Region
x::OInterval
y::OInterval
end

## not good for v0.5+
#call(f::Function, u::Region) = f(u.x, u.y)


#ValidatedNumerics.diam(x::OInterval) = diam(x.val)
diam(x::OInterval) = diam(x.val)
ImplicitEquations.diam(x::OInterval) = diam(x.val)

## extend functions for OInterval
## Notice these return BIntervals -- not Bools
Expand Down Expand Up @@ -116,7 +110,7 @@ rather a `BInterval` which allows for a "MAYBE" state. As such, a
simple ternary operator, like `x > 0 ? 1 : NaN` won't work, to screen values.

"""
screen(ex) = (ex == FALSE) ? NaN : 1
screen(ex) = (ex == FALSE) ? NaN : 1
const I_ = screen # indicator function like!

## Functions which are continuous everywhere
Expand Down Expand Up @@ -159,7 +153,7 @@ Base.tanh(x::OInterval) = sinh(x)/cosh(x)
Base.coth(x::OInterval) = 1/tanh(x)

function Base.asin(x::OInterval)
if x.val.hi < -1.0 || x.val.lo > 1.0
if x.val.hi < -1.0 || x.val.lo > 1.0
OInterval(x.val, FALSE, FALSE)
elseif (x.val.lo < -1.0) & (x.val.hi > 1.0)
OInterval(Interval(-pi/2, pi/2), x.def & MAYBE, x.cont)
Expand Down Expand Up @@ -208,7 +202,7 @@ Base.exp(x::OInterval) = OInterval(exp(x.val), x.def, x.cont)
## /
## division is slow
function /(x::OInterval, y::OInterval)
## 0 is the issue.
## 0 is the issue.
if 0.0 ∈ y.val
## maybe defined, maybe continuous
OInterval(x.val/y.val, x.def & MAYBE, x.cont & MAYBE)
Expand All @@ -218,7 +212,7 @@ function /(x::OInterval, y::OInterval)
end

## log
function Base.log(x::OInterval)
function Base.log(x::OInterval)
if x.val.hi <= 0
OInterval(x.val, FALSE, FALSE)
elseif x.val.lo <= 0
Expand Down Expand Up @@ -254,7 +248,6 @@ function ^(x::OInterval, q::Rational)
OInterval(val, x.def, x.cont)
end

^(x::OInterval, r::ForwardDiff.Dual) = warn("defined to resolve ambiguity")
function ^(x::OInterval, r::Real)
r < 0 && return(1/x^(-r))
if x.val.hi < 0
Expand Down Expand Up @@ -287,7 +280,7 @@ end

Base.max(x::OInterval, y::OInterval) = OInterval(max(x.val, y.val), x.def & y.def, x.cont & y.cont)
Base.min(x::OInterval, y::OInterval) = OInterval(min(x.val, y.val), x.def & y.def, x.cont & y.cont)


## others sign, mod, ...
function Base.sign(x::OInterval)
Expand All @@ -304,7 +297,7 @@ function xy_region(u, L, R, B, T, W, H)
c = B + py.lo * (T - B) / H
d = B + (py.hi) * (T - B) / H
delta = sqrt(eps())

x, y = OInterval(a+(u.x.cont==TRUE)*delta,b-delta), OInterval(c+0*delta,d-delta)
x, y
end
Expand All @@ -324,7 +317,7 @@ function compute(p::Pred, u::Region, L, R, B, T, W, H)

(fxy.def == FALSE) && return (FALSE)
isempty(fxy.val) && return (FALSE & fxy.def)

if p.op === ==
return((p.val ∈ fxy.val) ? MAYBE : FALSE)
elseif negate_op(p.op) === ==
Expand All @@ -340,7 +333,7 @@ end
## build up answer
function compute(ps::Preds, u::Region, L, R, B, T, W, H)
vals = [compute(p, u, L, R, B, T, W, H) for p in ps.ps]
val = shift!(vals)
val = popfirst!(vals)
for i in 1:length(ps.ops)
val = ps.ops[i](val, vals[i])
end
Expand All @@ -351,14 +344,14 @@ end

Does this function have a zero crossing? Heuristic check.

We return `TRUE` or `MAYBE`. However, that
We return `TRUE` or `MAYBE`. However, that
leaves some functions showing too much red in the case where there is no zero.

"""
function cross_zero(r::Pred, u::Region, L, R, B, T, W, H)
x, y = xy_region(u, L, R, B, T, W, H)
dx, dy = diam(x), diam(y)

n = 20 # number of random points chosen
λ1s, λ2s = [0.0; 1.0;rand(n)], [0.0; 1.0; rand(n)]
β1s, β2s = [1.0; 0.0; rand(n)], [1.0; 0.0; rand(n)]
Expand All @@ -370,7 +363,7 @@ function cross_zero(r::Pred, u::Region, L, R, B, T, W, H)
val = (r.f(ll...) - r.val) * (r.f(ur...) - r.val)
((val <= 0)==TRUE) && return(TRUE)
end
return(MAYBE)
return(MAYBE)
end


Expand Down
Loading