diff --git a/examples/3D/Sliced solid torus.ipynb b/examples/3D/Sliced solid torus.ipynb index 6498cc8..41711b5 100644 --- a/examples/3D/Sliced solid torus.ipynb +++ b/examples/3D/Sliced solid torus.ipynb @@ -27,11 +27,121 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "forward = IntervalConstraintProgramming.GeneratedFunction(Symbol[:x,:y,:z],Symbol[:_z_1_,:_z_2_,:_z_3_,:_z_4_,:_z_5_,:_z_6_,:_z_7_,:_z_8_],quote \n", + " _z_1_ = x ^ 2\n", + " _z_2_ = y ^ 2\n", + " _z_3_ = _z_1_ + _z_2_\n", + " _z_4_ = sqrt(_z_3_)\n", + " _z_5_ = 3 - _z_4_\n", + " _z_6_ = _z_5_ ^ 2\n", + " _z_7_ = z ^ 2\n", + " _z_8_ = _z_6_ + _z_7_\n", + "end)\n", + "backward = IntervalConstraintProgramming.GeneratedFunction(Symbol[:x,:y,:z,:_z_1_,:_z_2_,:_z_3_,:_z_4_,:_z_5_,:_z_6_,:_z_7_,:_z_8_],Symbol[:x,:y,:z],quote \n", + " (_z_8_,_z_6_,_z_7_) = plus_rev(_z_8_,_z_6_,_z_7_)\n", + " (_z_7_,z,_) = power_rev(_z_7_,z,2)\n", + " (_z_6_,_z_5_,_) = power_rev(_z_6_,_z_5_,2)\n", + " (_z_5_,_,_z_4_) = minus_rev(_z_5_,3,_z_4_)\n", + " (_z_4_,_z_3_) = sqrt_rev(_z_4_,_z_3_)\n", + " (_z_3_,_z_1_,_z_2_) = plus_rev(_z_3_,_z_1_,_z_2_)\n", + " (_z_2_,y,_) = power_rev(_z_2_,y,2)\n", + " (_z_1_,x,_) = power_rev(_z_1_,x,2)\n", + "end)\n", + "code = quote # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 144:\n", + " (_A_,x,y,z)->begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 144:\n", + " begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 145:\n", + " forward = begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 137:\n", + " (x,y,z)->begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 137:\n", + " begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 138:\n", + " begin \n", + " _z_1_ = x ^ 2\n", + " _z_2_ = y ^ 2\n", + " _z_3_ = _z_1_ + _z_2_\n", + " _z_4_ = sqrt(_z_3_)\n", + " _z_5_ = 3 - _z_4_\n", + " _z_6_ = _z_5_ ^ 2\n", + " _z_7_ = z ^ 2\n", + " _z_8_ = _z_6_ + _z_7_\n", + " end # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 139:\n", + " return (_z_1_,_z_2_,_z_3_,_z_4_,_z_5_,_z_6_,_z_7_,_z_8_)\n", + " end\n", + " end\n", + " end # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 146:\n", + " backward = begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 137:\n", + " (x,y,z,_z_1_,_z_2_,_z_3_,_z_4_,_z_5_,_z_6_,_z_7_,_z_8_)->begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 137:\n", + " begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 138:\n", + " begin \n", + " (_z_8_,_z_6_,_z_7_) = plus_rev(_z_8_,_z_6_,_z_7_)\n", + " (_z_7_,z,_) = power_rev(_z_7_,z,2)\n", + " (_z_6_,_z_5_,_) = power_rev(_z_6_,_z_5_,2)\n", + " (_z_5_,_,_z_4_) = minus_rev(_z_5_,3,_z_4_)\n", + " (_z_4_,_z_3_) = sqrt_rev(_z_4_,_z_3_)\n", + " (_z_3_,_z_1_,_z_2_) = plus_rev(_z_3_,_z_1_,_z_2_)\n", + " (_z_2_,y,_) = power_rev(_z_2_,y,2)\n", + " (_z_1_,x,_) = power_rev(_z_1_,x,2)\n", + " end # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 139:\n", + " return (x,y,z)\n", + " end\n", + " end\n", + " end # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 148:\n", + " (_z_1_,_z_2_,_z_3_,_z_4_,_z_5_,_z_6_,_z_7_,_z_8_) = forward(x,y,z) # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 150:\n", + " _z_8_ = _z_8_ ∩ _A_ # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 152:\n", + " (x,y,z) = backward(x,y,z,_z_1_,_z_2_,_z_3_,_z_4_,_z_5_,_z_6_,_z_7_,_z_8_) # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 154:\n", + " return (x,y,z)\n", + " end\n", + " end\n", + "end\n", + "forward = IntervalConstraintProgramming.GeneratedFunction(Symbol[:x,:y,:z],Symbol[:_z_9_,:_z_10_],quote \n", + " _z_9_ = x + y\n", + " _z_10_ = _z_9_ + z\n", + "end)\n", + "backward = IntervalConstraintProgramming.GeneratedFunction(Symbol[:x,:y,:z,:_z_9_,:_z_10_],Symbol[:x,:y,:z],quote \n", + " (_z_10_,_z_9_,z) = plus_rev(_z_10_,_z_9_,z)\n", + " (_z_9_,x,y) = plus_rev(_z_9_,x,y)\n", + "end)\n", + "code = quote # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 144:\n", + " (_A_,x,y,z)->begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 144:\n", + " begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 145:\n", + " forward = begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 137:\n", + " (x,y,z)->begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 137:\n", + " begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 138:\n", + " begin \n", + " _z_9_ = x + y\n", + " _z_10_ = _z_9_ + z\n", + " end # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 139:\n", + " return (_z_9_,_z_10_)\n", + " end\n", + " end\n", + " end # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 146:\n", + " backward = begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 137:\n", + " (x,y,z,_z_9_,_z_10_)->begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 137:\n", + " begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 138:\n", + " begin \n", + " (_z_10_,_z_9_,z) = plus_rev(_z_10_,_z_9_,z)\n", + " (_z_9_,x,y) = plus_rev(_z_9_,x,y)\n", + " end # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 139:\n", + " return (x,y,z)\n", + " end\n", + " end\n", + " end # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 148:\n", + " (_z_9_,_z_10_) = forward(x,y,z) # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 150:\n", + " _z_10_ = _z_10_ ∩ _A_ # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 152:\n", + " (x,y,z) = backward(x,y,z,_z_9_,_z_10_) # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 154:\n", + " return (x,y,z)\n", + " end\n", + " end\n", + "end\n" + ] + }, { "data": { "text/plain": [ @@ -40,7 +150,7 @@ "- expression: (x + y) + z ∈ [-∞, 1]\n" ] }, - "execution_count": 5, + "execution_count": 2, "metadata": {}, "output_type": "execute_result" } @@ -53,7 +163,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 3, "metadata": { "collapsed": false }, @@ -62,7 +172,7 @@ "name": "stdout", "output_type": "stream", "text": [ - " 2.505603 seconds (6.72 M allocations: 253.181 MB, 3.97% gc time)\n" + " 3.328242 seconds (7.76 M allocations: 313.713 MB, 3.67% gc time)\n" ] } ], @@ -73,7 +183,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 21, "metadata": { "collapsed": false }, @@ -82,22 +192,22 @@ "name": "stdout", "output_type": "stream", "text": [ - " 49.398598 seconds (161.52 M allocations: 5.873 GB, 5.38% gc time)\n" + " 12.920378 seconds (43.82 M allocations: 1.598 GB, 5.94% gc time)\n" ] }, { "data": { "text/plain": [ - "0.05" + "0.1" ] }, - "execution_count": 19, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "@time refine!(paving, 0.05)" + "@time refine!(paving, 0.1)" ] }, { @@ -131,7 +241,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 4, "metadata": { "collapsed": false }, @@ -143,7 +253,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 5, "metadata": { "collapsed": false }, @@ -161,7 +271,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 6, "metadata": { "collapsed": false }, @@ -186,26 +296,19 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 7, "metadata": { "collapsed": false, "scrolled": true }, "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Visualization packages loaded.\n" - ] - }, { "data": { "text/plain": [ - "Task (runnable) @0x000000011513ead0" + "Task (runnable) @0x0000000110be9450" ] }, - "execution_count": 18, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -222,6 +325,15 @@ "\n", "@async renderloop(window)" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/examples/3D/Tangle.ipynb b/examples/3D/Tangle.ipynb index 6fb3ad4..78bcf3b 100644 --- a/examples/3D/Tangle.ipynb +++ b/examples/3D/Tangle.ipynb @@ -20,7 +20,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 1, "metadata": { "collapsed": true }, @@ -31,7 +31,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 2, "metadata": { "collapsed": false }, @@ -40,7 +40,91 @@ "name": "stdout", "output_type": "stream", "text": [ - " 9.590588 seconds (17.55 M allocations: 663.344 MB, 3.43% gc time)\n" + "forward = IntervalConstraintProgramming.GeneratedFunction(Symbol[:x,:y,:z],Symbol[:_z_1_,:_z_2_,:_z_3_,:_z_4_,:_z_5_,:_z_6_,:_z_7_,:_z_8_,:_z_9_,:_z_10_,:_z_11_,:_z_12_,:_z_13_],quote \n", + " _z_1_ = x ^ 4\n", + " _z_2_ = y ^ 4\n", + " _z_3_ = _z_1_ + _z_2_\n", + " _z_4_ = z ^ 4\n", + " _z_5_ = _z_3_ + _z_4_\n", + " _z_6_ = x ^ 2\n", + " _z_7_ = y ^ 2\n", + " _z_8_ = _z_6_ + _z_7_\n", + " _z_9_ = z ^ 2\n", + " _z_10_ = _z_8_ + _z_9_\n", + " _z_11_ = 5_z_10_\n", + " _z_12_ = _z_5_ - _z_11_\n", + " _z_13_ = _z_12_ + 11.8\n", + "end)\n", + "backward = IntervalConstraintProgramming.GeneratedFunction(Symbol[:x,:y,:z,:_z_1_,:_z_2_,:_z_3_,:_z_4_,:_z_5_,:_z_6_,:_z_7_,:_z_8_,:_z_9_,:_z_10_,:_z_11_,:_z_12_,:_z_13_],Symbol[:x,:y,:z],quote \n", + " (_z_13_,_z_12_,_) = plus_rev(_z_13_,_z_12_,11.8)\n", + " (_z_12_,_z_5_,_z_11_) = minus_rev(_z_12_,_z_5_,_z_11_)\n", + " (_z_11_,_,_z_10_) = mul_rev(_z_11_,5,_z_10_)\n", + " (_z_10_,_z_8_,_z_9_) = plus_rev(_z_10_,_z_8_,_z_9_)\n", + " (_z_9_,z,_) = power_rev(_z_9_,z,2)\n", + " (_z_8_,_z_6_,_z_7_) = plus_rev(_z_8_,_z_6_,_z_7_)\n", + " (_z_7_,y,_) = power_rev(_z_7_,y,2)\n", + " (_z_6_,x,_) = power_rev(_z_6_,x,2)\n", + " (_z_5_,_z_3_,_z_4_) = plus_rev(_z_5_,_z_3_,_z_4_)\n", + " (_z_4_,z,_) = power_rev(_z_4_,z,4)\n", + " (_z_3_,_z_1_,_z_2_) = plus_rev(_z_3_,_z_1_,_z_2_)\n", + " (_z_2_,y,_) = power_rev(_z_2_,y,4)\n", + " (_z_1_,x,_) = power_rev(_z_1_,x,4)\n", + "end)\n", + "code = quote # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 144:\n", + " (_A_,x,y,z)->begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 144:\n", + " begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 145:\n", + " forward = begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 137:\n", + " (x,y,z)->begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 137:\n", + " begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 138:\n", + " begin \n", + " _z_1_ = x ^ 4\n", + " _z_2_ = y ^ 4\n", + " _z_3_ = _z_1_ + _z_2_\n", + " _z_4_ = z ^ 4\n", + " _z_5_ = _z_3_ + _z_4_\n", + " _z_6_ = x ^ 2\n", + " _z_7_ = y ^ 2\n", + " _z_8_ = _z_6_ + _z_7_\n", + " _z_9_ = z ^ 2\n", + " _z_10_ = _z_8_ + _z_9_\n", + " _z_11_ = 5_z_10_\n", + " _z_12_ = _z_5_ - _z_11_\n", + " _z_13_ = _z_12_ + 11.8\n", + " end # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 139:\n", + " return (_z_1_,_z_2_,_z_3_,_z_4_,_z_5_,_z_6_,_z_7_,_z_8_,_z_9_,_z_10_,_z_11_,_z_12_,_z_13_)\n", + " end\n", + " end\n", + " end # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 146:\n", + " backward = begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 137:\n", + " (x,y,z,_z_1_,_z_2_,_z_3_,_z_4_,_z_5_,_z_6_,_z_7_,_z_8_,_z_9_,_z_10_,_z_11_,_z_12_,_z_13_)->begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 137:\n", + " begin # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 138:\n", + " begin \n", + " (_z_13_,_z_12_,_) = plus_rev(_z_13_,_z_12_,11.8)\n", + " (_z_12_,_z_5_,_z_11_) = minus_rev(_z_12_,_z_5_,_z_11_)\n", + " (_z_11_,_,_z_10_) = mul_rev(_z_11_,5,_z_10_)\n", + " (_z_10_,_z_8_,_z_9_) = plus_rev(_z_10_,_z_8_,_z_9_)\n", + " (_z_9_,z,_) = power_rev(_z_9_,z,2)\n", + " (_z_8_,_z_6_,_z_7_) = plus_rev(_z_8_,_z_6_,_z_7_)\n", + " (_z_7_,y,_) = power_rev(_z_7_,y,2)\n", + " (_z_6_,x,_) = power_rev(_z_6_,x,2)\n", + " (_z_5_,_z_3_,_z_4_) = plus_rev(_z_5_,_z_3_,_z_4_)\n", + " (_z_4_,z,_) = power_rev(_z_4_,z,4)\n", + " (_z_3_,_z_1_,_z_2_) = plus_rev(_z_3_,_z_1_,_z_2_)\n", + " (_z_2_,y,_) = power_rev(_z_2_,y,4)\n", + " (_z_1_,x,_) = power_rev(_z_1_,x,4)\n", + " end # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/code_generation.jl, line 139:\n", + " return (x,y,z)\n", + " end\n", + " end\n", + " end # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 148:\n", + " (_z_1_,_z_2_,_z_3_,_z_4_,_z_5_,_z_6_,_z_7_,_z_8_,_z_9_,_z_10_,_z_11_,_z_12_,_z_13_) = forward(x,y,z) # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 150:\n", + " _z_13_ = _z_13_ ∩ _A_ # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 152:\n", + " (x,y,z) = backward(x,y,z,_z_1_,_z_2_,_z_3_,_z_4_,_z_5_,_z_6_,_z_7_,_z_8_,_z_9_,_z_10_,_z_11_,_z_12_,_z_13_) # /Users/dpsanders/.julia/v0.5/IntervalConstraintProgramming/src/contractor.jl, line 154:\n", + " return (x,y,z)\n", + " end\n", + " end\n", + "end\n", + " 9.758865 seconds (19.16 M allocations: 735.257 MB, 3.40% gc time)\n" ] } ], @@ -54,7 +138,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 3, "metadata": { "collapsed": false }, @@ -63,12 +147,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "227.004031 seconds (453.81 M allocations: 16.755 GB, 3.37% gc time)\n" + " 41.695163 seconds (87.37 M allocations: 3.235 GB, 3.45% gc time)\n" ] } ], "source": [ - "@time refine!(paving, 0.25)\n", + "@time refine!(paving, 0.5)\n", "\n", "inner = paving.inner\n", "boundary = paving.boundary;" @@ -98,7 +182,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "metadata": { "collapsed": true }, @@ -109,7 +193,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 5, "metadata": { "collapsed": true }, @@ -134,7 +218,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 6, "metadata": { "collapsed": false }, @@ -142,10 +226,10 @@ { "data": { "text/plain": [ - "Task (runnable) @0x000000011c886f50" + "Task (runnable) @0x000000010fe61d50" ] }, - "execution_count": 22, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } diff --git a/src/ast.jl b/src/ast.jl index ef77949..67e0ba8 100644 --- a/src/ast.jl +++ b/src/ast.jl @@ -139,7 +139,7 @@ end # function process_iterated_function!(flatAST::FlattenedAST, ex) function process_tuple!(flatAST::FlattenedAST, ex) - println("Entering process_tuple") + # println("Entering process_tuple") # @show flatAST # @show ex # top_args = [flatten!(flatAST, arg) for arg in ex.args] @@ -161,19 +161,36 @@ The name a is currently retained. TODO: It should later be made unique. """ function process_assignment!(flatAST::FlattenedAST, ex) - println("process_assignment!:") - # @show ex - # @show ex.args[1], ex.args[2] + # println("process_assignment!:") + # @show ex + # @show ex.args[1], ex.args[2] top = flatten!(flatAST, ex.args[2]) + # @show top var = ex.args[1] - push!(flatAST.intermediate, var) + # @show var + + # TODO: Replace the following by multiple dispatch + if isa(var, Expr) && var.head == :tuple + vars = [var.args...] + + elseif isa(var, Tuple) + vars = [var...] + + elseif isa(var, Vector) + vars = var + + else + vars = [var] + end + + append!(flatAST.intermediate, vars) - top_level_code = Assignment(var, :(), top) # empty operation + top_level_code = Assignment(vars, :(), top) # empty operation push!(flatAST.code, top_level_code) - # @show flatAST + # j@show flatAST return var @@ -183,17 +200,23 @@ end by rewriting it to the equivalent set of iterated functions""" function process_iterated_function!(flatAST::FlattenedAST, ex) total_function_call = ex.args[1] - argument = ex.args[2] + args = ex.args[2:end] + + # @show args function_name = total_function_call.args[2] power = total_function_call.args[3] # assumed integer - new_expr = :($function_name($argument)) + new_expr = :($function_name($(args...))) + + # @show new_expr for i in 2:power new_expr = :($function_name($new_expr)) end + # @show new_expr + flatten!(flatAST, new_expr) end diff --git a/src/code_generation.jl b/src/code_generation.jl index 07a5fc0..73fbbb0 100644 --- a/src/code_generation.jl +++ b/src/code_generation.jl @@ -1,5 +1,11 @@ function make_tuple(args) + + if isa(args, Symbol) + # args = [args] + return args + end + length(args) == 1 && return args[1] return Expr(:tuple, args...) @@ -10,19 +16,24 @@ function emit_forward_code(a::Assignment) args = isa(a.args, Vector) ? a.args : [a.args] + lhs = make_tuple(a.lhs) + if a.op == :() # empty - :($(a.lhs) = $(args...) ) + args = make_tuple(args) + :($lhs = $args) else - :($(a.lhs) = $(a.op)($(args...) ) ) + :($lhs = $(a.op)($(args...) ) ) end end function emit_forward_code(a::FunctionAssignment) f = a.func - args = make_tuple(a.lhs) - :($args = $(esc(f)).forward($(a.args...) ) ) + args = isa(a.args, Vector) ? a.args : [a.args] + lhs = make_tuple(a.lhs) + + :($lhs = $(esc(f)).forward($(a.args...) ) ) end @@ -43,7 +54,10 @@ function emit_backward_code(a::Assignment) rev_op = rev_ops[a.op] # find reverse operation if rev_op == :() # empty - return :($(args...) = $(a.lhs)) + args = make_tuple(args) + lhs = make_tuple(a.lhs) + return :($args = $lhs) + #return :($(args...) = $(a.lhs)) else rev_code = :($(rev_op)($(return_args...))) end diff --git a/src/contractor.jl b/src/contractor.jl index 426e453..862321d 100644 --- a/src/contractor.jl +++ b/src/contractor.jl @@ -136,6 +136,15 @@ function make_contractor(ex::Expr) # using an IntervalBox and intersection of IntervalBoxes end + top_args = make_tuple(top) + + local intersect_code + + if isa(top_args, Symbol) + intersect_code = :($top_args = $top_args ∩ _A_) # check type stability + else + intersect_code = :($top_args = IntervalBox($top_args) ∩ _A_) # check type stability + end code = @@ -147,7 +156,7 @@ function make_contractor(ex::Expr) $(forward_output) = forward($(forward.input_arguments...)) - $(top) = $(top) ∩ _A_ + $intersect_code $(backward_output) = backward($(backward.input_arguments...)) @@ -157,10 +166,10 @@ function make_contractor(ex::Expr) end - # @show forward - # @show backward - # - # @show code + # @show forward + # @show backward + # # + # @show code return :(Contractor($(augmented_input_arguments), $(Meta.quot(expr)), diff --git a/src/functions.jl b/src/functions.jl index 2945e3e..d54ffe1 100644 --- a/src/functions.jl +++ b/src/functions.jl @@ -26,6 +26,8 @@ type ConstraintFunction{F <: Function, G <: Function} output::Vector{Symbol} # output arguments for forward function forward::F backward::G + forward_code::Expr + backward_code::Expr end type FunctionArguments @@ -92,6 +94,8 @@ Example: `@function f(x, y) = x^2 + y^2` registered_functions[f] = FunctionArguments(flatAST.variables, flatAST.intermediate, return_arguments) + forward_function = make_function(forward_code) + backward_function = make_function(backward_code) return quote #$(esc(Meta.quot(f))) = ConstraintFunction($(all_vars), $(generated), $(forward_code), $(backward_code)) @@ -99,7 +103,10 @@ Example: `@function f(x, y) = x^2 + y^2` $(esc(f)) = ConstraintFunction($(flatAST.variables), $(flatAST.intermediate), - $(make_function(forward_code)), $(make_function(backward_code)) + $(forward_function), + $(backward_function), + $(Meta.quot(forward_function)), + $(Meta.quot(backward_function)) ) diff --git a/src/separator.jl b/src/separator.jl index 8768771..7e12cd8 100644 --- a/src/separator.jl +++ b/src/separator.jl @@ -6,20 +6,22 @@ ConstraintSeparator is a separator that represents a constraint defined directly using `@constraint`. """ # CHANGE TO IMMUTABLE AND PARAMETRIZE THE FUNCTION FOR EFFICIENCY -type ConstraintSeparator <: Separator +type ConstraintSeparator{C, II} <: Separator variables::Vector{Symbol} #separator::Function - constraint::Interval - contractor::Contractor + constraint::II # Interval or IntervalBox + contractor::C expression::Expr end +ConstraintSeparator(constraint, contractor, expression) = ConstraintSeparator(contractor.variables[2:end], constraint, contractor, expression) + doc"""CombinationSeparator is a separator that is a combination (union, intersection, or complement) of other separators. """ -type CombinationSeparator <: Separator +type CombinationSeparator{F} <: Separator variables::Vector{Symbol} - separator::Function + separator::F expression::Expr end @@ -50,11 +52,69 @@ end +doc"""`parse_comparison` parses comparisons like `x >= 10` +into the corresponding interval, expressed as `x ∈ [10,∞]` +Returns the expression and the constraint interval + +TODO: Allow something like [3,4]' for the complement of [3,4] +""" + +function parse_comparison(ex) + expr, limits = + @match ex begin + ((a_ <= b_) | (a_ < b_) | (a_ ≤ b_)) => (a, (-∞, b)) + ((a_ >= b_) | (a_ > b_) | (a_ ≥ b_)) => (a, (b, ∞)) + + ((a_ == b_) | (a_ = b_)) => (a, (b, b)) + + ((a_ <= b_ <= c_) + | (a_ < b_ < c_) + | (a_ <= b_ < c) + | (a_ < b_ <= c)) => (b, (a, c)) + + ((a_ >= b_ >= c_) + | (a_ > b_ > c_) + | (a_ >= b_ > c_) + | (a_ > b_ >= c)) => (b, (c, a)) + + ((a_ ∈ [b_, c_]) + | (a_ in [b_, c_]) + | (a_ ∈ b_ .. c_) + | (a_ in b_ .. c_)) => (a, (b, c)) + + _ => (ex, (-∞, ∞)) + + end + + a, b = limits + + return (expr, a..b) # expr ∈ [a,b] + +end -macro constraint(ex::Expr) # alternative name for constraint -- remove? - # @show ex - expr, constraint = parse_comparison(ex) + +function new_parse_comparison(ex) + @show ex + if @capture ex begin + (op_(a_, b_)) + end + + #return (op, a, b) + @show op, a, b + + elseif ex.head == :comparison + println("Comparison") + symbols = ex.args[1:2:5] + operators = ex.args[2:2:4] + + @show symbols + @show operators + + end +end + +function make_constraint(expr, constraint) if isa(expr, Symbol) expr = :(1 * $expr) # make into an expression! @@ -65,15 +125,24 @@ macro constraint(ex::Expr) # alternative name for constraint -- remove? full_expr = Meta.quot(:($expr ∈ $constraint)) code = quote end - push!(code.args, :($contractor_name = @contractor($(esc(expr))))) - push!(code.args, :(ConstraintSeparator($(contractor_name).variables[2:end], $constraint, $contractor_name, $full_expr))) + push!(code.args, :($(esc(contractor_name)) = @contractor($(esc(expr))))) + # push!(code.args, :(ConstraintSeparator($(esc(contractor_name)).variables[2:end], $constraint, $(esc(contractor_name)), $full_expr))) + + push!(code.args, :(ConstraintSeparator($constraint, $(esc(contractor_name)), $full_expr))) # @show code code +end + +macro constraint(ex::Expr) # alternative name for constraint -- remove? + # @show ex + expr, constraint = parse_comparison(ex) + make_constraint(expr, constraint) end + # doc"""Create a separator from a given constraint expression, written as # standard Julia code. # diff --git a/test/runtests.jl b/test/runtests.jl index 0370f2d..09f35c0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -30,7 +30,7 @@ end X = IntervalBox(II, II) S = @constraint x^2 + y^2 <= 1 - @test typeof(S) == IntervalConstraintProgramming.ConstraintSeparator + @test typeof(S) <: IntervalConstraintProgramming.ConstraintSeparator inner, outer = S(X) @test inner == (-1..1, -1..1) @@ -158,3 +158,21 @@ end @test C3(A, x) == sqrt(A / 16) end + +@testset "Multidimensional functions" begin + + @function g4(x, y) = (2x, 2y) + + A = IntervalBox(0.5..1, 0.5..1) + x = y = 0..1 + + C4 = @contractor g4(x, y) + + @test IntervalBox(C4(A, x, y)) == A / 2 + + + C5 = @contractor (g4↑2)(x, y) + + @test IntervalBox(C5(A, x, y)) == A / 4 + +end