-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
140 lines (136 loc) · 6.26 KB
/
main.cpp
File metadata and controls
140 lines (136 loc) · 6.26 KB
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
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <algorithm>
class SenseAmplifier {
public:
double width, length, supplyVoltage, inputVoltage, currentDrive;
SenseAmplifier(double w, double l, double vdd, double vin, double id)
: width(w), length(l), supplyVoltage(vdd), inputVoltage(vin), currentDrive(id) {}
double evaluate() const {
double power = supplyVoltage * currentDrive;
double speed = (width * length) / (currentDrive * supplyVoltage);
double noiseMargin = (width / length) - (currentDrive / supplyVoltage);
double area = width * length;
double cost = power + 1.0 / speed + (100.0 / noiseMargin) + area * 0.0001;
return cost;
}
};
class DEOptimizer {
public:
int populationSize;
int dimensions;
double crossoverRate;
double mutationFactor;
int generations;
std::vector<SenseAmplifier> population;
DEOptimizer(int popSize, int dims, double crossover, double mutation, int gens)
: populationSize(popSize), dimensions(dims), crossoverRate(crossover),
mutationFactor(mutation), generations(gens) {
srand(time(0));
}
void initializePopulation() {
for (int i = 0; i < populationSize; ++i) {
double width = 100 + rand() % 1000;
double length = 50 + rand() % 500;
double supplyVoltage = 0.9 + static_cast<double>(rand()) / RAND_MAX * 0.3;
double inputVoltage = 0.0 + static_cast<double>(rand()) / RAND_MAX * 1.2;
double currentDrive = 10 + rand() % 100;
SenseAmplifier sa(width, length, supplyVoltage, inputVoltage, currentDrive);
population.push_back(sa);
}
}
SenseAmplifier mutate(const SenseAmplifier &target, int idx1, int idx2, int idx3) {
SenseAmplifier &p1 = population[idx1];
SenseAmplifier &p2 = population[idx2];
SenseAmplifier &p3 = population[idx3];
double newWidth = target.width + mutationFactor * (p1.width - p2.width);
double newLength = target.length + mutationFactor * (p1.length - p3.length);
double newSupplyVoltage = target.supplyVoltage + mutationFactor * (p2.supplyVoltage - p3.supplyVoltage);
double newInputVoltage = target.inputVoltage + mutationFactor * (p1.inputVoltage - p3.inputVoltage);
double newCurrentDrive = target.currentDrive + mutationFactor * (p2.currentDrive - p1.currentDrive);
return SenseAmplifier(newWidth, newLength, newSupplyVoltage, newInputVoltage, newCurrentDrive);
}
SenseAmplifier crossover(const SenseAmplifier &target, const SenseAmplifier &mutant) {
double newWidth = target.width;
double newLength = target.length;
double newSupplyVoltage = target.supplyVoltage;
double newInputVoltage = target.inputVoltage;
double newCurrentDrive = target.currentDrive;
if (static_cast<double>(rand()) / RAND_MAX < crossoverRate) {
newWidth = mutant.width;
}
if (static_cast<double>(rand()) / RAND_MAX < crossoverRate) {
newLength = mutant.length;
}
if (static_cast<double>(rand()) / RAND_MAX < crossoverRate) {
newSupplyVoltage = mutant.supplyVoltage;
}
if (static_cast<double>(rand()) / RAND_MAX < crossoverRate) {
newInputVoltage = mutant.inputVoltage;
}
if (static_cast<double>(rand()) / RAND_MAX < crossoverRate) {
newCurrentDrive = mutant.currentDrive;
}
return SenseAmplifier(newWidth, newLength, newSupplyVoltage, newInputVoltage, newCurrentDrive);
}
void selectNewGeneration(int idx, const SenseAmplifier &candidate) {
double candidateFitness = candidate.evaluate();
double targetFitness = population[idx].evaluate();
if (candidateFitness < targetFitness) {
population[idx] = candidate;
}
}
void optimize() {
initializePopulation();
for (int gen = 0; gen < generations; ++gen) {
for (int i = 0; i < populationSize; ++i) {
int idx1, idx2, idx3;
do { idx1 = rand() % populationSize; } while (idx1 == i);
do { idx2 = rand() % populationSize; } while (idx2 == i || idx2 == idx1);
do { idx3 = rand() % populationSize; } while (idx3 == i || idx3 == idx1 || idx3 == idx2);
SenseAmplifier mutant = mutate(population[i], idx1, idx2, idx3);
SenseAmplifier candidate = crossover(population[i], mutant);
selectNewGeneration(i, candidate);
}
double bestFitness = population[0].evaluate();
int bestIndex = 0;
for (int i = 1; i < populationSize; ++i) {
double fitness = population[i].evaluate();
if (fitness < bestFitness) {
bestFitness = fitness;
bestIndex = i;
}
}
std::cout << "Generation " << gen << " Best Fitness: " << bestFitness << std::endl;
}
double bestFitness = population[0].evaluate();
int bestIndex = 0;
for (int i = 1; i < populationSize; ++i) {
double fitness = population[i].evaluate();
if (fitness < bestFitness) {
bestFitness = fitness;
bestIndex = i;
}
}
std::cout << "Optimized Best Fitness: " << bestFitness << std::endl;
std::cout << "Best Parameters: " << std::endl;
std::cout << "Width: " << population[bestIndex].width << " nm" << std::endl;
std::cout << "Length: " << population[bestIndex].length << " nm" << std::endl;
std::cout << "Supply Voltage: " << population[bestIndex].supplyVoltage << " V" << std::endl;
std::cout << "Input Voltage: " << population[bestIndex].inputVoltage << " V" << std::endl;
std::cout << "Current Drive: " << population[bestIndex].currentDrive << " uA" << std::endl;
}
};
int main() {
int populationSize = 50;
int dimensions = 5;
double crossoverRate = 0.9;
double mutationFactor = 0.8;
int generations = 100;
DEOptimizer optimizer(populationSize, dimensions, crossoverRate, mutationFactor, generations);
optimizer.optimize();
return 0;
}