Commit 29209792 by Tianqi Yang

Upload everything

parents
#include "blossom.h"
pair < double, vector < int > > solve_cpp ( Graph < double > g, vector < int > in_set ) {
int n = g.get_n (), m = g.get_m ();
vector<int> bts ( n + 2, 0 ), stb ( n + 2 );
int N = 0;
for ( auto x : in_set ) {
++N;
bts[x] = N;
stb[N] = x;
}
int M = 0;
vector<MWM::InputEdge> edges;
vector<int> ou ( N + 2 ), ov ( N + 2 );
for ( int i = 1; i <= N; ++i ) {
for ( auto v : g.getedges ( stb[i] ) ) {
if ( bts[v.v] && i < bts[v.v] ) {
edges.push_back ( { i, bts[v.v], 500000000 - static_cast < int > ( round ( v.w * 100000000 ) ) } );
ou[i + 1] += 1; ov[bts[v.v] + 1] += 1;
++M;
}
}
}
edges.resize ( M * 2 );
for ( int i = 1; i <= N + 1; ++i ) ov[i] += ov[i - 1];
for ( int i = 0; i < M; ++i ) edges[M + ( ov[edges[i].to]++ )] = edges[i];
for ( int i = 1; i <= N + 1; ++i ) ou[i] += ou[i - 1];
for ( int i = 0; i < M; ++i ) edges[ou[edges[i + M].from]++] = edges[i + M];
edges.resize ( M );
auto ans = MWM ( N, edges ).maximum_weighted_matching ();
vector < int > method ( n + 2 );
for ( int i = 1; i <= N; ++i ) method[stb[i]] = stb[ans.second[i]];
return make_pair ( ( 500000000LL * ( N / 2 ) - ans.first ) / 100000000.0, method );
}
\ No newline at end of file
This diff is collapsed. Click to expand it.
#!/bin/bash
g++ main.cpp consts.cpp blossom.cpp simulate_annealing.cpp -o main -O2 -std=c++11 -lpthread
#include "consts.h"
const double EPS = 1e-9;
const double WEIGHT_ROAD = 1.5;
const double WEIGHT_TRAIL = 1;
const double WEIGHT_PARK = 0.03;
const double WEIGHT_PICNIC = 0.06;
const double WEIGHT_RESTROOM = 0.05;
const double WEIGHT_CAMP = 0.06;
#pragma once
extern const double EPS;
extern const double WEIGHT_ROAD;
extern const double WEIGHT_TRAIL;
extern const double WEIGHT_PARK;
extern const double WEIGHT_PICNIC;
extern const double WEIGHT_RESTROOM;
extern const double WEIGHT_CAMP;
图片宽度为1813像素,长度为1312像素
左上角为原点,先列后行(如右下角坐标为(1813,1312))
图上298像素代表1/4 miles
*说明:P-Parking, A-Picnic Area, R-Restrooms, B-Boat Ramp, V-Pavilion
P 422 639
P 319 871
P 400 971
P 551 917
P 808 650
P 756 445
P 527 461
P 582 416
P 609 561
P 1153 589
P 1177 607
P 1112 716
P 1035 783
P 884 854
P 1127 1084
A 383 906
A 726 898
A 744 852
A 811 677
A 704 559
A 620 418
A 807 438
A 1129 576
A 1204 665
A 1111 745
A 1037 845
A 1328 945
A 1265 1033
A 1290 1104
A 1147 1166
A 1056 1180
A 401 688
R 455 975
R 683 871
R 635 580
R 773 465
R 1154 566
R 1069 1047
B 561 944
V 674 549
G 1193 1230
P 422 639
P 319 871
P 400 971
P 551 917
P 808 650
P 756 445
P 527 461
P 582 416
P 609 561
P 1153 589
P 1177 607
P 1112 716
P 1035 783
P 884 854
P 1127 1084
A 383 906
A 726 898
A 744 852
A 811 677
A 704 559
A 620 418
A 807 438
A 1129 576
A 1204 665
A 1111 745
A 1037 845
A 1328 945
A 1265 1033
A 1290 1104
A 1147 1166
A 1056 1180
A 401 688
R 455 975
R 683 871
R 635 580
R 773 465
R 1154 566
R 1069 1047
B 561 944
V 674 549
G 1193 1230
图片宽度为2542像素,长度为3274像素
左上角为原点,先列后行(如右下角坐标为(2542,3274))
图上424像素代表1 miles
*说明:P-Parking, F-Fire Station, C-Campground, B-Bunkers
P 2031 917
P 808 2571
P 2257 1167
P 1171 284
P 1717 2195
F 2210 1445
F 703 2835
C 719 2553
B 1208 710
G 2259 1171
P 2031 917
P 808 2571
P 2257 1167
P 1171 284
P 1717 2195
F 2210 1445
F 703 2835
C 719 2553
B 1208 710
G 2259 1171
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define LD long double
#define SC(t,x) static_cast<t>(x)
#define AR(t) vector < t >
#define PII pair < int, int >
#define PLL pair < LL, LL >
#define PIL pair < int, LL >
#define PLI pair < LL, int >
#define PQ priority_queue
#define GT(type) greater < type >
#define MP make_pair
#define PB push_back
#define PF push_front
#define POB pop_back
#define POF pop_front
#define PRF first
#define PRS second
#define INIT(ar,val) memset ( ar, val, sizeof ( ar ) )
#define lp(loop,start,end) for ( int loop = start; loop < end; ++loop )
#define lpd(loop,start,end) for ( int loop = start; loop > end; --loop )
#define lpi(loop,start,end) for ( int loop = start; loop <= end; ++loop )
#define lpdi(loop,start,end) for ( int loop = start; loop >= end; --loop )
#define qmax(a,b) (((a)>(b))?(a):(b))
#define qmin(a,b) (((a)<(b))?(a):(b))
#define qabs(a) (((a)>=0)?(a):(-(a)))
const int MAXN = 100007;
const int MAXM = MAXN * 2;
struct eT
{
void setd ( int _u, int _v, int _l )
{
u = _u, v = _v, last = _l;
}
int u, v, last;
}edge[MAXM*2];
int n, m;
int ke, la[MAXN];
int id[MAXM];
int deg[MAXN];
int ans[MAXM], ka;
bool vis[MAXM];
int getdist ( pair < int, int > x, pair < int, int > y )
{
return ( x.first - y.first ) * ( x.first - y.first ) + ( x.second - y.second ) * ( x.second - y.second );
}
void dfs ( int now )
{
for ( int i = la[now]; ~i; i = la[now] ){
la[now] = edge[i].last;
if ( !vis[i>>1] ){
vis[i>>1] = true;
dfs ( edge[i].v );
ans[++ka] = ( ( i & 1 ) ? -1 : 1 ) * id[i];
}
}
}
void euler ()
{
lp ( i, 0, ke ) deg[edge[i].u] ^= 1;
lpi ( i, 1, n ){
if ( deg[i] ){
printf ( "NO\n" );
return;
}
}
lpi ( i, 1, n ){
if ( ~la[i] ){
dfs ( i );
break;
}
}
}
int main (int argc, char **argv)
{
if (argc != 3){
cerr << "3 arguments required!" << endl;
return 1;
}
ifstream INFO (argv[1]);
INFO >> n >> m;
vector < pair < int, int > > point ( n + 1 );
for ( int i = 1; i <= n; ++i ){
int x, y;
INFO >> x >> y;
point[i] = make_pair ( x, y );
}
vector < pair < int, int > > es ( m + 1 );
for ( int i = 1; i <= m; ++i ){
int u, v;
INFO >> u >> v;
es[i] = make_pair ( u, v );
}
INFO.close ();
ifstream RES (argv[2]);
int S;
RES >> S;
double t1, t2, t3;
RES >> t1 >> t2 >> t3;
vector < int > count ( m + 1 );
for ( int i = 1; i <= m; ++i ){
// cerr << count[i] << " ";
RES >> count[i];
}
cerr << endl;
RES.close ();
int cm = 0;
INIT ( la, -1 );
for ( int i = 1; i <= m; ++i ){
cm += count[i];
for ( int c = 0; c < count[i]; ++c ){
edge[ke].setd ( es[i].first, es[i].second, la[es[i].first] );
id[ke] = i;
la[es[i].first] = ke++;
edge[ke].setd ( es[i].second, es[i].first, la[es[i].second] );
id[ke] = i;
la[es[i].second] = ke++;
}
}
// for ( int i = 0; i < ke; i += 2 ) cerr << edge[i].u << " " << edge[i].v << endl;
euler ();
if (ka == cm){
vector < int > vec;
for ( int i = cm; i > 0; --i ){
if ( ans[i] > 0 ) vec.push_back (es[ans[i]].first);
else vec.push_back (es[-ans[i]].second);
}
for ( int i = cm; i > 1; --i) {
if ( ans[i] > 0 ) assert ( es[ans[i]].second == vec[cm - i + 1] );
else assert ( es[-ans[i]].first == vec[cm - i + 1] );
}
// for ( auto x : vec ) cerr << x << " "; cerr << endl;
int beg = -1;
for ( int i = 0; i < cm; ++i ){
if ( vec[i] == S ){
beg = i;
break;
}
}
assert ( beg != -1 );
for ( int i = 0; i < cm; ++i ){
if ( !i || getdist ( point[vec[(beg+i-1)%cm]], point[vec[(beg+i)%cm]] ) > 2 ){
cout << point[vec[(beg+i)%cm]].first << " " << point[vec[(beg+i)%cm]].second << endl;
}
}
}else{
cerr << "ERROR, no euler cycle exists!" << endl;
}
}
\ No newline at end of file
#pragma once
#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
template < typename T >
struct Edge
{
Edge ( int u, int v, int id, T w );
int u, v, id;
T w;
};
struct Floyd;
template < typename T >
class Graph
{
public:
Graph ( int n );
void addedge ( int u, int v, T w );
std::vector < Edge < T > > & getedges ( int u );
int get_n () const;
int get_m () const;
Edge < T > get_edge_with_id ( int id ) const;
private:
friend struct Floyd;
int n, m;
std::vector < std::vector < Edge < T > > > edge;
std::vector < Edge < T > > alle;
};
struct Floyd
{
Floyd ( Graph < double > g )
: original_g ( g ), graph ( g.get_n () ), dist ( g.get_n () + 1, std::vector < double > ( g.get_n () + 1, INFINITY ) ), pre ( g.get_n () + 1, std::vector < int > ( g.get_n () + 1 ) )
{
int n = g.get_n ();
for ( int i = 1; i <= n; ++i ) {
dist[i][i] = 0;
pre[i][i] = -1;
for ( auto v : g.edge[i] ) {
dist[i][v.v] = v.w;
pre[i][v.v] = v.id;
}
}
for ( int k = 1; k <= n; ++k ) {
for ( int i = 1; i <= n; ++i ) {
for ( int j = 1; j <= n; ++j ) {
if ( dist[i][k] + dist[k][j] < dist[i][j] ) {
dist[i][j] = dist[i][k] + dist[k][j];
pre[i][j] = pre[k][j];
}
}
}
}
for ( int i = 1; i <= n; ++i ) {
for ( int j = i + 1; j <= n; ++j ) {
graph.addedge ( i, j, dist[i][j] );
}
}
}
std::vector < int > get_path ( int u, int v )
{
std::vector < int > ans;
for ( int t = v; t != u; t = ( ( original_g.get_edge_with_id ( pre[u][t] ).u == t ) ? original_g.get_edge_with_id ( pre[u][t] ).v : original_g.get_edge_with_id ( pre[u][t] ).u ) ) {
ans.push_back ( pre[u][t] );
}
reverse ( ans.begin (), ans.end () );
return ans;
}
std::vector < std::vector < double > > dist;
std::vector < std::vector < int > > pre;
Graph < double > original_g;
Graph < double > graph;
};
template < typename T >
Graph<T>::Graph ( int n )
: n ( n ), m ( 0 ), edge ( n + 2 )
{
}
template<typename T>
void Graph<T>::addedge ( int u, int v, T w )
{
++m;
edge[u].push_back ( Edge < T > ( u, v, m, w ) );
edge[v].push_back ( Edge < T > ( v, u, m, w ) );
alle.push_back ( Edge < T > ( u, v, m, w ) );
}
template<typename T>
std::vector<Edge<T>>& Graph<T>::getedges ( int u )
{
return edge[u];
}
template<typename T>
int Graph<T>::get_n () const
{
return n;
}
template<typename T>
int Graph<T>::get_m () const
{
return m;
}
template<typename T>
Edge<T> Graph<T>::get_edge_with_id ( int id ) const
{
return alle[id - 1];
}
struct Weight
{
Weight ( double length = 0, double weight = 0 )
: length ( length ), weight ( weight )
{}
double length;
double weight;
};
typedef Graph < Weight > WGraph;
template<typename T>
Edge<T>::Edge ( int u, int v, int id, T w )
: u ( u ), v ( v ), id ( id ), w ( w )
{
}
#include <bits/stdc++.h>
#include "blossom.h"
#include "simulate_annealing.h"
#include "consts.h"
using namespace std;
int main ( int argc, char **argv )
{
if ( argc != 4 ) {
cerr << "4 arguments required!" << endl;
return 1;
}
double max_length;
{
stringstream str_buf;
str_buf << argv[3];
str_buf >> max_length;
}
int S;
int n, m, spc;
ifstream IN ( argv[1] );
IN >> n >> m >> spc;
vector < int > node_type ( n + 2 );
for ( int i = 1; i <= n; ++i ) {
IN >> node_type[i];
}
vector < int > deg ( n + 2, 0 );
Graph < double > g ( n );
double sum_w = 0;
for ( int i = 1; i <= m; ++i ) {
int u, v;
double w;
IN >> u >> v >> w;
g.addedge ( u, v, w );
++deg[u], ++deg[v];
sum_w += w;
}
vector < double > node_weight ( n + 2 );
for ( int i = 1; i <= spc; ++i ) {
string sp_type;
int node;
IN >> sp_type >> node;
if ( sp_type[0] == 'P' ) node_weight[node] += WEIGHT_PARK;
else if ( sp_type[0] == 'A' ) node_weight[node] += WEIGHT_PICNIC;
else if ( sp_type[0] == 'R' ) node_weight[node] += WEIGHT_RESTROOM;
else if ( sp_type[0] == 'C' ) node_weight[node] += WEIGHT_CAMP;
else if ( sp_type[0] == 'G' ) S = node;
}
IN.close ();
WGraph wg ( n );
double all_weight_sum = 0;
for ( int i = 1; i <= n; ++i ) {
all_weight_sum += node_weight[i];
}
double c[3] = { 0, 0, 0 };
for ( int i = 1; i <= m; ++i ) {
auto ge = g.get_edge_with_id ( i );
int tu = node_type[ge.u], tv = node_type[ge.v];
double coef;
if ( tu == 1 && tv == 1 ) {
coef = WEIGHT_TRAIL;
c[0] += ge.w;
} else if ( tu == 2 && tv == 2 ) {
coef = WEIGHT_ROAD;
c[1] += ge.w;
} else {
coef = ( WEIGHT_TRAIL + WEIGHT_ROAD ) / 2;
c[2] += ge.w;
}
wg.addedge ( ge.u, ge.v, Weight ( ge.w, coef ) );
all_weight_sum += ge.w * coef;
}
// cerr << c[0] << " " << c[1] << " " << c[2] << endl;
Floyd floyd ( g );
vector < int > all_set;
for ( int i = 1; i <= n; ++i ) {
if ( deg[i] & 1 ) {
all_set.push_back ( i );
}
}
cout << "Length of Chinese Postman Problem: " << solve_cpp ( floyd.graph, all_set ).first + sum_w << "/" << sum_w << endl;
cout << endl << "Running simulated annealing with parameters:" << endl;
cout << "Node count: " << n << endl;
cout << "Edge count: " << m << endl;
cout << "Starting point: " << S << endl;
cout << "Maximum length: " << max_length << endl;
cout << "Sum of weight of all nodes and edges: " << all_weight_sum << endl;
auto sa_result = solve_sa ( wg, floyd, node_weight, S, max_length );
cout << "Result of simulated annealing: " << sa_result.weight_sum << "/" << all_weight_sum << ", path length: " << sa_result.path_length << endl;
ofstream OUT ( argv[2] );
OUT << S << endl;
OUT << sa_result.weight_sum << " " << all_weight_sum << " " << sa_result.path_length << endl;
for ( int i = 1; i <= m; ++i ) {
OUT << sa_result.edge_count[i] << " ";
}
OUT << endl;
OUT.close ();
}
\ No newline at end of file
#!/usr/bin/env python3
import sys
import os
import png
import math
import argparse
PIXEL_LENGTH = 0
BLACK = (0, 0, 0)
RED = (255, 0, 0)
WHITE = (255, 255, 255)
def main ():
parser = argparse.ArgumentParser (prog='png_to_graph.py', description='Convert PNG to graph')
parser.add_argument ('-i', '--input', dest='input', metavar='input_file', help='Input file name', required=True)
parser.add_argument ('-o', '--output', dest='output', metavar='output_file', help='Output file name', required=True)
parser.add_argument ('-d', '--desc', dest='desc', metavar='desc_file', help='Description file name', required=True)
parser.add_argument ('-s', '--shrink', dest='shrink', help='Shrink the graph', action='store_true', default=False)
parser.add_argument ('-l', '--length', dest='length', metavar='length', help='Number of pixels of a mile', type=int, required=True)
parser.add_argument ('-v', '--vertex', dest='vertex', metavar='vertex', help='Output the vertex information to this file', default=None)
args = parser.parse_args ()
PIXEL_LENGTH = 1 / args.length
png_reader = png.Reader (file=open (args.input, 'rb'))
png_info = png_reader.asRGB ()
W, H = png_info[0], png_info[1]
pixels_raw = list (png_info[2])
pixels = [[WHITE] * (W + 2)]
for i in range (H):
pixels.append ([WHITE])
for j in range (W):
pixels[i+1].append ((pixels_raw[i][3*j], pixels_raw[i][3*j+1], pixels_raw[i][3*j+2] ))
pixels[i+1].append (WHITE)
pixels.append ([WHITE] * (W + 2))
vertex = {}
color = [0]
edge = []
def getcolor (p):
if pixels[p[0]][p[1]] == BLACK:
return 1
else:
return 2
def getdist (u, v):
def sqr(x):
return x*x
return math.sqrt (sqr(u[0]-v[0]) + sqr(u[1]-v[1]))
def addedge (u, v):
def addnode (u):
if u not in vertex:
vertex[u] = len(vertex) + 1
color.append (getcolor (u))
addnode (u)
addnode (v)
if vertex[u] < vertex[v]:
edge.append ((vertex[u], vertex[v], getdist (u, v)))
for i in range (1, H+1):
for j in range (1, W+1):
if pixels[i][j] != WHITE:
for dx in range (-1, 2):
for dy in range (-1, 2):
if (dx or dy) and (pixels[i+dx][j+dy] != WHITE):
addedge ((i, j), (i+dx, j+dy))
sp_points = []
spp_set = set ()
with open (args.desc) as DESC:
for line in DESC.readlines ():
content = line.strip ().split ()
if len(content) == 0:
continue
tp = content[0]
y = int (content[1])
x = int (content[2])
min_dist = None
min_p = None
for i in vertex.keys ():
cur_dist = getdist (i, (x, y))
if min_dist is None or cur_dist < min_dist:
min_dist = cur_dist
min_p = vertex[i]
sp_points.append ((tp, min_p))
spp_set.add (min_p)
if args.shrink:
n = len(vertex)
g = [{} for i in range (n+1)]
def insedge (u, v, w):
g[u][v] = w
g[v][u] = w
def deledge (u, v):
g[u].pop (v)
g[v].pop (u)
for (u, v, w) in edge:
insedge (u, v, w)
rem_vertex = {}
for i in range (1, n+1):
rem_vertex[i] = 0
for i in range (1, n+1):
if len(g[i]) == 2 and i not in spp_set:
gl = list(g[i].keys ())
gw = sum (g[i].values ())
if color[i] == color[gl[0]] and color[i] == color[gl[1]]:
deledge (i, gl[0])
deledge (i, gl[1])
rem_vertex.pop (i)
insedge (gl[0], gl[1], gw)
rem_count = 0
for i in rem_vertex:
rem_count += 1
rem_vertex[i] = rem_count
new_vertex = {}
new_color = [0] * (rem_count + 1)
new_edge = []
for i in vertex:
if vertex[i] in rem_vertex:
new_vertex[i] = rem_vertex[vertex[i]]
new_color[new_vertex[i]] = color[vertex[i]]
for i in rem_vertex:
ci = rem_vertex[i]
for j in g[i]:
cj = rem_vertex[j]
if ci < cj:
new_edge.append ((ci, cj, g[i][j]))
vertex = new_vertex
edge = new_edge
color = new_color
for i in range (len(sp_points)):
sp_points[i] = (sp_points[i][0], rem_vertex[sp_points[i][1]])
new_spp_set = set ()
for i in spp_set:
new_spp_set.add (rem_vertex[i])
spp_set = new_spp_set
print ('Total length of edges:', sum (map (lambda x: x[2], edge)) * PIXEL_LENGTH)
with open (args.output, 'w') as OUT:
print (len(vertex), len(edge), len(sp_points), file=OUT)
print (' '.join (map(str, color[1:])), file=OUT)
for i in edge:
print (i[0], i[1], i[2] * PIXEL_LENGTH, file=OUT)
for i in sp_points:
print (i[0], i[1], file=OUT)
if args.vertex is not None:
rev_ver = [None] * (rem_count + 1)
for i in vertex:
rev_ver[vertex[i]] = i
with open (args.vertex, 'w') as VERT:
print (len(vertex), len(edge), file=VERT)
for i in rev_ver[1:]:
print (i[0], i[1], file=VERT)
for i in edge:
print (i[0], i[1], file=VERT)
if __name__ == '__main__':
main ()
#include <bits/stdc++.h>
#include "blossom.h"
#include "simulate_annealing.h"
#include <random>
#include <chrono>
using namespace std;
static const double DIST_DROP_RATE = 0.999;
static const double P_DROP_RATE = 0.9998;
static const double DIST_START = 5;
static const double P_START = 1;
static const int ROUND_COUNT = 50000;
class SA_Solver
{
public:
struct State
{
State ( SA_Solver *solver = nullptr )
: inv ( ( solver == nullptr ? 0 : solver->n + 2 ), 0 ), ine ( ( solver == nullptr ? 0 : solver->m + 2 ), false ), solver ( solver )
{}
void addedge ( int ei )
{
ine[ei] = true;
auto edge = solver->g.get_edge_with_id ( ei );
++inv[edge.u];
++inv[edge.v];
}
void deledge ( int ei )
{
ine[ei] = false;
auto edge = solver->g.get_edge_with_id ( ei );
--inv[edge.u];
--inv[edge.v];
}
State get_next ( double p ) const
{
State res = *this;
int ec = 0;
for ( int i = 1; i <= solver->m; ++i ) {
if ( res.ine[i] ) {
++ec;
}
}
for ( int i = 1; i <= solver->m; ++i ) {
if ( res.ine[i] && solver->urd ( solver->random_engine ) < p * solver->m / ec ) {
// cerr << "DEL : " << i << " " << "(" << solver->g.get_edge_with_id ( i ).u << "," << solver->g.get_edge_with_id ( i ).v << ") " << endl;
res.deledge ( i );
}
}
int nc = 0;
for ( int i = 1; i <= solver->n; ++i ) {
if ( res.inv[i] ) {
for ( auto edge : solver->g.getedges ( i ) ) {
if ( !res.ine[edge.id] ) {
++nc;
}
}
}
}
for ( int i = 1; i <= solver->n; ++i ) {
if ( res.inv[i] ) {
for ( auto edge : solver->g.getedges ( i ) ) {
if ( !res.ine[edge.id] && solver->urd ( solver->random_engine ) < p * solver->m / nc ) {
// cerr << "ADD : " << edge.id << " " << "(" << solver->g.get_edge_with_id ( edge.id ).u << "," << solver->g.get_edge_with_id ( edge.id ).v << ") " << endl;
res.addedge ( edge.id );
}
}
}
}
//for ( int i = 1; i <= solver->n; ++i ) {
// if ( res.inv[i] ) cerr << i << " ";
//}
//cerr << endl;
//for ( int i = 1; i <= solver->m; ++i ) {
// if ( res.ine[i] ) cerr << "(" << solver->g.get_edge_with_id ( i ).u << "," << solver->g.get_edge_with_id ( i ).v << ") ";
//}
//cerr << endl;
//cerr << ec << " " << nc << endl;
return res;
}
pair < pair < double, double >, vector < int > > get_length () const
{
//for ( int i = 1; i <= solver->n; ++i ) {
// if ( inv[i] ) cerr << i << " ";
//}
//cerr << endl;
//for ( int i = 1; i <= solver->m; ++i ) {
// if ( ine[i] ) cerr << "(" << solver->g.get_edge_with_id ( i ).u << "," << solver->g.get_edge_with_id ( i ).v << ") ";
//}
//cerr << endl;
vector < bool > visit ( solver->n + 2 );
for ( int i = 1; i <= solver->n; ++i ) {
if ( inv[i] ) {
dfs ( i, visit );
break;
}
}
for ( int i = 1; i <= solver->n; ++i ) {
if ( inv[i] && !visit[i] ) {
return make_pair ( make_pair ( -INFINITY, -INFINITY ), vector < int > () );
}
}
double sum_e = 0, sum_w = 0;
for ( int i = 1; i <= solver->n; ++i ) {
if ( inv[i] ) {
sum_w += solver->node_weight[i];
}
}
//for ( int i = 1; i <= solver->m; ++i ) {
// if ( ine[i] ) {
// sum_e += solver->g.get_edge_with_id ( i ).w.length;
// }
//}
vector < int > odd;
for ( int i = 1; i <= solver->n; ++i ) {
if ( inv[i] & 1 ) {
odd.push_back ( i );
}
}
auto result = solve_cpp ( solver->md.graph, odd );
sum_e += result.first;
vector < int > es ( solver->m + 1 );
for ( int i = 1; i <= solver->m; ++i ) {
if ( ine[i] ) {
if ( !es[i] ) {
sum_e += solver->g.get_edge_with_id ( i ).w.length;
sum_w += solver->g.get_edge_with_id ( i ).w.weight * solver->g.get_edge_with_id ( i ).w.length;
}
++es[i];
}
}
for ( auto x : odd ) {
int y = result.second[x];
if ( x < y ) {
vector < int > ces = solver->md.get_path ( x, y );
for ( auto e : ces ) {
if ( !es[e] ) {
sum_e += solver->g.get_edge_with_id ( e ).w.length;
sum_w += solver->g.get_edge_with_id ( e ).w.weight * solver->g.get_edge_with_id ( e ).w.length;
}
++es[e];
}
}
}
return make_pair ( make_pair ( sum_e, sum_w ), es );
}
double get_value ( double max_length ) const
{
pair < double, double > res = get_length ().first;
if ( res.first > max_length ) return max_length - res.first;
else return res.second;
}
void dfs ( int now, vector < bool > &visit ) const
{
if ( !inv[now] || visit[now] ) {
return;
}
visit[now] = true;
for ( auto edge : solver->g.getedges ( now ) ) {
if ( ine[edge.id] ) {
dfs ( edge.v, visit );
}
}
}
vector < int > inv;
vector < bool > ine;
SA_Solver *solver;
};
public:
SA_Solver ( WGraph g, Floyd md, vector < double > node_weight )
: g ( g ), md ( md ), node_weight ( node_weight ), n ( g.get_n () ), m ( g.get_m () )
, random_engine ( static_cast < unsigned > ( chrono::system_clock::now ().time_since_epoch ().count () ) )
, urd ( 0.0, 1.0 )
{}
State solve ( int S, double max_length )
{
double disturb = DIST_START / m, p = P_START;
State cur = State ( this ), now;
cur.inv[S] = 2;
State mp = cur;
double cv = cur.get_value ( max_length ), maxv = cv, nv;
int output_freq = 2000 / n + 1;
for ( int rd = 1; rd <= ROUND_COUNT; ++rd ) {
now = cur.get_next ( disturb );
nv = now.get_value ( max_length );
if ( rd % output_freq == 0 ) {
cerr << "\r";
for ( int i = 1; i <= 100; ++i ) {
cerr << " ";
}
cerr << "\r";
cerr << "round " << rd << "/" << ROUND_COUNT << " : " << setw ( 10 ) << fixed << nv << " " << setw ( 10 ) << fixed << cv << " " << setw ( 10 ) << fixed << maxv << " : with param " << setw ( 10 ) << fixed << disturb << " " << setw ( 10 ) << fixed << p;
}
if ( nv > cv || urd ( random_engine ) < exp ( ( nv - cv ) / p ) ) {
cur = now;
cv = nv;
}
if ( cv > maxv ) {
mp = cur;
maxv = cv;
}
disturb = max ( disturb * DIST_DROP_RATE, 2.0 / m );
p *= P_DROP_RATE;
}
cerr << "\r";
for ( int i = 1; i <= 100; ++i ) {
cerr << " ";
}
cerr << "\r";
return mp;
}
private:
friend struct State;
int n, m;
WGraph g;
Floyd md;
vector < double > node_weight;
mt19937 random_engine;
uniform_real_distribution < double > urd;
};
sa_result_t solve_sa ( WGraph g, Floyd md, vector<double> node_weight, int S, double max_length )
{
SA_Solver solver ( g, md, node_weight );
SA_Solver::State result = solver.solve ( S, max_length );
auto eval = result.get_length ();
if ( eval.first.first > max_length ) return sa_result_t ( 0, 0, vector < int > ( g.get_n () + 2 ) );
return sa_result_t ( eval.first.first, eval.first.second, eval.second );
}
sa_result_t::sa_result_t ( double path_length, double weight_sum, std::vector<int> edge_count )
: path_length ( path_length ), weight_sum ( weight_sum ), edge_count ( edge_count)
{
}
#pragma once
#include <vector>
#include "graph.h"
struct sa_result_t
{
sa_result_t ( double path_length, double weight_sum, std::vector < int > edge_count );
double path_length;
double weight_sum;
std::vector < int > edge_count;
};
sa_result_t solve_sa ( WGraph g, Floyd md, std::vector < double > node_weight, int S, double max_length );
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment