Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HLScript/HeuristicLab.ExtLibs/HeuristicLab.AutoDiff/1.0/AutoDiff-1.0/TVec.cs @ 10736

Last change on this file since 10736 was 8703, checked in by gkronber, 12 years ago

#1960 added HL wrapper plugin for AutoDiff

File size: 11.1 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using AutoDiff;
6using System.Diagnostics.Contracts;
7
8namespace AutoDiff
9{
10    /// <summary>
11    /// A column vector made of terms.
12    /// </summary>
13    [Serializable]
14    public class TVec
15    {
16        private readonly Term[] terms;
17
18        /// <summary>
19        /// Constructs a new instance of the <see cref="TVec"/> class given vector components.
20        /// </summary>
21        /// <param name="terms">The vector component terms</param>
22        public TVec(IEnumerable<Term> terms)
23        {
24            Contract.Requires(terms != null);
25            Contract.Requires(Contract.ForAll(terms, term => term != null));
26            Contract.Requires(terms.Any());
27
28            this.terms = terms.ToArray();
29        }
30
31        /// <summary>
32        /// Constructs a new instance of the <see cref="TVec"/> class given vector components.
33        /// </summary>
34        /// <param name="terms">The vector component terms</param>
35        public TVec(params Term[] terms)
36            : this(terms as IEnumerable<Term>)
37        {
38            Contract.Requires(terms != null);
39            Contract.Requires(Contract.ForAll(terms, term => term != null));
40            Contract.Requires(terms.Length > 0);
41        }
42
43        /// <summary>
44        /// Constructs a new instance of the <see cref="TVec"/> class using another vector's components.
45        /// </summary>
46        /// <param name="first">A vector containing the first vector components to use.</param>
47        /// <param name="rest">More vector components to add in addition to the components in <paramref name="first"/></param>
48        public TVec(TVec first, params Term[] rest)
49            : this(first.terms.Concat(rest ?? System.Linq.Enumerable.Empty<Term>()))
50        {
51            Contract.Requires(first != null);
52            Contract.Requires(Contract.ForAll(rest, term => term != null));
53        }
54
55        private TVec(Term[] left, Term[] right, Func<Term, Term, Term> elemOp)
56        {
57            Contract.Assume(left.Length == right.Length);
58            terms = new Term[left.Length];
59            for (int i = 0; i < terms.Length; ++i)
60                terms[i] = elemOp(left[i], right[i]);
61        }
62
63        private TVec(Term[] input, Func<Term, Term> elemOp)
64        {
65            terms = new Term[input.Length];
66            for (int i = 0; i < input.Length; ++i)
67                terms[i] = elemOp(input[i]);
68        }
69
70        /// <summary>
71        /// Gets a vector component given its zero-based index.
72        /// </summary>
73        /// <param name="index">The vector's component index.</param>
74        /// <returns>The vector component.</returns>
75        public Term this[int index]
76        {
77            get
78            {
79                Contract.Requires(index >= 0 && index < Dimension);
80                Contract.Ensures(Contract.Result<Term>() != null);
81
82                return terms[index];
83            }
84        }
85
86        /// <summary>
87        /// Gets a term representing the squared norm of this vector.
88        /// </summary>
89        public Term NormSquared
90        {
91            get
92            {
93                Contract.Ensures(Contract.Result<Term>() != null);
94
95                var powers = terms.Select(x => TermBuilder.Power(x, 2));
96                return TermBuilder.Sum(powers);
97            }
98        }
99
100        /// <summary>
101        /// Gets the dimensions of this vector
102        /// </summary>
103        public int Dimension
104        {
105            get
106            {
107                Contract.Ensures(Contract.Result<int>() > 0);
108
109                return terms.Length;
110            }
111        }
112
113        /// <summary>
114        /// Gets the first vector component
115        /// </summary>
116        public Term X
117        {
118            get
119            {
120                Contract.Ensures(Contract.Result<Term>() != null);
121
122                return this[0];
123            }
124        }
125
126        /// <summary>
127        /// Gets the second vector component.
128        /// </summary>
129        public Term Y
130        {
131            get
132            {
133                Contract.Requires(Dimension >= 2);
134                Contract.Ensures(Contract.Result<Term>() != null);
135
136                return this[1];
137            }
138        }
139
140        /// <summary>
141        /// Gets the third vector component
142        /// </summary>
143        public Term Z
144        {
145            get
146            {
147                Contract.Requires(Dimension >= 3);
148                Contract.Ensures(Contract.Result<Term>() != null);
149
150                return this[2];
151            }
152        }
153
154        /// <summary>
155        /// Gets an array of all vector components.
156        /// </summary>
157        /// <returns>An array of all vector components. Users are free to modify this array. It doesn't point to any
158        /// internal structures.</returns>
159        public Term[] GetTerms()
160        {
161            Contract.Ensures(Contract.Result<Term[]>() != null);
162            Contract.Ensures(Contract.Result<Term[]>().Length > 0);
163            Contract.Ensures(Contract.ForAll(Contract.Result<Term[]>(), term => term != null));
164
165            return (Term[])terms.Clone();
166        }
167
168        /// <summary>
169        /// Constructs a sum of two term vectors.
170        /// </summary>
171        /// <param name="left">The first vector in the sum</param>
172        /// <param name="right">The second vector in the sum</param>
173        /// <returns>A vector representing the sum of <paramref name="left"/> and <paramref name="right"/></returns>
174        public static TVec operator+(TVec left, TVec right)
175        {
176            Contract.Requires(left != null);
177            Contract.Requires(right != null);
178            Contract.Requires(left.Dimension == right.Dimension);
179            Contract.Ensures(Contract.Result<TVec>().Dimension == left.Dimension);
180
181            return new TVec(left.terms, right.terms, (x, y) => x + y);
182        }
183
184        /// <summary>
185        /// Constructs a difference of two term vectors,
186        /// </summary>
187        /// <param name="left">The first vector in the difference</param>
188        /// <param name="right">The second vector in the difference.</param>
189        /// <returns>A vector representing the difference of <paramref name="left"/> and <paramref name="right"/></returns>
190        public static TVec operator-(TVec left, TVec right)
191        {
192            Contract.Requires(left != null);
193            Contract.Requires(right != null);
194            Contract.Requires(left.Dimension == right.Dimension);
195            Contract.Ensures(Contract.Result<TVec>().Dimension == left.Dimension);
196
197            return new TVec(left.terms, right.terms, (x, y) => x - y);
198        }
199
200        /// <summary>
201        /// Inverts a vector
202        /// </summary>
203        /// <param name="vector">The vector to invert</param>
204        /// <returns>A vector repsesenting the inverse of <paramref name="vector"/></returns>
205        public static TVec operator-(TVec vector)
206        {
207            Contract.Requires(vector != null);
208            Contract.Ensures(Contract.Result<TVec>().Dimension == vector.Dimension);
209
210            return vector * -1;
211        }
212
213        /// <summary>
214        /// Multiplies a vector by a scalar
215        /// </summary>
216        /// <param name="vector">The vector</param>
217        /// <param name="scalar">The scalar</param>
218        /// <returns>A product of the vector <paramref name="vector"/> and the scalar <paramref name="scalar"/>.</returns>
219        public static TVec operator*(TVec vector, Term scalar)
220        {
221            Contract.Requires(vector != null);
222            Contract.Requires(scalar != null);
223            Contract.Ensures(Contract.Result<TVec>().Dimension == vector.Dimension);
224
225            return new TVec(vector.terms, x => scalar * x);
226        }
227
228        /// <summary>
229        /// Multiplies a vector by a scalar
230        /// </summary>
231        /// <param name="vector">The vector</param>
232        /// <param name="scalar">The scalar</param>
233        /// <returns>A product of the vector <paramref name="vector"/> and the scalar <paramref name="scalar"/>.</returns>
234        public static TVec operator *(Term scalar, TVec vector)
235        {
236            Contract.Requires(vector != null);
237            Contract.Requires(scalar != null);
238            Contract.Ensures(Contract.Result<TVec>().Dimension == vector.Dimension);
239
240            return vector * scalar;
241        }
242
243        /// <summary>
244        /// Constructs a term representing the inner product of two vectors.
245        /// </summary>
246        /// <param name="left">The first vector of the inner product</param>
247        /// <param name="right">The second vector of the inner product</param>
248        /// <returns>A term representing the inner product of <paramref name="left"/> and <paramref name="right"/>.</returns>
249        public static Term operator*(TVec left, TVec right)
250        {
251            Contract.Requires(left != null);
252            Contract.Requires(right != null);
253            Contract.Requires(left.Dimension == right.Dimension);
254            Contract.Ensures(Contract.Result<Term>() != null);
255
256            return InnerProduct(left, right);
257        }
258
259        /// <summary>
260        /// Constructs a term representing the inner product of two vectors.
261        /// </summary>
262        /// <param name="left">The first vector of the inner product</param>
263        /// <param name="right">The second vector of the inner product</param>
264        /// <returns>A term representing the inner product of <paramref name="left"/> and <paramref name="right"/>.</returns>
265        public static Term InnerProduct(TVec left, TVec right)
266        {
267            Contract.Requires(left != null);
268            Contract.Requires(right != null);
269            Contract.Requires(left.Dimension == right.Dimension);
270            Contract.Ensures(Contract.Result<Term>() != null);
271
272            var products = from i in System.Linq.Enumerable.Range(0, left.Dimension)
273                           select left.terms[i] * right.terms[i];
274
275            return TermBuilder.Sum(products);
276        }
277
278        /// <summary>
279        /// Constructs a 3D cross-product vector given two 3D vectors.
280        /// </summary>
281        /// <param name="left">The left cross-product term</param>
282        /// <param name="right">The right cross product term</param>
283        /// <returns>A vector representing the cross product of <paramref name="left"/> and <paramref name="right"/></returns>
284        public static TVec CrossProduct(TVec left, TVec right)
285        {
286            Contract.Requires(left != null);
287            Contract.Requires(right != null);
288            Contract.Requires(left.Dimension == 3);
289            Contract.Requires(right.Dimension == 3);
290            Contract.Ensures(Contract.Result<TVec>().Dimension == 3);
291
292            return new TVec(
293                left.Y * right.Z - left.Z * right.Y,
294                left.Z * right.X - left.X * right.Z,
295                left.X * right.Y - left.Y * right.X
296                );
297        }
298    }
299}
Note: See TracBrowser for help on using the repository browser.