Analysis: add classes to manage constraints on symbolic dimensions 16/16116/3
Calixte DENIZET [Mon, 9 Mar 2015 14:17:45 +0000 (15:17 +0100)]
The idea is to be able to impose some constraints on dimensions, for example:
function c=add(a,b)
  c = a + b;
endfunction

if add is called with double matrice argument, the function will have the signature add(double[r1,c1], double[r2,c2]).
On the addition, the checker will say that the result is unknown (since the dimensions are not always the same),
so in this case we can add a constraint r1==r2 and c1==c2, if this constraint is verified then it will be add to the
function signature.
The function signature will become:
  add(double[r1,c1], double[r2,c2]) with constraint r1==r2 && c1==c2

Change-Id: Ife39165c830221faba1e66676d663e39cde63105

scilab/modules/ast/Makefile.am
scilab/modules/ast/Makefile.in
scilab/modules/ast/ast.vcxproj
scilab/modules/ast/ast.vcxproj.filters
scilab/modules/ast/includes/analysis/gvn/InferenceConstraint.hxx [new file with mode: 0644]
scilab/modules/ast/src/cpp/analysis/InferenceConstraints.cpp [new file with mode: 0644]

index 3654667..e77cf32 100644 (file)
@@ -100,7 +100,8 @@ src/cpp/types/tlist.cpp \
 src/cpp/types/tostring_common.cpp \
 src/cpp/types/types.cpp \
 src/cpp/types/types_tools.cpp \
-src/cpp/types/void.cpp
+src/cpp/types/void.cpp \
+src/cpp/analysis/InferenceConstraints.cpp
 
 if ENABLE_DEBUG
 libsciast_la_SOURCES += src/cpp/types/inspector.cpp
index 337edd3..9da7394 100644 (file)
@@ -223,6 +223,7 @@ am__libsciast_la_SOURCES_DIST = src/c/operations/doublecomplex.c \
        src/cpp/types/threadId.cpp src/cpp/types/tlist.cpp \
        src/cpp/types/tostring_common.cpp src/cpp/types/types.cpp \
        src/cpp/types/types_tools.cpp src/cpp/types/void.cpp \
+       src/cpp/analysis/InferenceConstraints.cpp \
        src/cpp/types/inspector.cpp
 am__dirstamp = $(am__leading_dot)dirstamp
 @ENABLE_DEBUG_TRUE@am__objects_1 =  \
@@ -314,7 +315,9 @@ am_libsciast_la_OBJECTS =  \
        src/cpp/types/libsciast_la-tostring_common.lo \
        src/cpp/types/libsciast_la-types.lo \
        src/cpp/types/libsciast_la-types_tools.lo \
-       src/cpp/types/libsciast_la-void.lo $(am__objects_1)
+       src/cpp/types/libsciast_la-void.lo \
+       src/cpp/analysis/libsciast_la-InferenceConstraints.lo \
+       $(am__objects_1)
 libsciast_la_OBJECTS = $(am_libsciast_la_OBJECTS)
 AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -749,7 +752,7 @@ libsciast_la_SOURCES = src/c/operations/doublecomplex.c \
        src/cpp/types/threadId.cpp src/cpp/types/tlist.cpp \
        src/cpp/types/tostring_common.cpp src/cpp/types/types.cpp \
        src/cpp/types/types_tools.cpp src/cpp/types/void.cpp \
-       $(am__append_1)
+       src/cpp/analysis/InferenceConstraints.cpp $(am__append_1)
 libsciast_la_CPPFLAGS = \
        -I$(srcdir)/includes/ast \
        -I$(srcdir)/includes/exps \
@@ -1400,6 +1403,15 @@ src/cpp/types/libsciast_la-types_tools.lo:  \
        src/cpp/types/$(DEPDIR)/$(am__dirstamp)
 src/cpp/types/libsciast_la-void.lo: src/cpp/types/$(am__dirstamp) \
        src/cpp/types/$(DEPDIR)/$(am__dirstamp)
+src/cpp/analysis/$(am__dirstamp):
+       @$(MKDIR_P) src/cpp/analysis
+       @: > src/cpp/analysis/$(am__dirstamp)
+src/cpp/analysis/$(DEPDIR)/$(am__dirstamp):
+       @$(MKDIR_P) src/cpp/analysis/$(DEPDIR)
+       @: > src/cpp/analysis/$(DEPDIR)/$(am__dirstamp)
+src/cpp/analysis/libsciast_la-InferenceConstraints.lo:  \
+       src/cpp/analysis/$(am__dirstamp) \
+       src/cpp/analysis/$(DEPDIR)/$(am__dirstamp)
 src/cpp/types/libsciast_la-inspector.lo:  \
        src/cpp/types/$(am__dirstamp) \
        src/cpp/types/$(DEPDIR)/$(am__dirstamp)
@@ -1411,6 +1423,8 @@ mostlyclean-compile:
        -rm -f *.$(OBJEXT)
        -rm -f src/c/operations/*.$(OBJEXT)
        -rm -f src/c/operations/*.lo
+       -rm -f src/cpp/analysis/*.$(OBJEXT)
+       -rm -f src/cpp/analysis/*.lo
        -rm -f src/cpp/ast/*.$(OBJEXT)
        -rm -f src/cpp/ast/*.lo
        -rm -f src/cpp/operations/*.$(OBJEXT)
@@ -1437,6 +1451,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@src/c/operations/$(DEPDIR)/libsciast_la-matrix_power.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/c/operations/$(DEPDIR)/libsciast_la-matrix_transpose.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/c/operations/$(DEPDIR)/libsciast_la-operations_tools.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/cpp/analysis/$(DEPDIR)/libsciast_la-InferenceConstraints.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/cpp/ast/$(DEPDIR)/libsciast_la-debugvisitor.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/cpp/ast/$(DEPDIR)/libsciast_la-expHistory.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/cpp/ast/$(DEPDIR)/libsciast_la-macrovarvisitor.Plo@am__quote@
@@ -2173,6 +2188,13 @@ src/cpp/types/libsciast_la-void.lo: src/cpp/types/void.cpp
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsciast_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/cpp/types/libsciast_la-void.lo `test -f 'src/cpp/types/void.cpp' || echo '$(srcdir)/'`src/cpp/types/void.cpp
 
+src/cpp/analysis/libsciast_la-InferenceConstraints.lo: src/cpp/analysis/InferenceConstraints.cpp
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsciast_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/cpp/analysis/libsciast_la-InferenceConstraints.lo -MD -MP -MF src/cpp/analysis/$(DEPDIR)/libsciast_la-InferenceConstraints.Tpo -c -o src/cpp/analysis/libsciast_la-InferenceConstraints.lo `test -f 'src/cpp/analysis/InferenceConstraints.cpp' || echo '$(srcdir)/'`src/cpp/analysis/InferenceConstraints.cpp
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) src/cpp/analysis/$(DEPDIR)/libsciast_la-InferenceConstraints.Tpo src/cpp/analysis/$(DEPDIR)/libsciast_la-InferenceConstraints.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='src/cpp/analysis/InferenceConstraints.cpp' object='src/cpp/analysis/libsciast_la-InferenceConstraints.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsciast_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/cpp/analysis/libsciast_la-InferenceConstraints.lo `test -f 'src/cpp/analysis/InferenceConstraints.cpp' || echo '$(srcdir)/'`src/cpp/analysis/InferenceConstraints.cpp
+
 src/cpp/types/libsciast_la-inspector.lo: src/cpp/types/inspector.cpp
 @am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsciast_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/cpp/types/libsciast_la-inspector.lo -MD -MP -MF src/cpp/types/$(DEPDIR)/libsciast_la-inspector.Tpo -c -o src/cpp/types/libsciast_la-inspector.lo `test -f 'src/cpp/types/inspector.cpp' || echo '$(srcdir)/'`src/cpp/types/inspector.cpp
 @am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) src/cpp/types/$(DEPDIR)/libsciast_la-inspector.Tpo src/cpp/types/$(DEPDIR)/libsciast_la-inspector.Plo
@@ -2186,6 +2208,7 @@ mostlyclean-libtool:
 clean-libtool:
        -rm -rf .libs _libs
        -rm -rf src/c/operations/.libs src/c/operations/_libs
+       -rm -rf src/cpp/analysis/.libs src/cpp/analysis/_libs
        -rm -rf src/cpp/ast/.libs src/cpp/ast/_libs
        -rm -rf src/cpp/operations/.libs src/cpp/operations/_libs
        -rm -rf src/cpp/parse/.libs src/cpp/parse/_libs
@@ -2376,6 +2399,8 @@ distclean-generic:
        -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
        -rm -f src/c/operations/$(DEPDIR)/$(am__dirstamp)
        -rm -f src/c/operations/$(am__dirstamp)
+       -rm -f src/cpp/analysis/$(DEPDIR)/$(am__dirstamp)
+       -rm -f src/cpp/analysis/$(am__dirstamp)
        -rm -f src/cpp/ast/$(DEPDIR)/$(am__dirstamp)
        -rm -f src/cpp/ast/$(am__dirstamp)
        -rm -f src/cpp/operations/$(DEPDIR)/$(am__dirstamp)
@@ -2399,7 +2424,7 @@ clean-am: clean-generic clean-libtool clean-local \
        clean-pkglibLTLIBRARIES mostlyclean-am
 
 distclean: distclean-am
-       -rm -rf src/c/operations/$(DEPDIR) src/cpp/ast/$(DEPDIR) src/cpp/operations/$(DEPDIR) src/cpp/parse/$(DEPDIR) src/cpp/symbol/$(DEPDIR) src/cpp/system_env/$(DEPDIR) src/cpp/types/$(DEPDIR)
+       -rm -rf src/c/operations/$(DEPDIR) src/cpp/analysis/$(DEPDIR) src/cpp/ast/$(DEPDIR) src/cpp/operations/$(DEPDIR) src/cpp/parse/$(DEPDIR) src/cpp/symbol/$(DEPDIR) src/cpp/system_env/$(DEPDIR) src/cpp/types/$(DEPDIR)
        -rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
        distclean-local distclean-tags
@@ -2447,7 +2472,7 @@ install-ps-am:
 installcheck-am:
 
 maintainer-clean: maintainer-clean-am
-       -rm -rf src/c/operations/$(DEPDIR) src/cpp/ast/$(DEPDIR) src/cpp/operations/$(DEPDIR) src/cpp/parse/$(DEPDIR) src/cpp/symbol/$(DEPDIR) src/cpp/system_env/$(DEPDIR) src/cpp/types/$(DEPDIR)
+       -rm -rf src/c/operations/$(DEPDIR) src/cpp/analysis/$(DEPDIR) src/cpp/ast/$(DEPDIR) src/cpp/operations/$(DEPDIR) src/cpp/parse/$(DEPDIR) src/cpp/symbol/$(DEPDIR) src/cpp/system_env/$(DEPDIR) src/cpp/types/$(DEPDIR)
        -rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
 
index 3191828..fb97bd9 100644 (file)
@@ -263,6 +263,7 @@ lib /DEF:"$(ProjectDir)fileio_import.def" /SUBSYSTEM:WINDOWS /MACHINE:$(Platform
     <ClInclude Include="includes\analysis\Decorator.hxx" />
     <ClInclude Include="includes\analysis\ForList.hxx" />
     <ClInclude Include="includes\analysis\gvn\GVN.hxx" />
+    <ClInclude Include="includes\analysis\gvn\InferenceConstraint.hxx" />
     <ClInclude Include="includes\analysis\gvn\MultivariateMonomial.hxx" />
     <ClInclude Include="includes\analysis\gvn\MultivariatePolynomial.hxx" />
     <ClInclude Include="includes\analysis\gvn\OpValue.hxx" />
@@ -273,6 +274,7 @@ lib /DEF:"$(ProjectDir)fileio_import.def" /SUBSYSTEM:WINDOWS /MACHINE:$(Platform
     <ClInclude Include="includes\analysis\Result.hxx" />
     <ClInclude Include="includes\analysis\SymInfo.hxx" />
     <ClInclude Include="includes\analysis\TIType.hxx" />
+    <ClInclude Include="includes\analysis\tools.hxx" />
     <ClInclude Include="includes\ast\debugvisitor.hxx" />
     <ClInclude Include="includes\ast\deserializervisitor.hxx" />
     <ClInclude Include="includes\ast\dummyvisitor.hxx" />
@@ -447,6 +449,7 @@ lib /DEF:"$(ProjectDir)fileio_import.def" /SUBSYSTEM:WINDOWS /MACHINE:$(Platform
     <ClInclude Include="src\cpp\ast\run_OpExp.hpp" />
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="src\cpp\analysis\InferenceConstraints.cpp" />
     <ClCompile Include="src\cpp\ast\debugvisitor.cpp" />
     <ClCompile Include="src\cpp\ast\expHistory.cpp" />
     <ClCompile Include="src\cpp\ast\treevisitor.cpp" />
index 7b2025c..4a0df85 100644 (file)
@@ -60,6 +60,9 @@
     <Filter Include="Header Files\analysis\gvn">
       <UniqueIdentifier>{f05ded2d-aeba-4235-9374-99bcb9247786}</UniqueIdentifier>
     </Filter>
+    <Filter Include="Source Files\ast\analysis">
+      <UniqueIdentifier>{d2899833-14f7-4af4-8054-128d479c51c7}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <None Include="core_Import.def">
     <ClInclude Include="includes\analysis\gvn\VarExp.hxx">
       <Filter>Header Files\analysis\gvn</Filter>
     </ClInclude>
+    <ClInclude Include="includes\analysis\tools.hxx">
+      <Filter>Header Files\analysis</Filter>
+    </ClInclude>
+    <ClInclude Include="includes\analysis\gvn\InferenceConstraint.hxx">
+      <Filter>Header Files\analysis\gvn</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="src\cpp\ast\debugvisitor.cpp">
     <ClCompile Include="src\cpp\ast\treevisitor.cpp">
       <Filter>Source Files\ast</Filter>
     </ClCompile>
+    <ClCompile Include="src\cpp\analysis\InferenceConstraints.cpp">
+      <Filter>Source Files\ast\analysis</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/scilab/modules/ast/includes/analysis/gvn/InferenceConstraint.hxx b/scilab/modules/ast/includes/analysis/gvn/InferenceConstraint.hxx
new file mode 100644 (file)
index 0000000..02c8342
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+ *  Copyright (C) 2015 - Scilab Enterprises - Calixte DENIZET
+ *
+ *  This file must be used under the terms of the CeCILL.
+ *  This source file is licensed as described in the file COPYING, which
+ *  you should have received as part of this distribution.  The terms
+ *  are also available at
+ *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
+ *
+ */
+
+#ifndef __INFERENCE_CONSTRAINT_HXX__
+#define __INFERENCE_CONSTRAINT_HXX__
+
+#include <cmath>
+#include <unordered_set>
+#include <vector>
+
+#include "GVN.hxx"
+#include "tools.hxx"
+
+namespace analysis
+{
+
+struct MPolyConstraint;
+struct MPolyConstraintSet;
+
+struct InferenceConstraint
+{
+    enum Result { TRUE, FALSE, DUNNO } ;
+
+    virtual Result check(const std::vector<GVN::Value *> & values) const = 0;
+    virtual MPolyConstraintSet getMPConstraints(const std::vector<GVN::Value *> & values) const = 0;
+    virtual void applyConstraints(const std::vector<GVN::Value *> & values) const { }
+
+    inline static std::vector<const MultivariatePolynomial *> getArgs(const std::vector<GVN::Value *> & values)
+    {
+        std::vector<const MultivariatePolynomial *> args;
+        args.reserve(values.size());
+        for (const auto value : values)
+        {
+            args.emplace_back(value->poly);
+        }
+        return args;
+    }
+
+    inline static void applyEquality(GVN::Value & x, GVN::Value & y)
+    {
+        if (x != y)
+        {
+            if (x.poly->polynomial.size() < y.poly->polynomial.size())
+            {
+                y = x;
+            }
+            else
+            {
+                x = y;
+            }
+        }
+    }
+};
+
+struct SameDimsConstraint : public InferenceConstraint
+{
+    virtual Result check(const std::vector<GVN::Value *> & values) const override;
+    virtual MPolyConstraintSet getMPConstraints(const std::vector<GVN::Value *> & values) const override;
+    virtual void applyConstraints(const std::vector<GVN::Value *> & values) const override;
+};
+
+struct EqualConstraint : public InferenceConstraint
+{
+    virtual Result check(const std::vector<GVN::Value *> & values) const override;
+    virtual MPolyConstraintSet getMPConstraints(const std::vector<GVN::Value *> & values) const override;
+    virtual void applyConstraints(const std::vector<GVN::Value *> & values) const override;
+};
+
+struct PositiveConstraint : public InferenceConstraint
+{
+    virtual Result check(const std::vector<GVN::Value *> & values) const override;
+    virtual MPolyConstraintSet getMPConstraints(const std::vector<GVN::Value *> & values) const override;
+    virtual void applyConstraints(const std::vector<GVN::Value *> & values) const override;
+};
+
+struct GreaterConstraint : public InferenceConstraint
+{
+    virtual Result check(const std::vector<GVN::Value *> & values) const override;
+    virtual MPolyConstraintSet getMPConstraints(const std::vector<GVN::Value *> & values) const override;
+    virtual void applyConstraints(const std::vector<GVN::Value *> & values) const override;
+};
+
+struct MPolyConstraint : public InferenceConstraint
+{
+    enum Kind { EQ0, NEQ0, GT0, GEQ0 };
+
+    MultivariatePolynomial poly;
+    Kind kind;
+
+    MPolyConstraint(const MultivariatePolynomial & _poly, const Kind _kind) : poly(_poly), kind(_kind)
+    {
+        double common;
+        if (poly.getCommonCoeff(common) && common != 1 && common != 0)
+        {
+            if (kind == EQ0)
+            {
+                poly /= common;
+            }
+            else
+            {
+                poly /= std::abs(common);
+            }
+        }
+    }
+
+    virtual Result check(const std::vector<GVN::Value *> & values) const override;
+    virtual MPolyConstraintSet getMPConstraints(const std::vector<GVN::Value *> & values) const override;
+    virtual void applyConstraints(const std::vector<GVN::Value *> & values) const override;
+
+    struct Hash
+    {
+        inline std::size_t operator()(const MPolyConstraint & mpc) const
+        {
+            return tools::hash_combine(mpc.kind, mpc.poly.hash());
+        }
+    };
+
+    struct Eq
+    {
+        inline bool operator()(const MPolyConstraint & L, const MPolyConstraint & R) const
+        {
+            return L.kind == R.kind && L.poly == R.poly;
+        }
+    };
+};
+
+struct MPolyConstraintSet : public InferenceConstraint
+{
+    std::unordered_set<MPolyConstraint, MPolyConstraint::Hash, MPolyConstraint::Eq> constraints;
+
+    MPolyConstraintSet() { }
+    MPolyConstraintSet(const unsigned int size)
+    {
+        constraints.reserve(size);
+    }
+
+    inline void add(MPolyConstraint && mpc)
+    {
+        constraints.emplace(std::move(mpc));
+    }
+
+    inline void add(MultivariatePolynomial && poly, MPolyConstraint::Kind kind)
+    {
+        constraints.emplace(std::move(poly), kind);
+    }
+
+    inline void add(const MultivariatePolynomial & poly, MPolyConstraint::Kind kind)
+    {
+        constraints.emplace(poly, kind);
+    }
+
+    inline void add(const MPolyConstraintSet & set)
+    {
+        constraints.insert(set.constraints.begin(), set.constraints.end());
+    }
+
+    virtual Result check(const std::vector<GVN::Value *> & values) const override;
+    virtual MPolyConstraintSet getMPConstraints(const std::vector<GVN::Value *> & values) const override;
+    virtual void applyConstraints(const std::vector<GVN::Value *> & values) const override;
+};
+
+
+} // namespace analysis
+
+#endif // __INFERENCE_CONSTRAINT_HXX__
diff --git a/scilab/modules/ast/src/cpp/analysis/InferenceConstraints.cpp b/scilab/modules/ast/src/cpp/analysis/InferenceConstraints.cpp
new file mode 100644 (file)
index 0000000..d3d7eea
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+ *  Copyright (C) 2015 - Scilab Enterprises - Calixte DENIZET
+ *
+ *  This file must be used under the terms of the CeCILL.
+ *  This source file is licensed as described in the file COPYING, which
+ *  you should have received as part of this distribution.  The terms
+ *  are also available at
+ *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
+ *
+ */
+
+#include "gvn/InferenceConstraint.hxx"
+
+namespace analysis
+{
+InferenceConstraint::Result SameDimsConstraint::check(const std::vector<GVN::Value *> & values) const
+{
+    const GVN::Value & R1 = *values[0];
+    const GVN::Value & C1 = *values[1];
+    const GVN::Value & R2 = *values[2];
+    const GVN::Value & C2 = *values[3];
+
+    if (R1.value == R2.value)
+    {
+        if (C1.value == C2.value)
+        {
+            return Result::TRUE;
+        }
+
+        MultivariatePolynomial mp = *C1.poly - *C2.poly;
+        if (mp.constant != 0 && mp.isCoeffPositive(false))
+        {
+            return Result::FALSE;
+        }
+    }
+    else
+    {
+        MultivariatePolynomial mp = *R1.poly - *R2.poly;
+        if (mp.constant > 0 && mp.isCoeffPositive(false))
+        {
+            return Result::FALSE;
+        }
+    }
+    return Result::DUNNO;
+}
+
+MPolyConstraintSet SameDimsConstraint::getMPConstraints(const std::vector<GVN::Value *> & values) const
+{
+    MPolyConstraintSet set(2);
+    const GVN::Value & R1 = *values[0];
+    const GVN::Value & C1 = *values[1];
+    const GVN::Value & R2 = *values[2];
+    const GVN::Value & C2 = *values[3];
+
+    set.add(*R1.poly - *R2.poly, MPolyConstraint::Kind::EQ0);
+    set.add(*C1.poly - *C2.poly, MPolyConstraint::Kind::EQ0);
+
+    return set;
+}
+
+void SameDimsConstraint::applyConstraints(const std::vector<GVN::Value *> & values) const
+{
+    GVN::Value & R1 = *values[0];
+    GVN::Value & C1 = *values[1];
+    GVN::Value & R2 = *values[2];
+    GVN::Value & C2 = *values[3];
+
+    applyEquality(R1, R2);
+    applyEquality(C1, C2);
+}
+
+InferenceConstraint::Result EqualConstraint::check(const std::vector<GVN::Value *> & values) const
+{
+    const GVN::Value & x = *values[0];
+    const GVN::Value & y = *values[1];
+
+    if (x.value == y.value)
+    {
+        return Result::TRUE;
+    }
+    else
+    {
+        MultivariatePolynomial mp = *x.poly - *y.poly;
+        if (mp.constant > 0 && mp.isCoeffPositive(false))
+        {
+            return Result::FALSE;
+        }
+    }
+    return Result::DUNNO;
+}
+
+void EqualConstraint::applyConstraints(const std::vector<GVN::Value *> & values) const
+{
+    GVN::Value & x = *values[0];
+    GVN::Value & y = *values[1];
+
+    applyEquality(x, y);
+}
+
+MPolyConstraintSet EqualConstraint::getMPConstraints(const std::vector<GVN::Value *> & values) const
+{
+    MPolyConstraintSet set(1);
+    const GVN::Value & x = *values[0];
+    const GVN::Value & y = *values[1];
+
+    set.add(*x.poly - *y.poly, MPolyConstraint::Kind::EQ0);
+
+    return set;
+}
+
+InferenceConstraint::Result MPolyConstraint::check(const std::vector<GVN::Value *> & values) const
+{
+    MultivariatePolynomial mp = poly.eval(InferenceConstraint::getArgs(values));
+    //std::wcerr << "MPolyConstraint=" << poly << "::" << mp << std::endl;
+    switch (kind)
+    {
+        case EQ0 :
+        {
+            if (mp.isConstant(0))
+            {
+                // for all X, P(X) == 0
+                return Result::TRUE;
+            }
+            else if (mp.constant != 0 && mp.isCoeffPositive(false))
+            {
+                // P(X) = Q(X) + K where K != 0 and Q with positive coeffs
+                return Result::FALSE;
+            }
+            else
+            {
+                return Result::DUNNO;
+            }
+        }
+        case NEQ0 :
+            if (mp.constant != 0 && mp.isCoeffPositive(false))
+            {
+                return Result::TRUE;
+            }
+            else if (mp.isConstant(0))
+            {
+                return Result::FALSE;
+            }
+            else
+            {
+                return Result::DUNNO;
+            }
+        case GT0 :
+            if (mp.isCoeffStrictPositive())
+            {
+                return Result::TRUE;
+            }
+            else if (mp.constant < 0 && mp.isCoeffNegative(false))
+            {
+                return Result::FALSE;
+            }
+            else
+            {
+                return Result::DUNNO;
+            }
+        case GEQ0 :
+        {
+            if (mp.isCoeffPositive())
+            {
+                return Result::TRUE;
+            }
+            else if (mp.isConstant() && mp.constant < 0)
+            {
+                return Result::FALSE;
+            }
+            else
+            {
+                return Result::DUNNO;
+            }
+        }
+    }
+}
+
+MPolyConstraintSet MPolyConstraint::getMPConstraints(const std::vector<GVN::Value *> & values) const
+{
+    MPolyConstraintSet set(1);
+    set.add(poly.eval(InferenceConstraint::getArgs(values)), kind);
+
+    return set;
+}
+
+void MPolyConstraint::applyConstraints(const std::vector<GVN::Value *> & values) const
+{
+    if (kind == EQ0)
+    {
+        if (poly.constant == 0 && poly.polynomial.size() == 2)
+        {
+            const MultivariateMonomial & m1 = *poly.polynomial.begin();
+            const MultivariateMonomial & m2 = *std::next(poly.polynomial.begin());
+
+            if ((m1.coeff == 1 && m2.coeff == -1) || (m1.coeff == -1 && m2.coeff == 1) && (m1.monomial.size() == 1 && m2.monomial.size() == 1))
+            {
+                // We have a polynomial P such as P(X,Y)=X-Y
+                GVN::Value & x = *values[m1.monomial.begin()->var];
+                GVN::Value & y = *values[m2.monomial.begin()->var];
+
+                applyEquality(x, y);
+            }
+        }
+    }
+}
+
+InferenceConstraint::Result MPolyConstraintSet::check(const std::vector<GVN::Value *> & values) const
+{
+    for (const auto & constraint : constraints)
+    {
+        Result res = constraint.check(values);
+        if (res != Result::TRUE)
+        {
+            return res;
+        }
+    }
+    return Result::TRUE;
+}
+
+MPolyConstraintSet MPolyConstraintSet::getMPConstraints(const std::vector<GVN::Value *> & values) const
+{
+    MPolyConstraintSet set(constraints.size());
+    const std::vector<const MultivariatePolynomial *> args = InferenceConstraint::getArgs(values);
+    for (const auto & constraint : constraints)
+    {
+        set.add(constraint.poly.eval(args), constraint.kind);
+    }
+    return set;
+}
+
+void MPolyConstraintSet::applyConstraints(const std::vector<GVN::Value *> & values) const
+{
+    for (const auto & mpc : constraints)
+    {
+        mpc.applyConstraints(values);
+    }
+}
+
+InferenceConstraint::Result PositiveConstraint::check(const std::vector<GVN::Value *> & values) const
+{
+    const GVN::Value & x = *values[0];
+
+    if (x.poly->isCoeffPositive())
+    {
+        return Result::TRUE;
+    }
+    else if (x.poly->isConstant() && x.poly->constant < 0)
+    {
+        return Result::FALSE;
+    }
+
+    return Result::DUNNO;
+}
+
+void PositiveConstraint::applyConstraints(const std::vector<GVN::Value *> & values) const { }
+
+MPolyConstraintSet PositiveConstraint::getMPConstraints(const std::vector<GVN::Value *> & values) const
+{
+    MPolyConstraintSet set(1);
+    const GVN::Value & x = *values[0];
+
+    set.add(*x.poly, MPolyConstraint::Kind::GEQ0);
+
+    return set;
+}
+
+InferenceConstraint::Result GreaterConstraint::check(const std::vector<GVN::Value *> & values) const
+{
+    const GVN::Value & x = *values[0];
+    const GVN::Value & y = *values[1];
+
+    if (x.value == y.value)
+    {
+        return Result::FALSE;
+    }
+
+    MultivariatePolynomial mp = *x.poly - *y.poly;
+    if (mp.constant > 0 && mp.isCoeffPositive(false))
+    {
+        return Result::TRUE;
+    }
+    else if (mp.constant < 0 && mp.isCoeffNegative(false))
+    {
+        return Result::FALSE;
+    }
+
+    return Result::DUNNO;
+}
+
+void GreaterConstraint::applyConstraints(const std::vector<GVN::Value *> & values) const { }
+
+MPolyConstraintSet GreaterConstraint::getMPConstraints(const std::vector<GVN::Value *> & values) const
+{
+    MPolyConstraintSet set(1);
+    const GVN::Value & x = *values[0];
+    const GVN::Value & y = *values[1];
+
+    set.add(*x.poly - *y.poly, MPolyConstraint::Kind::GT0);
+
+    return set;
+}
+}