metaSMT git

metaSMT/support/cardinality.hpp

Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines