Linus/one baseline file

This commit is contained in:
Linus Baumberger
2026-05-17 16:17:00 +02:00
committed by salijagic
parent f294167b08
commit 1c5839e1d6
9 changed files with 240320 additions and 160 deletions
+7 -1
View File
@@ -7,11 +7,17 @@
*.csv *.csv
*.gif *.gif
*.mp4 *.mp4
!reference/*.csv
# Benchmark outputs (keep .gitkeep, ignore results)
benchmarks/*
!benchmarks/.gitkeep
# Compiled binaries # Compiled binaries
main main_*
sizes sizes
# Editor files # Editor files
.vscode .vscode
.DS_Store .DS_Store
+26 -6
View File
@@ -45,16 +45,21 @@ endif
# cross-file optimizations such as function inlining # cross-file optimizations such as function inlining
CXXFLAGS := -O3 -march=native -std=c++23 -Wall -Wextra -flto CXXFLAGS := -O3 -march=native -std=c++23 -Wall -Wextra -flto
SRC := main.cpp forces.cpp social_force_baseline.cpp VARIANT ?= baseline
VARIANT_SRC := variant_$(VARIANT).cpp
SRC := main.cpp $(VARIANT_SRC)
HEADERS := board.hpp forces.hpp pedestrian.hpp vector2d.hpp constants.hpp social_force.hpp HEADERS := board.hpp forces.hpp pedestrian.hpp vector2d.hpp constants.hpp social_force.hpp
TEST_SRC := test_vector2d.cpp test_board.cpp test_forces.cpp forces.cpp TEST_SRC := test_vector2d.cpp test_board.cpp test_forces.cpp $(VARIANT_SRC)
TEST_TARGET := run_tests TEST_TARGET := run_tests
TEST_LIBS := -lgtest -lgtest_main -pthread TEST_LIBS := -lgtest -lgtest_main -pthread
TARGET := main TARGET := main_$(VARIANT)
SIZES_TARGET := sizes SIZES_TARGET := sizes
# Default simulation parameters and output files. # Default simulation parameters and output files.
# These can be overridden from the make command line; see examples above. # These can be overridden from the make command line; see examples above.
N_P ?= 60 # Default number of pedestrians. N_P ?= 60 # Default number of pedestrians.
@@ -70,7 +75,11 @@ RANDOM_SEED ?= 0
# Pass random-seeding mode to the C++ code. # Pass random-seeding mode to the C++ code.
CXXFLAGS += -DRANDOM_SEED=$(RANDOM_SEED) CXXFLAGS += -DRANDOM_SEED=$(RANDOM_SEED)
.PHONY: all main run bench run-bench video sizes asm test clean clean-all # Benchmark suite parameters.
BENCH_SIZES ?= 50 100 200 500 1000 2000 5000 10000
BENCH_ITER ?= 1000
.PHONY: all main run bench run-bench bench-suite video sizes asm test clean clean-all
all: main all: main
@@ -91,6 +100,17 @@ bench: clean
run-bench: bench run-bench: bench
$(SUDO_BENCH) ./$(TARGET) $(N_P) $(N_ITER) $(SUDO_BENCH) ./$(TARGET) $(N_P) $(N_ITER)
# make bench-suite : compile once and run benchmarks across multiple pedestrian counts.
# Results are printed to stdout; redirect to a file to save them.
# make bench-suite > benchmarks/baseline.txt
# make bench-suite VARIANT=v1_cutoff BENCH_SIZES="100 500 1000" > benchmarks/v1_cutoff.txt
bench-suite: bench
@for n in $(BENCH_SIZES); do \
echo "=== N_P=$$n N_ITER=$(BENCH_ITER) ==="; \
$(SUDO_BENCH) ./$(TARGET) $$n $(BENCH_ITER); \
echo ""; \
done
# make video : compile the code, run the simulation, and generate the video. # make video : compile the code, run the simulation, and generate the video.
video: run video: run
python visualization.py $(CSV) $(MP4) python visualization.py $(CSV) $(MP4)
@@ -105,14 +125,14 @@ test: clean
./$(TEST_TARGET) ./$(TEST_TARGET)
# make asm : compile and generate assembly files. # make asm : compile and generate assembly files.
asm: clean main.s forces.s social_force_baseline.s asm: clean main.s variant_$(VARIANT).s
%.s: %.cpp $(HEADERS) %.s: %.cpp $(HEADERS)
$(CXX) -O3 -march=native -std=c++23 -Wall -Wextra -DRANDOM_SEED=$(RANDOM_SEED) -S $< -o $@ $(CXX) -O3 -march=native -std=c++23 -Wall -Wextra -DRANDOM_SEED=$(RANDOM_SEED) -S $< -o $@
# make clean : delete generated files from previous builds. # make clean : delete generated files from previous builds.
clean: clean:
rm -f $(TARGET) $(SIZES_TARGET) $(TEST_TARGET) *.o *.s rm -f main_* $(SIZES_TARGET) $(TEST_TARGET) *.o *.s
# make clean-all : delete all generated files from previous builds and runs. # make clean-all : delete all generated files from previous builds and runs.
# WARNING: this deletes all *.csv and *.mp4 files in this directory. # WARNING: this deletes all *.csv and *.mp4 files in this directory.
+77 -7
View File
@@ -77,6 +77,31 @@ make run-bench
Compiles and runs benchmark measurements. Compiles and runs benchmark measurements.
All build commands accept a `VARIANT` parameter to select an optimization variant:
```bash
make run-bench VARIANT=v1_cutoff N_P=100 N_ITER=10000
```
The default is `VARIANT=baseline`. Each variant compiles its own binary (`main_baseline`, `main_v1_cutoff`, etc.).
```bash
make bench-suite
```
Compiles once and runs benchmarks across multiple pedestrian counts (default: 50, 100, 200, 500, 1000, 2000, 5000, 10000 with 1000 iterations each). Redirect output to save results:
```bash
make bench-suite > benchmarks/baseline.txt
make bench-suite VARIANT=v1_cutoff > benchmarks/v1_cutoff.txt
```
Both `BENCH_SIZES` and `BENCH_ITER` can be overridden:
```bash
make bench-suite BENCH_SIZES="100 500 1000" BENCH_ITER=500
```
```bash ```bash
make test make test
``` ```
@@ -121,6 +146,7 @@ N_ITER=4000
CSV=positions.csv CSV=positions.csv
MP4=simulation.mp4 MP4=simulation.mp4
RANDOM_SEED=0 RANDOM_SEED=0
VARIANT=baseline
``` ```
They can be overridden from the shell. Parameters can be provided selectively and in any order. They can be overridden from the shell. Parameters can be provided selectively and in any order.
@@ -170,7 +196,7 @@ make main
This produces the executable: This produces the executable:
```text ```text
main main_baseline (or main_<variant>)
``` ```
The Makefile uses the following compiler flags: The Makefile uses the following compiler flags:
@@ -202,13 +228,16 @@ This compiles the code and runs the simulation with the default parameters. It p
You can also run the executable manually after compiling: You can also run the executable manually after compiling:
```bash ```bash
./main <number_of_pedestrians> <number_of_iterations> [csv_output_path] ./main_baseline <number_of_pedestrians> <number_of_iterations> [csv_output_path]
./main_<variant> <number_of_pedestrians> <number_of_iterations> [csv_output_path]
``` ```
Example: Example:
```bash ```bash
./main 60 4000 positions.csv ./main_baseline 60 4000 positions.csv
./main_<variant> 60 4000 positions.csv
``` ```
The third argument is optional. If it is provided, simulation states are written to the given CSV file. The third argument is optional. If it is provided, simulation states are written to the given CSV file.
@@ -292,9 +321,50 @@ make run-bench N_P=100 N_ITER=5000
``` ```
The benchmark output includes estimated work, operational intensity, measured cycles, and estimated performance in flops per cycle. The benchmark output includes estimated work, operational intensity, measured cycles, and estimated performance in flops per cycle.
--- ---
## Optimization Variants
The project supports multiple optimization variants through the `VARIANT` Makefile parameter. Each variant provides its own implementation of the force computations and simulation loop while sharing the same interface, benchmark harness, and test suite.
The default variant is `baseline`:
```bash
make run-bench # uses baseline
make run-bench VARIANT=baseline # equivalent
make run-bench VARIANT=v1_cutoff # uses a different variant
```
### File naming convention
Each variant consists of a single file in the project root:
```bash
variant_<name>.cpp # force computations and simulation loop
```
The file must implement the interfaces defined in `forces.hpp` and `social_force.hpp`. The baseline implementation is `variant_baseline.cpp`.
### Creating a new variant
1. Copy the baseline file:
```text
cp variant_baseline.cpp variant_v1_cutoff.cpp
```
2. Edit the new file with your optimization.
3. Build and test:
```bash
make test VARIANT=v1_cutoff
make run-bench VARIANT=v1_cutoff N_P=100 N_ITER=10000
```
### Verifying correctness
A reference CSV is stored in reference/baseline_n60_i4000.csv. To verify that a variant produces the same simulation output:
```bash
make run VARIANT=v1_cutoff N_P=60 N_ITER=4000 CSV=test_output.csv
diff reference/baseline_n60_i4000.csv test_output.csv
```
If the variant changes numerical results (e.g., distance cutoff skipping negligible forces), use a tolerance-based comparison instead of exact diff and justify the deviation.
---
## Tests ## Tests
Run all unit tests with: Run all unit tests with:
@@ -311,7 +381,7 @@ The test target compiles and runs the unit tests for the simulation components.
## Assembly generation ## Assembly generation
To generate assembly files: To generate assembly files for the currently selected VARIANT:
```bash ```bash
make asm make asm
@@ -362,7 +432,7 @@ make clean
This deletes files such as: This deletes files such as:
```text ```text
main main_*
sizes sizes
run_tests run_tests
*.o *.o
@@ -378,7 +448,7 @@ make clean-all
This deletes: This deletes:
```text ```text
main main_*
sizes sizes
run_tests run_tests
*.o *.o
View File
-140
View File
@@ -1,140 +0,0 @@
#include "forces.hpp"
#include "constants.hpp"
#include <math.h>
// Flop count: 2 ADDs, 5 MULTs, 1 SQRT
double w(Vector2d e, Vector2d f) {
if (e.dot(f) >= f.norm() * cos_phi)
return dt_neg;
else
return c_neg_times_dt;
}
// Flop count: 2 ADDs, 4 MULTs
Vector2d acceleration_term_dt(const Pedestrian &alpha) {
// # 2 MULTs
Vector2d desired_velocity = alpha.e * alpha.desired_v0;
Vector2d actual_velocity = alpha.curr_vel;
// # 2 ADDs, 2 MULTs
Vector2d f_alpha_0_dt = (desired_velocity - actual_velocity) * dt_times_tau_alpha_inv;
return f_alpha_0_dt;
}
// Flop count: 12 ADDs, 23 MULTs, 1 DIV, 4 SQRTs, 1 EXP
Vector2d pedestrian_repulsion_dt(const Pedestrian &alpha, const Pedestrian &beta) {
// # 2 ADDs
// $\vec{r}_{\alpha\beta}$
Vector2d r_ab = alpha.curr_pos - beta.curr_pos;
// # 1 ADD, 2 MULTs, 1 SQRT
// $\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert$
double r_ab_norm = r_ab.norm();
r_ab_norm = r_ab_norm > EPS ? r_ab_norm : EPS; // Avoid division by zero
// $v_\beta \Delta t \vec{e}_\beta$
Vector2d s_b_e = beta.s_b_e;
// # 2 ADDs
// $\vec{r}_{\alpha\beta} - \vec{v}_{\beta}\varDelta_{t}\vec{e}_{\beta}$
Vector2d r_ab2 = r_ab - s_b_e;
// # 1 ADD, 2 MULTs, 1 SQRT
// $\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert$
double r_ab2_norm = r_ab2.norm();
r_ab2_norm = r_ab2_norm > EPS ? r_ab2_norm : EPS; // Avoid division by zero
// # 1 ADD
// $\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert$
double r_ab_norm_sum = r_ab_norm + r_ab2_norm;
// # 1 ADD, 1 MULTs, 1 SQRT
//
// $2b = \sqrt{(\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert)^2 - (v_\beta \Delta t)^2}$
//
double two_b_sq = r_ab_norm_sum * r_ab_norm_sum - beta.s_b_sq;
two_b_sq = two_b_sq > EPS_SQ ? two_b_sq : EPS_SQ; // Avoid sqrt of negative and avoid division by zero
double two_b = sqrt(two_b_sq);
// # 5 MULTs, 1 DIV, 1 EXP
//
// $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}$
//
double scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV));
// # 1 MULT
//
// $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}$
//
double scalar_mult_r_ab = scalar_mult_common * r_ab2_norm;
// # 1 MULT
//
// $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}$
//
double scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm;
// # 2 ADDs, 4 MULTs
//
// $\vec{-f}_{\alpha \beta}(\vec{r}_{\alpha \beta}) = \frac{-V^0_{\alpha \beta}}{2\sigma}e^{-b / \sigma} 2\grad_{\vec{r}_{\alpha \beta}}b $
//
//
// $= \frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}\,\vec{r}_{\alpha \beta} + \frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}\,(\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta)$
//
//
//
// $2\grad_{\vec{r}_{\alpha \beta}}b = \frac{(\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert)(\frac{\vec{r}_{\alpha \beta}}{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert} + \frac{\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta}{\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert})}{2b}$
//
//
// $= \frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}\,\vec{r}_{\alpha \beta} + \frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}\,(\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta)$
//
//
Vector2d f_alpha_beta_neg = r_ab * scalar_mult_r_ab + r_ab2 * scalar_mult_r_ab2;
// # 2 ADDs, 7 MULTs, 1 SQRT
//
// $\vec{F}_{\alpha\beta}(\vec{e}_{\alpha}, \vec{r}_{\alpha \beta}).dt = w(\vec{e}_{\alpha}, -\vec{f}_{\alpha\beta}(\vec{r}_{\alpha \beta})).\vec{f}_{\alpha\beta}(\vec{r}_{\alpha \beta}).dt$
//
Vector2d f_alpha_beta_dt = f_alpha_beta_neg * w(alpha.e, f_alpha_beta_neg);
return f_alpha_beta_dt;
}
// Flop count: 10 ADDs, 18 MULTs, 1 DIVs, 2 SQRTs, 1 EXP
Vector2d obstacle_repulsion_dt(const Pedestrian &alpha, const Obstacle &B) {
// # 7 ADDs, 5 MULTs
// $\vec{r}_{\alpha B}$
Vector2d r_aB = alpha.curr_pos - B.find_nearest_obstacle_point(alpha.curr_pos);
// # 1 ADD, 2 MULTs, 1 SQRT
// $\Arrowvert \vec{r}_{\alpha B} \Arrowvert$
double r_aB_norm = r_aB.norm();
r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; // Avoid division by zero
// # 2 MULTs, 1 DIV, 1 EXP
//
// $\frac{-U^0_{\alpha B}}{R} e^{- \Arrowvert \vec{r}_{\alpha B} \Arrowvert / R}$
//
double scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm;
// # 2 MULTs
//
// $-\vec{F}_{\alpha B}(\vec{r}_{\alpha B}) = \frac{-U^0_{\alpha B}}{R} e^{- \Arrowvert \vec{r}_{\alpha B} \Arrowvert / R} \frac{\vec{r}_{\alpha B}}{\Arrowvert \vec{r}_{\alpha B} \Arrowvert}$
//
Vector2d f_alpha_B_neg = r_aB * scalar_mult;
// # 2 ADDs, 7 MULTs, 1 SQRT
//
// $\vec{F}_{\alpha B}(\vec{e}_{\alpha}, \vec{r}_{\alpha B}).dt = w(\vec{e}_{\alpha}, -\vec{F}_{\alpha B}(\vec{r}_{\alpha B})).\vec{F}_{\alpha B}(\vec{r}_{\alpha B}).dt$
//
Vector2d f_alpha_B_dt = f_alpha_B_neg * w(alpha.e, f_alpha_B_neg);
return f_alpha_B_dt;
}
+2 -2
View File
@@ -70,7 +70,7 @@ Vector2d acceleration_term_dt(const Pedestrian &alpha);
// - $\vec{r}_{\alpha \beta} = \vec{r}_\alpha - \vec{r}_\beta$ is the vector from beta's position to alpha's position, // - $\vec{r}_{\alpha \beta} = \vec{r}_\alpha - \vec{r}_\beta$ is the vector from beta's position to alpha's position,
// - $\vec{e}_\alpha$ is the desired direction of pedestrian alpha, // - $\vec{e}_\alpha$ is the desired direction of pedestrian alpha,
// //
// - $\vec{f}_{\alpha\beta}(\vec{r}_{\alpha \beta}) = -\nabla_{\vec{r}_{\alpha\beta}} V_{\alpha\beta}\left[b(\vec{r}_{\alpha\beta})\right]$ is the repulsive effect from beta on alpha (The expanded formula details are given in the code comments given inside the function's implementation in forces.cpp), // - $\vec{f}_{\alpha\beta}(\vec{r}_{\alpha \beta}) = -\nabla_{\vec{r}_{\alpha\beta}} V_{\alpha\beta}\left[b(\vec{r}_{\alpha\beta})\right]$ is the repulsive effect from beta on alpha (The expanded formula details are given in the code comments given inside the function's implementation in variants_baseline.cpp),
// //
// - $w(\vec{e}_{\alpha}, -\vec{f}_{\alpha\beta}(\vec{r}_{\alpha \beta}))$ the direction-dependent perception weighting function, for which the formula is detailed in the w() function above. // - $w(\vec{e}_{\alpha}, -\vec{f}_{\alpha\beta}(\vec{r}_{\alpha \beta}))$ the direction-dependent perception weighting function, for which the formula is detailed in the w() function above.
// //
@@ -94,7 +94,7 @@ Vector2d pedestrian_repulsion_dt(const Pedestrian &alpha, const Pedestrian &beta
// - $\vec{r}_{\alpha B} = \vec{r}_\alpha - \vec{r}^{\,\alpha}_B$ is the vector from the closest point on obstacle B (i.e., $\vec{r}^{\,\alpha}_B$) to pedestrian alpha's position, // - $\vec{r}_{\alpha B} = \vec{r}_\alpha - \vec{r}^{\,\alpha}_B$ is the vector from the closest point on obstacle B (i.e., $\vec{r}^{\,\alpha}_B$) to pedestrian alpha's position,
// - $\vec{e}_\alpha$ is the desired direction of pedestrian alpha, // - $\vec{e}_\alpha$ is the desired direction of pedestrian alpha,
// //
// - $\vec{F}_{\alpha B}(\vec{r}_{\alpha B}) = -\nabla_{\vec{r}_{\alpha B}} U_{\alpha B}(||\vec{r}_{\alpha B}||)$ is the repulsive effect from obstacle B on alpha (The expanded formula details are given in the code comments given inside the function's implementation in forces.cpp), // - $\vec{F}_{\alpha B}(\vec{r}_{\alpha B}) = -\nabla_{\vec{r}_{\alpha B}} U_{\alpha B}(||\vec{r}_{\alpha B}||)$ is the repulsive effect from obstacle B on alpha (The expanded formula details are given in the code comments given inside the function's implementation in variant_baseline.cpp),
// //
// - $w(\vec{e}_{\alpha}, -\vec{F}_{\alpha B}(\vec{r}_{\alpha B}))$ the direction-dependent perception weighting function, for which the formula is detailed in the w() function above. // - $w(\vec{e}_{\alpha}, -\vec{F}_{\alpha B}(\vec{r}_{\alpha B}))$ the direction-dependent perception weighting function, for which the formula is detailed in the w() function above.
// //
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,5 +1,5 @@
// ============================================================================= // =============================================================================
// Tests for forces.cpp // Tests for forces.hpp
// ============================================================================= // =============================================================================
#include "board.hpp" #include "board.hpp"
@@ -1,3 +1,8 @@
// This file is merged from the forces.cpp and social_forces_baseline.cpp
// The goal is that we from now on only have one file as our baseline
// This should make it more easy in the future to implement optimizations
// Our naming convention from now on is: variant_<variant_name>.cpp (Please make sure to keep that consistent, otherwise our Makefile wont work anymore)
#include "board.hpp" #include "board.hpp"
#include "constants.hpp" #include "constants.hpp"
#include "forces.hpp" #include "forces.hpp"
@@ -9,29 +14,167 @@
#include <cmath> #include <cmath>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <math.h> // keep — forces code uses unqualified sqrt/exp
#include <random> #include <random>
#include <tuple> #include <tuple>
#include <vector> #include <vector>
#define SEED 42 #define SEED 42
#define BOARD_WIDTH 10.0 #define BOARD_WIDTH 10.0
#define BOARD_LENGTH 50.0 #define BOARD_LENGTH 50.0
#define WALL_EPS 1e-3 #define WALL_EPS 1e-3
#define BOARD_WIDTH_MINUS_WALL_EPS 9.999 #define BOARD_WIDTH_MINUS_WALL_EPS 9.999
#ifndef RANDOM_SEED #ifndef RANDOM_SEED
// Fixed seeding is used by default to make simulations reproducible.
#define RANDOM_SEED 0 #define RANDOM_SEED 0
#endif #endif
#ifndef BENCHMARK #ifndef BENCHMARK
// Benchmarking is disabled by default.
#define BENCHMARK 0 #define BENCHMARK 0
#endif #endif
using namespace std; using namespace std;
// forces.cpp
// Flop count: 2 ADDs, 5 MULTs, 1 SQRT
double w(Vector2d e, Vector2d f) {
if (e.dot(f) >= f.norm() * cos_phi)
return dt_neg;
else
return c_neg_times_dt;
}
// Flop count: 2 ADDs, 4 MULTs
Vector2d acceleration_term_dt(const Pedestrian &alpha) {
// # 2 MULTs
Vector2d desired_velocity = alpha.e * alpha.desired_v0;
Vector2d actual_velocity = alpha.curr_vel;
// # 2 ADDs, 2 MULTs
Vector2d f_alpha_0_dt = (desired_velocity - actual_velocity) * dt_times_tau_alpha_inv;
return f_alpha_0_dt;
}
// Flop count: 12 ADDs, 23 MULTs, 1 DIV, 4 SQRTs, 1 EXP
Vector2d pedestrian_repulsion_dt(const Pedestrian &alpha, const Pedestrian &beta) {
// # 2 ADDs
// $\vec{r}_{\alpha\beta}$
Vector2d r_ab = alpha.curr_pos - beta.curr_pos;
// # 1 ADD, 2 MULTs, 1 SQRT
// $\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert$
double r_ab_norm = r_ab.norm();
r_ab_norm = r_ab_norm > EPS ? r_ab_norm : EPS; // Avoid division by zero
// $v_\beta \Delta t \vec{e}_\beta$
Vector2d s_b_e = beta.s_b_e;
// # 2 ADDs
// $\vec{r}_{\alpha\beta} - \vec{v}_{\beta}\varDelta_{t}\vec{e}_{\beta}$
Vector2d r_ab2 = r_ab - s_b_e;
// # 1 ADD, 2 MULTs, 1 SQRT
// $\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert$
double r_ab2_norm = r_ab2.norm();
r_ab2_norm = r_ab2_norm > EPS ? r_ab2_norm : EPS; // Avoid division by zero
// # 1 ADD
// $\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert$
double r_ab_norm_sum = r_ab_norm + r_ab2_norm;
// # 1 ADD, 1 MULTs, 1 SQRT
//
// $2b = \sqrt{(\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert)^2 - (v_\beta \Delta t)^2}$
//
double two_b_sq = r_ab_norm_sum * r_ab_norm_sum - beta.s_b_sq;
two_b_sq = two_b_sq > EPS_SQ ? two_b_sq : EPS_SQ; // Avoid sqrt of negative and avoid division by zero
double two_b = sqrt(two_b_sq);
// # 5 MULTs, 1 DIV, 1 EXP
//
// $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}$
//
double scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV));
// # 1 MULT
//
// $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}$
//
double scalar_mult_r_ab = scalar_mult_common * r_ab2_norm;
// # 1 MULT
//
// $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}$
//
double scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm;
// # 2 ADDs, 4 MULTs
//
// $\vec{-f}_{\alpha \beta}(\vec{r}_{\alpha \beta}) = \frac{-V^0_{\alpha \beta}}{2\sigma}e^{-b / \sigma} 2\grad_{\vec{r}_{\alpha \beta}}b $
//
//
// $= \frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}\,\vec{r}_{\alpha \beta} + \frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} -
// v_\beta \Delta t \vec{e}_\beta \Arrowvert}\,(\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta)$
//
//
//
// $2\grad_{\vec{r}_{\alpha \beta}}b = \frac{(\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert)(\frac{\vec{r}_{\alpha \beta}}{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert} + \frac{\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta}{\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert})}{2b}$
//
//
// $= \frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}\,\vec{r}_{\alpha \beta} + \frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}\,(\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta)$
//
//
Vector2d f_alpha_beta_neg = r_ab * scalar_mult_r_ab + r_ab2 * scalar_mult_r_ab2;
// # 2 ADDs, 7 MULTs, 1 SQRT
//
// $\vec{F}_{\alpha\beta}(\vec{e}_{\alpha}, \vec{r}_{\alpha \beta}).dt = w(\vec{e}_{\alpha}, -\vec{f}_{\alpha\beta}(\vec{r}_{\alpha \beta})).\vec{f}_{\alpha\beta}(\vec{r}_{\alpha \beta}).dt$
//
Vector2d f_alpha_beta_dt = f_alpha_beta_neg * w(alpha.e, f_alpha_beta_neg);
return f_alpha_beta_dt;
}
// Flop count: 10 ADDs, 18 MULTs, 1 DIVs, 2 SQRTs, 1 EXP
Vector2d obstacle_repulsion_dt(const Pedestrian &alpha, const Obstacle &B) {
// # 7 ADDs, 5 MULTs
// $\vec{r}_{\alpha B}$
Vector2d r_aB = alpha.curr_pos - B.find_nearest_obstacle_point(alpha.curr_pos);
// # 1 ADD, 2 MULTs, 1 SQRT
// $\Arrowvert \vec{r}_{\alpha B} \Arrowvert$
double r_aB_norm = r_aB.norm();
r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; // Avoid division by zero
// # 2 MULTs, 1 DIV, 1 EXP
//
// $\frac{-U^0_{\alpha B}}{R} e^{- \Arrowvert \vec{r}_{\alpha B} \Arrowvert / R}$
//
double scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm;
// # 2 MULTs
//
// $-\vec{F}_{\alpha B}(\vec{r}_{\alpha B}) = \frac{-U^0_{\alpha B}}{R} e^{- \Arrowvert \vec{r}_{\alpha B} \Arrowvert / R} \frac{\vec{r}_{\alpha B}}{\Arrowvert \vec{r}_{\alpha B} \Arrowvert}$
//
Vector2d f_alpha_B_neg = r_aB * scalar_mult;
// # 2 ADDs, 7 MULTs, 1 SQRT
//
// $\vec{F}_{\alpha B}(\vec{e}_{\alpha}, \vec{r}_{\alpha B}).dt = w(\vec{e}_{\alpha}, -\vec{F}_{\alpha B}(\vec{r}_{\alpha B})).\vec{F}_{\alpha B}(\vec{r}_{\alpha B}).dt$
//
Vector2d f_alpha_B_dt = f_alpha_B_neg * w(alpha.e, f_alpha_B_neg);
return f_alpha_B_dt;
}
// social_force_baseline.cpp
Pedestrian *init_pedestrians(int n_p) { Pedestrian *init_pedestrians(int n_p) {
#if RANDOM_SEED #if RANDOM_SEED
random_device rd; // Platform-provided random seed source. random_device rd; // Platform-provided random seed source.