Finding minimum total length of line segments to connect 2N points - c++

I'm trying to solve this problem by bruteforce, but it seems to run very slow when given 7 (which is 2*7 points).
Note: I only need to run it to maximum 2*8 points
Problem statement:
Given 2*N points in a 2d plane, connect them in pairs to form N line segments. Minimize the total length of all the line segments.
Example:
Input: 5 10 10 20 10 5 5 1 1 120 3 6 6 50 60 3 24 6 9 0 0
Output: 118.4
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <iomanip>
using namespace std;
class point{
public:
double x, y;
};
double getLength(point a, point b){
return hypot((a.x - b.x), (a.y - b.y));
}
static double mini = INT_MAX;
void solve(vector <point> vec, double sum){
double prevSum = sum;
if(sum > mini){
return;
}
if(vec.size() == 2){
sum += getLength(vec[0], vec[1]);
mini = min(mini, sum);
return;
}
for(int i = 0; i < vec.size() - 1; i++){
for(int j = i + 1; j < vec.size(); j++){
sum = prevSum;
vector <point> temp = vec;
sum += getLength(temp[i], temp[j]);
temp.erase(temp.begin() + j);
temp.erase(temp.begin() + i);
solve(temp, sum);
}
}
}
int main(){
point temp;
int input;
double sum = 0;
cin >> input;
vector<point> vec;
for(int i = 0; i < 2 * input; i++){
cin >> temp.x >> temp.y;
vec.push_back(temp);
}
solve(vec, sum);
cout << fixed << setprecision(2) << mini << endl;
}
How can I speed up this code ?

I don't think this is what you are looking for but I mention it for completeness sake anyway. The problem can be formulated as a Mixed Integer Programming (MIP) problem.
We have distances:
d(i,j) = distance between point i and j (only needed for i<j)
and decision variables
x(i,j) = 1 if points i and j are connected (only needed for i<j)
0 otherwise
Then we can write:
Solving this problem can be done with widely available MIP solvers and leads to proven optimal solutions. A small example with 50 points:

You can solve this iteratively by using next_permutation() to go through all the permutations one by one. Apologies for the messy code, but this should show you how to do it:
struct Point {
Point(int x, int y) : x(x), y(y) {
}
bool operator< (const Point& rhs) {
const int key1 = y * 1000 + x;
const int key2 = rhs.y * 1000 + rhs.x;
return key1 < key2;
}
double dist(const Point& next) {
const double h = (double)(next.x - x);
const double v = (double)(next.y - y);
return sqrt(h*h + v*v);
}
int x, y;
};
You need the operator so you have some sort of sorting key for your points, so next_permutation can go through them in lexicographical increasing order.
double getShortestDist(std::vector p) {
double min = 200000;
std::sort(p.begin(), p.end());
while(std::next_permutation(p.begin(), p.end())) {
double sum = 0.0;
for (int i = 0; i < p.size(); i+= 2) {
sum += p[i].dist(p[i+1]);
}
if (sum < min) {
min = sum;
}
}
return min;
}
int main(int argc, char*argv[]) {
static const int arr[] = {
10, 10, 20, 10, 5, 5, 1, 1, 120, 3, 6, 6, 50, 60, 3, 24, 6, 9, 0, 0
};
std::vector<Point> test;
for (int i = 0; i < 20; i += 2) {
test.push_back(Point(arr[i], arr[i+1]));
printf("%d %d\n", arr[i], arr[i+1]);
}
printf("Output: %d, %f", test.size(), getShortestDist(test));
}

Related

Print Sum of int > 0

Given a number S ( int > 0 ) and n (int > 0), print all the different subsets of len n which sum to S.
For S = 7 and n = 3, the output is the following, the output must be descending order:
5 + 1 + 1
4 + 2 + 1
3 + 3 + 1
3 + 2 + 2
Here is what I've tried so far:
vector<vector<int> > partitions(int X, int Y)
{
vector<vector<int> > v;
if (X <= 1 && X <= X - Y + 1)
{
v.resize(1);
v[0].push_back(X);
return v;
}
for (int y = min(X - 1, Y); y >= 1; y--)
{
vector<vector<int> > w = partitions(X - y, y);
for (int i = 0; i<w.size(); i++)
{
w[i].push_back(y);
v.push_back(w[i]);
}
}
return v;
}
int main()
{
vector<vector<int> > v = partitions(7, 3);
int i;
for (i = 0; i<v.size(); i++)
{
int x;
for (x = 0; x<v[i].size(); x++)
printf("%d ", v[i][x]);
printf("\n");
}
}
the first element in the matrix is s- n + 1 and full of 1 till the sum is reached, or if the s-n+1 is equal to s, then n is 1, so only s will be the solution.
p.s.: I don t know if this problem has a particular name
This may not be the best solution for your problem, since it's not a dynamic programming based solution. In this case, I'm using recursion to fill an array until I reduce the desired number to 0. In this solution, every combination will be stored in the increasing order of the elements so we prevent permutations of a already calculated solution.
#include <iostream>
void findCombinationGivenSize(int numbersArray[], int index, int num, int reducedNum, int maxNum){
if (reducedNum < 0)
return; // this is our base case
if (reducedNum == 0 && index == maxNum){ // both criteria were attended:
//the sum is up to num, and the subset contain maxNum numbers
for (int i = index - 1; i>=0; i--)
std::cout<< numbersArray[i] << " + ";
// here we will have a problem with an extra '+' on the end, but you can figure out easily how to remove it :)
std::cout<<std::endl;
return;
}
// Find the previous number stored in arrayNumber[]
int prev;
if(index == 0)
prev = 1;
else
prev = numbersArray[index-1];
for (int k = prev; k <= num; k++){
// next element of array is k
numbersArray[index] = k;
// call recursively with reduced number
findCombinationGivenSize(numbersArray, index + 1, num,reducedNum - k, maxNum);
}
}
void findCombinations(int number, int maxSubset){
int arrayNumbers[number];
findCombinationGivenSize(arrayNumbers, 0, number, number, maxSubset);
}
int main(){
int number = 7;
int maxPartitions = 3;
findCombinations(number, maxPartitions);
return 0;
}

generate a 2d array of integers from given sums of its rows and columns

I want to generate an array of integers where the total sum of each row and column in the array is known , for example if I create a 4 by 4 array in c++ and then populate it pseudo randomly with numbers between 1 and 100:
int array[4][4] = {} ;
for(int x = 0 ; x<4 ; x++){
for(int y = 0 ; y<4 ; y++){
array[x][y] = rand() % 100 + 1 ;
}
}
the array would be :
8, 50, 74, 59
31, 73, 45, 79
24, 10, 41, 66
93, 43, 88, 4
then if I sum each row and each column by :
int rowSum[4] = {} ;
int columnSum[4] = {} ;
for(int x = 0 ; x < 4; x++){
for(int y = 0 ; y < 4; y++){
rowSum[x] += array[x][y] ;
columnSum[y] += array[x][y] ;
}
}
the rowSum would be {191,228,141,228} and the columnSum = {156,176,248,208}
what I'm trying to do at this point is to generate any random 4x4 1~100 array that will satisfy rowSum and columnSum I understand there is thousands of different arrays that will sum up to the same row and column sum ,and I've been trying to write the part of the code that will generate it , I would really appreciate it if anyone can give me a clue .
It is very easy to find some solution.
Start with generating row that sum to given values. It could be as simple as making all values in each row approximately equal to rowSum[i]/n, give or take one. Of course sums of columns will not match at this point.
Now fix the columns from the leftmost to the rightmost. To fix i th column, distribute the difference between the desired sum and the actual sum equally between column entries, and then fix each row by distributing the added value equally between items i+1...n of the row.
It is easier done than said:
void reconstruct (int array[4][4], int rows[4], int cols[4])
{
// build an array with each row adding up to the correct row sum
for (int x = 0; x < 4; x++){
int s = rows[x];
for(int y = 0; y < 4 ; y++){
array[x][y] = s / (4 - y);
s -= array[x][y];
}
}
// adjust columns
for(int y = 0; y < 4 ; y++){
// calculate the adjustment
int s = 0;
for (int x = 0; x < 4; x++){
s += array[x][y];
}
int diff = s - cols[y];
// adjust the column by diff
for (int x = 0; x < 4; x++){
int k = diff / (4 - x);
array[x][y] -= k;
diff -= k;
// adjust the row by k
for (int yy = y + 1; yy < 4; ++yy)
{
int corr = k / (4 - yy);
array[x][yy] += corr;
k -= corr;
}
}
}
}
This array won't be random of course. One can randomise it by selecting x1, x2, y1, y2 and d at random and executing:
array[x1][y1] += d
array[x1][y2] -= d
array[x2][y1] -= d
array[x2][y2] += d
taking care that the resulting values won't spill out of the desired range.
Here's the quick and dirty brute force search mentioned in comments. It ought to give you a starting point. This is C, not C++.
You never said it, but I'm assuming you want the matrix elements to be non-negative. Consequently, this searches the space where each element a[i][j] can have any value in [0..min(rowsum[i], colsum[j])] with the search cut off when assigning the next array element value would admit no possible future solution.
#include <stdio.h>
int a[4][4] = {
{-1, -1, -1, -1},
{-1, -1, -1, -1},
{-1, -1, -1, -1},
{-1, -1, -1, -1}};
int rs[] = {191, 228, 141, 228};
int cs[] = {156, 176, 248, 208};
long long n_solutions = 0;
void research(int i, int j, int ii, int jj, int val);
void print_a(void);
void search(int i, int j) {
if (j < 3) {
if (i < 3) {
int m = rs[i] < cs[j] ? rs[i] : cs[j];
for (int val = 0; val <= m; ++val) research(i, j, i, j + 1, val);
} else {
if (rs[3] >= cs[j]) research(i, j, i, j + 1, cs[j]);
}
} else {
if (i < 3) {
if (cs[j] >= rs[i]) research(i, 3, i + 1, 0, rs[i]);
} else {
if (rs[3] == cs[3]) {
a[3][3] = rs[i];
if (++n_solutions % 100000000 == 0) {
printf("\n%lld\n", n_solutions);
print_a();
}
a[3][3] = -1;
}
}
}
}
void research(int i, int j, int ii, int jj, int val) {
a[i][j] = val; rs[i] -= val; cs[j] -= val;
search(ii, jj);
rs[i] += val; cs[j] += val; a[i][j] = -1;
}
void print_a(void) {
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j)
printf("%4d", a[i][j]);
printf("\n");
}
}
int main(void) {
search(0, 0);
printf("Total solutions: %lld\n", n_solutions);
return 0;
}
For example, if you replace the simple for loop with this, you won't get so many zeros in the upper left hand corner:
int b = m / 2; // m/2 can be replaced with any int in [0..m], e.g. a random value.
research(i, j, i, j + 1, b);
for (int d = 1; b + d <= m || b - d >= 0; ++d) {
if (b + d <= m) research(i, j, i, j + 1, b + d);
if (b - d >= 0) research(i, j, i, j + 1, b - d);
}
Here's the 2-billionth solution:
78 56 28 29
39 20 84 85
28 34 61 18
11 66 75 76
The problem becomes interesting if we place condition that the matrix elements must be non-negative integers. Here's an O(mn) JAVA solution based on greedy algorithm.
int m=rowSum.length;
int n=colSum.length;
int mat[][] = new int[m][n];
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
int tmp=Math.min(rowSum[i],colSum[j]);
mat[i][j]=tmp;
rowSum[i]-=tmp;
colSum[j]-=tmp;
}
}
return mat;

Expected Contant Expression [duplicate]

This question already has answers here:
How do I use arrays in C++?
(5 answers)
Why aren't variable-length arrays part of the C++ standard?
(10 answers)
Closed 8 years ago.
I was implementing a version of the closest pair problem using the algorithmic technique of divide and conquer. However, when I try and compile my code, in several spots I get the error "Expected constant expression". I am aware that arrays are supposed to have constant values in them, but I'm not quite sure what's wrong in this case. I tried to research solutions and many people suggested using malloc, but it seems to be generally frowned upon. Would someone be able to help me fix this? Below is the code with the errors commented hopefully well enough that you can see them. Thank you so much in advance for your help, I really appreciate it!
#include <iostream>
#include <float.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
//A struct to represent the points on an x,y plane
struct Point{
int x, y;
};
//function to sort x coordinates
int compareX(const void* a, const void* b){
Point *p1 = (Point *)a, *p2 = (Point *)b;
return (p1->x - p2->x);
}
//function to sort y coordinates
int compareY(const void* a, const void* b){
Point *p1 = (Point *)a, *p2 = (Point *)b;
return (p1->y - p2->y);
}
//function to find the distance between any two points
float dist(Point p1, Point p2){
return sqrt( (float)(p1.x - p2.x) * (p1.x - p2.x) +
(float)(p1.y - p2.y) * (p1.y - p2.y)
);
}
//utility function to find the minimum of any two float values
float min(float x, float y){
if(x < y)
return x;
else
return y;
}
//brute force function to find the closest of two points
float bruteforce(Point P[], int n){
float min = FLT_MAX;
for(int i=0; i<n; i++){
for(int j = i+1; j < n; j++)
if(dist(P[i], P[j]) < min)
min = dist(P[i], P[j]);
}
return min;
}
//function to find the distance between the closest points of a given size
float closestArray(Point array1[], int size, float d){
float min = d; //initialize the minimum distance as d
//go through the points 1 by 1 and try the next until the difference is smaller than d
for (int i=0; i < size; i++)
for (int j= i + 1; j< size && (array1[i].y - array1[i].y) < min; j++)
if(dist(array1[i],array1[j]) < min)
min = dist(array1[i], array1[j]);
return min;
}
float closestPoint(Point Px[], Point Py[], int n){
if(n <= 3)
return bruteforce(Px, n);
//find the middle point
int mid = n/2;
Point midPoint = Px[mid];
//divide the points along the vertical line
Point Pyleft[mid + 1]; //left of vertical line <--- ERROR
Point Pyright[n-mid-1]; //right of vertical line <--- ERROR
int li = 0; //index of left subarray
int ri = 0; //index of right subarray
for ( int i =0; i<n; i++){
if (Py[i].x <= midPoint.x)
Pyleft[li++] = Py[i];
else
Pyright[ri++] = Py[i];
}
//calculate the smallest ditance dl on the left middle point and dr on the right side
float dl = closestPoint(Px, Pyleft, mid);
float dr = closestPoint(Px + mid, Pyright, n-mid);
//find the smaller of the two distances
float d = min(dl, dr);
//build another array Q that contains points closer than d to the line passing through the middle
Point q[n]; // <--- ERROR
int j = 0;
for (int i = 0; i<n; i++)
if(abs(Py[i].x - midPoint.x) < d)
q[j] = Py[i], j++;
return min(d, closestArray(q, j, d) );
}
//function that finds the smallerst distance
float closest(Point P[], int n){
Point Px[n]; //<--- ERROR
Point Py[n]; //<---ERROR
for(int i=0; i < n; i++)
{
Px[i] = P[i];
Py[i] = P[i];
}
qsort(Px, n, sizeof(Point), compareX);
qsort(Py, n, sizeof(Point), compareY);
//recursive function to find smallest distance
return closestPoint(Px, Py, n);
}
int main()
{
Point P[] = {{2, 3}, {12, 30}, {40, 50}, {5, 1}, {12, 10}, {3, 4}};
int n = sizeof(P) / sizeof(P[0]);
cout << "The smallest distance is " << closest(P, n);
return 0;
}

Find path with sum of numbers is maximum

I'm trying to find path with sum of numbers is maximum. It's only allowed to move right and down through the matrix.
I've coded it but it doesn't give me the maximum sum, and I can't figure out why it does so!.
Thanks in advance.
Here's my code
/*Given grid of positive numbers, strat from (0,0) ad end at (n,n).
Move only to RIGHT and DOWN. Find path with sum of numbers is maximum. */
#include<iostream>
using namespace std;
int grid[2][3] = { { 5, 1, 2 }, { 6, 7, 8 } };
int max(int x, int y){
if (x >= y){
return x;
}
else if (x < y){
return y;
}
}
bool valid(int r, int c){
if (r + 1 == 2 || c + 1 == 3)
return false;
else
return true;
}
int maxPathSum(int row, int column){
if (!valid(row, column))
return 0;
if (row == 1 && column == 2) //base condition
return grid[row][column];
int path1 = maxPathSum(row, column + 1); //Right
int path2 = maxPathSum(row + 1, column); //Down
return grid[row][column] + max(path1, path2);
}
int main()
{
cout << maxPathSum(0, 0) << endl;
return 0;
}
the correct answer should be 26, but the output is 6.
Your function Valid should be
bool valid (int r, int c)
{
return r < 2 && c < 3;
}
and then you got 26 (Live example).
BTW, you may use dynamic programming for this problem.
You can also use dynamic programming to solve the problem
Here is the code:
#include <bits/stdc++.h>
using namespace std;
int grid[2][3] = { { 5, 1, 2 }, { 6, 7, 8 } };
int dp[3][4];
int main()
{
for(int i=0;i<4;i++)
dp[0][i] = 0;
for(int i=0;i<3;i++)
dp[i][0] = 0;
for(int i=1;i<3;i++)
{
for(int j=1;j<4;j++)
{
dp[i][j] = grid[i-1][j-1] + max(dp[i][j-1], dp[i-1][j]);
}
}
cout << dp[2][3];
return 0;
}
Live example
Apart from DP, you can also use simple (n,m) Matrix based solution. The good part is this approach wont need recursion as DP does which can cause memory issues if matrix is bigger and space complexity is just O(n x m) i.e. input array itself. And the time complexity is also O(n x m). Following code in java illustrate the approach -
package com.company.dynamicProgramming;
import static java.lang.Integer.max;
public class MaxSumPathInMatrix {
public static void main (String[] args)
{
int mat[][] = { { 10, 10, 2, 0, 20, 4 },
{ 1, 0, 0, 30, 2, 5 },
{ 200, 10, 4, 0, 2, 0 },
{ 1, 0, 2, 20, 0, 4 }
};
System.out.println(findMaxSum2(mat));
}
/*
Given a matrix of N * M. Find the maximum path sum in matrix.
Find the one path having max sum - originating from (0,0) with traversal to either right or down till (N-1, M-1)
*/
static int findMaxSum2(int mat[][])
{
int M = mat[0].length;
int N = mat.length;
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
{
if(i==0 && j!=0){
mat[i][j]+=mat[i][j-1];
}
else if(i!=0 && j==0){
mat[i][j]+=mat[i-1][j];
}
else if (i!=0 && j!=0){
mat[i][j]+= max(mat[i-1][j], mat[i][j-1]);
}
}
}
return mat[N-1][M-1];
}
}
Run it as -
251
Process finished with exit code 0
Further Even if you are using Dynamic Programming(DP) then use Memoization concept to reduce the time complexity.. Here is the code with DP plus memoization along complexity calculation -
package com.company.dynamicProgramming;
import java.util.HashMap;
import java.util.Map;
import static java.lang.Integer.max;
public class MaxSumPathInMatrix {
static int complexity = 0;
public static void main (String[] args)
{
int mat[][] = { { 10, 10, 2, 0, 20, 4 },
{ 1, 0, 0, 30, 2, 5 },
{ 200, 10, 4, 0, 2, 0 },
{ 1, 0, 2, 20, 0, 4 }
};
System.out.println("Max Sum : " + findMaxSum2_dp(mat, 0, 0, new HashMap<>()));
System.out.println("Time complexity : " +complexity);
}
/*
~~~> solve via ~dp~ and ~memoization~
Given a matrix of N * M. Find the maximum path sum in matrix.
Find the one path having max sum - originating from (0,0) with traversal to either right or down till (m-1, n-1)
*/
static int findMaxSum2_dp(int mat[][], int i, int j, Map<String, Integer> memo){
int M = mat[0].length;
int N = mat.length;
Integer sum = memo.get(i+"-"+j);
if(sum!= null){
return sum;
}
complexity++;
if(i==N-1 && j<M-1){
mat[i][j] += findMaxSum2_dp(mat, i, j+1, memo);
memo.put(i+"-"+j, mat[i][j]);
return mat[i][j];
}
else if(i<N-1 && j==M-1){
mat[i][j] += findMaxSum2_dp(mat, i+1, j, memo);
memo.put(i+"-"+j, mat[i][j]);
return mat[i][j];
}
else if (i<N-1 && j<M-1){
int s1 = findMaxSum2_dp(mat, i+1, j, memo);
int s2 = findMaxSum2_dp(mat, i, j+1, memo);
mat[i][j] += max(s1, s2);
memo.put(i+"-"+j, mat[i][j]);
return mat[i][j];
}
return mat[N-1][M-1] += max(mat[N-1][M-2], mat[N-2][M-1]);
}
}
Two important points to note in above code -
I am storing max sum of any sub matrix [i][j] in a store(HashMap), whenever it's max sum is ready. And in further steps if this sub matrix [i][j] reappears then I take it from store instead of processing again. As a illustration - you can see [N-1][M-1] appears 2 times in below diagram of recursion -
[N][M] = max([N][M-1]) , [N-1][M]
/ \
/ \
/ \
[N][M-1] = max ([N-1][M-1], [N][M-2]) [N-1][M] = max ([N-2][M], [N-1][M-1])
Connected with Point 1 : I have provisioned a complexity variable which I increment if I have to calculate max sum for matrix [i][j] i.e. wont find in the store. If you see the result it shows 25 in 6x4 matrix i.e. the time complexity is just O(NxM).

Ising Model in C++

I'm writing a code in C++ for a 2D Ising model. Here's what the code should do:
Generate random NxN lattice, with each site either +1 or -1 value.
Select a site at random
If site when flipped (+1 to -1 or -1 to +1) is a state of lower energy, flip state ie. if dE < 0, flip state. If flipped state is of higher energy, flip with acceptance rate w = e^{-b(dE)}. Where dE is the change in energy if state is flipped.
4.Do this for all NxN sites, without repetition. This is considered one sweep.
Do like 100 sweeps.
I'm having trouble with steps 1, 2 and 3, would appreciate any help! For step 1, I managed to create and display a lattice, but I can't seem to extract the value of a site at location (x, y). Steps 2 and 3, how do I use a boolean expression of some sort to flip according to acceptance probability?
#include <cstdlib>
#include <ctime>
using namespace std;
#include <iostream>
int main() //random generation of spin configuration
{
int L; //Total number of spins L = NxN
int N = 30 //A square lattice of length 30
double B=1; //magnetic field
double M; //Total Magnetization = Sum Si
double E; //Total Energy
int T = 1.0;
int nsweeps = 100; //number of sweeps
int de; //change in energy when flipped
double Boltzmann; //Boltzmann factor
int x,y; //randomly chosen lattice site
int i,j,a,c; //counters
int ROWS = 5;
int COLS = 5;
int matrix[ROWS][COLS];
srand ( static_cast<unsigned> ( time ( 0 ) ) );
for ( int i = 0; i < ROWS; i++ )
{
for ( int j = 0; j < COLS; j++ )
{
matrix[i][j] = rand () % 2 *2-1;
}
}
// showing the matrix on the screen
for(int i=0;i<ROWS;i++) // loop 3 times for three lines
{
for(int j=0;j<COLS;j++) // loop for the three elements on the line
{
cout<<matrix[i][j]; // display the current element out of the array
}
cout<<endl; // when the inner loop is done, go to a new line
}
return 0; // return 0 to the OS.
//boundary conditions and range
if(x<0) x += N;
if(x>=L) x -= N;
if(y<0) y += N;
if(y>=L) y -= N;
//counting total energy of configuration
{ int neighbour = 0; // nearest neighbour count
for(int i=0; i<L; i++)
for(int j=0; j<L; j++)
{ if(spin(i,j)==spin(i+1, j)) // count from each spin to the right and above
neighbour++;
else
neighbour--;
if(spin(i, j)==spin(i, j+1))
neighbour++;
else
neighbour--;
}
E = -J*neighbour - B*M;
//flipping spin
int x = int(srand48()*L); //retrieves spin from randomly choosen site
int y = int(srand48()*L);
int delta_M = -2*spin(x, y); //calculate change in Magnetization M
int delta_neighbour = spin(spinx-1, y) + spin(x+1, y)+ spin(x, y-1) + spin(x, y+1);
int delta_neighbour = -2*spin(x,y)* int delta_neighbour;
double delta_E = -J*delta_neighbour -B*delta_M;
//flip or not
if (delta_E<=0)
{ (x, y) *= -1; // flip spin and update values
M += delta_M;
E += delta_E;
}
}
To follow up on my comment:
There are too many issues with your code for a single answer. Try to
build your program step by step. Use functions which perform one
thing, and this they do well. Test each function individually and if
necessary try to find out why it does not work. Then post specific
questions again.
To get you started:
Store your lattice as a std::vector<int> lattice(N*N)
Access element (x,y) with data[x+N*y].
Example:
#include <vector>
struct IsingModel
{
unsigned size_;
std::vector<int> lattice_;
// access element (x,y)
int& at(int x, int y) {
return lattice_[x + y*size_];
}
int at(int x, int y) const {
return lattice_[x + y*size_];
}
// generate size x size lattice
IsingModel(unsigned size)
: size_(size), lattice_(size*size, +1) {
}
static int BoolToSpin(bool v) {
return v ? +1 : -1;
}
// initialize spin randomly
void initializeRandom() {
for(int y=0; y<size_; y++) {
for(int x=0; x<size_; x++) {
at(x,y) = BoolToSpin(rand()%2);
}
}
}
static int Energy(int a, int b) {
return (a == b) ? +1 : -1;
}
// compute total energy
unsigned computeTotalEnergy() const {
unsigned energy = 0;
for(int y=1; y<size_-1; y++) {
for(int x=1; x<size_-1; x++) {
energy += Energy(at(x,y), at(x+1,y));
energy += Energy(at(x,y), at(x,y+1));
}
}
return energy ;
}
};
#include <iostream>
#include <cstdlib>
#include <ctime>
int main() {
srand(static_cast<unsigned>(time(0))); // intialize random number generator
IsingModel im(10);
im.initializeRandom();
unsigned energy = im.computeTotalEnergy();
std::cout << energy << std::endl; // print energy
}