/******************************************************************************* * * MIT License * * Copyright (C) 2022-2024 Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * *******************************************************************************/ #pragma once #include #include #include #include #include #include #include #include namespace TensileLite { namespace Serialization { template struct MappingTraits< Matching::DistanceMatchingTable, IO> { using Table = Matching::DistanceMatchingTable; using iot = IOTraits; static void mapping(IO& io, Table& table) { iot::mapRequired(io, "table", table.table); if(!iot::outputting(io)) { using Entry = typename Table::Entry; using KBEntry = typename Table::KBEntry; using std::get; auto comp = [](Entry const& e1, Entry const& e2) { return e1.key < e2.key || (e1.key == e2.key && e1.speed > e2.speed); }; std::sort(table.table.begin(), table.table.end(), comp); if constexpr(std::is_same>{}) { if(Debug::Instance().gridBasedKDTree()) { // Creating K map for(auto it = table.table.begin(); it != table.table.end(); ++it) { auto k = it->key.size() > 3 ? it->key[3] : it->key[2]; auto b = it->key.size() > 3 ? it->key[2] : 1; auto key = std::tuple(it->key[0], it->key[1]); table.kSolutionMap[key].emplace_back(KBEntry{static_cast(k), static_cast(b), it->value}); } // Creating kd-tree std::vector> pts; for(auto it = table.kSolutionMap.begin(); it != table.kSolutionMap.end(); ++it) { pts.push_back({get<0>(it->first), get<1>(it->first)}); } table.kdTree.build(table.kdTree.root, begin(pts), end(pts), 0); } } } } const static bool flow = false; }; template struct MappingTraits, IO> { using Library = ProblemMatchingLibrary; using Properties = typename Library::Table::Properties; using Element = typename Library::Element; using iot = IOTraits; static void mapping(IO& io, Library& lib) { Properties properties; if(iot::outputting(io)) { properties = lib.table->properties; } iot::mapRequired(io, "properties", properties); bool success = false; if(properties.size() == 0) iot::setError(io, "Matching table must have at least one property."); else if(properties.size() == 1) success = mappingKey>(io, lib, properties); else if(properties.size() == 2) success = mappingKey>(io, lib, properties); else if(properties.size() == 3) success = mappingKey>(io, lib, properties); else if(properties.size() == 4) success = mappingKey>(io, lib, properties); else if(properties.size() == 5) success = mappingKey>(io, lib, properties); else if(properties.size() == 6) success = mappingKey>(io, lib, properties); else if(properties.size() == 7) success = mappingKey>(io, lib, properties); else if(properties.size() == 8) success = mappingKey>(io, lib, properties); else if(properties.size() == 9) success = mappingKey>(io, lib, properties); else if(properties.size() == 10) success = mappingKey>(io, lib, properties); if(!success) success = mappingKey>(io, lib, properties); if(!success) iot::setError(io, "Can't write out key: wrong type."); } template static bool mappingKey(IO& io, Library& lib, Properties const& properties) { std::string distanceType; if(iot::outputting(io)) distanceType = lib.table->distanceType(); iot::mapRequired(io, "distance", distanceType); bool success = false; std::string tensile_metric = Debug::Instance().getMetric(); if(!tensile_metric.empty()) distanceType = tensile_metric; if(distanceType == "Euclidean") { success = mappingDistance>( io, lib, properties); } else if(distanceType == "Equality") { success = mappingDistance>(io, lib, properties); } else if(distanceType == "Range") { success = mappingDistance>(io, lib, properties); } else if(distanceType == "JSD") { success = mappingDistance>(io, lib, properties); } else if(distanceType == "Manhattan") { success = mappingDistance>( io, lib, properties); } else if(distanceType == "Ratio") { success = mappingDistance>(io, lib, properties); } else if(distanceType == "Random") { success = mappingDistance>(io, lib, properties); } else if(distanceType == "GridBased") { success = mappingDistance>( io, lib, properties); } else { iot::setError(io, concatenate("Unknown distance function ", distanceType)); } return success; } template static bool mappingDistance(IO& io, Library& lib, Properties const& properties) { using Table = Matching::DistanceMatchingTable, Distance>; std::shared_ptr table; if(iot::outputting(io)) { table = std::dynamic_pointer_cast
(lib.table); if(!table) return false; } else { table = std::make_shared
(); table->properties = properties; lib.table = table; } MappingTraits::mapping(io, *table); return true; } const static bool flow = false; }; template struct MappingTraits, IO> { using Entry = Matching::MatchingTableEntry; using iot = IOTraits; static void mapping(IO& io, Entry& entry) { int32_t index = -1; iot::mapRequired(io, "key", entry.key); iot::mapOptional(io, "speed", entry.speed); iot::mapOptional(io, "index", index); // TODO there is probably a way to make this properly general if(index != -1) { using SSLibrary = SingleSolutionLibrary; auto ctx = static_cast*>(iot::getContext(io)); if(ctx == nullptr || ctx->solutions == nullptr) { iot::setError(io, "SingleSolutionLibrary requires that context be set to " "a SolutionMap."); } auto iter = ctx->solutions->find(index); if(iter == ctx->solutions->end()) { std::ostringstream msg; msg << "[MatchingLibrary] Invalid solution index: " << index; iot::setError(io, msg.str()); } else { std::shared_ptr solution = iter->second; entry.value = std::make_shared(solution); } } else { iot::mapRequired(io, "value", entry.value); } } const static bool flow = true; }; template struct MappingTraits>, IO> : public BaseClassMappingTraits, IO, true> { }; template struct SubclassMappingTraits, IO> : public DefaultSubclassMappingTraits< SubclassMappingTraits, IO>, Matching::Distance, IO> { using Self = SubclassMappingTraits, IO>; using Base = DefaultSubclassMappingTraits, IO>, Matching::Distance, IO>; using SubclassMap = typename Base::SubclassMap; const static SubclassMap subclasses; static SubclassMap GetSubclasses() { return SubclassMap({Base::template Pair>(), Base::template Pair>(), Base::template Pair>(), Base::template Pair>(), Base::template Pair>()}); } }; template const typename SubclassMappingTraits, IO>::SubclassMap SubclassMappingTraits, IO>::subclasses = SubclassMappingTraits, IO>::GetSubclasses(); template struct MappingTraits, IO> : public AutoMappingTraits, IO> { }; template struct MappingTraits, IO> : public AutoMappingTraits, IO> { }; template struct MappingTraits, IO> : public AutoMappingTraits, IO> { }; template struct MappingTraits, IO> : public AutoMappingTraits, IO> { }; template struct MappingTraits, IO> : public AutoMappingTraits, IO> { }; } // namespace Serialization } // namespace TensileLite