Vec2<float> abs(const Vec2<float> &v) { Vec2<float> rv; rv.x = abs_float(v.x); rv.y = abs_float(v.y); return rv; }
Vec4<float> abs(const Vec4<float> &v) { Vec4<float> rv; rv.x = abs_float(v.x); rv.y = abs_float(v.y); rv.z = abs_float(v.z); rv.w = abs_float(v.w); return rv; }
VecN<float, N> abs(const VecN<float, N> &v) { VecN<float, N> rv; for(unsigned int i=0; i < N; i++) { rv.v[i] = abs_float(v.v[i]); } return rv; }
float abs(const float v) { return abs_float(v); }
//average SGD implemented by Julius 2014.08.27 void LLC_SGD(double *w, double *x, double *centers, int *knn_idx, int knn, int d) { int i, j, iter=0, iter0=-1; float GAMMA = 2, adaGAMMA=GAMMA; memset(w, 0.01, knn*sizeof(double)); //minimizing 0.5*||x - w*centers||2,2 + 0.5*lambda*||w||2,2 srand(time(NULL)); float past_grad[64] = {0}; //w[0] = w[1] = 0.25; init_w(w, knn); eval_obj_iter = 0; while(iter < knn*30) { for(i=0; i<BATCH_SIZE; i++) batch_idx[i] = rand()%d; //[0, 127] adaGAMMA = GAMMA*pow(1+GAMMA*BETA_SGD*(iter0+1), -0.75); //adaGAMMA = GAMMA; if(iter > knn*8) iter0++; //if(iter0 == 0) // printf("============Start averaging!!============\n"); //printf("adaGAMMA[%d]: %f\n", iter, adaGAMMA); float wcenters[BATCH_SIZE]={0}, sub_grad=0; //mini-batch SGD, if BATCH_SIZE = 1, then it is shrunk to SGD if(BATCH_SIZE > 1) { //mini-batch SGD for(j=0; j<BATCH_SIZE; j++) { int idx = batch_idx[j]; for(i=0; i<knn; i++) wcenters[j] += w[i]*centers[knn_idx[i]*d+idx]; wcenters[j] = x[idx] - wcenters[j]; } for(i=0; i<knn; i++) { sub_grad=0; for(j=0; j<BATCH_SIZE; j++) { int idx = batch_idx[j]; sub_grad += wcenters[j]*centers[knn_idx[i]*d+idx]; } sub_grad /= BATCH_SIZE; //average over mini-batch gradients sub_grad += BETA_SGD*w[i]; sub_grad *= adaGAMMA; if(abs_float(sub_grad) < 5e-4) //neglect too small update continue; w[i] += (sub_grad); w[i] = (w[i] > 1) ? 1: w[i]; w[i] = (w[i] < -1) ? -1: w[i]; } } else { //SGD int idx = batch_idx[0]; for(i=0; i<knn; i++) wcenters[0] += w[i]*centers[knn_idx[i]*d+idx]; for(i=0; i<knn; i++) { sub_grad = (x[idx] - wcenters[0])*centers[knn_idx[i]*d+idx]; //calculate sub_grad[0~127] sub_grad += BETA_SGD*w[i]; sub_grad *= adaGAMMA; if(abs_float(sub_grad) < 5e-4) //neglect too small update continue; double lower_bound, upper_bound; double tentaive_w = w[i] + sub_grad; if(w[i] > 0) { lower_bound = 0; //avg_w - 2*avg < x < avg_w + 2*avg upper_bound = 2*w[i]; } else { lower_bound = 2*w[i]; upper_bound = 0; } w[i] += (sub_grad); w[i] = (tentaive_w > upper_bound) ? upper_bound: tentaive_w; w[i] = (tentaive_w < lower_bound) ? lower_bound: tentaive_w; w[i] = (w[i] > 1) ? 1: w[i]; w[i] = (w[i] < -1) ? -1: w[i]; } } if(iter0 == 0) { for(i=0; i<knn; i++) avg_w[i] = w[i]; } if(iter0 >= 0) { for(i=0; i<knn; i++) { double past_w = avg_w[i]; avg_w[i] = w[i] + (double)iter0/(iter0+1)*(avg_w[i]-w[i]); past_grad[i] = avg_w[i] - past_w; double tentaive_w = avg_w[i] + 2*past_grad[i]; //momentum is used double lower_bound, upper_bound; if(avg_w[i] > 0) { lower_bound = -2*avg_w[i]; //avg_w - 3*avg < x < avg_w + 3*avg upper_bound = 4*avg_w[i]; } else { lower_bound = 4*avg_w[i]; upper_bound = -2*avg_w[i]; } avg_w[i] = (tentaive_w > upper_bound) ? upper_bound: tentaive_w; avg_w[i] = (tentaive_w < lower_bound) ? lower_bound: tentaive_w; avg_w[i] = (avg_w[i] > 1) ? 1: avg_w[i]; avg_w[i] = (avg_w[i] < -1) ? -1: avg_w[i]; //printf("[%d](w, grad) = (%f, %f)\n", i, avg_w[i], past_grad[i]); } #ifdef SGD_DEBUGGING eval_obj(avg_w, x, centers, knn_idx, knn, d); #endif } //norm_w(w, d); else { #ifdef SGD_DEBUGGING eval_obj(w, x, centers, knn_idx, knn, d); #endif } iter++; } double sum=0; for(i=0; i<knn; i++) sum += avg_w[i]; for(i=0; i<knn; i++) { avg_w[i] /= sum; if(abs_double(avg_w[i]) < TOLERANCE) //cut-off small values avg_w[i] = 0; } #ifdef SGD_DEBUGGING printf("LLC_SGD w: ("); for(i=0; i<knn; i++) printf("%f ", avg_w[i]); printf(")\n"); #endif }
static void tick_physics(struct GameState *game_state, float dt) { // Projectile kinematics. for (uint32 i = 0; i < game_state->projectile_count; ++i) { struct Projectile *projectile = &game_state->projectiles[i]; // r = r0 + (v*t) + (a*t^2)/2 projectile->position = vec2_add(projectile->position, vec2_mul(projectile->velocity, dt)); } // Ship kinematics. for (uint32 i = 0; i < game_state->ship_count; ++i) { struct Ship *ship = &game_state->ships[i]; vec2 move_acceleration = vec2_zero(); // v = v0 + (a*t) ship->move_velocity = vec2_add(ship->move_velocity, vec2_mul(move_acceleration, dt)); // r = r0 + (v*t) + (a*t^2)/2 ship->position = vec2_add(vec2_add(ship->position, vec2_mul(ship->move_velocity, dt)), vec2_div(vec2_mul(move_acceleration, dt * dt), 2.0f)); } // // TODO: spatial hashing // // Projectile collision. for (uint32 i = 0; i < game_state->projectile_count; ++i) { struct Projectile *projectile = &game_state->projectiles[i]; struct AABB projectile_aabb = aabb_from_transform(projectile->position, projectile->size); // Projectile-building collision. for (uint32 j = 0; j < game_state->building_count; ++j) { struct Building *building = &game_state->buildings[j]; struct AABB building_aabb = aabb_from_transform(building->position, building->size); if (aabb_aabb_intersection(projectile_aabb, building_aabb)) { // TODO: damage building if not friendly destroy_projectile(game_state, projectile); break; } } // NOTE: owner may be dead and destroyed at this point, so checking for NULL might be required. struct Ship *owner = get_ship_by_id(game_state, projectile->owner); // Projectile-ship collision. for (uint32 j = 0; j < game_state->ship_count; ++j) { struct Ship *ship = &game_state->ships[j]; if (ship->id == projectile->owner) continue; #if 0 // Allow projectiles to pass through teammates. if (ship->team == projectile->team) continue; #endif struct AABB ship_aabb = aabb_from_transform(ship->position, ship->size); if (aabb_aabb_intersection(projectile_aabb, ship_aabb)) { // Disable friendly fire. if (ship->team != projectile->team) damage_ship(game_state, ship, projectile->damage); destroy_projectile(game_state, projectile); break; } } } // TODO: optimize // Ship collision. if (game_state->ship_count >= 2) { for (uint32 i = 0; i < game_state->ship_count - 1; ++i) { struct Ship *a = &game_state->ships[i]; struct AABB a_aabb = aabb_from_transform(a->position, a->size); vec2 a_center = vec2_div(vec2_add(a_aabb.min, a_aabb.max), 2.0f); vec2 a_half_extents = vec2_div(vec2_sub(a_aabb.max, a_aabb.min), 2.0f); // Ship-building collision. for (uint32 j = 0; j < game_state->building_count; ++j) { struct Building *building = &game_state->buildings[j]; struct AABB b_aabb = aabb_from_transform(building->position, building->size); if (aabb_aabb_intersection(a_aabb, b_aabb)) { vec2 b_center = vec2_div(vec2_add(b_aabb.min, b_aabb.max), 2.0f); vec2 b_half_extents = vec2_div(vec2_sub(b_aabb.max, b_aabb.min), 2.0f); vec2 intersection = vec2_sub(vec2_abs(vec2_sub(b_center, a_center)), vec2_add(a_half_extents, b_half_extents)); if (intersection.x > intersection.y) { a->move_velocity.x = 0.0f; if (a->position.x < building->position.x) a->position.x += intersection.x/2.0f; else a->position.x -= intersection.x/2.0f; } else { a->move_velocity.y = 0.0f; if (a->position.y < building->position.y) a->position.y += intersection.y/2.0f; else a->position.y -= intersection.y/2.0f; } } } // Ship-ship collision. for (uint32 j = i + 1; j < game_state->ship_count; ++j) { struct Ship *b = &game_state->ships[j]; struct AABB b_aabb = aabb_from_transform(b->position, b->size); if (aabb_aabb_intersection(a_aabb, b_aabb)) { vec2 b_center = vec2_div(vec2_add(b_aabb.min, b_aabb.max), 2.0f); vec2 b_half_extents = vec2_div(vec2_sub(b_aabb.max, b_aabb.min), 2.0f); vec2 intersection = vec2_sub(vec2_abs(vec2_sub(b_center, a_center)), vec2_add(a_half_extents, b_half_extents)); if (intersection.x > intersection.y) { if (abs_float(a->move_velocity.x) > abs_float(b->move_velocity.x)) a->move_velocity.x = 0.0f; else b->move_velocity.x = 0.0f; if (a->position.x < b->position.x) { a->position.x += intersection.x/2.0f; b->position.x -= intersection.x/2.0f; } else { a->position.x -= intersection.x/2.0f; b->position.x += intersection.x/2.0f; } } else { if (abs_float(a->move_velocity.y) > abs_float(b->move_velocity.y)) a->move_velocity.y = 0.0f; else b->move_velocity.y = 0.0f; if (a->position.y < b->position.y) { a->position.y += intersection.y/2.0f; b->position.y -= intersection.y/2.0f; } else { a->position.y -= intersection.y/2.0f; b->position.y += intersection.y/2.0f; } } } } } } }