diff options
author | justanothercatgirl <sotov2070@gmail.com> | 2025-03-05 20:12:26 +0300 |
---|---|---|
committer | justanothercatgirl <sotov2070@gmail.com> | 2025-03-05 20:12:26 +0300 |
commit | 620b996f2ffe5e9e426b88f57e4f46bc9af7f237 (patch) | |
tree | abb62586d4d569807ecefc007eef2316d521084c | |
parent | e10c7380486e07b277001ab3aa653b74aa990f79 (diff) |
added 204
-rw-r--r-- | 204/Makefile | 18 | ||||
-rw-r--r-- | 204/README.md | 5 | ||||
-rw-r--r-- | 204/compile_flags.txt | 4 | ||||
-rw-r--r-- | 204/data | 10 | ||||
-rw-r--r-- | 204/data2 | 15 | ||||
-rw-r--r-- | 204/data2__ | 2 | ||||
l--------- | 204/include | 1 | ||||
-rw-r--r-- | 204/main.cpp | 52 | ||||
-rw-r--r-- | 204/plots.gp | 62 | ||||
-rw-r--r-- | libprakpp/include/praktable.hpp | 144 |
10 files changed, 263 insertions, 50 deletions
diff --git a/204/Makefile b/204/Makefile new file mode 100644 index 0000000..224506f --- /dev/null +++ b/204/Makefile @@ -0,0 +1,18 @@ + +CFLAGS = -std=c++2c -mavx -Iinclude -ggdb + +.PHONY: all run_main clean gnuplot + +run: gnuplot + +gnuplot: plots.gp run_main + gnuplot $< &>/dev/null + +run_main: main + ./main + +main: main.cpp include/* + $(CXX) -o $@ $< $(CFLAGS) + +clean: + rm -fr main *.png *.plot diff --git a/204/README.md b/204/README.md new file mode 100644 index 0000000..96fd716 --- /dev/null +++ b/204/README.md @@ -0,0 +1,5 @@ +<!-- Шаблон для прака --> +<!-- файлы, заканчивающиеся на .plot считаются генерируемыми и удаляются через make clean --> +# Обработка <> прака + + diff --git a/204/compile_flags.txt b/204/compile_flags.txt new file mode 100644 index 0000000..34ae930 --- /dev/null +++ b/204/compile_flags.txt @@ -0,0 +1,4 @@ +-Iinclude +-std=c++2c +-mavx2 + diff --git a/204/data b/204/data new file mode 100644 index 0000000..94abed5 --- /dev/null +++ b/204/data @@ -0,0 +1,10 @@ +T F2 F s ss +290.65 0.050 ? ? ? +291.15 0.050 ? ? ? +291.65 0.050 ? ? ? +333 0.042 ? ? ? +332 0.0425 ? ? ? +352 0.041 ? ? ? +349 0.041 ? ? ? +322 0.043 ? ? ? +315 0.045 ? ? ? diff --git a/204/data2 b/204/data2 new file mode 100644 index 0000000..696eb10 --- /dev/null +++ b/204/data2 @@ -0,0 +1,15 @@ +x1 f1 x2 f2 x3 f3 x4 f4 +111.5 0.021 114 0.029 108 0.026 110 0.027 +118 0.025 120 0.024 120 0.019 120 0.019 +120 0.024 130 0.015 125 0.0145 130 0.010 +123 0.020 135 0.010 130 0.010 120 0.019 +130 0.015 125 0.019 130 0.010 110 0.028 +135 0.010 115 0.028 122 0.017 100 0.036 +120 0.024 105 0.037 110 0.028 93 0.040 +115 0.0285 95 0.041 85 0.042 84 0.042 +110 0.033 85 0.049 0 0 0 0 +105 0.037 83 0.05 0 0 0 0 +100 0.041 0 0 0 0 0 0 +90 0.045 0 0 0 0 0 0 +82 0.05 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 diff --git a/204/data2__ b/204/data2__ new file mode 100644 index 0000000..6b6c8ee --- /dev/null +++ b/204/data2__ @@ -0,0 +1,2 @@ +T1 T2 T3 T4 +293.15 293.15 348 343 diff --git a/204/include b/204/include new file mode 120000 index 0000000..2225752 --- /dev/null +++ b/204/include @@ -0,0 +1 @@ +../libprakpp/include/
\ No newline at end of file diff --git a/204/main.cpp b/204/main.cpp new file mode 100644 index 0000000..64a11e2 --- /dev/null +++ b/204/main.cpp @@ -0,0 +1,52 @@ +#include <iostream> + +#include "include/praktable.hpp" + +using table = prak::table<f64>; +using f64p = prak::pvalue<f64>; +using f64v = std::vector<f64>; +using vecarg = const std::vector<f64> &; +using argvec = const std::vector<f64> &; + +void ex1(std::string file) { + table t(file); + f64p F1 = {0.0215, 0.0005}, D = {0.0061, 0.0001}, k = {0.91, 0.01}; + f64 sgm = (D.err / D.val) * (D.err / D.val) + (k.err / k.val) * (k.err / k.val); + f64 F_err = std::sqrt(2.0) * F1.err; + t .apply([&F1](vecarg a){ return a[0] - F1.val;}, {"F2"}, "F") + .apply([&](vecarg a){ return a[0] / (2 * k.val * prak::PI * D.val);}, {"F"}, "s") + .apply([&](vecarg a){ return a[0] * std::sqrt(F_err * F_err / (a[1] * a[1]) + sgm);}, {"s", "F"}, "ss") + .write_plot("s(T).plot", "T", "s", "ss") + .add_columns({"q", "sq", "U", "sU"}); + auto [A, B] = t.least_squares_linear("T", "s", std::make_optional("ss"), std::nullopt); + t .apply([&A](vecarg a){ return -a[0] * A.val;}, {"T"}, "q") + .apply([&A](vecarg a){ return a[0] * A.err;}, {"T"}, "sq") + .apply_function(prak::sum<f64>, {"s", "q"}, {"ss", "sq"}, "U", "sU") + .write_plot("q(T).plot", "T", "q", "sq") + .write_plot("U(T).plot", "T", "U", "sU") + .print(); + auto [qA, qB] = t.least_squares_linear("T", "q", "sq", std::nullopt); + auto [UA, UB] = t.least_squares_linear("T", "U", "sU", std::nullopt); + std::cout + << "s(T)" << A << "x+" << B << std::endl + << "q(T)" << qA << "x+" << qB << std::endl + << "U(T)" << UA << "x+" << UB << std::endl; +} + +void ex2(std::string file) { + table t(file); + const char* strs = "1234"; + std::string x = "x"; + std::string f = "f"; + std::string l = "f(x)"; + for (int i = 0; i < 4; ++i) { + table _t({x, f}, {t.begin(x + strs[i]), t.begin(f + strs[i])}, t.find_index(x + strs[i], 0)); + _t.write_plot(l + strs[i] + ".plot", "x", "f", std::nullopt).print(); + } +} + +int main() { + ex1("data"); + ex2("data2"); + return 0; +} diff --git a/204/plots.gp b/204/plots.gp new file mode 100644 index 0000000..cbf7a1c --- /dev/null +++ b/204/plots.gp @@ -0,0 +1,62 @@ +set term pngcairo size 1000, 800 +set grid + +f1(x) = a1*x+b1 +fit f1(x) 's(T).plot' using 1:2:3 yerr via a1, b1 +f2(x) = a2*x+b2 +fit f2(x) 'q(T).plot' using 1:2:3 yerr via a2, b2 +f3(x) = a3*x+b3 +fit f3(x) 'U(T).plot' using 1:2:3 yerr via a3, b3 + + +set output 's(T).png' +set title "Зависимость коэффицента поверхностного натяжения от температуры" +set xlabel "T, К" +set ylabel "sigma, Н/м" + +plot 's(T).plot' using 1:2:3 with yerrorbars notitle lc 0 pt 1 lw 2, \ + f1(x) title "" lc rgb "red" + + +set output 'q(T),U(T).png' +set title "Зависимости теплоты изотермического образования и поверхностной плотности внутренней энергии от температуры" +set ytics nomirror +set y2tics +set xlabel "Т, К" +set ylabel "q, дж/м^2" +set y2label "U, дж/м^2" +set yrange[1.1:1.8] +set y2range[1:10] +plot 'q(T).plot' using 1:2:3 with yerrorbars axes x1y1 notitle lc 0 pt 1 lw 2, \ + 'U(T).plot' using 1:2:3 with yerrorbars axes x1y2 notitle lc 0 pt 1 lw 2, \ + f2(x) lc rgb "red" axes x1y1 notitle, \ + f3(x) lc rgb "red" axes x1y2 notitle, \ + 'q(T).plot' with lines lc rgb "green" axes x1y1 title "q(T)", \ + 'U(T).plot' with lines lc rgb "blue" axes x1y2 title "U(T)" +unset y2tics +unset y2label +unset xrange +unset yrange + +set xlabel "x, мм" +set ylabel "f, мН" + +set output 'f1(x).png' +set title "Зависимость силы натяжения от координаты (T = 293К)" +plot 'f(x)1.plot' notitle lc 0 pt 1 lw 2 ,\ + 'f(x)1.plot' notitle with lines lc rgb "blue" + +set output 'f2(x).png' +set title "Зависимость силы натяжения от координаты (T = 293К)" +plot 'f(x)2.plot' notitle lc 0 pt 1 lw 2 ,\ + 'f(x)2.plot' notitle with lines lc rgb "blue" + +set output 'f3(x).png' +set title "Зависимость силы натяжения от координаты (T = 343-333К)" +plot 'f(x)3.plot' notitle lc 0 pt 1 lw 2 ,\ + 'f(x)3.plot' notitle with lines lc rgb "red" + +set output 'f4(x).png' +set title "Зависимость силы натяжения от координаты (T = 336-330К)" +plot 'f(x)4.plot' notitle lc 0 pt 1 lw 2 ,\ + 'f(x)4.plot' notitle with lines lc rgb "green" diff --git a/libprakpp/include/praktable.hpp b/libprakpp/include/praktable.hpp index 06519ee..daccedc 100644 --- a/libprakpp/include/praktable.hpp +++ b/libprakpp/include/praktable.hpp @@ -20,15 +20,15 @@ namespace prak { -/// truncate a string to n characters, or return in unmodified +// truncate a string to n characters, or return in unmodified inline std::string truncate_or(const std::string &str, size_t n) { if (str.size() >= n) return str.substr(0, n); return str; } -/// Unused for now. -/// TODO: Remove +// Unused for now. +// TODO: Remove template <typename T> struct opt_value { enum struct t: unsigned char { @@ -55,7 +55,7 @@ struct opt_value { }; -/// Class that can store, print, and apply operations to a table used by lab works +// Class that can store, print, and apply operations to a table used by lab works template <typename dtype> class table { std::vector<dtype> data; @@ -85,11 +85,14 @@ public: table *parent; size_t columns; size_t col_index = 0, data_index = 0; - using iterator_category = std::forward_iterator_tag; + using iterator_category = std::bidirectional_iterator_tag; using value_type = dtype; using difference_type = ptrdiff_t; using pointer = dtype *; using reference = dtype &; + iterator() = default; + iterator(const iterator& other) = default; + iterator& operator=(const iterator& other) = default; iterator(table *new_parent, const std::string &column, size_t row_idx = 0) : parent{new_parent}, columns(new_parent->columns) { @@ -97,21 +100,41 @@ public: data_index = col_index + row_idx * new_parent->columns; } iterator &operator++() { data_index += columns; return *this; } + iterator &operator--() { data_index -= columns; return *this; } iterator operator++(int) { iterator ret = *this; ++(*this); return ret; } + iterator operator--(int) { iterator ret = *this; --(*this); return ret; } iterator &operator+(int x) { data_index += columns * x; return *this; } - bool operator==(iterator other) { return data_index == other.data_index && parent == other.parent && col_index == other.col_index; } - bool operator!=(iterator other) { return data_index != other.data_index || parent != other.parent || col_index != other.col_index; } + iterator &operator-(int x) { data_index -= columns * x; return *this; } + std::strong_ordering operator<=>(const iterator& other) { + return parent == other.parent && col_index == other.col_index && data_index <=> other.data_index; + } + bool operator==(const iterator& other) { + return parent == other.parent && col_index == other.col_index && data_index == other.data_index; + } value_type &operator*() { return parent->data[data_index]; }; }; - /// Optional rownames: names of rows + // Optional rownames: names of rows std::vector<std::string> opt_rownames; - /// Mandatory columnnames: names of columns + // Mandatory columnnames: names of columns std::vector<std::string> names; - /// width used for printing, defaults to 8 + // width used for printing, defaults to 8 size_t column_width = 12; - /// default constructor + // default constructor table() = default; + + table(const std::vector<std::string> &cols, std::vector<iterator> iters, size_t rows) + : rows{rows}, columns{cols.size()} + { + names = cols; + data = std::vector<dtype>(rows * cols.size()); + for (size_t row = 0; row < rows; ++row) { + for (size_t col = 0; col < columns; ++col) { + data[row * columns + col] = *iters[col]; + ++iters[col]; + } + } + } explicit table(const std::vector<std::string> &columns, size_t rows, const dtype &deflt) : rows{rows}, columns{columns.size()} @@ -120,7 +143,7 @@ public: data = std::vector<dtype>(rows * columns.size(), deflt); } - /// Data: array of ararys, not freed automatically. + // Data: array of ararys, not freed automatically. explicit table(const std::vector<std::string> &columns, dtype **data, size_t rows /*size_t columns = strings.size()*/) : rows{rows}, columns{columns.size()} { @@ -132,9 +155,9 @@ public: data[i * columns.size() + j] = data[i][j]; } - /// Strings: names for columns - /// `new_data` format: { { entry1_a, entry2_a, ...} { entry1_b, entry2_b, ... }, ... } - /// where `a`, `b`, ... are columns + // Strings: names for columns + // `new_data` format: { { entry1_a, entry2_a, ...} { entry1_b, entry2_b, ... }, ... } + // where `a`, `b`, ... are columns explicit table(std::vector<std::string> &&strings, std::vector<std::vector<dtype>> &&new_data) : rows{new_data.size() ? new_data[0].size() : 0}, columns{strings.size()} { @@ -165,7 +188,7 @@ public: return data.at(names.size() * row + column); } - /// prints a table. defaults to using std::cout, but any std::ostream can be passed in it. + // prints a table. defaults to using std::cout, but any std::ostream can be passed in it. void print(std::ostream &stream = std::cout) const { stream << "columns: " << columns << ", rows: " << rows << std::endl; bool print_names = opt_rownames.size() == data.size() / columns; @@ -196,15 +219,15 @@ public: stream << '|' << std::endl << '|' << rowsep << '|' << std::endl; } - /// Returns whether the amount of names is correct - /// If it is incorrect, names won't be displayed during printing + // Returns whether the amount of names is correct + // If it is incorrect, names won't be displayed during printing bool set_rownames(std::vector<std::string> &&names) { opt_rownames = names; return opt_rownames.size() == data.size() / names.size(); } - /// apply a function to several columns and store result in another column - /// function must accept std::vector or arguments + // apply a function to several columns and store result in another column + // function must accept std::vector or arguments table &apply(function_type function, stringvec args, std::optional<std::string> result) { size_t result_index = result.has_value() ? index(*result) : 0; for (size_t i = 0; i < rows; ++i) { @@ -228,6 +251,22 @@ public: } return *this; } + + table &apply_function( + function_type function, + const std::vector<std::string> cols, + const std::vector<std::string> sgms, + const std::string& res, + const std::string& ress) { + std::vector<iterator> __cols(cols.size()), + __sgms(sgms.size()); + for (size_t i = 0; i < __cols.size() && i < __sgms.size(); ++i) { + __cols[i] = begin(cols[i]); + __sgms[i] = begin(sgms[i]); + } + + return apply_function_n(function, __cols, __sgms, rows, res, ress); + } table &apply_function_n( function_type function, @@ -253,7 +292,7 @@ public: } return *this; } - /// adds a column with name `name` and data `column_data` + // adds a column with name `name` and data `column_data` table &add_column(const std::string &name, std::vector<dtype> column_data) { if (column_data.size() == 0) column_data = std::vector<dtype>(rows, dtype{}); std::vector<dtype> data_new(rows * (++columns)); @@ -270,8 +309,13 @@ public: table &add_column(const std::string &name, dtype dflt = dtype{}) { return add_column(name, std::vector<dtype>(rows, dflt)); } + table &add_columns(const std::vector<std::string> &cols, dtype dflt = dtype{}) { + for (const auto &str : cols) + add_column(str, dflt); + return *this; + } - /// Deletes a column from a table. + // Deletes a column from a table. table &delete_col(const std::string &colname) { std::vector<dtype> data_new(rows * (--columns)); size_t idx = index(colname); @@ -286,7 +330,7 @@ public: return *this; } - /// Deletes several columns + // Deletes several columns table &delete_cols(const stringvec &cols) noexcept(false) { size_t columns_new = columns - cols.size(); std::vector<dtype> data_new(rows * columns_new); @@ -314,7 +358,7 @@ public: } - /// Appends a row to the table. if name is set, appends it to `opt_rownames` + // Appends a row to the table. if name is set, appends it to `opt_rownames` void add_row(std::vector<dtype> values, std::optional<std::string> name = std::nullopt) { if (values.size() == 0) values = std::vector<dtype>(columns, dtype{}); data.resize(columns * (++rows)); @@ -328,17 +372,17 @@ public: return os; } - /// Reads a table from a file in a format: - /// ``` - /// col1 col2 col3 ... - /// val1 val2 val3 ... - /// val4 val5 val6 ... - /// ... - /// ``` - /// Note tha `val` may either be a real number or a question mark, denoting that the value is unknown - /// `col` may be any string without whitespaeces. - /// if the first column is named "__name__" (as in python), first val in each row is a string used as - /// a row name. + // Reads a table from a file in a format: + // ``` + // col1 col2 col3 ... + // val1 val2 val3 ... + // val4 val5 val6 ... + // ... + // ``` + // Note tha `val` may either be a real number or a question mark, denoting that the value is unknown + // `col` may be any string without whitespaeces. + // if the first column is named "__name__" (as in python), first val in each row is a string used as + // a row name. void read(std::ifstream& f) { std::string header; std::getline(f >> std::ws, header); @@ -375,14 +419,14 @@ public: columns = names.size(); } - /// Reads a table from a file specified by `path`. - /// For details, refer to documentation of `void read(std::ifstream&)` overload + // Reads a table from a file specified by `path`. + // For details, refer to documentation of `void read(std::ifstream&)` overload void read(const std::string &path) { std::ifstream f(path); read(f); } - /// Fills a specified column with the same value `v` + // Fills a specified column with the same value `v` table &fill_column(const std::string &column, dtype v) { apply([&v](const std::vector<dtype>& _) -> dtype { return v; }, {}, column); return *this; @@ -403,7 +447,7 @@ public: return *this; } - /// returns an std::pair with coefficients A and B in that order + // returns an std::pair with coefficients A and B in that order std::pair<prak::pvalue<dtype>, prak::pvalue<dtype>> least_squares_linear(std::string x, std::string y, std::optional<std::string> sigma, std::optional<dtype> sigma_fixed) noexcept(false) { @@ -423,7 +467,7 @@ public: return ret; } - /// calculate an average of the column + // calculate an average of the column dtype col_avg(const std::string &column) { dtype accum = dtype{}; for (auto it = begin(column); it != end(column); ++it) @@ -431,7 +475,7 @@ public: return accum / rows; } - /// calculate standard deviation of the column + // calculate standard deviation of the column dtype col_stddev(const std::string &column) { dtype accum = dtype{}; dtype avg = col_avg(column); @@ -440,9 +484,9 @@ public: return std::sqrt(accum); } - /// takes columns [columns], calculates average and standard deviation for each row, puts them into `avg` and `stddev` and deleted original columns - /// if create_columns is true, creates columns avg and stddev - /// This is common thing to do, so might as well write a function for that + // takes columns [columns], calculates average and standard deviation for each row, puts them into `avg` and `stddev` and deleted original columns + // if create_columns is true, creates columns avg and stddev + // This is common thing to do, so might as well write a function for that table& into_avgstddev(const std::vector<std::string> &columns, const std::string &avg_out, const std::string &stddev_out, bool create_columns = false) { if (create_columns) { add_column(avg_out, std::vector<dtype>(rows, dtype{})); @@ -454,8 +498,8 @@ public: return *this; } - /// applies a function `func` to arguments in columns `args`, stores the result in column `result` and standard error in column `result_sigma`. - /// `sigmas` must be in a 1-to-1 correspondance with `args` + // applies a function `func` to arguments in columns `args`, stores the result in column `result` and standard error in column `result_sigma`. + // `sigmas` must be in a 1-to-1 correspondance with `args` table& apply_with_err(function_t<dtype> func, const stringvec &args, const stringvec &sigmas, const std::string &result, const std::string result_sigma) { if (args.size() != sigmas.size()) throw dimension_error("Args and Sigmas did not have the same dimentinons"); size_t result_index = index(result), @@ -481,7 +525,7 @@ public: return col_idx; } - /// Serialize data in format `data[args[0]][i] data[args[1]][i] data[args[2]][i]...` + // Serialize data in format `data[args[0]][i] data[args[1]][i] data[args[2]][i]...` void print_plot(const stringvec &args, std::ostream &out = std::cout) const { std::vector<size_t> offsets(args.size()); for (size_t i = 0; i < args.size(); ++i) { @@ -495,7 +539,7 @@ public: } } - /// Serialize data in format `data[xs][i] data[ys][i] <data[xss][i]> <data>[yss][i]>`, readable by gnuplot with xyerrorbars + // Serialize data in format `data[xs][i] data[ys][i] <data[xss][i]> <data>[yss][i]>`, readable by gnuplot with xyerrorbars table &write_plot_4(const std::string &file, const std::string &xs, const std::string &ys, const std::string &xss, const std::string &yss) { std::ofstream out(file); size_t xi = index(xs), yi = index(ys), xsi = index(xss), ysi = index(yss); @@ -507,7 +551,7 @@ public: return *this; } - /// Serialize data in format `data[xs][i] data[ys][i] <data[ss][i]>`, readable by gnuplot with yerrorbars + // Serialize data in format `data[xs][i] data[ys][i] <data[ss][i]>`, readable by gnuplot with yerrorbars table &write_plot(const std::string &xs, const std::string &ys, std::optional<std::string> yss = std::nullopt, std::ostream &out = std::cout) { size_t nosigma = std::numeric_limits<size_t>::max(); size_t xsi = index(xs), ysi = index(ys), ssi = nosigma; @@ -521,7 +565,7 @@ public: return *this; } - /// Serialize data into a file `file`. For details, refer to documentation for overload with std::ifstream as an argument + // Serialize data into a file `file`. For details, refer to documentation for overload with std::ifstream as an argument table &write_plot(const std::string &file, const std::string &xs, const std::string &ys, std::optional<std::string> yss = std::nullopt) { std::ofstream out(file); return write_plot(xs, ys, yss, out); |