MathWorx

Group.js

Summary

This file defines the Group class, instance methods, and static objects/methods. It depends on the Set class, but as long as easyload.js is loaded first, Set.js will automatically be included with this file.


Class Summary
Group  

/**MathWorx Copyright (c) 2008 Shane Steinert-Threlkeld
Dual-licensed under the MIT and GNU GPL Licenses.
For more information, see LICENSE file */

/** @fileoverview This file defines the Group class, instance methods, and static objects/methods.  It depends on the Set class, but as long as easyload.js is loaded first, Set.js will automatically be included with this file. */

dependencies = ['Set'];
require(dependencies);

/**Generator function for a new group (mathematical).
 * @requires Set 
 * @param {Array} elements the set of elements that defines the set in the group
 * @param {Function} operator if a function, must take two parameters (elements of the set); if a string: 'addition' or 'multiplication'
 * @constructor
 * **/

function Group(elements, operator) {
	if(elements instanceof Array) {
		this.set = new Set(elements);
	}
	if(elements instanceof Set) {
		this.set = elements;
	}
	/**Either a function, or a string 'addition' or 'multiplication'
	@type Function */
	this.operation = operator;
	//booleans for each of the 4 axioms of a well-formed group
	/**Whether or not the group has closure 
	@type Boolean */
	this.hasClosure = false;
	/**Whether or not the group is associative
	@type Boolean */
	this.hasAssociativity = false;
	/**Whether or not the group has an identity element
	@type Boolean */
	this.hasIdentity = false;
	/**Whether or not the group satisfies the inverse axiom 
	@type Boolean */
	this.hasInverse = false;
	/**{Object} the identity element, if it exists */
	this.identity;
}

Group.prototype = {


	/**Determines if the group does or does not have closure and sets the binary hasClosure.
	 * @return {Boolean} true if group has closure, false otherwise**/
	testClosure: function() {
		for(i = 0; i < this.set.cardinality; i++) {
			for(j = 0; j < this.set.cardinality;) {
				if(!(this.set.inSet(this.operand(this.set.elements[i],this.set.elements[j])))) {
					this.hasClosure = false;
					return this.hasClosure;
				}
			}
		}
		this.hasClosure = true;
		return this.hasClosure;
	},

	/**Sets the identity element if it exists and hasIdentity to true.**/
	setIdentity: function() {
		for(i = 0; i < this.set.cardinality; i++) {
			if(this.operand(this.set.elements[i],this.set.elements[i])==this.set.elements[i]) {
				this.hasIdentity = true;
				this.identity = this.set.elements[i]
			}
		}
	},

	/**Gets the identity element if it exists.  Should be called after setIdentity() already has been.
	 * @return {Object} the identity element if it exists, false otherwise*/
	getIdentity: function() {
		if(this.hasIdentity) {
			return this.identity;
		} else {
			return false;
		}
	},

	/**Tells whether or not group has identity element.  Should be called after setIdentity() already has been.
	 * @return {Boolean} true if has identity element, false otherwise**/
	testIdentity: function() {
		return this.hasIdentity;
	},

	/**Tests whether or not group is associative.
	 * @return {Boolean} true if group is associative, false otherwise**/
	testAssociativity: function() {
		for(i = 0; i < this.set.cardinality; i++) {
			for(j = 0; j < this.set.cardinality; j++) {
				for(k = 0; k < this.set.cardinality; k++) {
					if(this.operand(this.operand(this.set.elements[i],this.set.elements[j]),this.set.elements[k]) != this.operand(this.set.elements[i],this.operand(this.set.elements[j],this.set.elements[k]))) {
						this.hasAssociativity = false;
						return this.hasAssociativity;
					}
				}
			}
		}
		this.hasAssociativity = true;
		return this.hasAssociativity;
	},

	/**Tests for the existence of an inverse element for every element.  Should be called after setIdentity().
	 * @return {Boolean} true if every element has an inverse, false otherwise**/
	testInverse: function() {
		//number of elements that have inverses
		var numInverses = 0;
		var temp;
		if(this.hasIdentity) {
			for(i = 0; i < this.set.cardinality; i++) {
				temp = false;
				for(j = 0; j < this.set.cardinality; j++) {
					if(this.operand(this.set.elements[i],this.set.elements[j]) == this.identity && this.operand(this.set.elements[j],this.set.elements[i]) == this.identity) {
						temp = true;
					}
				}
				if(temp) {
					numInverses++;
				}
			}
			if(numInverses >= this.set.cardinality) {
				this.hasInverse = true;
			}
			return this.hasInverse;
		} else {
			return this.hasInverse;
		}
	},

	/**Tests to see whether the group satisfies all four axioms in the definition of a formal group.
	 * @return {Boolean} true if the group does, false otherwise**/
	isGroup: function() {
		if(this.hasClosure && this.hasAssociativity && this.hasIdentity && this.hasInverse) {
			return true;
		} else {
			return false;
		}
	},

	/**Tests if a given array (in this case, a permutation) is a cycle of the set.
	@param {Array} array - the array to test
	@return {Boolean} true if array is a cycle, false otherwise */
	testCycle: function(array) {
		var tempvec = new Array();
		var cycle2 = new Array();
		var userCycle = new Array();
		userCycle = array;

		//handle single-element cycles
		if(userCycle.length == 1) {
			if(this.set.elements[userCycle[0]] == userCycle[0]) {
				return true;
			} else {
				return false;
			}
		}
		
		for(i = 0; i < userCycle.length; i++) {
			cycle2[i] = this.set.elements[userCycle[i]];
		}
		var temp = cycle2[userCycle.length - 1];
		for(i = 0; i < cycle2.length; i++) {
			tempvec[i] = cycle2[i];
		}
		cycle2[0] = temp;
		for(i = 1; i < userCycle.length; i++) {
			cycle2[i] = tempvec[i-1];
		}

		if(cycle2.compareArray(userCycle)) {
			return true;
		} else {
			return false;
		}
	},

	/**The actual binary operation that is carried out for the group.
	 * @param {Object} el1 - the first element
	 * @param {Object} el2 - the second element
	 * @return {Object} (el1 operation el2)**/
	operand: function(el1, el2) {
		if(typeof this.operation == 'function') {
			return this.operation(el1, el2);
		} else {
			if(this.operation == 'multiplication') {
				return el1 * el2;
			}
			if(this.operation == 'addition') {
				return el1 + el2;
			}
		}
	}
}


MathWorx

Documentation generated by JSDoc on Tue Aug 5 10:22:22 2008