-
Notifications
You must be signed in to change notification settings - Fork 2
/
Curve.java
1408 lines (1259 loc) · 53.3 KB
/
Curve.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* Curve class consists basic operations which can be performed on curves along with minplus and maxplus operations
*
* @version 1.0
*/
public class Curve {
private double x_intercept; // refers to'x' in straight line equation : y=m*x +c
private double y_intercept;//refers to the 'c' in straight line equation: y = m*x + c
private double slope;//refers to 'm' in in straight line equation: y = m*x + c
private int numSeg;
List<Segments> ds = new ArrayList<>();//List which stores the segments of the curve
private double period = 0; //Flag which represents if the curve is periodic or not. O means not periodic.
/*
*getter and setter method for getting the X_intercept value and setting the X_intercept value.
*/
public double getX_intercept() {
return x_intercept;
}
public void setX_intercept(double x_intercept) {
this.x_intercept = x_intercept;
}
/*
*getter and setter method for getting the y_intercept value and setting the y_intercept value.
*/
public double getY_intercept() {
return y_intercept;
}
public void setY_intercept(double y_intercept) {
this.y_intercept = y_intercept;
}
/*
*getter and setter method for getting the slope value and setting the slope value.
*/
public double getSlope()
{
return slope;
}
public void setSlope(double slope) {
this.slope = slope;
}
/*
*getter and setter method for getting the ds arraylist value and setting the ds arraylist value.
*/
public List<Segments> getDs() {
return ds;
}
public void setDs(List<Segments> ds) {
this.ds = ds;
}
/*
*getter and setter method for getting the period value and setting the period value.
*/
public double getPeriod() {
return period;
}
public void setPeriod(double period) {
this.period = period;
}
/*************************************************************************************
* creating a curve with x-intercepts, y-intercepts and slope for different segments
* Curve Constructor which takes input values of any number
* To create curve objects for the Curve methods
* @param ...seg input numbers containing elements of the curve
*************************************************************************************/
public Curve(double ...seg) //...seg for taking any number of inputs
{
int j=0;
/*
*Checking whether periodicity value is provided in the input or not.
*Each segment consists of starting points(x co-oridnate and y co-ordinate) and slope.
*If there is no reminder when divided by 3, then the periodicity value is not provided in the input.
*/
if(seg.length % 3 == 0)
{ for(int i = 1;i<=(seg.length/3);i++)
{
/*store the 3 values in the 'segment' object by initializing constructor of Segments class*/
Segments segment = new Segments(seg[j], seg[j+1], seg[j+2]);
ds.add(segment); // now add the segment object to the 'ds' arraylist
j +=3; //increment counter by 3 to get the next set of 3 values.
}
numSeg = ds.size()-1;
}
/*
*Checking whether periodicity value is provided in the input or not.
*Each segment consists of starting points(x co-oridnate and y co-ordinate) and slope.
*If there is reminder of 1 when divided by 3, then the periodicity value is provided in the input.
* This periodicity value is the last value from the inputs and it represents the units on X axis for which the curve repeats itself.
*/
else if (seg.length % 3 == 1)
{
/*Store the periodicity value in the variable 'period' of type double */
period = seg[seg.length-1];
//System.out.println("period is "+ period);
for(int i = 1;i<=((seg.length/3)+1);i++)
{
/*
*Checking if periodicity is greater than the starting points of any segment
*/
if(period > seg[j]) //if greater proceed as usual
{
/*store the 3 values in the 'segment' object by initializing constructor of Segments class*/
Segments segment = new Segments(seg[j], seg[j+1], seg[j+2]);
//ds.add((Segments)(segment.add(seg[j], seg[j+1], seg[j+2])));
ds.add(segment);// now add the segment object to the 'ds' arraylist
}
/*if not greater then period variable refers to repeatibility of the curve again for every 'period' units*/
else
{
/*the y co-ordiate and slope values are assessed based on the 'period' value and then stored in the segment object.*/
Segments segment = new Segments(period,(seg[1]+(seg[j-1]*period) + (seg[j-2] -seg[j-1]*seg[j-3])),seg[2]);
ds.add(segment);// now add the segment object to the 'ds' arraylist
i = (seg.length/3)+1;
}
j +=3;//increment counter by 3 to get the next set of 3 values.
numSeg=ds.size()-1;
}
}
}
/********************************************************************************************************
* Curve Constructor which takes an input Arraylist
* Heplful when creating curve objects for the Curve methods
* @param curvearray Arraylist containing elements of the curve
* @param flag flag to check the type of arraylist, flag is 1 for multiplication of 2 curves method
********************************************************************************************************/
public Curve(ArrayList<Double> curvearray, int flag)
{
if(flag==1)//if the arraylist is obtained from the multiplication of two curves,flag is set to 1
{
int j=0;
/*
*Multiplication of two curves results in either parabolic, hyperbolic or elliptical curves and hence slope cannot be calculated.
*Therefore only x co-oridnates and y co-ordinates are stored in the input Arraylist.
*/
if(curvearray.size() % 2 == 0)
{ for(int i = 1;i<=(curvearray.size()/2);i++)//loop through the arraylist
{
Segments segment = new Segments(curvearray.get(j), curvearray.get(j+1));//store the 2 values in the 'segment' object by initializing constructor of Segments class
ds.add(segment); // now add the segment object to the 'ds' arraylist
j +=2; //increment counter by 2 to get the next set of co-ordinates.
}
}
}
else //if flag is not equal to 1 then it is an general curve.
{
int j=0;
if(curvearray.size() % 3 == 0)
{ for(int i = 1;i<=(curvearray.size()/3);i++)//loop through the arraylist
{
Segments segment = new Segments(curvearray.get(j), curvearray.get(j+1),curvearray.get(j+2));//store the 3 values in the 'segment' object by initializing constructor of Segments class
ds.add(segment); // now add the segment object to the 'ds' arraylist
j +=3;//increment counter by 3 to get the next set of co-ordinates and slope values.
}
}
}
}
/*********************************************************************************
* evaluateYatX To Evaluate Y value at a given X co-ordinate of any curve
* @param x Co-ordinate
* @return Y value at the given x co-ordinate on the curve
*********************************************************************************/
public double evaluateYatX(double x)
{
double y = 0;
/*
*if the curve has no periodicity, implements below code
*/
if(period == 0)
{
//System.out.println("number of segments: " + ds.size());
for(int i = 0;i<ds.size();i++)//looping through the curve arraylist
{
if(x >= ds.get(i).getarrayValue(0))//if condition to identify the segment the x value belongs to
{
slope = ds.get(i).getarrayValue(2); //get the slope value from the corresponding segment
y_intercept = ds.get(i).getarrayValue(1) - slope * ds.get(i).getarrayValue(0);//calculate y_intercept value, which equals (y - slope * x).
y = (slope * x) + y_intercept;//calculate y value which equals (slope * x + y_intercept)
}
}
//System.out.println("y_intercept is : " + y_intercept);
//System.out.println("slope is : "+ slope);
}
/*
*If curve has periodicity, implements below code
*/
else
{
//System.out.println("number of segments: " + (ds.size()-1));
if(x/period <= 1)//Checking if period is before all the segments start
{
for(int i = 0;i<ds.size();i++)
{
if(x >= ds.get(i).getarrayValue(0))//if condition to identify the segment the x value belongs to
{
slope = ds.get(i).getarrayValue(2); //get the slope value from the corresponding segment
y_intercept = ds.get(i).getarrayValue(1) - slope * ds.get(i).getarrayValue(0);//calculate y_intercept value, which equals (y - slope * x).
y = (slope * x) + y_intercept;//calculate y value which equals (slope * x + y_intercept)
}
}
//System.out.println("y_intercept is : " + y_intercept);
//System.out.println("slope is : "+ slope);
}
else//if the period starts after all the segments start, implements below
{
double xVal = 0;
//int numSeg = ds.size() - 1; //stores number of segments in the curve arraylist
/*
* A do while loop to add the new values to the curve arraylist till it reaches the x value
*/
do
{
int size=ds.size();
//System.out.println("size is " +size);
xVal = ds.get(size-1).getarrayValue(0)+ds.get(size-numSeg).getarrayValue(0)-ds.get(size-numSeg-1).getarrayValue(0); //Calculates the x value of the next segment to be stored in the arraylist
double slopeVal = ds.get(size-numSeg).getarrayValue(2);//Calculates the slope value of the next segment to be stored in the arraylist
double yVal = ds.get(size-1).getarrayValue(1)+ds.get(size-numSeg).getarrayValue(1)-ds.get(size-numSeg-1).getarrayValue(1);//Calculates the y value of the next segment to be stored in the arraylist
Segments segment = new Segments(xVal, yVal, slopeVal); // Add the above 3 values to the segment object
ds.add(segment);// add the segement to the curve arraylist
}while(xVal < x); /*repeat this till X value is less than or equal to the input x value.*/
for(int i = 0;i<ds.size();i++)
{
if(x >= ds.get(i).getarrayValue(0))//if condition to identify the segment the x value belongs to
{
slope = ds.get(i).getarrayValue(2);//get the slope value from the corresponding segment
y_intercept = ds.get(i).getarrayValue(1) - slope * ds.get(i).getarrayValue(0);//calculate y_intercept value, which equals (y - slope * x).
y = (slope * x) + y_intercept;//calculate y value which equals (slope * x + y_intercept)
}
}
//System.out.println("y_intercept is : " + y_intercept);
//System.out.println("slope is : "+ slope);
}
}
return y;
}
/*********************************************************************************
* ExpandOnXaxis To expand the Y values till the given X co-ordinate of any curve
* @param timePeriod
* @return Expanded Curve
*********************************************************************************/
public Curve ExpandOnXaxis(double timePeriod)
{
Curve expandedCurve;//intialize new curve object to store final result
ArrayList<Double> exp1= new ArrayList<>();//intialize new array object
//int numSeg = ds.size()-1;
//ArrayList<Double> exp2= new ArrayList<>();
if((ds.get(ds.size()-1).getarrayValue(0))<timePeriod && period !=0)//if condition to identify the segment the x value belongs to.
{
for (int i = 0; i < ds.size(); i++)//storing the parent curve object into an arraylist
{
exp1.add(ds.get(i).getarrayValue(0));
exp1.add(ds.get(i).getarrayValue(1));
exp1.add(ds.get(i).getarrayValue(2));
}
double xVal =0;
/*
* A do while loop to add the new values to the curve arraylist till it reaches the x value .
*/
do
{
int size=ds.size();
//System.out.println("size is " +size);
exp1.add(ds.get(size-1).getarrayValue(0)+ds.get(size-numSeg).getarrayValue(0)-ds.get(size-numSeg-1).getarrayValue(0));
//exp1.add(expandedCurve.getCellValue((size-1),(0))+expandedCurve.getCellValue((size-numSeg),(0))-expandedCurve.getCellValue((size-numSeg-1),0)); //Calculates the x value of the next segment to be stored in the arraylist
exp1.add(ds.get(size-numSeg).getarrayValue(2));
//exp1.add(expandedCurve.getCellValue((size-numSeg),2));//Calculates the slope value of the next segment to be stored in the arraylist
exp1.add(ds.get(size-1).getarrayValue(1)+ds.get(size-numSeg).getarrayValue(1)-ds.get(size-numSeg-1).getarrayValue(1));
//exp1.add(expandedCurve.getCellValue((size-1),1) + expandedCurve.getCellValue((size-numSeg),1)-expandedCurve.getCellValue((size-numSeg-1),1));//Calculates the y value of the next segment to be stored in the arraylist
//Segments segment = new Segments(xVal, yVal, slopeVal); // Add the above 3 values to the segment object
//ds.add(segment);// add the segement to the curve arraylist
}while(xVal <= timePeriod); /*repeat this till X value is less than or equal to the input x value.*/
}
else
{
for (int i = 0; i < ds.size(); i++)
{
exp1.add(ds.get(i).getarrayValue(0));
exp1.add(ds.get(i).getarrayValue(1));
exp1.add(ds.get(i).getarrayValue(2));
}
}
expandedCurve = new Curve(exp1, 2); //store the elements in the curve object
return expandedCurve;
}
/*********************************************************************************
* evaluateSatX To Evaluate slope value at a given X co-ordinate of any curve
* @param x Co-ordinate
* @return slope value at the given x co-ordinate on the curve
*********************************************************************************/
public double evaluateSatX(double x)
{
double y = evaluateYatX(x);//Calculating Y value at the given X value.
for(int i = 0;i<ds.size()-1;i++)
{
if(y > ds.get(i).getarrayValue(1)&& y <ds.get(i+1).getarrayValue(1) )//if condition to identify the segment the y value belongs to
{
slope = ds.get(i).getarrayValue(2); //get the slope value from the corresponding segment
}
//System.out.println("x value: "+ x + " y value: "+ y + " slope: "+ slope);
}
return slope;
}
/***************************************************************************************************
* multiplicationOfTwoCurves Multiplies two curve objects and returns the resultant curve object
* @param c1 First Curve
* @param c2 Second Curve
* @param timePeriod Time period until which the two curves are multiplied
* @return c3 Resultant Curve which consists of only x and y co-ordinates without slope value
***************************************************************************************************/
public static Curve multiplicationOfTwoCurves(Curve curve1, Curve curve2, double timePeriod)
{
Curve c1 = curve1.ExpandOnXaxis( timePeriod); // Using evaluateYatX method to expand the arraylist till timeperiod
Curve c2 = curve2.ExpandOnXaxis(timePeriod); // Using evaluateYatX method to expand the arraylist till timeperiod
ArrayList<Double> al1 = new ArrayList<>(); // new arraylist to store the the x co-ordinates
/*
*for loop to get the x-co-ordinates from the first curve and store them in an arraylist
*/
for (int i = 0; i < c1.size(); i++)
al1.add(c1.getCellValue(i,0));
/*
*for loop to get the x-co-ordinates from the second curve and store them in an arraylist
*/
for (int i = 0; i < c2.size(); i++)
al1.add(c2.getCellValue(i,0));
/*checking and adding intersection point of two curves.*/
al1.add(IntersectionOfCurves(c1,c2,timePeriod));
/*sort the elements in the arraylist in ascending order*/
Collections.sort(al1);
/*remove duplicate elements in the arraylist*/
List<Double> al2 = al1.stream().distinct().collect(Collectors.toList());
/*new arraylist to store resultant values of multplication of the curves*/
ArrayList<Double> al3 = new ArrayList<>();
/*loop through each element of arraylist holding unique x values*/
for(double xval : al2 )
{
al3.add(xval);// add the x value to the new arraylist
/*
*add the resultant y value to the new arraylist by
*multiplying the corresponding y values at the given x value of both curves
*/
al3.add(c1.evaluateYatX(xval) * c2.evaluateYatX(xval));
}
Curve c3 = new Curve(al3,1); // new curve object created with the input as the final resultant arraylist
return c3;
}
/***************************************************************************************************************************
* Ceil method implments the ceil of the curve for a given curve upto the given timeperiod and returns the resultant curve
* @param curve1 Input curve
* @param timePeriod Timeperiod until which the curve must be ceiled
* @return ceiledcurve
***************************************************************************************************************************/
public static Curve ceil(Curve c1, int timePeriod)
{
ArrayList<Double> ceil1 = new ArrayList<>(); // To store the values of the ceiled curve
double slope = 0; //ceiled curve is divided into segments with zero slope.
Curve curve1 = c1.ExpandOnXaxis(timePeriod);
//curve1.evaluateYatX(timePeriod); // expanding the curve through the evaluateYatX method till X is timePeriod
for (int i =0; i<timePeriod;i++) //Y value is evaluated in increments of 1 on x axis till it reaches timeperiod
{
if(curve1.EvaluateXatY(i) <= timePeriod) // condition to check if the X value at given Y value is less than the time period
{
ceil1.add(curve1.EvaluateXatY(i));//add the x value evaluated at the given y value of the segment
ceil1.add((double)i+1);//add the y value which is the starting point of the segment
ceil1.add(slope);// add slope value which is zero for each segment
}
}
Curve ceiledcurve = new Curve(ceil1,2); //create the curve object with input as the ceil1 arraylist containing x,y and slope values of each segment
return ceiledcurve;
}
/*****************************************************************************************************************************
* floor method implements the floor of the curve for a given curve upto the given timeperiod and returns the resultant curve
* @param curve1 Input curve
* @param timePeriod imeperiod until which the curve must floored
* @return flooredcurve
******************************************************************************************************************************/
public static Curve floor(Curve c1, int timePeriod)
{
ArrayList<Double> floor1 = new ArrayList<>(); // To store the values of the floored curve
double slope = 0;//floored curve is divided into segments with zero slope.
Curve curve1 = c1.ExpandOnXaxis(timePeriod);
//curve1.evaluateYatX(timePeriod); // expanding the curve through the evaluateYatX method till X is timePeriod
for (int i =0; i<timePeriod;i++) //Y value is evaluated in increments of 1 on x axis till it reaches timeperiod
{
if(curve1.EvaluateXatY(i) <= timePeriod)// condition to check if the X value at given Y value is less than the time period
{
floor1.add(curve1.EvaluateXatY(i));//add the x value evaluated at the given y value of the segment
floor1.add((double)i); //add the y value which is the starting point of the segment
floor1.add(slope); // add slope value which is zero for each segment
}
}
Curve flooredcurve = new Curve(floor1,2); //create the curve object with input as the floor1 arraylist containing x,y and slope values of each segment
return flooredcurve;
}
/******************************************************************************
* EvaluateXatY Method returns the value of X at a given Y of the input curve
* @param y y co-ordinate at which the x value is required
* @return x x co-ordinate at the given y co-ordinate
******************************************************************************/
public double EvaluateXatY(double y)
{
double x = 0; //intializing variable
for(int i = 0;i<ds.size();i++)//looping through the curve arraylist
{
if(y > ds.get(i).getarrayValue(1))//if condition to identify the segment the y value belongs to
{
slope = ds.get(i).getarrayValue(2); //get the slope value from the corresponding segment
y_intercept = ds.get(i).getarrayValue(1) - slope * ds.get(i).getarrayValue(0);//calculate y_intercept value, which equals (y - slope * x).
x = (y - y_intercept)/(slope);//calculate x value
}
}
return x;
}
/***********************************************************************
* scaleOnX To scale the curve on X axis by a scaling factor.
* @param curve1 Input Curve
* @param scalingFactor Factor by which the X co-ordinates are scaled.
* @return Scaled Curve on X axis
***********************************************************************/
public static Curve scaleOnX(Curve curve1, double scalingFactor)
{
Curve scaledCurve;//Initialize Curve object to store the result curve
double slope1;//Initialize variable to store slope values
ArrayList<Double> ScaleOnX = new ArrayList<>(); //Initialize an array list for easy computation.
/*
* For loop to store all values of the input curve into the arraylist
*/
for (int i = 0; i < curve1.size(); i++)
{
ScaleOnX.add(curve1.getCellValue(i,0));
ScaleOnX.add(curve1.getCellValue(i,1));
ScaleOnX.add(curve1.getCellValue(i,2));
}
/*
* Multiply all the x values by the scaling factor
*/
for(int i =0; i <ScaleOnX.size(); i = i+3)
{
ScaleOnX.set(i, ScaleOnX.get(i) * scalingFactor );
}
/*
* For computing the new slope values and storing them
*/
for(int i= 2; i<ScaleOnX.size(); i = i+3 )
{
if(i<=ScaleOnX.size()-4)//condition to check if it is not the last segment
{
/*
* slope is calculated using mathematical approach of 'dy/dx'.
*/
slope1 = (ScaleOnX.get(i+2) - ScaleOnX.get(i-1) )/(ScaleOnX.get(i+1) - ScaleOnX.get(i-2));
ScaleOnX.set(i, slope1);
}
else //If last segement, compute slope by below process
{
/*
* slope is calculated by computing the next x and y values at an increment of 0.01 and then use dy/dx.
*/
slope1 = (ScaleOnX.get(i-1) - curve1.evaluateYatX(curve1.getCellValue(curve1.size()-1, 0)+0.01))/(ScaleOnX.get(i-2) - (curve1.getCellValue(curve1.size()-1, 0)+0.01)*scalingFactor);
ScaleOnX.set(i, slope1);
}
}
scaledCurve = new Curve(ScaleOnX, 2);//Constructor to store the elements in the curve object
return scaledCurve;
}
/***************************************************************************************
* scaleOnY To scale the curve on Y axis by a scaling factor.
* @param curve1 Input Curve
* @param scalingFactor Factor by which the Y co-ordinates are scaled.
* @return Scaled Curve on Y axis
****************************************************************************************/
public static Curve scaleOnY(Curve curve1, double scalingFactor)
{
Curve scaledCurve;//Initialize Curve object to store the result curve
double slope1;//Initialize variable to store slope values
ArrayList<Double> ScaleOnY = new ArrayList<>(); //Initialize an array list for computation.
/*
* For loop to store all values of the input curve into the arraylist
*/
for (int i = 0; i < curve1.size(); i++)
{
ScaleOnY.add(curve1.getCellValue(i,0));
ScaleOnY.add(curve1.getCellValue(i,1));
ScaleOnY.add(curve1.getCellValue(i,2));
}
/*
* Multiply all the y values by the scaling factor
*/
for(int i =1; i <ScaleOnY.size(); i = i+3)
{
ScaleOnY.set(i, ScaleOnY.get(i) * scalingFactor );
}
/*
* For computing the new slope values and storing them
*/
for(int i= 2; i<ScaleOnY.size(); i = i+3 )
{
if(i<=ScaleOnY.size()-4)//condition to check if it is not the last segment
{
/*
* slope is calculated using mathematical approach of 'dy/dx'.
*/
slope1 = (ScaleOnY.get(i-1) - ScaleOnY.get(i+2))/(ScaleOnY.get(i-2) - ScaleOnY.get(i+1));
ScaleOnY.set(i, slope1);
}
else //If last segment, compute slope by below process
{
/*
* slope is calculated by computing the next x and y values at an increment of 0.01 and then use dy/dx.
*/
slope1 = ((curve1.evaluateYatX(curve1.getCellValue(curve1.size()-1, 0)+0.01))*scalingFactor - ScaleOnY.get(i-1))/((curve1.getCellValue(curve1.size()-1, 0)+0.01)- ScaleOnY.get(i-2));
ScaleOnY.set(i, slope1);
}
}
scaledCurve = new Curve(ScaleOnY, 2); //Constructor to store the elements in the curve object
return scaledCurve;
}
/*****************************************************
* Invert To compute the inverse of the given curve.
* @param curve1 Input Curve
* @return Inverted curve
*****************************************************/
public static Curve Invert(Curve curve1)
{
Curve Inverted;//Initialize Curve object to store the result curve
double slope1;//Initialize variable to store slope values
ArrayList<Double> Invert = new ArrayList<>(); //Initialize an array list for computation.
/*
* If condition to check if the inverted curve should
* start at x and y co-ordinates (0,0)
*/
if(curve1.getCellValue(0, 1)!=0)
{
Invert.add(0,0.0);
Invert.add(0,0.0);
Invert.add(0,0.0);
}
/*
* Store the values in the Arraylist by inverting x and y values
*/
for (int i = 0; i < curve1.size(); i++)
{
Invert.add(curve1.getCellValue(i,1));
Invert.add(curve1.getCellValue(i,0));
Invert.add(curve1.getCellValue(i,2));
}
/*
* For computing the new slope values and storing them
*/
for(int i= 2; i<Invert.size(); i = i+3 )
{
if(i<=Invert.size()-4)//condition to check if it is not the last segment
{
/*
* slope is calculated using mathematical approach of 'dy/dx'.
*/
slope1 = (Invert.get(i+2) - Invert.get(i-1))/(Invert.get(i+1) - Invert.get(i-2));
Invert.set(i, slope1);
}
else//If last segment, compute slope by below process
{
/*
* slope is calculated by computing the next x and y values at an increment of 0.01 and then use dy/dx.
*/
slope1 = ( Invert.get(i-1) - (curve1.getCellValue(curve1.size()-1, 0)+0.01))/(Invert.get(i-2) - (curve1.evaluateYatX(curve1.getCellValue(curve1.size()-1, 0)+0.01)));
Invert.set(i, slope1);
}
}
Inverted = new Curve(Invert, 2);//Constructor to store the elements in the curve object
return Inverted;
}
/*****************************************************
* Affine function : To compute the Affine(Shifting and scaling) of the given curve.
* @param curve1 Input Curve
* @param scaling factor
* @param x_offset
* @return Affine curve
*****************************************************/
public static Curve affine(Curve curve1, double scalingFactor, double x_offset)
{
/*Curve to store the result after scaling*/
Curve affine1;
/*Using the scaleOnX function by providing the scaling factor*/
affine1= scaleOnX(curve1, scalingFactor);
for(int i =0; i<affine1.size();i++){
//System.out.println(affine1.getSegmentValue(i));
}
/*Curve to store the result after shifting*/
Curve affine2;
/*Using the shiftOnX function by providing the x_offset*/
affine2 = shiftOnX(affine1,x_offset);
return affine2;
}
/*****************************************************
* shiftOnX function : To shift the given curve by a offset on x-axis.
* @param curve1 Input Curve
* @param x_offset
* @return shiftedCurve
*****************************************************/
public static Curve shiftOnX(Curve curve1, double x_offset)
{
/*Array list to hold the values of the curve*/
ArrayList<Double> Shifter = new ArrayList<>();
/*Curve to store the result*/
Curve shifted;
/*
* if x_offset is greater than 0 append the first segment of resultant curve as [0,0,0]
* as the curve should start from the point x=0.
*/
if(x_offset>0)
{
Shifter.add(0.0);
Shifter.add(0.0);
Shifter.add(0.0);
for (int i = 0; i < curve1.size(); i++)
{
if(curve1.getCellValue(i,1) ==0 && curve1.getCellValue(i,2)==0)
{
/*if the y-value and slope of the segment are 0
* Do nothing
* */
}
else
{
/*add the offset to the x-value in the segment*/
Shifter.add(curve1.getCellValue(i,0) + x_offset);
Shifter.add(curve1.getCellValue(i,1));
Shifter.add(curve1.getCellValue(i,2));
}
}
}
else
{
for (int i = 0; i < curve1.size(); i++)
{
/*
* if x_offset is lesser than 0 append the first segment of resultant curve
* as the curve should start from the point x=0.
*/
if(curve1.getCellValue(i,0) + x_offset < 0)
{
Shifter.add(0.0);
Shifter.add(curve1.evaluateYatX(Math.abs(x_offset)));
Shifter.add(curve1.getCellValue(i,2));
}
else
{
Shifter.add(curve1.getCellValue(i,0) + x_offset);
Shifter.add(curve1.getCellValue(i,1));
Shifter.add(curve1.getCellValue(i,2));
}
}
}
shifted = new Curve(Shifter,2);
return shifted;
}
/*****************************************************
* MultiplyScalar function : To multiply the given curve by a scalar.
* @param curve1 Input Curve
* @param scalar to multiply
* @return scaledCurve
*****************************************************/
public static Curve multiplyScalar(Curve a,double scalar)
{
/*Array list to hold the values of the curve*/
ArrayList<Double> mulScalar = new ArrayList<>();
/*Resultant curve*/
Curve mScalar;
for (int i = 0; i < a.size(); i++)
{
mulScalar.add(a.getCellValue(i,0)*scalar);//multiplying the x-values by scalar
mulScalar.add(a.getCellValue(i,1)*scalar);// multiplying the y-values by scalar
mulScalar.add(a.getCellValue(i,2));// no change i slope
}
mScalar = new Curve(mulScalar,2);//Constructor to store the elements in the curve object
return mScalar;
}
/***************************************************************************************************
* AdditionOfTwoCurves : Adds two curves and returns the resultant curve
* @param c1 First Curve
* @param c2 Second Curve
* @param timePeriod Time period until which the two curves are multiplied
* @return c3 Resultant Curve
***************************************************************************************************/
public static Curve addCurve(Curve curve1, Curve curve2, double timePeriod)
{
Curve c1 = curve1.ExpandOnXaxis( timePeriod);// Using ExpandOnXaxis method to expand the arraylist till timeperiod
Curve c2 = curve2.ExpandOnXaxis( timePeriod);// Using ExpandOnXaxis method to expand the arraylist till timeperiod
ArrayList<Double> al1 = new ArrayList<>(); // new arraylist to store the the x co-ordinates
/*
*for loop to get the x-co-ordinates from the first curve and store them in an arraylist
*/
for (int i = 0; i < c1.size(); i++)
al1.add(c1.getCellValue(i,0));
/*
*for loop to get the x-co-ordinates from the second curve and store them in an arraylist
*/
for (int i = 0; i < c2.size(); i++)
al1.add(c2.getCellValue(i,0));
Collections.sort(al1);//sort the elements in the arraylist in ascending order
List<Double> al2 = al1.stream().distinct().collect(Collectors.toList()); //remove duplicate elements in the arraylist
ArrayList<Double> al3 = new ArrayList<>(); //new arraylist to store resultant values of addition of the curves
/*loop through each element of arraylist holding unique x values*/
for(double xval : al2 )
{
al3.add(xval);// add the x value to the new arraylist
/*
*add the resultant y value to the new arraylist by
*adding the corresponding y values at the given x value of both curves
*/
al3.add(c1.evaluateYatX(xval) + c2.evaluateYatX(xval));
al3.add(c1.evaluateSatX(xval)+ c2.evaluateSatX(xval));
}
Curve c3 = new Curve(al3,2); // new curve object created with the input as the final resultant arraylist
return c3;
}
/***************************************************************************************************
* MaximumOfTwoCurves : Resultant curve provides the maximum of two curves.
* @param c1 First Curve
* @param c2 Second Curve
* @param timePeriod Time period until which the two curves are multiplied
* @return c3 Resultant Curve
***************************************************************************************************/
public static Curve curveMax(Curve curve1, Curve curve2, double timePeriod)
{
Curve c1 = curve1.ExpandOnXaxis(timePeriod);// Using ExpandOnXaxis method to expand the arraylist till timeperiod
Curve c2 = curve2.ExpandOnXaxis(timePeriod);// Using ExpandOnXaxis method to expand the arraylist till timeperiod
ArrayList<Double> al1 = new ArrayList<>(); // new arraylist to store the the x co-ordinates
/*
*for loop to get the x-co-ordinates from the first curve and store them in an arraylist
*/
for (int i = 0; i < c1.size(); i++)
al1.add(c1.getCellValue(i,0));
/*
*for loop to get the x-co-ordinates from the second curve and store them in an arraylist
*/
for (int i = 0; i < c2.size(); i++)
al1.add(c2.getCellValue(i,0));
/*
* finding the intersection point of the curves and adding to the array list
*/
al1.add(IntersectionOfCurves(c1,c2,timePeriod));
Collections.sort(al1);//sort the elements in the arraylist in ascending order
List<Double> al2 = al1.stream().distinct().collect(Collectors.toList()); //remove duplicate elements in the arraylist
ArrayList<Double> al3 = new ArrayList<>(); //new arraylist to store resultant values of Maximum of the curves
/*loop through each element of arraylist holding unique x values*/
for(double xval : al2 )
{
al3.add(xval);// add the x value to the new arraylist
/*
* Evaluating and comparing the y-values of both the curves
* if c1 curve is greater than c2 curve then add the y-value and slope in the arraylist
*/
if(c1.evaluateYatX(xval) > c2.evaluateYatX(xval) )
{
al3.add(c1.evaluateYatX(xval));
al3.add(c1.evaluateSatX(xval));
}
else if(c1.evaluateYatX(xval) <c2.evaluateYatX(xval))
{
/* if c2 curve is greater than c1 curve then add the y-value and slope in the arraylist*/
al3.add(c2.evaluateYatX(xval));
al3.add(c2.evaluateSatX(xval));
}
else
{
if(c1.evaluateSatX(xval)>c2.evaluateSatX(xval))
{
al3.add(c1.evaluateYatX(xval));
al3.add(c1.evaluateSatX(xval));
}
else
{
al3.add(c2.evaluateYatX(xval));
al3.add(c2.evaluateSatX(xval));
}
}
}
Curve c3 = new Curve(al3,2); // new curve object created with the input as the final resultant arraylist
return c3;
}
/***************************************************************************************************
* IntersectionOfCurves : Provides the intersection point on x-axis of two curves.
* @param c1 First Curve
* @param c2 Second Curve
* @param timePeriod Time period until which the two curves are multiplied
* @return intersection x-point
***************************************************************************************************/
public static double IntersectionOfCurves(Curve curve1, Curve curve2, double timeperiod)
{
double Ipoint = 0;// declaring and intitalizing intersection point to 0
final double THRESHOLD = .01; // limitng the number of decimal places to 0.01
/*Looping through the curve for the timeperiod for every change of 0.01 in x-axis*/
for(double i = 0; i<timeperiod; i = i+ 0.01 )
{
/*Evaluating the y-values for both the curves and subtracting to find the intersection point */
if(Math.abs(curve1.evaluateYatX(i) - curve2.evaluateYatX(i)) < THRESHOLD)
{
Ipoint = i;
}
}
/*
* Using the Decimal format class for limiting the number of decimal places to 3
*/
DecimalFormat newFormat = new DecimalFormat("##########.###");
double twoDecimal = Double.valueOf(newFormat.format(Ipoint));
return twoDecimal;// returning the intersection point after limiting.
}
/***************************************************************************************************
* MaximumOfTwoCurves : Resultant curve provides the maximum of two curves.
* @param c1 First Curve
* @param c2 Second Curve
* @param timePeriod Time period until which the two curves are multiplied
* @return c3 Resultant Curve
***************************************************************************************************/
public static Curve curveMin(Curve curve1, Curve curve2, double timePeriod)
{
Curve c1 = curve1.ExpandOnXaxis(timePeriod);// Using ExpandOnXaxis method to expand the arraylist till timeperiod
Curve c2 = curve2.ExpandOnXaxis(timePeriod);// Using ExpandOnXaxis method to expand the arraylist till timeperiod
ArrayList<Double> al1 = new ArrayList<>(); // new arraylist to store the the x co-ordinates
/*
*for loop to get the x-co-ordinates from the first curve and store them in an arraylist
*/
for (int i = 0; i < c1.size(); i++)
al1.add(c1.getCellValue(i,0));
/*
*for loop to get the x-co-ordinates from the second curve and store them in an arraylist
*/
for (int i = 0; i < c2.size(); i++)
al1.add(c2.getCellValue(i,0));
al1.add(IntersectionOfCurves(c1,c2,timePeriod));
Collections.sort(al1);//sort the elements in the arraylist in ascending order
List<Double> al2 = al1.stream().distinct().collect(Collectors.toList()); //remove duplicate elements in the arraylist
ArrayList<Double> al3 = new ArrayList<>(); //new arraylist to store resultant values of minimum of the curves
/*loop through each element of arraylist holding unique x values*/
for(double xval : al2 )
//for (int i = 0; i )
{
al3.add(xval);// add the x value to the new arraylist
/*
* Evaluating and comparing the y-values of both the curves
* if c1 curve is lesser than c2 curve then add the y-value and slope in the arraylist
*/
if(c1.evaluateYatX(xval) < c2.evaluateYatX(xval) )
{
al3.add(c1.evaluateYatX(xval));
al3.add(c1.evaluateSatX(xval));
}
else if(c1.evaluateYatX(xval) > c2.evaluateYatX(xval) )
{
/* if c2 curve is lesser than c1 curve then add the y-value and slope in the arraylist*/
al3.add(c2.evaluateYatX(xval));
al3.add(c2.evaluateSatX(xval));
}
else
{
if(c1.evaluateSatX(xval) < c2.evaluateSatX(xval))
{
al3.add(c1.evaluateYatX(xval));
al3.add(c1.evaluateSatX(xval));
}
else
{
al3.add(c2.evaluateYatX(xval));
al3.add(c2.evaluateSatX(xval));
}
}
}
Curve c3 = new Curve(al3,2); // new curve object created with the input as the final resultant arraylist
return c3;
}
/***************************************************************************************************
* Min-plus Convlution : Resultant curve provides the min-plus convolution of two curves.
* @param c1 First Curve
* @param c2 Second Curve
* @param timePeriod Time period until which the two curves are multiplied
* @return c3 Resultant Curve
***************************************************************************************************/
public static Curve minConv(Curve curve1, Curve curve2, int timePeriod)
{
/*declaring and intialising the latency*/
double capT = 0;
//double b=0;
Curve minc1 = curve1.ExpandOnXaxis(timePeriod);// Using ExpandOnXaxis method to expand the arraylist till timeperiod
Curve minc2 = curve2.ExpandOnXaxis(timePeriod);// Using ExpandOnXaxis method to expand the arraylist till timeperiod
Curve minCf;
/* if the size of both the curves are only one segment then Minimum of two curves is the resultant curve*/
if(minc1.size() == 1 && minc2.size() == 1)
minCf = curveMin(minc1,minc2,timePeriod);
else
{