<commit_before>// Copyright 2022 D-Wave Systems Inc.
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.

#pragma once

#include <memory>
#include <unordered_set>
#include <utility>
#include <vector>

#include "dimod/abc.h"
#include "dimod/constraint.h"
#include "dimod/expression.h"
#include "dimod/vartypes.h"

namespace dimod {

template <class Bias, class Index = int>
class ConstrainedQuadraticModel {
 public:
    /// The first template parameter (Bias).
    using bias_type = Bias;

    /// The second template parameter (Index).
    using index_type = Index;

    /// Unsigned integral type that can represent non-negative values.
    using size_type = std::size_t;

    ConstrainedQuadraticModel();

    ConstrainedQuadraticModel(const ConstrainedQuadraticModel& other);
    ConstrainedQuadraticModel(ConstrainedQuadraticModel&& other) noexcept;
    ~ConstrainedQuadraticModel() = default;
    ConstrainedQuadraticModel& operator=(ConstrainedQuadraticModel other);

    index_type add_constraint();

    template <class B, class I, class T>
    index_type add_constraint(const abc::QuadraticModelBase<B, I>& lhs, Sense sense, bias_type rhs,
                              const std::vector<T>& mapping);

    index_type add_constraint(abc::QuadraticModelBase<bias_type, index_type>&& lhs, Sense sense, bias_type rhs,
                              std::vector<index_type> mapping);

    /// Add a constraint.
    /// @param constraint As created by ConstrainedQuadraticModel::new_constraint()
    /// @exception Throws std::logic_error If the constraint's parent is not this model.
    /// If an exception is thrown, there are no changes to the model.
    index_type add_constraint(Constraint<bias_type, index_type> constraint);

    index_type add_constraints(index_type n);

    index_type add_linear_constraint(std::initializer_list<index_type> variables,
                                     std::initializer_list<bias_type> biases, Sense sense,
                                     bias_type rhs);

    index_type add_variable(Vartype vartype, bias_type lb, bias_type ub);

    index_type add_variable(Vartype vartype);

    index_type add_variables(Vartype vartype, index_type n);

    index_type add_variables(Vartype vartype, index_type n, bias_type lb, bias_type ub);

    void change_vartype(Vartype vartype, index_type v);

    void clear();

    Constraint<bias_type, index_type>& constraint_ref(index_type c);
    const Constraint<bias_type, index_type>& constraint_ref(index_type c) const;

    std::weak_ptr<Constraint<bias_type, index_type>> constraint_weak_ptr(index_type c);
    std::weak_ptr<const Constraint<bias_type, index_type>> constraint_weak_ptr(index_type c) const;

    template <class T>
    void fix_variable(index_type v, T assignment);

    /// Return the lower bound on variable ``v``.
    bias_type lower_bound(index_type v) const;

    /// Return a new constraint without adding it to the model.
    Constraint<bias_type, index_type> new_constraint() const;

    /// Return the number of constraints in the model.
    size_type num_constraints() const;

    /// Return the number of variables in the model.
    size_type num_variables() const;

    /// Remove a constraint from the model.
    void remove_constraint(index_type c);

    void remove_variable(index_type v);

    void set_lower_bound(index_type v, bias_type lb);

    template <class B, class I>
    void set_objective(const abc::QuadraticModelBase<B, I>& objective);

    template <class B, class I, class T>
    void set_objective(const abc::QuadraticModelBase<B, I>& objective,
                       const std::vector<T>& mapping);

    void set_upper_bound(index_type v, bias_type ub);
    void set_vartype(index_type v, Vartype vartype);

    void substitute_variable(index_type v, bias_type multiplier, bias_type offset);

    /// Return the upper bound on variable ``v``.
    bias_type upper_bound(index_type v) const;

    /// Return the variable type of variable ``v``.
    Vartype vartype(index_type v) const;

    Expression<bias_type, index_type> objective;

    friend void swap(ConstrainedQuadraticModel& first, ConstrainedQuadraticModel& second) {
        first.myswap(second);
    }

 private:
    // I can't figure out how to get Expression to grant friendship to friend swap...
    // Will look into it some other time.
    void myswap(ConstrainedQuadraticModel& other) {
        using std::swap;

        // for objective and constraints, we need to make sure that their
        // parent_ pointers are pointing at the correct object.

        swap(this->objective, other.objective);
        this->objective.parent_ = this;
        other.objective.parent_ = &other;

        swap(this->constraints_, other.constraints_);
        for (auto& c_ptr : this->constraints_) {
            c_ptr->parent_ = this;
        }
        for (auto& c_ptr : other.constraints_) {
            c_ptr->parent_ = &other;
        }

        swap(this->varinfo_, other.varinfo_);
    }

    std::vector<std::shared_ptr<Constraint<bias_type, index_type>>> constraints_;

    struct varinfo_type {
        Vartype vartype;
        bias_type lb;
        bias_type ub;

        varinfo_type(Vartype vartype, bias_type lb, bias_type ub)
                : vartype(vartype), lb(lb), ub(ub) {
            assert(lb <= ub);

            assert(lb >= vartype_info<bias_type>::min(vartype));
            assert(ub <= vartype_info<bias_type>::max(vartype));

            assert(vartype != Vartype::BINARY || lb == 0);
            assert(vartype != Vartype::BINARY || ub == 1);

            assert(vartype != Vartype::SPIN || lb == -1);
            assert(vartype != Vartype::SPIN || ub == +1);
        }

        explicit varinfo_type(Vartype vartype)
                : vartype(vartype),
                  lb(vartype_info<bias_type>::default_min(vartype)),
                  ub(vartype_info<bias_type>::default_max(vartype)) {}
    };

    std::vector<varinfo_type> varinfo_;
};

template <class bias_type, class index_type>
ConstrainedQuadraticModel<bias_type, index_type>::ConstrainedQuadraticModel()
        : objective(this), constraints_(), varinfo_() {}

template <class bias_type, class index_type>
ConstrainedQuadraticModel<bias_type, index_type>::ConstrainedQuadraticModel(
        const ConstrainedQuadraticModel& other)
        : objective(other.objective), constraints_(other.constraints_), varinfo_(other.varinfo_) {
    objective.parent_ = this;
    for (auto& c_ptr : constraints_) {
        c_ptr->parent_ = this;
    }
}

template <class bias_type, class index_type>
ConstrainedQuadraticModel<bias_type, index_type>::ConstrainedQuadraticModel(
        ConstrainedQuadraticModel&& other) noexcept
        : ConstrainedQuadraticModel() {
    swap(*this, other);
}

template <class bias_type, class index_type>
ConstrainedQuadraticModel<bias_type, index_type>&
ConstrainedQuadraticModel<bias_type, index_type>::operator=(ConstrainedQuadraticModel other) {
    swap(*this, other);
    return *this;
}

template <class bias_type, class index_type>
index_type ConstrainedQuadraticModel<bias_type, index_type>::add_constraint() {
    constraints_.push_back(std::make_shared<Constraint<bias_type, index_type>>(this));
    return constraints_.size() - 1;
}

template <class bias_type, class index_type>
index_type ConstrainedQuadraticModel<bias_type, index_type>::add_constraint(
        Constraint<bias_type, index_type> constraint) {
    if (constraint.parent_ != this) {
        throw std::logic_error("given constraint has a different parent");
    }
    constraints_.push_back(
            std::make_shared<Constraint<bias_type, index_type>>(std::move(constraint)));
    return constraints_.size() - 1;
}

template <class bias_type, class index_type>
template <class B, class I, class T>
index_type ConstrainedQuadraticModel<bias_type, index_type>::add_constraint(
        const abc::QuadraticModelBase<B, I>& lhs, Sense sense, bias_type rhs,
        const std::vector<T>& mapping) {
    assert(mapping.size() == lhs.num_variables());

    auto constraint = new_constraint();

    for (size_type i = 0; i < lhs.num_variables(); ++i) {
        assert(mapping[i] >= 0 && static_cast<size_type>(mapping[i]) < num_variables());
        assert(vartype(mapping[i]) == lhs.vartype(i));
        assert(lower_bound(mapping[i]) == lhs.lower_bound(i));
        assert(upper_bound(mapping[i]) == lhs.upper_bound(i));

        constraint.add_linear(mapping[i], lhs.linear(i));
    }

    // quadratic biases
    for (auto it = lhs.cbegin_quadratic(); it != lhs.cend_quadratic(); ++it) {
        constraint.add_quadratic(mapping[it->u], mapping[it->v], it->bias);
    }

    // offset
    constraint.add_offset(lhs.offset());

    // sense and rhs
    constraint.set_sense(sense);
    constraint.set_rhs(rhs);

    return add_constraint(std::move(constraint));
}

template <class bias_type, class index_type>
index_type ConstrainedQuadraticModel<bias_type, index_type>::add_constraint(
        abc::QuadraticModelBase<bias_type, index_type>&& lhs, Sense sense, bias_type rhs,
        std::vector<index_type> mapping) {
    using std::swap;  // ADL

    assert(mapping.size() == lhs.num_variables());

    Constraint<bias_type, index_type> constraint = new_constraint();

    // move the underlying biases/offset
    static_cast<abc::QuadraticModelBase<bias_type, index_type>&>(constraint) = std::move(lhs);

    // and set the labels based on the mapping
    constraint.relabel_variables(std::move(mapping));

    // sense and rhs
    constraint.set_sense(sense);
    constraint.set_rhs(rhs);

    return add_constraint(std::move(constraint));
}

template <class bias_type, class index_type><commit_msg>Remove superfluous line<commit_after>// Copyright 2022 D-Wave Systems Inc.
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.

#pragma once

#include <memory>
#include <unordered_set>
#include <utility>
#include <vector>

#include "dimod/abc.h"
#include "dimod/constraint.h"
#include "dimod/expression.h"
#include "dimod/vartypes.h"

namespace dimod {

template <class Bias, class Index = int>
class ConstrainedQuadraticModel {
 public:
    /// The first template parameter (Bias).
    using bias_type = Bias;

    /// The second template parameter (Index).
    using index_type = Index;

    /// Unsigned integral type that can represent non-negative values.
    using size_type = std::size_t;

    ConstrainedQuadraticModel();

    ConstrainedQuadraticModel(const ConstrainedQuadraticModel& other);
    ConstrainedQuadraticModel(ConstrainedQuadraticModel&& other) noexcept;
    ~ConstrainedQuadraticModel() = default;
    ConstrainedQuadraticModel& operator=(ConstrainedQuadraticModel other);

    index_type add_constraint();

    template <class B, class I, class T>
    index_type add_constraint(const abc::QuadraticModelBase<B, I>& lhs, Sense sense, bias_type rhs,
                              const std::vector<T>& mapping);

    index_type add_constraint(abc::QuadraticModelBase<bias_type, index_type>&& lhs, Sense sense, bias_type rhs,
                              std::vector<index_type> mapping);

    /// Add a constraint.
    /// @param constraint As created by ConstrainedQuadraticModel::new_constraint()
    /// @exception Throws std::logic_error If the constraint's parent is not this model.
    /// If an exception is thrown, there are no changes to the model.
    index_type add_constraint(Constraint<bias_type, index_type> constraint);

    index_type add_constraints(index_type n);

    index_type add_linear_constraint(std::initializer_list<index_type> variables,
                                     std::initializer_list<bias_type> biases, Sense sense,
                                     bias_type rhs);

    index_type add_variable(Vartype vartype, bias_type lb, bias_type ub);

    index_type add_variable(Vartype vartype);

    index_type add_variables(Vartype vartype, index_type n);

    index_type add_variables(Vartype vartype, index_type n, bias_type lb, bias_type ub);

    void change_vartype(Vartype vartype, index_type v);

    void clear();

    Constraint<bias_type, index_type>& constraint_ref(index_type c);
    const Constraint<bias_type, index_type>& constraint_ref(index_type c) const;

    std::weak_ptr<Constraint<bias_type, index_type>> constraint_weak_ptr(index_type c);
    std::weak_ptr<const Constraint<bias_type, index_type>> constraint_weak_ptr(index_type c) const;

    template <class T>
    void fix_variable(index_type v, T assignment);

    /// Return the lower bound on variable ``v``.
    bias_type lower_bound(index_type v) const;

    /// Return a new constraint without adding it to the model.
    Constraint<bias_type, index_type> new_constraint() const;

    /// Return the number of constraints in the model.
    size_type num_constraints() const;

    /// Return the number of variables in the model.
    size_type num_variables() const;

    /// Remove a constraint from the model.
    void remove_constraint(index_type c);

    void remove_variable(index_type v);

    void set_lower_bound(index_type v, bias_type lb);

    template <class B, class I>
    void set_objective(const abc::QuadraticModelBase<B, I>& objective);

    template <class B, class I, class T>
    void set_objective(const abc::QuadraticModelBase<B, I>& objective,
                       const std::vector<T>& mapping);

    void set_upper_bound(index_type v, bias_type ub);
    void set_vartype(index_type v, Vartype vartype);

    void substitute_variable(index_type v, bias_type multiplier, bias_type offset);

    /// Return the upper bound on variable ``v``.
    bias_type upper_bound(index_type v) const;

    /// Return the variable type of variable ``v``.
    Vartype vartype(index_type v) const;

    Expression<bias_type, index_type> objective;

    friend void swap(ConstrainedQuadraticModel& first, ConstrainedQuadraticModel& second) {
        first.myswap(second);
    }

 private:
    // I can't figure out how to get Expression to grant friendship to friend swap...
    // Will look into it some other time.
    void myswap(ConstrainedQuadraticModel& other) {
        using std::swap;

        // for objective and constraints, we need to make sure that their
        // parent_ pointers are pointing at the correct object.

        swap(this->objective, other.objective);
        this->objective.parent_ = this;
        other.objective.parent_ = &other;

        swap(this->constraints_, other.constraints_);
        for (auto& c_ptr : this->constraints_) {
            c_ptr->parent_ = this;
        }
        for (auto& c_ptr : other.constraints_) {
            c_ptr->parent_ = &other;
        }

        swap(this->varinfo_, other.varinfo_);
    }

    std::vector<std::shared_ptr<Constraint<bias_type, index_type>>> constraints_;

    struct varinfo_type {
        Vartype vartype;
        bias_type lb;
        bias_type ub;

        varinfo_type(Vartype vartype, bias_type lb, bias_type ub)
                : vartype(vartype), lb(lb), ub(ub) {
            assert(lb <= ub);

            assert(lb >= vartype_info<bias_type>::min(vartype));
            assert(ub <= vartype_info<bias_type>::max(vartype));

            assert(vartype != Vartype::BINARY || lb == 0);
            assert(vartype != Vartype::BINARY || ub == 1);

            assert(vartype != Vartype::SPIN || lb == -1);
            assert(vartype != Vartype::SPIN || ub == +1);
        }

        explicit varinfo_type(Vartype vartype)
                : vartype(vartype),
                  lb(vartype_info<bias_type>::default_min(vartype)),
                  ub(vartype_info<bias_type>::default_max(vartype)) {}
    };

    std::vector<varinfo_type> varinfo_;
};

template <class bias_type, class index_type>
ConstrainedQuadraticModel<bias_type, index_type>::ConstrainedQuadraticModel()
        : objective(this), constraints_(), varinfo_() {}

template <class bias_type, class index_type>
ConstrainedQuadraticModel<bias_type, index_type>::ConstrainedQuadraticModel(
        const ConstrainedQuadraticModel& other)
        : objective(other.objective), constraints_(other.constraints_), varinfo_(other.varinfo_) {
    objective.parent_ = this;
    for (auto& c_ptr : constraints_) {
        c_ptr->parent_ = this;
    }
}

template <class bias_type, class index_type>
ConstrainedQuadraticModel<bias_type, index_type>::ConstrainedQuadraticModel(
        ConstrainedQuadraticModel&& other) noexcept
        : ConstrainedQuadraticModel() {
    swap(*this, other);
}

template <class bias_type, class index_type>
ConstrainedQuadraticModel<bias_type, index_type>&
ConstrainedQuadraticModel<bias_type, index_type>::operator=(ConstrainedQuadraticModel other) {
    swap(*this, other);
    return *this;
}

template <class bias_type, class index_type>
index_type ConstrainedQuadraticModel<bias_type, index_type>::add_constraint() {
    constraints_.push_back(std::make_shared<Constraint<bias_type, index_type>>(this));
    return constraints_.size() - 1;
}

template <class bias_type, class index_type>
index_type ConstrainedQuadraticModel<bias_type, index_type>::add_constraint(
        Constraint<bias_type, index_type> constraint) {
    if (constraint.parent_ != this) {
        throw std::logic_error("given constraint has a different parent");
    }
    constraints_.push_back(
            std::make_shared<Constraint<bias_type, index_type>>(std::move(constraint)));
    return constraints_.size() - 1;
}

template <class bias_type, class index_type>
template <class B, class I, class T>
index_type ConstrainedQuadraticModel<bias_type, index_type>::add_constraint(
        const abc::QuadraticModelBase<B, I>& lhs, Sense sense, bias_type rhs,
        const std::vector<T>& mapping) {
    assert(mapping.size() == lhs.num_variables());

    auto constraint = new_constraint();

    for (size_type i = 0; i < lhs.num_variables(); ++i) {
        assert(mapping[i] >= 0 && static_cast<size_type>(mapping[i]) < num_variables());
        assert(vartype(mapping[i]) == lhs.vartype(i));
        assert(lower_bound(mapping[i]) == lhs.lower_bound(i));
        assert(upper_bound(mapping[i]) == lhs.upper_bound(i));

        constraint.add_linear(mapping[i], lhs.linear(i));
    }

    // quadratic biases
    for (auto it = lhs.cbegin_quadratic(); it != lhs.cend_quadratic(); ++it) {
        constraint.add_quadratic(mapping[it->u], mapping[it->v], it->bias);
    }

    // offset
    constraint.add_offset(lhs.offset());

    // sense and rhs
    constraint.set_sense(sense);
    constraint.set_rhs(rhs);

    return add_constraint(std::move(constraint));
}

template <class bias_type, class index_type>
index_type ConstrainedQuadraticModel<bias_type, index_type>::add_constraint(
        abc::QuadraticModelBase<bias_type, index_type>&& lhs, Sense sense, bias_type rhs,
        std::vector<index_type> mapping) {
    assert(mapping.size() == lhs.num_variables());

    Constraint<bias_type, index_type> constraint = new_constraint();

    // move the underlying biases/offset
    static_cast<abc::QuadraticModelBase<bias_type, index_type>&>(constraint) = std::move(lhs);

    // and set the labels based on the mapping
    constraint.relabel_variables(std::move(mapping));

    // sense and rhs
    constraint.set_sense(sense);
    constraint.set_rhs(rhs);

    return add_constraint(std::move(constraint));
}

template <class bias_type, class index_type>
{'fraction_non_alphanumeric': 0.10839776842517374, 'fraction_numerical': 0.0015660174219438191, 'mean_word_length': 3.562402321946863, 'pattern_counts': {'":': 0, '<': 145, '<?xml version=': 0, '>': 163, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2760759', 'n_tokens_mistral': 6276, 'n_tokens_neox': 6104, 'n_words': 1536}