metaSMT git
|
00001 #pragma once 00002 00003 #include <metaSMT/frontend/Logic.hpp> 00004 00005 using namespace metaSMT; 00006 using namespace metaSMT::solver; 00007 using namespace metaSMT::logic; 00008 00009 namespace metaSMT { 00010 00011 template<typename Context, typename Boolean> 00012 typename Context::result_type 00013 one_hot(Context &ctx, std::vector<Boolean> const &ps) { 00014 assert(ps.size() > 0 && "One hot encoding requires at least one input variable"); 00015 00016 if (ps.size() == 1) { 00017 return evaluate(ctx, equal(ps[0], True)); 00018 } 00019 00020 typename Context::result_type zero_rail = evaluate(ctx, ps[0]); 00021 typename Context::result_type one_rail = evaluate(ctx, Not(ps[0])); 00022 00023 for (unsigned u = 1; u < ps.size() - 1; ++u) { 00024 zero_rail = evaluate(ctx, Ite(ps[u], one_rail, zero_rail)); 00025 one_rail = evaluate(ctx, Ite(ps[u], False, one_rail)); 00026 } 00027 00028 return evaluate(ctx, Ite(ps[ps.size()-1], one_rail, zero_rail)); 00029 } 00030 00031 template <typename Context, typename Boolean> 00032 typename Context::result_type 00033 cardinality_geq(Context &ctx, std::vector<Boolean> const &ps, unsigned cardinality) { 00034 assert(ps.size() > 0 && "Greater equal cardinality constraint requires at least one input variable"); 00035 00036 if (ps.size() < cardinality) { 00037 return evaluate(ctx, False); 00038 } 00039 00040 if (ps.size() == cardinality) { 00041 typename Context::result_type res = evaluate(ctx, True); 00042 for (unsigned u = 0; u < ps.size(); ++u) 00043 res = evaluate(ctx, And(res, ps[u])); 00044 return res; 00045 } 00046 00047 if (cardinality == 0) { 00048 return evaluate(ctx, True); 00049 } 00050 00051 // Now: 0 <= cardinality < ps.size() 00052 unsigned const rail_size = cardinality; 00053 std::vector<typename Context::result_type> rails[2]; 00054 rails[0].resize(rail_size); 00055 rails[1].resize(rail_size); 00056 00057 // Tableau algorithm - Iteratively calculate all elements 00058 for (unsigned v = 0; v < ps.size() - cardinality + 1; ++v) { 00059 for (unsigned u = 0; u < cardinality; ++u) { 00060 if (u == 0 && v == 0) { 00061 rails[0][0] = evaluate(ctx, ps[0]); 00062 } else if (u == 0) { 00063 rails[v%2][0] = evaluate(ctx, Ite(evaluate(ctx, ps[v]), True, rails[(v-1)%2][0])); 00064 } else if (v == 0) { 00065 rails[0][u] = evaluate(ctx, Ite(evaluate(ctx, ps[u]), rails[0][u-1], False)); 00066 } else { 00067 rails[v%2][u] = evaluate(ctx, Ite(ps[u+v], rails[v%2][u-1], rails[(v-1)%2][u])); 00068 } 00069 } 00070 } 00071 return rails[(ps.size() - cardinality) % 2][cardinality - 1]; 00072 } 00073 00074 template <typename Context, typename Boolean> 00075 typename Context::result_type 00076 cardinality_lt(Context &ctx, std::vector<Boolean> const &ps, unsigned cardinality) { 00077 assert(ps.size() > 0 && "Lower than cardinality constraint requires at least one input variable"); 00078 return evaluate(ctx, Not(cardinality_geq(ctx, ps, cardinality))); 00079 } 00080 00081 template <typename Context, typename Boolean> 00082 typename Context::result_type 00083 cardinality_eq(Context &ctx, std::vector<Boolean> const &ps, unsigned cardinality) { 00084 assert(ps.size() > 0 && "Equality cardinality constraint requires at least one input variable"); 00085 return evaluate(ctx, And(cardinality_geq(ctx, ps, cardinality), cardinality_lt(ctx, ps, cardinality+1))); 00086 } 00087 00088 } // metaSMT 00089