point

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

const int INF=0x3f3f3f3f;
const int MAX_N=100+5;
const int MAX_M=200+5;
const int M=25;

struct node{
    int b[M*3];
};

struct point{
    double x,y,z;
    point(){}
    point(double x_,double y_,double z_){
        x=x_;y=y_;z=z_;
    }
};

int n;
double data[MAX_N][3];

int m;
node pop[MAX_M],pop_next[MAX_M];
double fit[MAX_M];

double L[3],R[3];

double Rand(){
    return rand()/(RAND_MAX+1.0);
}

double res_res=1e18;

point get(node &nod){
    double x=0,y=0,z=0;
    for(int j=0;j<M*3;j++){
        if(nod.b[j]){
            if(j%3==0){
                x+=(1<<(j/3));
            }
            else if(j%3==1){
                y+=(1<<(j/3));
            }
            else{
                z+=(1<<(j/3));
            }
        }
    }
    x=x/((1<<M)-1)*(R[0]-L[0])+L[0];
    y=y/((1<<M)-1)*(R[1]-L[1])+L[1];
    z=z/((1<<M)-1)*(R[2]-L[2])+L[2];
    point p(x,y,z);
    return p;
}

void get_fit(){
    double cnt=0;
    for(int i=0;i<m;i++){
        double ans=0;
        point poi=get(pop[i]);
        double x=poi.x,y=poi.y,z=poi.z;
        for(int j=0;j<n;j++){
            double r=sqrt((x-data[j][0])*(x-data[j][0])
                +(y-data[j][1])*(y-data[j][1])
                +(z-data[j][2])*(z-data[j][2]));
            ans=max(ans,r);
        }
        cnt+=ans;
        res_res=min(res_res,ans);
        fit[i]=ans;
    }
    //cout<<cnt/m<<endl;
    double s=0;
    for(int i=0;i<m;i++)s=max(s,fit[i]);
    for(int i=0;i<m;i++)fit[i]=-fit[i]+s;
    s=0;
    for(int i=0;i<m;i++)s+=fit[i];
    for(int i=0;i<m;i++)fit[i]/=s;
    for(int i=1;i<m;i++)fit[i]+=fit[i-1];
}

int select(){
    double p=Rand();
    int lb=-1,ub=m;
    while(ub-lb>1){
        int mid=(lb+ub)/2;
        if(fit[mid]>=p)ub=mid;
        else lb=mid;
    }
    return ub;
}

void GA(int m_=100,int iter=100,double f1=0.8,double f2=0.05){
    m=m_;
    for(int i=0;i<m;i++){
        for(int j=0;j<M*3;j++)pop[i].b[j]=rand()%2;
    }
    for(int cas=0;cas<iter;cas++){
        get_fit();
        for(int i=0;i<m;i+=2){
            int id1=select(),id2=select();
            //cout<<cas<<":"<<id1<<","<<id2<<endl;
            pop_next[i]=pop[id1];
            pop_next[i+1]=pop[id2];
            double p=Rand();
            if(p<f1){
                int k=rand()%(M*3);
                for(int j=0;j<k;j++)
                    swap(pop_next[i].b[j],pop_next[i+1].b[j]);
            }
            p=Rand();
            if(p<f2){
                int k=rand()%(M*3);
                pop_next[i].b[k]^=1;
            }
            p=Rand();
            if(p<f2){
                int k=rand()%(M*3);
                pop_next[i+1].b[k]^=1;
            }
        }
        for(int i=0;i<m;i++)swap(pop[i],pop_next[i]);
    }
}

void after(double f=1e7){
    double x=0,y=0,z=0;
    for(int i=0;i<m;i++){
        point poi=get(pop[i]);
        x+=poi.x;y+=poi.y;z+=poi.z;
    }
    x/=m;y/=m;z/=m;
    //cout<<x<<" "<<y<<" "<<z<<endl;
    double ans=0;
    for(int j=0;j<n;j++){
        double r=sqrt((x-data[j][0])*(x-data[j][0])
            +(y-data[j][1])*(y-data[j][1])
            +(z-data[j][2])*(z-data[j][2]));
        ans=max(ans,r);
    }
    //cout<<ans<<endl;
    ans=min(ans,f);
    L[0]=x-ans;R[0]=x+ans;
    L[1]=y-ans;R[1]=y+ans;
    L[2]=z-ans;R[2]=z+ans;
    GA();
}

void solve(){
    for(int i=0;i<3;i++){
        L[i]=-100005;
        R[i]=100005;
    }
    GA(100,100,0.8,0.05);
    for(int i=0;i<100;i++)after();
    after(1);
    //after(0.5);
    //after(0.1);
}

int main(){
    srand(time(NULL));
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        for(int j=0;j<3;j++)scanf("%lf",&data[i][j]);
    }
    solve();
    printf("%.12f\n",res_res);
    return 0;
}

/*
3
0 0 0
3 0 0
0 4 0

4
0 0 0
1 0 0
0 1 0
0 0 1


9
0 0 0
1 0 0
0 1 0
0 0 1
1 2 3
3 4 5
5 7 8
2 3 5
7 4 4
*/
#GA1
import random
import math
import matplotlib.pyplot as plt
from matplotlib.pyplot import MultipleLocator
from min_circle_covering import min_cir

data = []

DNA_LEN = 4
pop = []
pop_next = []
fit = []
L = [0.0, 0.0]
R = [100.0, 100.0]


def decoding(pop_i):
    x = y = 0.0
    for i in range(DNA_LEN * 2):
        if i % 2 == 0:
            x = x * 2 + pop_i[i]
        else:
            y = y * 2 + pop_i[i]
    x = x / ((1 << DNA_LEN) - 1) * (R[0] - L[0]) + L[0]
    y = y / ((1 << DNA_LEN) - 1) * (R[1] - L[1]) + L[1]
    return x, y


def get_fit():
    ret_id, ret_len = [0, 1e18]
    for i in range(len(pop)):
        x, y = decoding(pop[i])
        ans = 0.0
        for d in data:
            ans = max(ans, math.sqrt((x - d[0]) * (x - d[0]) + (y - d[1]) * (y - d[1])))
        fit[i] = ans

        if fit[i] < ret_len:
            ret_id = i
            ret_len = fit[i]

    aver = 0.0
    for i in range(len(fit)):
        aver += fit[i]
    aver /= len(fit)
    # print(aver)

    ans = 0.0
    for i in range(len(fit)):
        ans = max(ans, fit[i])
    for i in range(len(fit)):
        fit[i] = -fit[i] + ans + 1e-4
    ans = 0.0
    for i in range(len(fit)):
        ans += fit[i]
    for i in range(len(fit)):
        fit[i] /= ans
    for i in range(1, len(fit)):
        fit[i] += fit[i - 1]
    return ret_id, ret_len


def select():
    p = random.random()
    lb = -1
    ub = len(fit)
    while ub - lb > 1:
        mid = (lb + ub) // 2
        if fit[mid] >= p:
            ub = mid
        else:
            lb = mid
    return ub


def ga(m=100, iter_=100, f1=0.8, f2=0.05, c='m', marker='o'):
    if m % 2 == 1:
        m += 1
    pop.clear()
    pop_next.clear()
    fit.clear()
    for i in range(m):
        pop.append([])
        pop_next.append([])
        fit.append(0.0)
        for j in range(DNA_LEN * 2):
            pop[i].append(random.randint(0, 1))
            pop_next[i].append(0)

    ret_x = ret_y = 0.0
    ret_len = 1e18

    for _ in range(iter_):
        x_sca = []
        y_sca = []
        for p in pop:
            x, y = decoding(p)
            x_sca.append(x)
            y_sca.append(y)
        if 'sca' in locals():
            sca.remove()
        sca = ax.scatter(x_sca, y_sca, c=c, marker=marker)
        plt.show()
        plt.pause(0.01)

        ret_id, ret_len_i = get_fit()
        if ret_len_i < ret_len:
            ret_len = ret_len_i
            ret_x, ret_y = decoding(pop[ret_id])

        for i in range(0, len(pop), 2):
            id1 = select()
            id2 = select()
            pop_next[i] = pop[id1][:]
            pop_next[i + 1] = pop[id2][:]
            if random.random() < f1:
                k = random.randint(0, DNA_LEN * 2 - 1)
                for j in range(k):
                    t = pop_next[i][j]
                    pop_next[i][j] = pop_next[i + 1][j]
                    pop_next[i + 1][j] = t
            if random.random() < f2:
                k = random.randint(0, DNA_LEN * 2 - 1)
                pop_next[i][k] ^= 1
            if random.random() < f2:
                k = random.randint(0, DNA_LEN * 2 - 1)
                pop_next[i + 1][k] ^= 1
        for i in range(len(pop)):
            t = pop[i]
            pop[i] = pop_next[i]
            pop_next[i] = t

    ret_id, ret_len_i = get_fit()
    if ret_len_i < ret_len:
        ret_len = ret_len_i
        ret_x, ret_y = decoding(pop[ret_id])

    if 'sca' in locals():
        sca.remove()
    ax.plot(ret_x, ret_y, c=c, marker='*')
    plt.show()

    return ret_x, ret_y, ret_len


if __name__ == "__main__":
    fig, ax = plt.subplots(figsize=(6, 6))
    plt.ion()
    ax.axis([L[0], R[0], L[1], R[1]])
    x_major_locator = MultipleLocator((R[0] - L[0]) / ((1 << DNA_LEN) - 1))
    y_major_locator = MultipleLocator((R[1] - L[1]) / ((1 << DNA_LEN) - 1))
    ax.xaxis.set_major_locator(x_major_locator)
    ax.yaxis.set_major_locator(y_major_locator)
    ax.grid()
    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
    plt.rcParams['axes.unicode_minus'] = False
    ax.set_title('模拟二次遗传算法求解最小圆覆盖(精度分析)', fontsize=13, color='k')

    # random.seed(0)
    L = [0.0, 0.0]
    R = [100.0, 100.0]
    data.clear()
    for i in range(10):
        data.append([random.uniform(L[0], R[0]), random.uniform(L[1], R[1])])
    #data=[[26.69411449181589, 57.99634495734579], [97.82875519057713, 54.60916766199934], [89.60766528337717, 59.4440751173273], [31.569971251362063, 4.417891529107065], [99.99663140140832, 90.1432275454114], [76.09621979865234, 21.102401056269382], [38.28058014688098, 3.35069512559244], [67.52867091864785, 28.6231223587763], [41.30496236274295, 88.41547023635408], [53.70056427516741, 66.32820243206412]]

    for d in data:
        ax.plot(d[0], d[1], c='b', marker='.')

    best_x, best_y, best_len1 = min_cir(data)
    print('增量法:', best_len1)
    ax.plot(best_x, best_y, c='k', marker='*')
    plt.show()
    plt.pause(1)

    L = [0.0, 0.0]
    R = [100.0, 100.0]
    best_x, best_y, best_len2 = ga(m=100, iter_=100, f1=0.8, f2=0.05, c='g', marker='o')
    print('遗传算法:', best_len2)

    plt.pause(1)
    aver_x, aver_y = [0.0, 0.0]
    for _ in range(len(pop)):
        x, y = decoding(pop[select()])
        aver_x += x
        aver_y += y
    aver_x /= len(pop)
    aver_y /= len(pop)
    # aver_x = (aver_x + best_x * 100) / (len(pop) + 100)
    # aver_y = (aver_y + best_y * 100) / (len(pop) + 100)
    # aver_x=best_x
    # aver_y= best_y

    L_new = [max(aver_x - 10, L[0]), max(aver_y - 10, L[1])]
    R_new = [min(aver_x + 10, R[0]), min(aver_y + 10, R[1])]

    L = L_new
    R = R_new
    best_x, best_y, best_len3 = ga(m=100, iter_=100, f1=0.8, f2=0.05, c='r', marker='.')
    print('二次遗传算法:', best_len3)

    plt.ioff()
    plt.show()
#GA12
import random
import math
import matplotlib.pyplot as plt
from matplotlib.pyplot import MultipleLocator

data = []

DNA_LEN = 4
pop = []
pop_next = []
fit = []
L = [0.0, 0.0]
R = [100.0, 100.0]


def decoding(pop_i):
    x = y = 0.0
    for i in range(DNA_LEN * 2):
        if i % 2 == 0:
            x = x * 2 + pop_i[i]
        else:
            y = y * 2 + pop_i[i]
    x = x / ((1 << DNA_LEN) - 1) * (R[0] - L[0]) + L[0]
    y = y / ((1 << DNA_LEN) - 1) * (R[1] - L[1]) + L[1]
    return x, y


def get_fit():
    ret_id, ret_len = [0, 1e18]
    for i in range(len(pop)):
        x, y = decoding(pop[i])
        ans = 0.0
        for d in data:
            ans = max(ans, math.sqrt((x - d[0]) * (x - d[0]) + (y - d[1]) * (y - d[1])))
        fit[i] = ans

        if fit[i] < ret_len:
            ret_id = i
            ret_len = fit[i]

    aver = 0.0
    for i in range(len(fit)):
        aver += fit[i]
    aver /= len(fit)
    #print(aver)

    ans = 0.0
    for i in range(len(fit)):
        ans = max(ans, fit[i])
    for i in range(len(fit)):
        fit[i] = -fit[i] + ans + 1e-4
    ans = 0.0
    for i in range(len(fit)):
        ans += fit[i]
    for i in range(len(fit)):
        fit[i] /= ans
    for i in range(1, len(fit)):
        fit[i] += fit[i - 1]
    return ret_id, ret_len


def select():
    p = random.random()
    lb = -1
    ub = len(fit)
    while ub - lb > 1:
        mid = (lb + ub) // 2
        if fit[mid] >= p:
            ub = mid
        else:
            lb = mid
    return ub


def ga(m=100, iter_=100, f1=0.8, f2=0.05, c='m', marker='o'):
    if m % 2 == 1:
        m += 1
    pop.clear()
    pop_next.clear()
    fit.clear()
    for i in range(m):
        pop.append([])
        pop_next.append([])
        fit.append(0.0)
        for j in range(DNA_LEN * 2):
            pop[i].append(random.randint(0, 1))
            pop_next[i].append(0)

    ret_x = ret_y = 0.0
    ret_len = 1e18

    for _ in range(iter_):
        ret_id, ret_len_i = get_fit()
        if ret_len_i < ret_len:
            ret_len = ret_len_i
            ret_x, ret_y = decoding(pop[ret_id])

        for i in range(0, len(pop), 2):
            id1 = select()
            id2 = select()
            pop_next[i] = pop[id1][:]
            pop_next[i + 1] = pop[id2][:]
            if random.random() < f1:
                k = random.randint(0, DNA_LEN * 2 - 1)
                for j in range(k):
                    t = pop_next[i][j]
                    pop_next[i][j] = pop_next[i + 1][j]
                    pop_next[i + 1][j] = t
            if random.random() < f2:
                k = random.randint(0, DNA_LEN * 2 - 1)
                pop_next[i][k] ^= 1
            if random.random() < f2:
                k = random.randint(0, DNA_LEN * 2 - 1)
                pop_next[i + 1][k] ^= 1
        for i in range(len(pop)):
            t = pop[i]
            pop[i] = pop_next[i]
            pop_next[i] = t

    ret_id, ret_len_i = get_fit()
    if ret_len_i < ret_len:
        ret_len = ret_len_i
        ret_x, ret_y = decoding(pop[ret_id])

    return ret_x, ret_y, ret_len


if __name__ == "__main__":
    # random.seed(0)
    for cas in range(100):
        L = [0.0, 0.0]
        R = [100.0, 100.0]
        data.clear()
        for i in range(10):
            data.append([random.uniform(L[0], R[0]), random.uniform(L[1], R[1])])

        L = [0.0, 0.0]
        R = [100.0, 100.0]
        best_x, best_y, best_len1 = ga(m=100, iter_=100, f1=0.8, f2=0.05, c='g', marker='o')
        #print(best_len1)

        aver_x,aver_y = [0.0, 0.0]
        for _ in range(len(pop)):
            x, y = decoding(pop[select()])
            aver_x += x
            aver_y += y
        aver_x /= len(pop)
        aver_y /= len(pop)
        #aver_x = (aver_x + best_x * 100) / (len(pop) + 100)
        #aver_y = (aver_y + best_y * 100) / (len(pop) + 100)
        #aver_x=best_x
        #aver_y= best_y
        L_new = [max(aver_x - 10, L[0]), max(aver_y - 10, L[1])]
        R_new = [min(aver_x + 10, R[0]), min(aver_y + 10, R[1])]

        L = L_new
        R = R_new
        best_x, best_y, best_len2 = ga(m=100, iter_=100, f1=0.8, f2=0.05, c='r', marker='.')
        #print(best_len2)
        if best_len2>best_len1:
            print(best_len1,best_len2)
            print(data)
#GA13
import random
import math
import matplotlib.pyplot as plt
from matplotlib.pyplot import MultipleLocator
from min_circle_covering import min_cir

data = []

DNA_LEN = 25
pop = []
pop_next = []
fit = []
L = [0.0, 0.0]
R = [1e5, 1e5]


def decoding(pop_i):
    x = y = 0.0
    for i in range(DNA_LEN * 2):
        if i % 2 == 0:
            x = x * 2 + pop_i[i]
        else:
            y = y * 2 + pop_i[i]
    x = x / ((1 << DNA_LEN) - 1) * (R[0] - L[0]) + L[0]
    y = y / ((1 << DNA_LEN) - 1) * (R[1] - L[1]) + L[1]
    return x, y


def get_fit():
    ret_id, ret_len = [0, 1e18]
    for i in range(len(pop)):
        x, y = decoding(pop[i])
        ans = 0.0
        for d in data:
            ans = max(ans, math.sqrt((x - d[0]) * (x - d[0]) + (y - d[1]) * (y - d[1])))
        fit[i] = ans

        if fit[i] < ret_len:
            ret_id = i
            ret_len = fit[i]

    aver = 0.0
    for i in range(len(fit)):
        aver += fit[i]
    aver /= len(fit)
    # print(aver)

    ans = 0.0
    for i in range(len(fit)):
        ans = max(ans, fit[i])
    for i in range(len(fit)):
        fit[i] = -fit[i] + ans + 1e-4
    ans = 0.0
    for i in range(len(fit)):
        ans += fit[i]
    for i in range(len(fit)):
        fit[i] /= ans
    for i in range(1, len(fit)):
        fit[i] += fit[i - 1]
    return ret_id, ret_len


def select():
    p = random.random()
    lb = -1
    ub = len(fit)
    while ub - lb > 1:
        mid = (lb + ub) // 2
        if fit[mid] >= p:
            ub = mid
        else:
            lb = mid
    return ub


def ga(m=100, iter_=100, f1=0.8, f2=0.05, c='m', marker='o'):
    if m % 2 == 1:
        m += 1
    pop.clear()
    pop_next.clear()
    fit.clear()
    for i in range(m):
        pop.append([])
        pop_next.append([])
        fit.append(0.0)
        for j in range(DNA_LEN * 2):
            pop[i].append(random.randint(0, 1))
            pop_next[i].append(0)

    ret_x = ret_y = 0.0
    ret_len = 1e18

    for _ in range(iter_):
        x_sca = []
        y_sca = []
        for p in pop:
            x, y = decoding(p)
            x_sca.append(x)
            y_sca.append(y)
        if 'sca' in locals():
            sca.remove()
        sca = ax.scatter(x_sca, y_sca, c=c, marker=marker)
        plt.show()
        plt.pause(0.01)

        ret_id, ret_len_i = get_fit()
        if ret_len_i < ret_len:
            ret_len = ret_len_i
            ret_x, ret_y = decoding(pop[ret_id])

        for i in range(0, len(pop), 2):
            id1 = select()
            id2 = select()
            pop_next[i] = pop[id1][:]
            pop_next[i + 1] = pop[id2][:]
            if random.random() < f1:
                k = random.randint(0, DNA_LEN * 2 - 1)
                for j in range(k):
                    t = pop_next[i][j]
                    pop_next[i][j] = pop_next[i + 1][j]
                    pop_next[i + 1][j] = t
            if random.random() < f2:
                k = random.randint(0, DNA_LEN * 2 - 1)
                pop_next[i][k] ^= 1
            if random.random() < f2:
                k = random.randint(0, DNA_LEN * 2 - 1)
                pop_next[i + 1][k] ^= 1
        for i in range(len(pop)):
            t = pop[i]
            pop[i] = pop_next[i]
            pop_next[i] = t

    ret_id, ret_len_i = get_fit()
    if ret_len_i < ret_len:
        ret_len = ret_len_i
        ret_x, ret_y = decoding(pop[ret_id])

    if 'sca' in locals():
        sca.remove()
    ax.plot(ret_x, ret_y, c=c, marker='*')
    plt.show()
    plt.pause(0.5)
    return ret_x, ret_y, ret_len


def ga_after(f=1e7):
    aver_x = aver_y = 0.0
    for i in range(len(pop)):
        id = select()
        xi, yi = decoding(pop[id])
        aver_x += xi
        aver_y += yi
    aver_x /= len(pop)
    aver_y /= len(pop)
    ans = 0.0
    for d in data:
        ans = max(ans, math.sqrt((aver_x - d[0]) ** 2 + (aver_y - d[1]) ** 2))
    ans = min(ans, f)
    L[0] = aver_x - ans
    R[0] = aver_x + ans
    L[1] = aver_y - ans
    R[1] = aver_y + ans
    ax.axis([L[0] - ans, R[0] + ans, L[1] - ans, R[1] + ans])
    plt.show()
    return ga(m=100, iter_=100, f1=0.8, f2=0.05, c='m', marker='o')


def solve(num=50):
    L[0] = 0.0
    R[0] = 1e5
    L[1] = 0.0
    R[1] = 1e5
    best_len = ga(m=100, iter_=100, f1=0.8, f2=0.05, c='m', marker='o')[2]
    for i in range(num):
        best_len = min(best_len, ga_after()[2])
    best_len = min(best_len, ga_after(1.0)[2])
    return best_len


if __name__ == "__main__":
    fig, ax = plt.subplots(figsize=(6, 6))
    plt.ion()
    ax.axis([L[0], R[0], L[1], R[1]])
    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
    plt.rcParams['axes.unicode_minus'] = False
    ax.set_title('模拟改进遗传算法求解最小圆覆盖(精度分析)', fontsize=13, color='k')

    # random.seed(0)
    for i in range(30):
        # data.append([random.uniform(L[0], R[0]), random.uniform(L[1], R[1])])
        k = (L[0] + R[0]) / 2
        data.append([random.uniform(k, k + 100), random.uniform(k, k + 100)])
    for d in data:
        ax.plot(d[0], d[1], c='b', marker='o')

    best_x, best_y, best_len1 = min_cir(data)
    print('增量法:', best_len1)
    # ax.plot(best_x, best_y, c='k', marker='*')
    plt.show()
    plt.pause(1)

    #print('遗传算法', ga(m=100, iter_=500, f1=0.8, f2=0.05, c='m', marker='o')[2])
    print('改进遗传算法:', solve(num=3))

    plt.ioff()
    plt.show()
#GA14
import random
import math
import matplotlib.pyplot as plt
from matplotlib.pyplot import MultipleLocator
from min_circle_covering import min_cir

data = []

DNA_LEN = 25
pop = []
pop_next = []
fit = []
L = [0.0, 0.0]
R = [1e5, 1e5]


def decoding(pop_i):
    x = y = 0.0
    for i in range(DNA_LEN * 2):
        if i % 2 == 0:
            x = x * 2 + pop_i[i]
        else:
            y = y * 2 + pop_i[i]
    x = x / ((1 << DNA_LEN) - 1) * (R[0] - L[0]) + L[0]
    y = y / ((1 << DNA_LEN) - 1) * (R[1] - L[1]) + L[1]
    return x, y


def get_fit():
    ret_id, ret_len = [0, 1e18]
    for i in range(len(pop)):
        x, y = decoding(pop[i])
        ans = 0.0
        for d in data:
            ans = max(ans, math.sqrt((x - d[0]) * (x - d[0]) + (y - d[1]) * (y - d[1])))
        fit[i] = ans

        if fit[i] < ret_len:
            ret_id = i
            ret_len = fit[i]

    aver = 0.0
    for i in range(len(fit)):
        aver += fit[i]
    aver /= len(fit)
    # print(aver)

    ans = 0.0
    for i in range(len(fit)):
        ans = max(ans, fit[i])
    for i in range(len(fit)):
        fit[i] = -fit[i] + ans + 1e-4
    ans = 0.0
    for i in range(len(fit)):
        ans += fit[i]
    for i in range(len(fit)):
        fit[i] /= ans
    for i in range(1, len(fit)):
        fit[i] += fit[i - 1]
    return ret_id, ret_len


def select():
    p = random.random()
    lb = -1
    ub = len(fit)
    while ub - lb > 1:
        mid = (lb + ub) // 2
        if fit[mid] >= p:
            ub = mid
        else:
            lb = mid
    return ub


def ga(m=100, iter_=100, f1=0.8, f2=0.05):
    if m % 2 == 1:
        m += 1
    pop.clear()
    pop_next.clear()
    fit.clear()
    for i in range(m):
        pop.append([])
        pop_next.append([])
        fit.append(0.0)
        for j in range(DNA_LEN * 2):
            pop[i].append(random.randint(0, 1))
            pop_next[i].append(0)

    ret_x = ret_y = 0.0
    ret_len = 1e18

    for _ in range(iter_):
        ret_id, ret_len_i = get_fit()
        if ret_len_i < ret_len:
            ret_len = ret_len_i
            ret_x, ret_y = decoding(pop[ret_id])

        for i in range(0, len(pop), 2):
            id1 = select()
            id2 = select()
            pop_next[i] = pop[id1][:]
            pop_next[i + 1] = pop[id2][:]
            if random.random() < f1:
                k = random.randint(0, DNA_LEN * 2 - 1)
                for j in range(k):
                    t = pop_next[i][j]
                    pop_next[i][j] = pop_next[i + 1][j]
                    pop_next[i + 1][j] = t
            if random.random() < f2:
                k = random.randint(0, DNA_LEN * 2 - 1)
                pop_next[i][k] ^= 1
            if random.random() < f2:
                k = random.randint(0, DNA_LEN * 2 - 1)
                pop_next[i + 1][k] ^= 1
        for i in range(len(pop)):
            t = pop[i]
            pop[i] = pop_next[i]
            pop_next[i] = t

    ret_id, ret_len_i = get_fit()
    if ret_len_i < ret_len:
        ret_len = ret_len_i
        ret_x, ret_y = decoding(pop[ret_id])

    return ret_x, ret_y, ret_len


def ga_after(f=1e7):
    aver_x = aver_y = 0.0
    for i in range(len(pop)):
        id = select()
        xi, yi = decoding(pop[id])
        aver_x += xi
        aver_y += yi
    aver_x /= len(pop)
    aver_y /= len(pop)
    ans = 0.0
    for d in data:
        ans = max(ans, math.sqrt((aver_x - d[0]) ** 2 + (aver_y - d[1]) ** 2))
    ans = min(ans, f)
    L[0] = aver_x - ans
    R[0] = aver_x + ans
    L[1] = aver_y - ans
    R[1] = aver_y + ans
    return ga(m=100, iter_=100, f1=0.8, f2=0.05)


def solve(num=50):
    L[0] = 0.0
    R[0] = 1e5
    L[1] = 0.0
    R[1] = 1e5
    best_len = ga(m=100, iter_=100, f1=0.8, f2=0.05)[2]
    for i in range(num):
        best_len = min(best_len, ga_after()[2])
    best_len = min(best_len, ga_after(1.0)[2])
    return best_len


if __name__ == "__main__":
    # random.seed(0)
    for i in range(100):
        data.append([random.uniform(L[0], R[0]), random.uniform(L[1], R[1])])
        k = (L[0] + R[0]) / 2
        #data.append([random.uniform(k, k + 100), random.uniform(k, k + 100)])
    best_x, best_y, best_len1 = min_cir(data)
    print('增量法:', best_len1)

    L[0] = 0.0
    R[0] = 1e5
    L[1] = 0.0
    R[1] = 1e5

    print('遗传算法:', ga(m=100, iter_=100 * 30, f1=0.8, f2=0.05)[2])

    print('改进遗传算法:', solve(num=30))

#GA2
import sys

from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu, QVBoxLayout, QSizePolicy, QMessageBox, QWidget, \
    QPushButton
from PyQt5.QtGui import QIcon

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
from PyQt5.QtCore import QTimer
import random
import numpy as np
from scipy import interpolate
import GA22

pol_Y_best1 = pol_Y_aver1 = pol_Y_best_s1 = pol_Y_best2 = pol_Y_aver2 = pol_Y_best_s2 = []


class PlotCanvas(FigureCanvas):

    def __init__(self, parent=None, width=5, height=4, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = fig.add_subplot(111)

        FigureCanvas.__init__(self, fig)
        self.setParent(parent)

        FigureCanvas.setSizePolicy(self,
                                   QSizePolicy.Expanding,
                                   QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)
        self.update_figure4()
        plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
        plt.rcParams['axes.unicode_minus'] = False

    def update_figure1(self):
        self.axes.cla()
        self.axes.plot([i for i in range(len(pol_Y_aver1))], pol_Y_aver1, label='标准遗传算法')
        self.axes.plot([i for i in range(len(pol_Y_aver2))], pol_Y_aver2, label='改进遗传算法')
        self.axes.legend()
        self.axes.set_title('每代平均半径')
        self.axes.set_xlabel('迭代次数')
        self.axes.set_ylabel('平均半径')
        self.draw()

    def update_figure2(self):
        self.axes.cla()
        self.axes.plot([i for i in range(len(pol_Y_best1))], pol_Y_best1, label='标准遗传算法')
        self.axes.plot([i for i in range(len(pol_Y_best2))], pol_Y_best2, label='改进遗传算法')
        self.axes.legend()
        self.axes.set_title('每代最小半径')
        self.axes.set_xlabel('迭代次数')
        self.axes.set_ylabel('最小半径')
        self.draw()

    def update_figure3(self):
        self.axes.cla()
        self.axes.plot([i for i in range(len(pol_Y_best_s1))], pol_Y_best_s1, label='标准遗传算法')
        self.axes.plot([i for i in range(len(pol_Y_best_s2))], pol_Y_best_s2, label='改进遗传算法')
        self.axes.legend()
        self.axes.set_title('当前累计最小半径')
        self.axes.set_xlabel('迭代次数')
        self.axes.set_ylabel('累计最小半径')
        self.draw()

    def update_figure4(self):
        global pol_Y_best1, pol_Y_aver1, pol_Y_best_s1, pol_Y_best2, pol_Y_aver2, pol_Y_best_s2
        pol_Y_best1, pol_Y_aver1, pol_Y_best_s1, pol_Y_best2, pol_Y_aver2, pol_Y_best_s2 = GA22.get()
        self.axes.cla()
        self.axes.set_title('数据处理完成')
        self.draw()


class App(QMainWindow):

    def __init__(self):
        super().__init__()
        self.left = 100
        self.top = 100
        self.title = '标准遗传算法和改进遗传算法最小球覆盖对比实验'
        self.width = 1700
        self.height = 900
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        m = PlotCanvas(self, width=17, height=9)  # 实例化一个画布对象
        m.move(0, 0)

        button1 = QPushButton('平均半径', self)
        button1.move(1540, 310)
        button1.resize(150, 60)
        button1.clicked.connect(m.update_figure1)

        button2 = QPushButton('最小半径', self)
        button2.move(1540, 510)
        button2.resize(150, 60)
        button2.clicked.connect(m.update_figure2)

        button3 = QPushButton('累计最小半径', self)
        button3.move(1540, 710)
        button3.resize(150, 60)
        button3.clicked.connect(m.update_figure3)

        button4 = QPushButton('更换实验数据', self)
        button4.move(1540, 110)
        button4.resize(150, 60)
        button4.clicked.connect(m.update_figure4)
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())
#GA22
import random
import math
import matplotlib.pyplot as plt
from matplotlib.pyplot import MultipleLocator
from min_circle_covering import min_cir

data = []

DNA_LEN = 25
pop = []
pop_next = []
fit = []
L = [-1e5, -1e5, -1e5]
R = [1e5, 1e5, 1e5]


def decoding(pop_i):
    p = [0.0, 0.0, 0.0]
    for i in range(DNA_LEN * 3):
        p[i % 3] = p[i % 3] * 2 + pop_i[i]
    for i in range(3):
        p[i % 3] = p[i % 3] / ((1 << DNA_LEN) - 1) * (R[i] - L[i]) + L[i]
    return p


pol_Y_aver = []
pol_Y_best = []


def get_fit():
    ret_id, ret_len = [0, 1e18]
    for i in range(len(pop)):
        p = decoding(pop[i])
        ans = 0.0
        for d in data:
            ans = max(ans, math.sqrt((p[0] - d[0]) ** 2 + (p[1] - d[1]) ** 2 + (p[2] - d[2]) ** 2))
        fit[i] = ans

        if fit[i] < ret_len:
            ret_id = i
            ret_len = fit[i]

    aver = 0.0
    for i in range(len(fit)):
        aver += fit[i]
    aver /= len(fit)
    # print(aver)
    pol_Y_aver.append(aver)
    pol_Y_best.append(ret_len)

    ans = 0.0
    for i in range(len(fit)):
        ans = max(ans, fit[i])
    for i in range(len(fit)):
        fit[i] = -fit[i] + ans + 1e-4
    ans = 0.0
    for i in range(len(fit)):
        ans += fit[i]
    for i in range(len(fit)):
        fit[i] /= ans
    for i in range(1, len(fit)):
        fit[i] += fit[i - 1]
    return ret_id, ret_len


def select():
    p = random.random()
    lb = -1
    ub = len(fit)
    while ub - lb > 1:
        mid = (lb + ub) // 2
        if fit[mid] >= p:
            ub = mid
        else:
            lb = mid
    return ub


def ga(m=100, iter_=100, f1=0.8, f2=0.05):
    if m % 2 == 1:
        m += 1
    pop.clear()
    pop_next.clear()
    fit.clear()
    for i in range(m):
        pop.append([])
        pop_next.append([])
        fit.append(0.0)
        for j in range(DNA_LEN * 3):
            pop[i].append(random.randint(0, 1))
            pop_next[i].append(0)

    ret_p = [0.0, 0.0, 0.0]
    ret_len = 1e18

    for _ in range(iter_):
        ret_id, ret_len_i = get_fit()
        if ret_len_i < ret_len:
            ret_len = ret_len_i
            ret_p = decoding(pop[ret_id])

        for i in range(0, len(pop), 2):
            id1 = select()
            id2 = select()
            pop_next[i] = pop[id1][:]
            pop_next[i + 1] = pop[id2][:]
            if random.random() < f1:
                k = random.randint(0, DNA_LEN * 3 - 1)
                for j in range(k):
                    t = pop_next[i][j]
                    pop_next[i][j] = pop_next[i + 1][j]
                    pop_next[i + 1][j] = t
            if random.random() < f2:
                k = random.randint(0, DNA_LEN * 3 - 1)
                pop_next[i][k] ^= 1
            if random.random() < f2:
                k = random.randint(0, DNA_LEN * 3 - 1)
                pop_next[i + 1][k] ^= 1
        for i in range(len(pop)):
            t = pop[i]
            pop[i] = pop_next[i]
            pop_next[i] = t

    ret_id, ret_len_i = get_fit()
    if ret_len_i < ret_len:
        ret_len = ret_len_i
        ret_p = decoding(pop[ret_id])

    return ret_p, ret_len


def ga_after(f=1e7, m=100, iter_=100, f1=0.8, f2=0.05):
    p_aver = [0.0, 0.0, 0.0]
    for i in range(len(pop)):
        id = select()
        pi = decoding(pop[id])
        for j in range(3):
            p_aver[j] += pi[j]

    for i in range(3):
        p_aver[i] /= len(pop)

    ans = 0.0
    for d in data:
        ans = max(ans, math.sqrt((p_aver[0] - d[0]) ** 2 + (p_aver[1] - d[1]) ** 2 + (p_aver[2] - d[2]) ** 2))

    ans = min(ans, f)
    for i in range(3):
        L[i] = p_aver[i] - ans
        R[i] = p_aver[i] + ans
    return ga(m=m, iter_=iter_, f1=f1, f2=f2)


def solve(num=10, m=100, iter_=100, f1=0.8, f2=0.05):
    for i in range(3):
        L[i] = -1e5 + 5
        R[i] = 1e5 + 5
    best_len = ga(m=m, iter_=iter_, f1=f1, f2=f2)[1]

    for i in range(num - 2):
        best_len = min(best_len, ga_after(f=1e7, m=m, iter_=iter_, f1=f1, f2=f2)[1])
    best_len = min(best_len, ga_after(f=1.0, m=m, iter_=iter_, f1=f1, f2=f2)[1])
    return best_len

def get():
    for i in range(3):
        L[i] = -1e5 + 5
        R[i] = 1e5 + 5
    data.clear()
    for i in range(10):
        x = random.uniform(L[0], R[0])
        y = random.uniform(L[1], R[1])
        z = random.uniform(L[2], R[2])
        #x = random.uniform(0, 100)
        #y = random.uniform(0, 100)
        #z = random.uniform(0, 100)
        data.append([x, y, z])

    for i in range(3):
        L[i] = -1e5 + 5
        R[i] = 1e5 + 5

    pol_Y_best.clear()
    pol_Y_aver.clear()
    print(ga(m=100, iter_=100 * 50, f1=0.8, f2=0.05)[1])
    pol_Y_best1 = pol_Y_best[:]
    pol_Y_aver1 = pol_Y_aver[:]
    pol_Y_best_s1 = pol_Y_best[:]
    for i in range(1, len(pol_Y_best_s1)):
        pol_Y_best_s1[i] = min(pol_Y_best_s1[i], pol_Y_best_s1[i - 1])

    pol_Y_best.clear()
    pol_Y_aver.clear()
    print(solve(num=50, m=100, iter_=100, f1=0.8, f2=0.05))
    pol_Y_best2 = pol_Y_best[:]
    pol_Y_aver2 = pol_Y_aver[:]
    pol_Y_best_s2 = pol_Y_best[:]
    for i in range(1, len(pol_Y_best_s2)):
        pol_Y_best_s2[i] = min(pol_Y_best_s2[i], pol_Y_best_s2[i - 1])
    return pol_Y_best1,pol_Y_aver1,pol_Y_best_s1,pol_Y_best2,pol_Y_aver2,pol_Y_best_s2

if __name__ == "__main__":
    for i in range(10):
        x = random.uniform(L[0], R[0])
        y = random.uniform(L[1], R[1])
        z = random.uniform(L[2], R[2])
        #x = random.uniform(0, 100)
        #y = random.uniform(0, 100)
        #z = random.uniform(0, 100)
        data.append([x, y, z])

    for i in range(3):
        L[i] = -1e5 + 5
        R[i] = 1e5 + 5

    pol_Y_best.clear()
    pol_Y_aver.clear()
    print(ga(m=100, iter_=100 * 3, f1=0.8, f2=0.05)[1])
    pol_Y_best1 = pol_Y_best[:]
    pol_Y_aver1 = pol_Y_aver[:]
    pol_Y_best_s1 = pol_Y_best[:]
    for i in range(1, len(pol_Y_best_s1)):
        pol_Y_best_s1[i] = min(pol_Y_best_s1[i], pol_Y_best_s1[i - 1])

    pol_Y_best.clear()
    pol_Y_aver.clear()
    print(solve(num=3, m=100, iter_=100, f1=0.8, f2=0.05))
    pol_Y_best2 = pol_Y_best[:]
    pol_Y_aver2 = pol_Y_aver[:]
    pol_Y_best_s2 = pol_Y_best[:]
    for i in range(1, len(pol_Y_best_s2)):
        pol_Y_best_s2[i] = min(pol_Y_best_s2[i], pol_Y_best_s2[i - 1])

    plt.ion()
    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
    plt.rcParams['axes.unicode_minus'] = False

    plt.figure(1)
    plt.plot([i for i in range(len(pol_Y_aver1))], pol_Y_aver1, label='标准遗传算法')
    plt.plot([i for i in range(len(pol_Y_aver2))], pol_Y_aver2, label='改进遗传算法')
    plt.legend()
    plt.xlabel('迭代次数')
    plt.ylabel('平均半径')
    plt.title('每代平均半径')
    plt.show()

    plt.figure(2)
    plt.plot([i for i in range(len(pol_Y_best1))], pol_Y_best1, label='标准遗传算法')
    plt.plot([i for i in range(len(pol_Y_best2))], pol_Y_best2, label='改进遗传算法')
    plt.legend()
    plt.xlabel('迭代次数')
    plt.ylabel('最小半径')
    plt.title('每代最小半径')
    plt.show()

    plt.figure(3)
    plt.plot([i for i in range(len(pol_Y_best_s1))], pol_Y_best_s1, label='标准遗传算法')
    plt.plot([i for i in range(len(pol_Y_best_s2))], pol_Y_best_s2, label='改进遗传算法')
    plt.legend()
    plt.xlabel('迭代次数')
    plt.ylabel('累计最小半径')
    plt.title('当前累计最小半径')
    plt.show()

    plt.ioff()
    plt.show()

import random
import math


def get_d(p1, p2):
    return math.sqrt((p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1]))


def get_o(p1, p2, p3):
    a = p2[0] - p1[0]
    b = p2[1] - p1[1]
    c = p3[0] - p2[0]
    d = p3[1] - p2[1]
    e = p2[0] * p2[0] + p2[1] * p2[1] - p1[0] * p1[0] - p1[1] * p1[1]
    f = p3[0] * p3[0] + p3[1] * p3[1] - p2[0] * p2[0] - p2[1] * p2[1]
    ret_x = (f * b - e * d) / (c * b - a * d) / 2.0
    ret_y = (a * f - e * c) / (a * d - b * c) / 2.0
    return ret_x, ret_y


def min_cir(data):
    p = data[:]
    for i in range(len(p)):
        j = random.randint(0, len(p) - 1)
        t = p[i]
        p[i] = p[j]
        p[j] = t

    o = [0.0, 0.0]
    r = 0.0
    for i in range(len(p)):
        if get_d(p[i], o) > r:
            o = [p[i][0], p[i][1]]
            r = 0
            for j in range(i):
                if get_d(p[j], o) > r:
                    o = [(p[i][0] + p[j][0]) / 2.0, (p[i][1] + p[j][1]) / 2.0]
                    r = get_d(p[i], p[j]) / 2.0
                    for k in range(j):
                        if get_d(p[k], o) > r:
                            o[0], o[1] = get_o(p[i], p[j], p[k])
                            r = get_d(p[i], o)
    return o[0], o[1], r


if __name__ == "__main__":
    n = int(input())
    data = []
    for i in range(n):
        x, y = map(float, input().split())
        data.append([x, y])
    x, y, r = min_cir(data)
    print('%.10f' % r)
    print('%.10f' % x, '%.10f' % y)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值