CoDiPack  3.0.0
A Code Differentiation Package
SciComp TU Kaiserslautern
Loading...
Searching...
No Matches
commonReaderWriterBase.hpp
1/*
2 * CoDiPack, a Code Differentiation Package
3 *
4 * Copyright (C) 2015-2025 Chair for Scientific Computing (SciComp), University of Kaiserslautern-Landau
5 * Homepage: http://scicomp.rptu.de
6 * Contact: Prof. Nicolas R. Gauger (codi@scicomp.uni-kl.de)
7 *
8 * Lead developers: Max Sagebaum, Johannes Blühdorn (SciComp, University of Kaiserslautern-Landau)
9 *
10 * This file is part of CoDiPack (http://scicomp.rptu.de/software/codi).
11 *
12 * CoDiPack is free software: you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, either version 3 of the
15 * License, or (at your option) any later version.
16 *
17 * CoDiPack is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty
19 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 *
21 * See the GNU General Public License for more details.
22 * You should have received a copy of the GNU
23 * General Public License along with CoDiPack.
24 * If not, see <http://www.gnu.org/licenses/>.
25 *
26 * For other licensing options please contact us.
27 *
28 * Authors:
29 * - SciComp, University of Kaiserslautern-Landau:
30 * - Max Sagebaum
31 * - Johannes Blühdorn
32 * - Former members:
33 * - Tim Albring
34 */
35#pragma once
36
37#include <cstdio>
38#include <cstdlib>
39#include <string>
40#include <vector>
41
42#include "../../config.h"
43#include "tapeReaderWriterInterface.hpp"
44
46namespace codi {
51 std::string fileName;
52
54 CommonReaderWriterMethods(std::string const& name) : fileName(name) {};
57
59 std::string modifyFileName(std::string const& suffix) {
60 std::string::size_type sepPosition = fileName.rfind('.');
61 return fileName.substr(0, sepPosition) + suffix;
62 }
63
67 void openFile(FILE*& fileHandle, std::string const& name, std::string const& mode) {
68 fileHandle = fopen(name.c_str(), mode.c_str());
69 if (nullptr == fileHandle) {
70 CODI_EXCEPTION("Could not open file %s", name.c_str());
71 }
72 }
73 };
74
83 template<typename T_Type>
85 using Type = CODI_DD(T_Type, CODI_DEFAULT_LHS_EXPRESSION);
86 using Identifier = typename Type::Identifier;
87 using Tape = typename Type::Tape;
88
89 std::vector<Identifier> inputVariables;
90 std::vector<Identifier> outputVariables;
91
93 CommonBaseTapeWriter(std::string const& name, std::vector<Identifier> const& in,
94 std::vector<Identifier> const& out)
96
97 protected:
98
100 void printIoText(Tape& tape) {
101 FILE* ioFileHandleTxt = nullptr;
102 this->openFile(ioFileHandleTxt, modifyFileName("IO.txt"), "w");
103
104 fprintf(ioFileHandleTxt, "%zu Inputs = ", inputVariables.size());
105 for (size_t inputCount = 0; inputCount < inputVariables.size(); inputCount++) {
106 fprintf(ioFileHandleTxt, "%d ", inputVariables[inputCount]);
107 }
108 fprintf(ioFileHandleTxt, "\n%zu Outputs = ", outputVariables.size());
109 for (size_t outputCount = 0; outputCount < outputVariables.size(); outputCount++) {
110 fprintf(ioFileHandleTxt, "%d ", outputVariables[outputCount]);
111 }
112 fprintf(ioFileHandleTxt, "\nLargest Index = %d", tape.getIndexManager().getLargestCreatedIndex());
113 fclose(ioFileHandleTxt);
114 }
115
117 void printIoBinary(Tape& tape) {
118 FILE* ioFileHandleBinary = nullptr;
119
120 this->openFile(ioFileHandleBinary, modifyFileName("IO.dat"), "wb");
121
122 size_t nInputs = inputVariables.size();
123 size_t nOutputs = outputVariables.size();
124
125 fwrite(&nInputs, sizeof(nInputs), 1, ioFileHandleBinary);
126 fwrite(&inputVariables[0], sizeof(Identifier), nInputs, ioFileHandleBinary);
127 fwrite(&nOutputs, sizeof(nOutputs), 1, ioFileHandleBinary);
128 fwrite(&outputVariables[0], sizeof(Identifier), nOutputs, ioFileHandleBinary);
129 Identifier largestIndex = tape.getIndexManager().getLargestCreatedIndex();
130 fwrite(&largestIndex, sizeof(Identifier), 1, ioFileHandleBinary);
131
132 fclose(ioFileHandleBinary);
133 }
134 };
135
142 template<typename T_Type>
143 struct CommonBaseTapeReader : public TapeReaderInterface<T_Type>, public CommonReaderWriterMethods {
144 using Type = CODI_DD(T_Type, CODI_DEFAULT_LHS_EXPRESSION);
145 using Tape = typename Type::Tape;
146 using Identifier = typename Type::Identifier;
147
148 std::vector<Identifier> inputVariables;
149 std::vector<Identifier> outputVariables;
150 size_t nInputs;
151 size_t nOutputs;
152
154
156 CommonBaseTapeReader() : CommonReaderWriterMethods(), tape() {};
157
158 protected:
159
162 FILE* ioFileHandleTxt;
163 this->openFile(ioFileHandleTxt, modifyFileName("IO.txt"), "r+");
164
165 fscanf(ioFileHandleTxt, "%zu Inputs = ", &nInputs);
166 inputVariables.resize(nInputs, 0);
167 for (size_t inputCount = 0; inputCount < nInputs; inputCount++) {
168 fscanf(ioFileHandleTxt, "%d ", &inputVariables[inputCount]);
169 }
170 fscanf(ioFileHandleTxt, "\n%zu Outputs = ", &nOutputs);
171 outputVariables.resize(nOutputs, 0);
172 for (size_t outputCount = 0; outputCount < nOutputs; outputCount++) {
173 fscanf(ioFileHandleTxt, "%d ", &outputVariables[outputCount]);
174 }
175 fscanf(ioFileHandleTxt, "\nLargest Index = %d", &largestIndex);
176 fclose(ioFileHandleTxt);
177 }
178
181 FILE* fileIoHandleBin;
182 this->openFile(fileIoHandleBin, modifyFileName("IO.dat"), "rb");
183
184 fread(&nInputs, sizeof(nInputs), 1, fileIoHandleBin);
185 inputVariables.resize(nInputs, 0);
186 fread(inputVariables.data(), sizeof(Identifier), nInputs, fileIoHandleBin);
187 fread(&nOutputs, sizeof(nOutputs), 1, fileIoHandleBin);
188 outputVariables.resize(nOutputs, 0);
189 fread(outputVariables.data(), sizeof(Identifier), nOutputs, fileIoHandleBin);
190 fread(&largestIndex, sizeof(Identifier), 1, fileIoHandleBin);
191 }
192
195 return tape;
196 }
197
199 std::vector<Identifier> const& getInputs() const& {
200 return inputVariables;
201 }
202
204 std::vector<Identifier> const& getOutputs() const& {
205 return outputVariables;
206 }
207
209 void updateUserIO(Identifier const& linearOffset) {
210 if (Tape::TapeTypes::IsLinearIndexHandler && !TapeTraits::IsPrimalValueTape<Tape>::value) {
211 // For the linear case, user IO is updated with a potential offset.
212 for (size_t inputCount = 0; inputCount < inputVariables.size(); inputCount++) {
213 inputVariables[inputCount] -= linearOffset;
214 }
215
216 for (size_t outputCount = 0; outputCount < outputVariables.size(); outputCount++) {
217 outputVariables[outputCount] -= linearOffset;
218 }
219 }
220 }
221 };
222
230 template<typename T_Type>
232 using Type = CODI_DD(T_Type, CODI_DEFAULT_LHS_EXPRESSION);
234
235 using Tape = typename Type::Tape;
236 using Identifier = typename Type::Identifier;
237 using Real = typename Type::Real;
238
240
241 FILE* fileHandleGraph = nullptr;
242
245 std::vector<Identifier> identifierPrefix;
246 std::vector<Identifier> identifierExtensions;
248 std::vector<IdentifierType> identifierType;
250
251 CommonTextTapeWriter(bool writeDotHeaderFooter, std::string const& name, std::vector<Identifier> const& in,
252 std::vector<Identifier> const& out)
253 : Base(name, in, out),
255 fileHandleGraph(nullptr),
260 identifierType(0) {}
261
263 void start(Tape& tape) {
264 // Resize vectors to maximum index.
265 identifierPrefix.resize(tape.getIndexManager().getLargestCreatedIndex() + 1, 0);
266 identifierExtensions.resize(tape.getIndexManager().getLargestCreatedIndex() + 1, 0);
267 identifierType.resize(tape.getIndexManager().getLargestCreatedIndex() + 1, IdentifierType::Temp);
268
269 // Record the input and output identifiers in the identifierType vector. This is used later to colour code the
270 // nodes and avoids searching through the input and output vectors for each statement.
271 for (size_t inputCount = 0; inputCount < this->inputVariables.size(); inputCount++) {
272 identifierType[this->inputVariables[inputCount]] = IdentifierType::Input;
273 }
274
275 for (size_t outputCount = 0; outputCount < this->outputVariables.size(); outputCount++) {
276 identifierType[this->outputVariables[outputCount]] = IdentifierType::Output;
277 }
278
279 this->openFile(fileHandleGraph, this->fileName, "w");
280
282 // Print out the header and add a color index.
283 fprintf(fileHandleGraph,
284 "digraph Net {\nInputs [label = \"Inputs\", color=\"blue\"];\nOutputs [label = \"Outputs\", "
285 "color=\"red\"];\nInter [label = \"Inter\"];\n");
286 }
287 }
288
290 void finish() {
292 fprintf(this->fileHandleGraph, "}");
293 }
294 fclose(this->fileHandleGraph);
295 }
296
297 protected:
298
300 std::string formatAggregateName(Identifier const& aggregate) {
301 return "Aggregate" + std::to_string(aggregate);
302 }
303
305 std::string formatNodePrefix(Identifier const& identifier) {
306 std::string prefix = "";
307 if (0 != identifierPrefix[identifier]) {
308 prefix = formatAggregateName(identifierPrefix[identifier]) + ":";
309 }
310 return prefix;
311 }
312
314 std::string formatNodeName(Identifier const& identifier, int extensionOffset = 0) {
315 return "A" + std::to_string(identifier) + "_" +
316 std::to_string(identifierExtensions[identifier] + extensionOffset);
317 }
318
320 std::string formatNodeNameForLink(Identifier const& identifier) {
321 return formatNodePrefix(identifier) + formatNodeName(identifier);
322 }
323
325 std::string nodeColorProperties(Identifier const& identifier) {
326 if (identifierType[identifier] == IdentifierType::Input) {
327 return "blue";
328 } else if (identifierType[identifier] == IdentifierType::Output) {
329 return "red";
330 } else {
331 return "black";
332 }
333 }
334
336 std::string createNode(size_t nIdentifiers, Identifier const* identifiers, std::string const& label) {
337 std::string name = "";
338 std::string finalLabel = "";
339 std::string shape = "";
340 if (1 == nIdentifiers) {
341 name = formatNodeName(identifiers[0], 1);
342 finalLabel = formatNodeLabel(identifiers[0]);
343 if (0 != label.size()) {
344 finalLabel += " = " + label;
345 }
346 } else {
347 aggregateCounter += 1;
350 finalLabel = "{ " + label + " | {";
351
352 // Update the prefix for the lhs identifiers.
353 for (size_t i = 0; i < nIdentifiers; i += 1) {
354 if (0 != i) {
355 finalLabel += " | ";
356 }
357 finalLabel += "<" + formatNodeName(identifiers[i], 1) + "> " + formatNodeLabel(identifiers[i]);
358 }
359
360 finalLabel += "}}";
361 shape = ", shape=\"record\"";
362 }
363
364 std::string node = name + " [label = \"" + finalLabel + "\", color=\"" + nodeColorProperties(identifiers[0]) +
365 "\"" + shape + "];\n";
366 fprintf(this->fileHandleGraph, "%s", node.c_str());
367
368 return name;
369 }
370
372 std::string formatNodeLabel(Identifier const& identifier) {
373 std::string result;
374
375 if (this->identifierType[identifier] == IdentifierType::Input) {
376 result = "X";
377 } else if (this->identifierType[identifier] == IdentifierType::Output) {
378 result = "Y";
379 } else {
380 result = "T";
381 }
382
383 result += std::to_string(identifier);
384
385 return result;
386 }
387
389 void replaceAll(std::string& str, const std::string& search, const std::string& replace) {
390 size_t start_pos = 0;
391 while ((start_pos = str.find(search, start_pos)) != std::string::npos) {
392 str.replace(start_pos, search.length(), replace);
393 start_pos += replace.length();
394 }
395 }
396
401 std::string modifyMathRep(std::string const& mathRep, Identifier const* const rhsIdentifiers,
402 size_t const& nActiveValues) {
403 std::string result = mathRep;
404
405 // Iterate through the RHS and replace x1..xn with the identifier type and the identifier value.
406 for (size_t curArg = 0; curArg < nActiveValues; curArg++) {
407 std::string searchString = "x" + std::to_string(rhsIdentifiers[curArg]);
408 std::string replaceString = formatNodeLabel(rhsIdentifiers[curArg]);
409
410 replaceAll(result, searchString, replaceString);
411 }
412
413 return result;
414 }
415
417 void placeUnusedRhsNodes(Identifier const* const rhsIdentifiers, Config::ArgumentSize const& nArguments) {
418 // Check if the identifierExtension is zero for any of the rhsIdentifiers. A zero extension indicates that the
419 // node has not been placed. The type of the identifier is then checked to add the correct colour coding.
420 for (size_t argCount = 0; argCount < nArguments; argCount++) {
421 if (this->identifierExtensions[rhsIdentifiers[argCount]] == 0) {
422 createNode(1, &rhsIdentifiers[argCount], "");
423 updateLhsIdentifiers(1, &rhsIdentifiers[argCount]);
424 }
425 }
426 }
427
429 void createEdge(Identifier const& from, std::string const& to, std::string const& label = "") {
430 std::string edge = formatNodeNameForLink(from) + " -> " + to;
431
432 if (0 != label.size()) {
433 edge += " [label=\"" + label + "\"];";
434 }
435 edge += "\n";
436 fprintf(this->fileHandleGraph, "%s", edge.c_str());
437 }
438
440 void updateLhsIdentifiers(size_t nIdentifiers, Identifier const* identifiers) {
441 for (size_t i = 0; i < nIdentifiers; i += 1) {
442 this->identifierExtensions[identifiers[i]] += 1;
443
445 identifierPrefix[identifiers[i]] = aggregateCounter;
446 }
447 }
448
449 lastNodeWasAggregate = false;
450 }
451 };
452}
#define CODI_DD(Type, Default)
Abbreviation for CODI_DECLARE_DEFAULT.
Definition macros.hpp:96
uint8_t ArgumentSize
Type for the number of arguments in statements.
Definition config.h:117
CoDiPack - Code Differentiation Package.
Definition codi.hpp:94
void restoreIoText()
Constructor.
Definition commonReaderWriterBase.hpp:161
void updateUserIO(Identifier const &linearOffset)
This method is used to remove any offset and to update the largest created index.
Definition commonReaderWriterBase.hpp:209
typename Type::Tape Tape
See TapeReaderInterface.
Definition commonReaderWriterBase.hpp:145
T_Type Type
See TapeReaderInterface.
Definition commonReaderWriterBase.hpp:144
Tape & getTape()
Used to get a reference to the restored tape.
Definition commonReaderWriterBase.hpp:194
size_t nOutputs
Size of the output vector.
Definition commonReaderWriterBase.hpp:151
std::vector< Identifier > const & getInputs() const &
Used to get the restored inputs of the tape.
Definition commonReaderWriterBase.hpp:199
std::vector< Identifier > outputVariables
Stores the restored output variables from the tape file.
Definition commonReaderWriterBase.hpp:149
Tape tape
The newly resorted tape.
Definition commonReaderWriterBase.hpp:153
std::vector< Identifier > const & getOutputs() const &
Definition commonReaderWriterBase.hpp:204
Identifier largestIndex
The largest index on the stored tape.
Definition commonReaderWriterBase.hpp:155
typename Type::Identifier Identifier
See TapeReaderInterface.
Definition commonReaderWriterBase.hpp:146
size_t nInputs
Size of the input vector.
Definition commonReaderWriterBase.hpp:150
std::vector< Identifier > inputVariables
Stores the restored input variables from the tape file.
Definition commonReaderWriterBase.hpp:148
void restoreIoBinary()
Restore the IO for the binary readers.
Definition commonReaderWriterBase.hpp:180
void printIoText(Tape &tape)
Generate the IO file in a text format.
Definition commonReaderWriterBase.hpp:100
std::vector< Identifier > outputVariables
The identifiers which have been registered as outputs.
Definition commonReaderWriterBase.hpp:90
CommonBaseTapeWriter(std::string const &name, std::vector< Identifier > const &in, std::vector< Identifier > const &out)
Constructor.
Definition commonReaderWriterBase.hpp:93
std::vector< Identifier > inputVariables
The identifiers which have been registered as inputs.
Definition commonReaderWriterBase.hpp:89
T_Type Type
See TapeWriterInterface.
Definition commonReaderWriterBase.hpp:85
typename Type::Tape Tape
See TapeWriterInterface.
Definition commonReaderWriterBase.hpp:87
typename Type::Identifier Identifier
See TapeWriterInterface.
Definition commonReaderWriterBase.hpp:86
void printIoBinary(Tape &tape)
Generate the IO file in a binary format.
Definition commonReaderWriterBase.hpp:117
CommonReaderWriterMethods(std::string const &name)
Constructor.
Definition commonReaderWriterBase.hpp:54
CommonReaderWriterMethods()
Constructor.
Definition commonReaderWriterBase.hpp:56
std::string fileName
The base file name provided by the user.
Definition commonReaderWriterBase.hpp:51
std::string modifyFileName(std::string const &suffix)
Remove the file extension and replace it with a new suffix.
Definition commonReaderWriterBase.hpp:59
void openFile(FILE *&fileHandle, std::string const &name, std::string const &mode)
Definition commonReaderWriterBase.hpp:67
std::vector< Identifier > identifierExtensions
Definition commonReaderWriterBase.hpp:246
void replaceAll(std::string &str, const std::string &search, const std::string &replace)
Replaces all substrings of search with replace in str.
Definition commonReaderWriterBase.hpp:389
std::string formatNodePrefix(Identifier const &identifier)
Create the prefix for a node name.
Definition commonReaderWriterBase.hpp:305
std::string formatNodeName(Identifier const &identifier, int extensionOffset=0)
Add the identifier extension of the identifier to the node name.
Definition commonReaderWriterBase.hpp:314
std::vector< IdentifierType > identifierType
Definition commonReaderWriterBase.hpp:248
FILE * fileHandleGraph
The handle for the writer.
Definition commonReaderWriterBase.hpp:241
std::vector< Identifier > identifierPrefix
Used to prefix nodes of aggregated types. Zero means no prefix.
Definition commonReaderWriterBase.hpp:245
void start(Tape &tape)
Destructor.
Definition commonReaderWriterBase.hpp:263
typename Type::Identifier Identifier
See TapeWriterInterface.
Definition commonReaderWriterBase.hpp:236
std::string modifyMathRep(std::string const &mathRep, Identifier const *const rhsIdentifiers, size_t const &nActiveValues)
Replaces all general identifiers in the math representation with the input, output or temporary annot...
Definition commonReaderWriterBase.hpp:401
std::string formatNodeNameForLink(Identifier const &identifier)
Prefixes the node name with the prefix for the identifier.
Definition commonReaderWriterBase.hpp:320
bool writeDotHeaderFooter
This flag sets toggles the heading and color index.
Definition commonReaderWriterBase.hpp:239
std::string formatNodeLabel(Identifier const &identifier)
Return a string with the current identifier type and the identifier value.
Definition commonReaderWriterBase.hpp:372
std::string nodeColorProperties(Identifier const &identifier)
Returns the color for a given identifier.
Definition commonReaderWriterBase.hpp:325
CommonTextTapeWriter(bool writeDotHeaderFooter, std::string const &name, std::vector< Identifier > const &in, std::vector< Identifier > const &out)
Constructor.
Definition commonReaderWriterBase.hpp:251
std::string formatAggregateName(Identifier const &aggregate)
Create the prefix for a node name.
Definition commonReaderWriterBase.hpp:300
std::string createNode(size_t nIdentifiers, Identifier const *identifiers, std::string const &label)
Creates a new node for a given Identifier and label.
Definition commonReaderWriterBase.hpp:336
typename Type::Tape Tape
See TapeWriterInterface.
Definition commonReaderWriterBase.hpp:235
T_Type Type
See TapeWriterInterface.
Definition commonReaderWriterBase.hpp:232
void createEdge(Identifier const &from, std::string const &to, std::string const &label="")
Return a string that creates an edge between two nodes in the .dot language.
Definition commonReaderWriterBase.hpp:429
typename Type::Real Real
See TapeWriterInterface.
Definition commonReaderWriterBase.hpp:237
Identifier aggregateCounter
Counts up or types of aggregate nodes.
Definition commonReaderWriterBase.hpp:243
CommonBaseTapeWriter< T_Type > Base
See CommonBaseTapeWriter.
Definition commonReaderWriterBase.hpp:233
bool lastNodeWasAggregate
Indicates if the lats created node was for an aggreate.
Definition commonReaderWriterBase.hpp:244
void updateLhsIdentifiers(size_t nIdentifiers, Identifier const *identifiers)
Update the identifiers extension and the prefix.
Definition commonReaderWriterBase.hpp:440
void placeUnusedRhsNodes(Identifier const *const rhsIdentifiers, Config::ArgumentSize const &nArguments)
Ensure that all the nodes on the rhs have been placed in the .dot file before creating edges to them.
Definition commonReaderWriterBase.hpp:417
void finish()
After all the statements have been written, the finish method finalizes the writing process.
Definition commonReaderWriterBase.hpp:290
The interface is used by all the tape readers. The tape readers are used to restore a tape from eithe...
Definition tapeReaderWriterInterface.hpp:252
If the tape inherits from PrimalValueBaseTape.
Definition tapeTraits.hpp:95
The interface used by all the tape writers. The tape writers are used to generate text,...
Definition tapeReaderWriterInterface.hpp:129