-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProgram.cs
417 lines (367 loc) · 17.7 KB
/
Program.cs
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
/*--------------------------------------------------------------------------------------------------------------------
| Logistic Map and Predator-Prey Bifurcation |
--------------------------------------------------------------------------------------------------------------------*/
namespace FinalExam
{
class Program
{
static void Main(string[] args)
{
//test of Vector and FunctionVector
FunctionVector fv = new FunctionVector(3);
fv[0] = x => x[0] + x[1] + x[2];
fv[1] = x => x[0] + x[1] * x[2];
fv[2] = x => x[0] * x[1] + x[2];
Vector tmp = fv.Evaluate(new Vector(new double[] { 1, -1, 3 }));
Console.WriteLine("tmp = {0}", tmp);
//predator prey simulation
//(1) single value
PredPrey p = new PredPrey();
p.Nsettle = 1000;
Vector v0 = new Vector(new double[] { 0.83, 0.55 });
p.Delta = 1.38;
p.run1sim(v0, "outfile.csv");
//(2) produce bifurcation plot data use default values
p.runsimDrange(v0, 1.26, 1.4, 1000, "outfile1.csv");
//(3) produce second bifurcation plot
p.R = 3;
p.B = 3.5;
p.D = 2;
v0 = new Vector(new double[] { 0.57, 0.37 });
p.runsimDrange(v0, 0.5, 0.95, 1000, "outfile2.csv");
}
}
// Delegate for a method that takes a double and two vectors as input
public delegate double Function(Vector arg);
/*=======================================================================================================================*/
/* PredPrey CLASS */
/*=======================================================================================================================*/
/// <summary>
/// Generates data to produce a bifurcation diagram for discrete predator-prey model
/// Public methods:
/// run1sim(Vector v0, string filename): runs simulation for one value of delta
/// runsimDrange(Vector v0, double deltafrom, double deltato, int numsteps, string filename):
/// runs simulation for a range of values of delta
/// </summary>
class PredPrey
{
/*-------------------------------------------------------------------------------------------------------------------*/
/* Private data */
/*-------------------------------------------------------------------------------------------------------------------*/
private FunctionVector fv = new FunctionVector();
private double delta = 0.5;
private double r = 2;
private double b = 0.6;
private double d = 0.5;
private int nsettle = 200;
private int nreps = 200;
/*-------------------------------------------------------------------------------------------------------------------*/
/* Properties */
/*-------------------------------------------------------------------------------------------------------------------*/
public double Delta
{
get => delta;
set
{
if (value > 0) delta = value;
else throw new Exception("delta must be greater than 0");
}
}
public double R { get => r; set => r = value; }
public double B { get => b; set => b = value; }
public double D { get => d; set => d = value; }
public int Nsettle
{
get => nsettle;
set
{
if (value > 1) nsettle = value;
else nsettle = 200;
}
}
public int Nreps
{
get => nreps;
set
{
if (value > 1) nreps = value;
else nreps = 200;
}
}
/*-------------------------------------------------------------------------------------------------------------------*/
/* Constructors */
/*-------------------------------------------------------------------------------------------------------------------*/
public PredPrey()
{
fv[0] = v => (R * v[0] * (1 - v[0])) - (B * v[0] * v[1]);
fv[1] = v => (-D + B * v[0]) * v[1];
}
/*-------------------------------------------------------------------------------------------------------------------*/
/* Public methods */
/*-------------------------------------------------------------------------------------------------------------------*/
public void runsimDrange(Vector v0, double deltafrom, double deltato, int numsteps, string filename)
{
double range = deltato - deltafrom;
// Run simulation for the given values of delta
for (double del = deltafrom; del <= deltato; del += (range / (numsteps - 1)))
{
this.delta = del;
run1sim(v0, filename);
}
}
public void run1sim(Vector v0, string filename)
{
// Create storage as v0 gets passed by reference
Vector vn = new Vector(v0.Length);
vn = v0;
// Create file to take output, "true" means existing information in file is not overwritten
// between calls to run1sim by other methods
StreamWriter output = new StreamWriter(@filename, true);
// Check file exists
FileInfo finfo = new FileInfo(@filename);
try
{
if (!finfo.Exists) throw new Exception("File does not exist");
}
catch (Exception)
{
Console.WriteLine("{0}, cannot proceed");
}
// Iterate solution until it settles
Vector vnp1 = new Vector(vn.Length);
for (int n = 0; n < nsettle; n++)
{
vnp1 = vn + delta * (fv.Evaluate(vn));
vn = vnp1;
}
// Iterate for nreps
for (int n = 0; n < nreps; n++)
{
vnp1 = vn + delta * (fv.Evaluate(vn));
output.WriteLine("{0}, {1}, {2}", delta, vn[0], vn[1]);
vn = vnp1;
}
output.Close();
}
}
/*=======================================================================================================================*/
/* FunctionVector CLASS */
/*=======================================================================================================================*/
/// <summary>
/// Creates a vector of functions. The functions are assigned to a delegate of type 'Function'.
/// Has a public method 'Evaluate()', which evaluates each function in the FunctionVector and returns a vector of doubles.
/// Allows use of [] notation for indexing (public Function this[])
/// </summary>
///
public class FunctionVector
{
/*-------------------------------------------------------------------------------------------------------------------*/
/* Private data */
/*-------------------------------------------------------------------------------------------------------------------*/
// Array of function elements
private Function[] functionVector;
/*-------------------------------------------------------------------------------------------------------------------*/
/* Constructors */
/*-------------------------------------------------------------------------------------------------------------------*/
// Make FunctionVector size 2 with default lambda functions returning 0
public FunctionVector()
{
this.functionVector = new Function[2];
this.functionVector[0] = (x) => 0;
this.functionVector[1] = (x) => 0;
}
// Size array of delegates, or makes it size 2 if argument less than one
public FunctionVector(int size)
{
size = size >= 1 ? size : 2;
Function[] funcs = new Function[size];
this.functionVector = funcs;
}
// Size array of delegates according to the size of functions, and make
// array delegates reference the delegates in functions
public FunctionVector(Function[] functions)
{
this.functionVector = functions;
}
/*-------------------------------------------------------------------------------------------------------------------*/
/* Indexing and public methods */
/*-------------------------------------------------------------------------------------------------------------------*/
// Indexer for function array
public Function this[int index]
{
get { return this.functionVector[index]; }
set { this.functionVector[index] = value; }
}
// Method to evaluate each function in the FunctionVector
public Vector Evaluate(Vector values)
{
Vector tmp = new Vector(this.functionVector.Length);
for (int i = 0; i < this.functionVector.Length; i++)
tmp[i] = this.functionVector[i](values);
return tmp;
}
}
/*=======================================================================================================================*/
/* Vector CLASS */
/*=======================================================================================================================*/
/// <summary>
/// Represents a vector.
/// Allows use of [] notation for indexing (public double this[])
/// Default constructor creates a zero-Vector length 2.
///
/// Overloaded operators:
/// + Binary Vector addition
/// - Binary Vector subtraction
/// * Vector multiplication (assume dot product is meant)
/// * Post-multiply Vector by double
///
/// Public methods:
/// ToString(): Returns vector as a row in curly brackets.
/// SetSize(): Resizes vector and copies over as many elements as possible
/// </summary>
///
public class Vector
{
/*-------------------------------------------------------------------------------------------------------------------*/
/* Private data and properties */
/*-------------------------------------------------------------------------------------------------------------------*/
// Array of vector elements
private double[] values;
public double[] Values
{
get
{
return values;
}
set
{
if (value.Length == this.Length) values = value;
else Console.WriteLine("Input array must have same length as existing vector");
}
}
public int Length { get => values.Length; }
/*-------------------------------------------------------------------------------------------------------------------*/
/* Constructors */
/*-------------------------------------------------------------------------------------------------------------------*/
// Default constructor, creates vector length 2
public Vector()
{
this.values = new double[2];
}
// Constructor takes an integer defining length as its argument. Defaults to 2 if
// incorrect input
public Vector(int length)
{
length = length >= 1 ? length : 2;
double[] values = new double[length];
this.values = values;
}
// Constructor takes an array of doubles
public Vector(double[] values)
{
this.values = values;
}
/*-------------------------------------------------------------------------------------------------------------------*/
/* Public methods */
/*-------------------------------------------------------------------------------------------------------------------*/
// Resize vector and copy over as many elements as possible
public void SetSize(int size)
{
if (size <= 1)
throw new ArgumentException("Vector must be length 1 or greater");
double[] tmp = new double[size];
int len = Math.Min(size, this.Length);
for (int i = 0; i < len; i++)
{
tmp[i] = this.values[i];
}
this.values = tmp;
}
/*-------------------------------------------------------------------------------------------------------------------*/
/* Operator overloading */
/*-------------------------------------------------------------------------------------------------------------------*/
// Overload + operator for binary addition
public static Vector operator +(Vector left, Vector right)
{
Vector sum = new Vector(left.Values.Length);
if (left.Length != right.Length)
throw new ArgumentException("Addition only possible for vectors of equal length");
for (int i = 0; i < left.Length; i++)
{
sum[i] = left[i] + right[i];
}
return sum;
}
// Overload - operator for binary subtraction
public static Vector operator -(Vector left, Vector right)
{
Vector diff = new Vector(left.Values.Length);
if (left.Length != right.Length)
throw new ArgumentException("Subtraction only possible for vectors of equal length");
for (int i = 0; i < left.Length; i++)
{
diff.Values[i] = left[i] - right[i];
}
return diff;
}
// Overload * operator for inner product
public static double operator *(Vector left, Vector right)
{
double dotProd = 0;
if (left.Length != right.Length)
throw new ArgumentException("Inner product only possible for vectors of equal dimension");
for (int i = 0; i < left.Length; i++)
{
dotProd += left[i] * right[i];
}
return dotProd;
}
// Overload * operator to postmultiply Vector by double
public static Vector operator *(Vector left, double right)
{
Vector result = new Vector(left.Length);
for (int i = 0; i < left.Length; i++)
{
result[i] = left[i] * right;
}
return result;
}
// Overload * operator to premultiply Vector by double
public static Vector operator *(double left, Vector right)
{
Vector result = new Vector(right.Length);
for (int i = 0; i < right.Length; i++)
{
result[i] = right[i] * left;
}
return result;
}
/*-------------------------------------------------------------------------------------------------------------------*/
/* Indexing and overrides */
/*-------------------------------------------------------------------------------------------------------------------*/
// Indexer to allow use of [] notation
public double this[int i]
{
get { return this.Values[i]; }
set { this.Values[i] = value; }
}
// Override array string representation to return a row vector in curly brackets to three decimal places
public override string ToString()
{
string tmp = "{";
for (int i = 0; i < values.Length - 1; i++)
{
tmp += String.Format("{0:0.0}", this[i]);
tmp += ", ";
}
tmp += String.Format("{0:0.0}", this[values.Length - 1]);
return tmp += "}";
}
}
}