001: package org.zilonis.network.beta;
002:
003: /**
004: * Copyright (c) 2005 Elie Levy <elie.levy@zilonis.org>
005: * All rights reserved
006: *
007: * This License governs use of the accompanying Software, and your use of the
008: * Software constitutes acceptance of this license.
009: *
010: * You may use this Software for any non-commercial purpose, subject to the
011: * restrictions in this license. Some purposes which can be non-commercial are
012: * teaching, academic research, and personal experimentation. You may also
013: * distribute this Software with books or other teaching materials, or publish
014: * the Software on websites, that are intended to teach the use of the
015: * Software.
016: *
017: *
018: * You may not use or distribute this Software or any derivative works in any
019: * form for commercial purposes. Examples of commercial purposes would be
020: * running business operations, licensing, leasing, or selling the Software, or
021: * distributing the Software for use with commercial products.
022: *
023: * You may modify this Software and distribute the modified Software for
024: * non-commercial purposes, however, you may not grant rights to the Software
025: * or derivative works that are broader than those provided by this License.
026: * For example, you may not distribute modifications of the Software under
027: * terms that would permit commercial use, or under terms that purport to
028: * require the Software or derivative works to be sublicensed to others.
029: *
030: * You may use any information in intangible form that you remember after
031: * accessing the Software. However, this right does not grant you a license to
032: * any of the copyrights or patents for anything you might create using such
033: * information.
034: *
035: * In return, we simply require that you agree:
036: *
037: * Not to remove any copyright or other notices from the Software.
038: *
039: *
040: * That if you distribute the Software in source or object form, you will
041: * include a verbatim copy of this license.
042: *
043: *
044: * That if you distribute derivative works of the Software in source code form
045: * you do so only under a license that includes all of the provisions of this
046: * License, and if you distribute derivative works of the Software solely in
047: * object form you do so only under a license that complies with this License.
048: *
049: *
050: * That if you have modified the Software or created derivative works, and
051: * distribute such modifications or derivative works, you will cause the
052: * modified files to carry prominent notices so that recipients know that they
053: * are not receiving the original Software. Such notices must state: (i) that
054: * you have changed the Software; and (ii) the date of any changes.
055: *
056: *
057: * THAT THE SOFTWARE COMES "AS IS", WITH NO WARRANTIES. THIS MEANS NO EXPRESS,
058: * IMPLIED OR STATUTORY WARRANTY, INCLUDING WITHOUT LIMITATION, WARRANTIES OF
059: * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE OR ANY WARRANTY OF TITLE
060: * OR NON-INFRINGEMENT. ALSO, YOU MUST PASS THIS DISCLAIMER ON WHENEVER YOU
061: * DISTRIBUTE THE SOFTWARE OR DERIVATIVE WORKS.
062: *
063: *
064: * THAT NEITHER ZILONIS NOR THE AUTHOR WILL BE LIABLE FOR ANY DAMAGES RELATED
065: * TO THE SOFTWARE OR THIS LICENSE, INCLUDING DIRECT, INDIRECT, SPECIAL,
066: * CONSEQUENTIAL OR INCIDENTAL DAMAGES, TO THE MAXIMUM EXTENT THE LAW PERMITS,
067: * NO MATTER WHAT LEGAL THEORY IT IS BASED ON. ALSO, YOU MUST PASS THIS
068: * LIMITATION OF LIABILITY ON WHENEVER YOU DISTRIBUTE THE SOFTWARE OR
069: * DERIVATIVE WORKS.
070: *
071: *
072: * That if you sue anyone over patents that you think may apply to the Software
073: * or anyone's use of the Software, your license to the Software ends
074: * automatically.
075: *
076: *
077: * That your rights under the License end automatically if you breach it in any
078: * way.
079: *
080: *
081: * Elie Levy reserves all rights not expressly granted to you in this
082: * license.
083: *
084: */
085:
086: import static java.util.logging.Level.FINEST;
087: import static org.zilonis.network.Condition.BOOLEAN_EXPRESSION;
088: import static org.zilonis.network.Condition.CONJUNCTIVE_NEGATION_CONDITION;
089: import static org.zilonis.network.Condition.NEGATIVE_CONDITION;
090: import static org.zilonis.network.Condition.POSITIVE_CONDITION;
091:
092: import java.util.logging.Logger;
093:
094: import org.zilonis.network.Condition;
095: import org.zilonis.network.LeftActivatable;
096: import org.zilonis.network.Token;
097: import org.zilonis.network.WME;
098: import org.zilonis.network.alpha.AlphaMemory;
099: import org.zilonis.network.alpha.AlphaNetwork;
100: import org.zilonis.network.negative.NCCNode;
101: import org.zilonis.network.negative.NCCPartnerNode;
102: import org.zilonis.network.negative.NegativeNode;
103: import org.zilonis.scope.Scope;
104: import org.zilonis.scope.ScopedLinkedList;
105: import org.zilonis.symbol.Triplet;
106:
107: public abstract class BaseNode implements LeftActivatable {
108:
109: private ScopedLinkedList<LeftActivatable> children;
110:
111: private final static Logger logger = Logger
112: .getLogger("org.zilonis.network.beta.BaseNode");
113:
114: public BaseNode() {
115: children = new ScopedLinkedList<LeftActivatable>();
116: }
117:
118: public void activateChildren(Scope scope, WME wme, Token token) {
119: Iterable<LeftActivatable> childIterable = getLeftActivatableIterable(scope);
120: for (LeftActivatable leftActivable : childIterable) {
121: logger.finest("left activating:" + leftActivable);
122: leftActivable.leftActivate(scope, new Token(scope, token,
123: wme));
124: }
125: }
126:
127: public void setChildren(ScopedLinkedList<LeftActivatable> children) {
128: this .children = children;
129: }
130:
131: public ScopedLinkedList<LeftActivatable> getChildren() {
132: return children;
133: }
134:
135: public Iterable<LeftActivatable> getLeftActivatableIterable(
136: Scope scope) {
137: return children.getIterable(scope);
138: }
139:
140: public void addChild(Scope scope, LeftActivatable child) {
141: children.add(scope, child);
142: }
143:
144: public void addAsSecondChild(Scope scope, LeftActivatable child) {
145: children.addAsSecondChild(scope, child);
146: }
147:
148: public static void printPrev(Condition condition) {
149: logger.finest("************** printing earlier cond");
150: while (condition != null) {
151: logger.finest(condition.getTriplet().toString());
152: condition = condition.getPrev();
153: }
154: logger.finest("************** end of earlier cond");
155: }
156:
157: public static BaseNode buildNodeForPositiveCondition(Scope scope,
158: AlphaNetwork alphaNetwork, BaseNode baseNode,
159: Condition condition) {
160: Triplet triplet = condition.getTriplet();
161: boolean indexThisNode = triplet.isVariable(Triplet.IDENTIFIER);
162: if (indexThisNode) {
163: logger.finest("creating an indexed node for:" + triplet);
164: Triplet tripletWithOnlyIdentifier = new Triplet(triplet
165: .get(Triplet.IDENTIFIER), "attribute", "value");
166: logger.finest("the triplet withonly identifier is:"
167: + tripletWithOnlyIdentifier);
168: if (logger.isLoggable(FINEST))
169: printPrev(condition);
170: Test tests[] = Test.getTests(tripletWithOnlyIdentifier,
171: condition.getPrev());
172: logger.finest("the node has:" + tests.length
173: + " tests for id");
174: if (tests.length == 0)
175: return notIndexedPositiveNode(scope, alphaNetwork,
176: baseNode, condition);
177: int hashField = tests[0].getField2();
178: int hashLevelsUp = tests[0].getLength();
179: IndexedBetaMemory indexedBetaMemory = baseNode
180: .buildOrShareIndexedBetaMemory(scope, hashField,
181: hashLevelsUp);
182: condition.setIndexedBetaMemory(indexedBetaMemory);
183: AlphaMemory alphaMemory = alphaNetwork.getAlphaMemory(
184: scope, triplet);
185: tests = Test.getTests(triplet, condition.getPrev());
186: return indexedBetaMemory.getIndexedJoinNode(scope,
187: alphaMemory, tests);
188: }
189:
190: return notIndexedPositiveNode(scope, alphaNetwork, baseNode,
191: condition);
192: }
193:
194: public static BaseNode notIndexedPositiveNode(Scope scope,
195: AlphaNetwork alphaNetwork, BaseNode baseNode,
196: Condition condition) {
197: Triplet triplet = condition.getTriplet();
198: BetaMemory betaMemory = baseNode.buildOrShareBetaMemory(scope);
199: condition.setBetaMemory(betaMemory);
200: AlphaMemory alphaMemory = alphaNetwork.getAlphaMemory(scope,
201: triplet);
202: Test tests[] = Test.getTests(triplet, condition.getPrev());
203: return betaMemory.getJoinNode(scope, alphaMemory, tests);
204: }
205:
206: public static BaseNode buildOrShareNode(Scope scope,
207: AlphaNetwork alphaNetwork, BaseNode baseNode,
208: Condition condition) {
209: while (condition != null) {
210: if (condition.isType(POSITIVE_CONDITION)) {
211: baseNode = buildNodeForPositiveCondition(scope,
212: alphaNetwork, baseNode, condition);
213: } else if (condition.isType(NEGATIVE_CONDITION)) {
214: Triplet triplet = condition.getTriplet();
215: logger.finest("generating negative: " + triplet);
216: Test tests[] = Test.getTests(triplet, condition
217: .getPrev());
218: AlphaMemory alphaMemory = alphaNetwork.getAlphaMemory(
219: scope, triplet);
220: baseNode = baseNode.buildOrShareNegativeNode(scope,
221: alphaMemory, tests, condition);
222: } else if (condition.isType(CONJUNCTIVE_NEGATION_CONDITION)) {
223: logger.finest("building new ncc node");
224: baseNode = baseNode.buildOrShareNCCNode(scope,
225: alphaNetwork, condition);
226: logger.finest("baseNode:" + baseNode);
227: } else if (condition.isType(BOOLEAN_EXPRESSION)) {
228: baseNode = baseNode.buildOrShareExpressionNode(scope,
229: condition);
230: }
231: condition = condition.getNext();
232: }
233: return baseNode;
234: }
235:
236: public IndexedBetaMemory buildOrShareIndexedBetaMemory(Scope scope,
237: int hashField, int hashLevelsUp) {
238: for (LeftActivatable child : getLeftActivatableIterable(scope))
239: if (child instanceof IndexedBetaMemory) {
240: IndexedBetaMemory indexedBetaMemory = (IndexedBetaMemory) child;
241: if ((indexedBetaMemory.getIndex().getHashField() == hashField)
242: && (indexedBetaMemory.getIndex()
243: .getHashLevelsUp() == hashLevelsUp))
244: return indexedBetaMemory;
245: }
246: IndexedBetaMemory child = new IndexedBetaMemory(hashField,
247: hashLevelsUp);
248: children.add(scope, child);
249: update(scope, child);
250: return child;
251: }
252:
253: public BetaMemory buildOrShareBetaMemory(Scope scope) {
254: for (LeftActivatable child : getLeftActivatableIterable(scope))
255: if (child instanceof BetaMemory)
256: return (BetaMemory) child;
257: BetaMemory child = new BetaMemory();
258: children.add(scope, child);
259: update(scope, child);
260: return child;
261: }
262:
263: public NegativeNode buildOrShareNegativeNode(Scope scope,
264: AlphaMemory alphaMemory, Test tests[], Condition condition) {
265: for (LeftActivatable node : getLeftActivatableIterable(scope))
266: if (node instanceof NegativeNode) {
267: NegativeNode negativeNode = (NegativeNode) node;
268: if ((negativeNode.getAlphaMemory() == alphaMemory)
269: && (negativeNode.testsMatch(scope, tests)))
270: return negativeNode;
271: }
272: NegativeNode negativeNode = new NegativeNode(scope,
273: alphaMemory, tests);
274: condition.setNegativeNode(negativeNode);
275: alphaMemory.addChild(scope, negativeNode);
276: addChild(scope, negativeNode);
277: update(scope, negativeNode);
278: return negativeNode;
279: }
280:
281: public BaseNode buildOrShareNCCNode(Scope scope,
282: AlphaNetwork alphaNetwork, Condition condition) {
283: BaseNode baseNode = buildOrShareNode(scope, alphaNetwork, this ,
284: condition.getTop());
285: logger.finest("baseNode = " + baseNode);
286: for (LeftActivatable child : getLeftActivatableIterable(scope)) {
287: if (child instanceof NCCNode) {
288: NCCNode nccNode = (NCCNode) child;
289: if (nccNode.getPartner().getParent() == baseNode) {
290: condition.setNccNode(nccNode);
291: condition.setNccPartnerNode(nccNode.getPartner());
292: return nccNode;
293: }
294: }
295: }
296: NCCNode nccNode = new NCCNode();
297: condition.setNccNode(nccNode);
298: addAsSecondChild(scope, nccNode);
299: NCCPartnerNode nccPartnerNode = new NCCPartnerNode(baseNode,
300: condition.getNumberOfSubConditions());
301: condition.setNccPartnerNode(nccPartnerNode);
302: baseNode.addChild(scope, nccPartnerNode);
303: nccNode.setPartner(nccPartnerNode);
304: nccPartnerNode.setPartner(nccNode);
305: update(scope, nccPartnerNode);
306: update(scope, nccNode);
307: return nccNode;
308: }
309:
310: public ExpressionNode buildOrShareExpressionNode(Scope scope,
311: Condition condition) {
312: for (LeftActivatable child : getLeftActivatableIterable(scope)) {
313: if (child instanceof ExpressionNode) {
314: ExpressionNode expressionNode = (ExpressionNode) child;
315: // if the expresion content is equal, then the variables have
316: // to be equal too. This comparison here is sort of soft.
317: // needs to be reviewed and improved to maximize reuse.
318: if (expressionNode.getExpression().equals(
319: condition.getExpression()))
320: return expressionNode;
321: }
322: }
323: // the expression node does not hold any tokens. For that reason
324: // the update is not needed. We can return a brand new ExpressionNode
325: ExpressionNode expressionNode = new ExpressionNode(condition,
326: this );
327: addChild(scope, expressionNode);
328: return expressionNode;
329: }
330:
331: public String toString(Scope scope) {
332: return "baseNode";
333: }
334:
335: public abstract void update(Scope scope, LeftActivatable production);
336: }
|