<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SyMath
{    
    /// <summary>
    /// Decompose an expression into a linear combination of basis variables.
    /// </summary>
    public class LinearCombination
    {
        private class Term
        {
            public Expression b, A;
            public Expression Ab { get { return A * b; } }

            public Term(Expression b) { this.b = b; this.A = Constant.Zero; }

            public override string ToString()
            {
                return Ab.ToString();
            }
        };
        private List<Term> terms;

        private void AddTerm(IEnumerable<Expression> B, Expression t)
        {
            if (t.DependsOn(B))
            {
                foreach (Expression b in B)
                {
                    Expression Tb = t / b;
                    if (!Tb.DependsOn(B))
                    {
                        this[b] = this[b] + Tb;
                        return;
                    }
                }
            }
            this[Constant.One] = this[Constant.One] + t;
        }

        /// <summary>
        /// Basis variables of this linear combination.
        /// </summary>
        public IEnumerable<Expression> Basis { get { return terms.Select(i => i.b); } }

        /// <summary>
        /// Coefficients of this linear combination.
        /// </summary>
        /// <param name="b">Basis variable to access the coefficient for.</param>
        /// <returns></returns>
        public Expression this[Expression b]
        {
            get { return terms.Single(i => i.b.Equals(b)).A; }
            set { terms.SingleOrDefault(i => i.b.Equals(b)).A = value; }
        }

        private object tag;
        public object Tag { get { return tag; } set { tag = value; } }

        /// <summary>
        /// Create a new empty linear combination.
        /// </summary>
        /// <param name="B">Basis variables.</param>
        public LinearCombination(IEnumerable<Expression> B)
        {
            // Add terms for the basis.
            terms = B.Select(i => new Term(i)).ToList();
            terms.Add(new Term(Constant.One));
        }

        /// <summary>
        /// Create a new linear combination.
        /// </summary>
        /// <param name="B">Basis variables.</param>
        /// <param name="E">Expression to get coefficients from.</param>
        public LinearCombination(IEnumerable<Expression> B, Expression E) : this(B)
        {
            foreach (Expression t in Add.TermsOf(E.Expand()))
                AddTerm(B, t);
        }

        /// <summary>
        /// Create an Expression equal to this linear combination.
        /// </summary>
        public Expression ToExpression() { return Add.New(terms.Select(i => i.Ab).Except(Constant.Zero)); }
        
        /// <summary>
        /// The pivot is the first term in this expression.
        /// </summary>
        private Term Pivot { get { return terms.FirstOrDefault(i => !i.A.IsZero() && !i.b.Equals(Constant.One)); } }
        public Expression PivotCoefficient { get { return Pivot != null ? Pivot.A : null; } }
        public Expression PivotVariable { get { return Pivot != null ? Pivot.b : null; } }

        /// <summary>
        /// Column index of the pivot in the linear combination.<commit_msg>Added SwapColumns operation<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SyMath
{    
    /// <summary>
    /// Decompose an expression into a linear combination of basis variables.
    /// </summary>
    public class LinearCombination
    {
        private class Term
        {
            public Expression b, A;
            public Expression Ab { get { return A * b; } }

            public Term(Expression b) { this.b = b; this.A = Constant.Zero; }

            public override string ToString()
            {
                return Ab.ToString();
            }
        };
        private List<Term> terms;

        private void AddTerm(IEnumerable<Expression> B, Expression t)
        {
            if (t.DependsOn(B))
            {
                foreach (Expression b in B)
                {
                    Expression Tb = t / b;
                    if (!Tb.DependsOn(B))
                    {
                        this[b] = this[b] + Tb;
                        return;
                    }
                }
            }
            this[Constant.One] = this[Constant.One] + t;
        }

        /// <summary>
        /// Basis variables of this linear combination.
        /// </summary>
        public IEnumerable<Expression> Basis { get { return terms.Select(i => i.b); } }

        /// <summary>
        /// Coefficients of this linear combination.
        /// </summary>
        /// <param name="b">Basis variable to access the coefficient for.</param>
        /// <returns></returns>
        public Expression this[Expression b]
        {
            get { return terms.Single(i => i.b.Equals(b)).A; }
            set { terms.SingleOrDefault(i => i.b.Equals(b)).A = value; }
        }

        private object tag;
        public object Tag { get { return tag; } set { tag = value; } }

        /// <summary>
        /// Create a new empty linear combination.
        /// </summary>
        /// <param name="B">Basis variables.</param>
        public LinearCombination(IEnumerable<Expression> B)
        {
            // Add terms for the basis.
            terms = B.Select(i => new Term(i)).ToList();
            terms.Add(new Term(Constant.One));
        }

        /// <summary>
        /// Create a new linear combination.
        /// </summary>
        /// <param name="B">Basis variables.</param>
        /// <param name="E">Expression to get coefficients from.</param>
        public LinearCombination(IEnumerable<Expression> B, Expression E) : this(B)
        {
            foreach (Expression t in Add.TermsOf(E.Expand()))
                AddTerm(B, t);
        }

        public void SwapColumns(IEnumerable<Expression> NewBasis)
        {
            List<Term> old = terms;
            terms = new List<Term>();
            foreach (Expression i in NewBasis)
                terms.Add(old.Single(j => j.b.Equals(i)));
            terms.Add(old.Single(i => i.b.Equals(Constant.One)));
        }

        /// <summary>
        /// Create an Expression equal to this linear combination.
        /// </summary>
        public Expression ToExpression() { return Add.New(terms.Select(i => i.Ab).Except(Constant.Zero)); }
        
        /// <summary>
        /// The pivot is the first term in this expression.
        /// </summary>
        private Term Pivot { get { return terms.FirstOrDefault(i => !i.A.IsZero() && !i.b.Equals(Constant.One)); } }
        public Expression PivotCoefficient { get { return Pivot != null ? Pivot.A : null; } }
        public Expression PivotVariable { get { return Pivot != null ? Pivot.b : null; } }

        /// <summary>
        /// Column index of the pivot in the linear combination.
{'fraction_non_alphanumeric': 0.1269192844062544, 'fraction_numerical': 0.0, 'mean_word_length': 1.5266903914590748, 'pattern_counts': {'":': 0, '<': 66, '<?xml version=': 0, '>': 80, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4026173', 'n_tokens_mistral': 1905, 'n_tokens_neox': 1840, 'n_words': 526}