Nowhere differentiable continuous function: Difference between revisions

From JSXGraph Wiki
No edit summary
No edit summary
 
(30 intermediate revisions by the same user not shown)
Line 1: Line 1:
This page shows the graph of the nowhere differentiable, but continuous function
:<math> f(x) = \sum_{k=1}^{N} a^k\cos(b^k\pi x), </math>
where <math>0< a <1</math> and <math>ab>1+3/2\pi</math>.
<jsxgraph width="500" height="500" box="box">
<jsxgraph width="500" height="500" box="box">
(function(){
var bd = JXG.JSXGraph.initBoard('box', {axis:true, boundingbox: [-5, 3, 5, -3]});
var a = bd.create('slider', [[0.5,2],[2.5,2],[0,0.3,1]], {name:'a'});
var b = bd.create('slider', [[0.5,1.5],[2.5,1.5],[0,20,100]], {name:'b'});
var N = bd.create('slider', [[0.5,1.0],[2.5,1.0],[0,2,30]], {name:'N'});
var f = function(x){
            var k, s=0.0, n = N.Value(), aa= a.Value(), bb = b.Value();
            for (k=1; k<n; k++) {
                s += Math.pow(aa,k)*Math.cos(Math.pow(bb,k)*Math.PI*x);
            }
            return s;
        };
var c = bd.create('functiongraph', [f], {doAdvancedPlot:false, numberPointsHigh:6000, numberPointsLow:500, strokeWidth:1});
})();
</jsxgraph>
=== Reference ===
Wei-Chi Yang, "Technology has shaped up mathematics comunities",
Proceedings of the Sixteenth Asian Technology Conference in Mathmatics (ATCM 16), pp 81-96.
=== The underlying JavaScript code ===
<source lang="javascript">
  var bd = JXG.JSXGraph.initBoard('box', {axis:true, boundingbox: [-5, 3, 5, -3]});
  var bd = JXG.JSXGraph.initBoard('box', {axis:true, boundingbox: [-5, 3, 5, -3]});
  var a = bd.create('slider', [[0.5,2],[2.5,2],[0,0.25,1]], {name:'a'});
  var a = bd.create('slider', [[0.5,2],[2.5,2],[0,0.3,1]], {name:'a'});
  var b = bd.create('slider', [[0.5,1.5],[2.5,1.5],[0,5,50]], {name:'b'});  
  var b = bd.create('slider', [[0.5,1.5],[2.5,1.5],[0,20,100]], {name:'b'});  
  var N = bd.create('slider', [[0.5,1.0],[2.5,1.0],[0,1,50]], {name:'N'});  
  var N = bd.create('slider', [[0.5,1.0],[2.5,1.0],[0,2,30]], {name:'N'});  
  var f = function(x){
  var f = function(x){
             var i, s=0.0, n = N.Value(), aa= a.Value(), bb = b.Value();  
             var k, s=0.0, n = N.Value(), aa= a.Value(), bb = b.Value();  
             for (i=0; i<n; i++) {
             for (k=1; k<n; k++) {
                 s += Math.pow(a,i)*Math.cos(Math.pow(b,i)*Math.PI*x);
                 s += Math.pow(aa,k)*Math.cos(Math.pow(bb,k)*Math.PI*x);
             }
             }
console.log(aa,bb,n);
             return s;
             return s;
         };
         };
  var c = bd.create('functiongraph', [f], {});
  var c = bd.create('functiongraph', [f], {
                    doAdvancedPlot:false,
                    numberPointsHigh:15000, numberPointsLow:1000,
                    strokeWidth:1});
</source>


== Speed optimization ==
<jsxgraph width="500" height="500" box="box2">
(function(){
var bd = JXG.JSXGraph.initBoard('box2', {axis:true, boundingbox: [-5, 3, 5, -3]});
var a = bd.create('slider', [[0.5,2],[2.5,2],[0,0.3,1]], {name:'a'});
var b = bd.create('slider', [[0.5,1.5],[2.5,1.5],[0,20,100]], {name:'b'});
var N = bd.create('slider', [[0.5,1.0],[2.5,1.0],[0,2,30]], {name:'N'});
var f = function(x, suspendedUpdate){
            var k, s=0.0;
            if (!suspendedUpdate) {
                this.n = N.Value();
                this.aa= a.Value();
                this.bb = b.Value();
                this.aArr = [1.0];
                this.bArr = [1.0*Math.PI];
                for (k=1; k<this.n; k++) {
                  this.aArr[k] = this.aArr[k-1]*this.aa;
                  this.bArr[k] = this.bArr[k-1]*this.bb;
                }   
            }
            for (k=1; k<this.n; k++) {
                s += this.aArr[k]*Math.cos(this.bArr[k]*x);
            }
            return s;
        };
var c = bd.create('functiongraph', [f], {doAdvancedPlot:false, numberPointsHigh:6000, numberPointsLow:500, strokeWidth:1});
})();
</jsxgraph>
</jsxgraph>


This is a speed optimized version of the above JSXGraph construction.
First, the code is wrapped into an anonymous function which is executed at once.
<source lang="javascript">
(function(){
})();
</source>
The only reason to do this is to avoid global variables. Otherwise, these variables would interfere with the variables of the same name in the above construction.


In order to optimize the execution speed the second parameter "suspendedUpdate" of the function is used. This parameter is set true in the first call of the function during an update of the board. Since in each update the function is called several thousand times it is useful to compute values that do not change during the update only once. In the above case, in each call of the function the powers <math>aa^k</math> and <math>bb^k</math> are used many times. Since <math>aa</math> and <math>bb</math> do not change during a single update, we can precompute these values and store them.


<source lang="javascript">
(function(){
var bd = JXG.JSXGraph.initBoard('box2', {axis:true, boundingbox: [-5, 3, 5, -3]});
var a = bd.create('slider', [[0.5,2],[2.5,2],[0,0.3,1]], {name:'a'});
var b = bd.create('slider', [[0.5,1.5],[2.5,1.5],[0,20,100]], {name:'b'});
var N = bd.create('slider', [[0.5,1.0],[2.5,1.0],[0,2,30]], {name:'N'});
var f = function(x, suspendedUpdate){
            var k, s=0.0;
            if (!suspendedUpdate) {
                this.n = N.Value();
                this.aa= a.Value();
                this.bb = b.Value();
                this.aArr = [1.0];
                this.bArr = [1.0*Math.PI];
                for (k=1; k<this.n; k++) {
                  this.aArr[k] = this.aArr[k-1]*this.aa;
                  this.bArr[k] = this.bArr[k-1]*this.bb;
                }   
            }
            for (k=1; k<this.n; k++) {
                s += this.aArr[k]*Math.cos(this.bArr[k]*x);
            }
            return s;
        };
var c = bd.create('functiongraph', [f], {doAdvancedPlot:false, numberPointsHigh:6000, numberPointsLow:500, strokeWidth:1});
})();
</source>
[[Category:Examples]]
[[Category:Examples]]
[[Category:Curves]]
[[Category:Curves]]

Latest revision as of 15:11, 14 January 2021

This page shows the graph of the nowhere differentiable, but continuous function

[math]\displaystyle{ f(x) = \sum_{k=1}^{N} a^k\cos(b^k\pi x), }[/math]

where [math]\displaystyle{ 0\lt a \lt 1 }[/math] and [math]\displaystyle{ ab\gt 1+3/2\pi }[/math].

Reference

Wei-Chi Yang, "Technology has shaped up mathematics comunities", Proceedings of the Sixteenth Asian Technology Conference in Mathmatics (ATCM 16), pp 81-96.

The underlying JavaScript code

 var bd = JXG.JSXGraph.initBoard('box', {axis:true, boundingbox: [-5, 3, 5, -3]});
 var a = bd.create('slider', [[0.5,2],[2.5,2],[0,0.3,1]], {name:'a'});
 var b = bd.create('slider', [[0.5,1.5],[2.5,1.5],[0,20,100]], {name:'b'}); 
 var N = bd.create('slider', [[0.5,1.0],[2.5,1.0],[0,2,30]], {name:'N'}); 
 var f = function(x){
            var k, s=0.0, n = N.Value(), aa= a.Value(), bb = b.Value(); 
            for (k=1; k<n; k++) {
                s += Math.pow(aa,k)*Math.cos(Math.pow(bb,k)*Math.PI*x);
            }
            return s;
         };
 var c = bd.create('functiongraph', [f], {
                    doAdvancedPlot:false, 
                    numberPointsHigh:15000, numberPointsLow:1000, 
                    strokeWidth:1});

Speed optimization

This is a speed optimized version of the above JSXGraph construction. First, the code is wrapped into an anonymous function which is executed at once.

(function(){
})();

The only reason to do this is to avoid global variables. Otherwise, these variables would interfere with the variables of the same name in the above construction.

In order to optimize the execution speed the second parameter "suspendedUpdate" of the function is used. This parameter is set true in the first call of the function during an update of the board. Since in each update the function is called several thousand times it is useful to compute values that do not change during the update only once. In the above case, in each call of the function the powers [math]\displaystyle{ aa^k }[/math] and [math]\displaystyle{ bb^k }[/math] are used many times. Since [math]\displaystyle{ aa }[/math] and [math]\displaystyle{ bb }[/math] do not change during a single update, we can precompute these values and store them.

(function(){
 var bd = JXG.JSXGraph.initBoard('box2', {axis:true, boundingbox: [-5, 3, 5, -3]});
 var a = bd.create('slider', [[0.5,2],[2.5,2],[0,0.3,1]], {name:'a'});
 var b = bd.create('slider', [[0.5,1.5],[2.5,1.5],[0,20,100]], {name:'b'}); 
 var N = bd.create('slider', [[0.5,1.0],[2.5,1.0],[0,2,30]], {name:'N'}); 
 var f = function(x, suspendedUpdate){
            var k, s=0.0;
            if (!suspendedUpdate) {
                this.n = N.Value();
                this.aa= a.Value();
                this.bb = b.Value();
                this.aArr = [1.0];
                this.bArr = [1.0*Math.PI];
                for (k=1; k<this.n; k++) {
                  this.aArr[k] = this.aArr[k-1]*this.aa;
                  this.bArr[k] = this.bArr[k-1]*this.bb;
                }     
            }
            for (k=1; k<this.n; k++) {
                s += this.aArr[k]*Math.cos(this.bArr[k]*x);
            }
            return s;
         };
 var c = bd.create('functiongraph', [f], {doAdvancedPlot:false, numberPointsHigh:6000, numberPointsLow:500, strokeWidth:1});
})();