Implement GSCSConstraint and suppoorting classes

This commit is contained in:
Benjamin Johnson 2023-05-06 16:24:08 +10:00
parent 2be7334ce2
commit bddf6cfd03
11 changed files with 1256 additions and 27 deletions

View file

@ -364,6 +364,8 @@ GSCSConstraint.m \
GSCSVariable.m \
GSCSSolution.m \
GSCSFloatComparator.m \
GSCSLinearExpression.m \
GSCSStrength.m
# Turn off NSMenuItem warning that NSMenuItem conforms to <NSObject>,
# but does not implement <NSObject>'s methods itself (it inherits
@ -684,8 +686,11 @@ GSAutoLayoutEngine.h \
GSCassowarySolver.h \
GSCSConstraint.h \
GSCSVariable.h \
GSCSFloatComparator.h \
GSCSSolution.h \
GSCSFloatComparator.h
GSCSLinearExpression.h \
GSCSConstraintOperator.h \
GSCSStrength.h
libgnustep-gui_HEADER_FILES = ${GUI_HEADERS}

View file

@ -1,31 +1,124 @@
/* Copyright (C) 2023 Free Software Foundation, Inc.
By: Benjamin Johnson
Date: 19-3-2023
This file is part of the GNUstep Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110 USA.
*/
#import "GSCSConstraintOperator.h"
#import "GSCSLinearExpression.h"
#import "GSCSStrength.h"
#import "GSCSVariable.h"
#import <Foundation/Foundation.h>
#ifndef _GS_CS_CONSTRAINT_H
#define _GS_CS_CONSTRAINT_H
enum GSCSConstraintType
{
GSCSConstraintTypeEdit,
GSCSConstraintTypeStay,
GSCSConstraintTypeLinear,
GSCSConstraintTypeLinearInequity
};
typedef enum GSCSConstraintType GSCSConstraintType;
@interface GSCSConstraint : NSObject
{
GSCSConstraintType _type;
GSCSStrength *_strength;
GSCSLinearExpression *_expression;
GSCSVariable *_variable;
}
- (instancetype) initWithType: (GSCSConstraintType)type
strength: (GSCSStrength *)strength
expression: (GSCSLinearExpression *)expression
variable: (GSCSVariable *)variable;
- (instancetype) initLinearConstraintWithExpression:
(GSCSLinearExpression *)expression;
- (instancetype) initLinearInequityConstraintWithExpression:
(GSCSLinearExpression *)expression;
- (instancetype) initLinearConstraintWithExpression:
(GSCSLinearExpression *)expression
strength: (GSCSStrength *)strength
variable: (GSCSVariable *)variable;
- (instancetype) initEditConstraintWithVariable: (GSCSVariable *)variable
stength: (GSCSStrength *)strength;
- (instancetype) initStayConstraintWithVariable: (GSCSVariable *)variable
strength: (GSCSStrength *)strength;
- (instancetype) initWithLhsVariable: (GSCSVariable *)lhs
equalsConstant: (CGFloat)rhs;
- (instancetype) initWithLhsVariable: (GSCSVariable *)lhs
equalsRhsVariable: (GSCSVariable *)rhs;
+ (GSCSConstraint *) constraintWithLeftVariable: (GSCSVariable *)lhs
operator: (GSCSConstraintOperator) operator
rightVariable: (GSCSVariable *)rhsVariable;
+ (GSCSConstraint *) constraintWithLeftVariable: (GSCSVariable *)lhs
operator: (GSCSConstraintOperator) operator
rightConstant: (CGFloat)rhs;
+ (GSCSConstraint *) constraintWithLeftVariable: (GSCSVariable *)lhs
operator: (GSCSConstraintOperator) operator
rightExpression: (GSCSLinearExpression *)rhs;
+ (GSCSConstraint *) constraintWithLeftConstant: (CGFloat)lhs
operator: (GSCSConstraintOperator) operator
rightVariable: (GSCSVariable *)rhs;
+ (GSCSConstraint *) constraintWithLeftExpression: (GSCSLinearExpression *)lhs
operator: (GSCSConstraintOperator) operator
rightVariable: (GSCSVariable *)rhs;
+ (GSCSConstraint *) constraintWithLeftExpression: (GSCSLinearExpression *)lhs
operator: (GSCSConstraintOperator) operator
rightExpression: (GSCSLinearExpression *)rhs;
+ (GSCSConstraint *) constraintWithLeftExpression: (GSCSLinearExpression *)lhs
operator: (GSCSConstraintOperator) operator
rightConstant: (CGFloat)rhs;
+ (instancetype) editConstraintWithVariable: (GSCSVariable *)variable;
- (BOOL) isRequired;
- (BOOL) isEditConstraint;
- (BOOL) isStayConstraint;
- (BOOL) isInequality;
- (GSCSLinearExpression *) expression;
- (GSCSConstraintType) type;
- (GSCSStrength *) strength;
- (GSCSVariable *) variable;
@end

View file

@ -1,19 +1,19 @@
/* Copyright (C) 2023 Free Software Foundation, Inc.
By: Benjamin Johnson
Date: 19-3-2023
This file is part of the GNUstep Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
@ -21,7 +21,346 @@
*/
#import "GSCSConstraint.h"
#import "GSCSFloatComparator.h"
#import "GSCSVariable.h"
@implementation GSCSConstraint
- (instancetype) init
{
return [self initWithType: GSCSConstraintTypeLinear
strength: nil
expression: nil
variable: nil];
}
- (instancetype) initWithType: (GSCSConstraintType)type
strength: (GSCSStrength *)strength
expression: (GSCSLinearExpression *)expression
variable: (GSCSVariable *)variable
{
self = [super init];
if (self)
{
ASSIGN(_strength, strength != nil ? [strength copy]
: [GSCSStrength strengthRequired]);
ASSIGN(_expression, expression);
ASSIGN(_variable, variable);
_type = type;
}
return self;
}
- (instancetype) initLinearConstraintWithExpression:
(GSCSLinearExpression *)expression
strength: (GSCSStrength *)strength
variable: (GSCSVariable *)variable
{
return [self initWithType: GSCSConstraintTypeLinear
strength: strength
expression: expression
variable: variable];
}
- (instancetype) initLinearConstraintWithExpression:
(GSCSLinearExpression *)expression
{
return
[self initLinearConstraintWithExpression: expression
strength: [GSCSStrength strengthRequired]
variable: nil];
}
- (instancetype) initLinearInequityConstraintWithExpression:
(GSCSLinearExpression *)expression
{
return
[self initWithType: GSCSConstraintTypeLinearInequity
strength: [GSCSStrength strengthRequired]
expression: expression
variable: nil];
}
- (instancetype) initEditConstraintWithVariable: (GSCSVariable *)variable
stength: (GSCSStrength *)strength
{
GSCSLinearExpression *expression =
[[GSCSLinearExpression alloc] initWithVariable: variable
coefficient: -1
constant: [variable value]];
GSCSConstraint *constraint = [self initWithType: GSCSConstraintTypeEdit
strength: strength
expression: expression
variable: variable];
RELEASE(expression);
return constraint;
}
- (instancetype) initStayConstraintWithVariable: (GSCSVariable *)variable
strength: (GSCSStrength *)strength
{
GSCSLinearExpression *expression =
[[GSCSLinearExpression alloc] initWithVariable: variable
coefficient: -1
constant: [variable value]];
GSCSConstraint *constraint = [[GSCSConstraint alloc] initWithType: GSCSConstraintTypeStay
strength: strength
expression: expression
variable: variable];
RELEASE(expression);
return constraint;
}
- (instancetype) initWithLhsVariable: (GSCSVariable *)lhs
equalsRhsVariable: (GSCSVariable *)rhs
{
GSCSLinearExpression *expression =
[[GSCSLinearExpression alloc] initWithVariable: lhs];
[expression addVariable: rhs coefficient: -1];
GSCSConstraint *constraint = [self initLinearConstraintWithExpression: expression];
RELEASE(expression);
return constraint;
}
- (instancetype) initWithLhsVariable: (GSCSVariable *)lhs
equalsConstant: (CGFloat)rhs
{
GSCSLinearExpression *expression =
[[GSCSLinearExpression alloc] initWithVariable: lhs
coefficient: 1
constant: -rhs];
GSCSConstraint *constraint = [self initLinearConstraintWithExpression: expression];
RELEASE(expression);
return constraint;
}
+ (GSCSConstraint *) constraintWithLeftVariable: (GSCSVariable *)lhs
operator: (GSCSConstraintOperator) operator
rightVariable: (GSCSVariable *)rhsVariable
{
if (operator== GSCSConstraintOperatorEqual)
{
GSCSLinearExpression *expression =
[[GSCSLinearExpression alloc] initWithVariable: lhs];
[expression addVariable: rhsVariable coefficient: -1];
RELEASE(expression);
return AUTORELEASE([[GSCSConstraint alloc]
initLinearConstraintWithExpression: expression]);
}
else
{
GSCSLinearExpression *rhsExpression =
[[GSCSLinearExpression alloc] initWithVariable: rhsVariable];
if (operator== GSCSConstraintOperationGreaterThanOrEqual)
{
[rhsExpression multiplyConstantAndTermsBy: -1];
[rhsExpression addVariable: lhs];
}
else if (operator== GSCSConstraintOperatorLessThanOrEqual)
{
[rhsExpression addVariable: lhs coefficient: -1];
}
RELEASE(rhsExpression);
return AUTORELEASE([[GSCSConstraint alloc]
initLinearInequityConstraintWithExpression: rhsExpression]);
}
}
+ (GSCSConstraint *) constraintWithLeftVariable: (GSCSVariable *)lhs
operator: (GSCSConstraintOperator) operator
rightConstant: (CGFloat)rhs
{
GSCSLinearExpression *expression;
GSCSConstraint *constraint;
if (operator== GSCSConstraintOperatorEqual)
{
expression = [[GSCSLinearExpression alloc] init];
[expression addVariable: lhs coefficient: 1];
[expression setConstant: -rhs];
constraint = [[GSCSConstraint alloc]
initLinearConstraintWithExpression: expression
strength: [GSCSStrength strengthRequired]
variable: nil];
}
else
{
expression =
[[GSCSLinearExpression alloc] initWithConstant: rhs];
if (operator== GSCSConstraintOperationGreaterThanOrEqual)
{
[expression multiplyConstantAndTermsBy: -1];
[expression addVariable: lhs coefficient: 1.0];
}
else if (operator== GSCSConstraintOperatorLessThanOrEqual)
{
[expression addVariable: lhs coefficient: -1.0];
}
constraint = [[GSCSConstraint alloc]
initLinearInequityConstraintWithExpression: expression];
}
RELEASE(expression);
return AUTORELEASE(constraint);
}
+ (GSCSConstraint *) constraintWithLeftVariable: (GSCSVariable *)lhs
operator: (GSCSConstraintOperator) operator
rightExpression: (GSCSLinearExpression *)rhs
{
GSCSLinearExpression *lhsExpression =
[[GSCSLinearExpression alloc] initWithVariable: lhs];
GSCSConstraint *constraint = [self constraintWithLeftExpression:lhsExpression operator:operator rightExpression:rhs];
RELEASE(lhsExpression);
return constraint;
}
+ (GSCSConstraint *) constraintWithLeftConstant: (CGFloat)lhs
operator: (GSCSConstraintOperator) operator
rightVariable: (GSCSVariable *)rhs
{
GSCSLinearExpression *valueExpression =
[[GSCSLinearExpression alloc] initWithConstant: lhs];
GSCSConstraint *constraint = nil;
if (operator== GSCSConstraintOperatorEqual)
{
[valueExpression addVariable: rhs coefficient: -1.0];
constraint = [[GSCSConstraint alloc]
initLinearConstraintWithExpression: valueExpression];
}
else
{
if (operator== GSCSConstraintOperationGreaterThanOrEqual)
{
[valueExpression addVariable: rhs coefficient: -1.0];
}
else if (operator== GSCSConstraintOperatorLessThanOrEqual)
{
[valueExpression multiplyConstantAndTermsBy: -1];
[valueExpression addVariable: rhs coefficient: 1.0];
}
constraint = [[GSCSConstraint alloc]
initLinearInequityConstraintWithExpression: valueExpression];
}
RELEASE(valueExpression);
return constraint;
}
+ (GSCSConstraint *) constraintWithLeftExpression: (GSCSLinearExpression *)lhs
operator: (GSCSConstraintOperator) operator
rightVariable: (GSCSVariable *)rhs
{
GSCSLinearExpression *rhsExpression =
[[GSCSLinearExpression alloc] initWithVariable: rhs];
return [self constraintWithLeftExpression:lhs operator:operator rightExpression:rhsExpression];
}
+ (GSCSConstraint *) constraintWithLeftExpression: (GSCSLinearExpression *)lhs
operator: (GSCSConstraintOperator) operator
rightExpression: (GSCSLinearExpression *)rhs
{
GSCSLinearExpression *expression = [rhs copy];
GSCSConstraint *constraint;
if (operator== GSCSConstraintOperatorEqual)
{
[expression addExpression: lhs multiplier: -1];
constraint = [[GSCSConstraint alloc]
initLinearConstraintWithExpression: expression];
}
else
{
if (operator== GSCSConstraintOperationGreaterThanOrEqual)
{
[expression multiplyConstantAndTermsBy: -1];
[expression addExpression: lhs];
}
else if (operator== GSCSConstraintOperatorLessThanOrEqual)
{
[expression addExpression: lhs multiplier: -1];
}
constraint = [[GSCSConstraint alloc]
initLinearInequityConstraintWithExpression: expression];
}
RELEASE(expression);
return AUTORELEASE(constraint);
}
+ (GSCSConstraint *) constraintWithLeftExpression: (GSCSLinearExpression *)lhs
operator: (GSCSConstraintOperator) operator
rightConstant: (CGFloat)rhs
{
GSCSLinearExpression *rhsExpression =
[[GSCSLinearExpression alloc] initWithConstant: rhs];
GSCSConstraint *constraint = [self constraintWithLeftExpression:lhs operator:operator rightExpression:rhsExpression];
RELEASE(rhsExpression);
return constraint;
}
+ (instancetype) editConstraintWithVariable: (GSCSVariable *)variable
{
return AUTORELEASE([[self alloc]
initEditConstraintWithVariable: variable
stength: [GSCSStrength strengthStrong]]);
}
- (BOOL) isRequired
{
return [_strength isRequired];
}
- (BOOL) isEditConstraint
{
return _type == GSCSConstraintTypeEdit;
}
- (BOOL) isStayConstraint
{
return _type == GSCSConstraintTypeStay;
}
- (BOOL) isInequality
{
return _type == GSCSConstraintTypeLinearInequity;
}
- (GSCSLinearExpression *) expression
{
return _expression;
}
- (GSCSVariable *) variable
{
return _variable;
}
- (GSCSStrength *) strength
{
return _strength;
}
- (GSCSConstraintType) type
{
return _type;
}
- (void) dealloc
{
RELEASE(_strength);
RELEASE(_expression);
RELEASE(_variable);
[super dealloc];
}
@end

View file

@ -0,0 +1,34 @@
/* Copyright (C) 2023 Free Software Foundation, Inc.
By: Benjamin Johnson
Date: 19-3-2023
This file is part of the GNUstep Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110 USA.
*/
#ifndef GSCSConstraintOperator_h
#define GSCSConstraintOperator_h
enum GSCSConstraintOperator
{
GSCSConstraintOperatorEqual,
GSCSConstraintOperationGreaterThanOrEqual,
GSCSConstraintOperatorLessThanOrEqual,
};
typedef enum GSCSConstraintOperator GSCSConstraintOperator;
#endif /* GSCSConstraintOperator_h */

View file

@ -0,0 +1,92 @@
/* Copyright (C) 2023 Free Software Foundation, Inc.
By: Benjamin Johnson
Date: 19-3-2023
This file is part of the GNUstep Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110 USA.
*/
#import "GSCSVariable.h"
#import <Foundation/Foundation.h>
#ifndef _GS_CS_LINEAR_EXPRESSION_H
#define _GS_CS_LINEAR_EXPRESSION_H
@interface GSCSLinearExpression : NSObject <NSCopying>
{
NSMapTable *_terms;
CGFloat _constant;
NSMutableArray *_termVariables;
}
- (instancetype) initWithConstant: (CGFloat)constant;
- (instancetype) initWithVariable: (GSCSVariable *)variable;
- (instancetype) initWithVariable: (GSCSVariable *)variable
coefficient: (CGFloat)value
constant: (CGFloat)constant;
- (instancetype) initWithVariables: (NSArray *)variables;
- (CGFloat) constant;
- (void) setConstant: (CGFloat)constant;
- (NSMapTable *) terms;
- (NSArray *) termVariables;
- (NSNumber *) multiplierForTerm: (GSCSVariable *)variable;
- (void) removeVariable: (GSCSVariable *)variable;
- (void) multiplyConstantAndTermsBy: (CGFloat)value;
- (void) divideConstantAndTermsBy: (CGFloat)value;
- (CGFloat) coefficientForTerm: (GSCSVariable *)variable;
- (CGFloat) newSubject: (GSCSVariable *)subject;
- (void) addVariable: (GSCSVariable *)variable;
- (void) addVariable: (GSCSVariable *)variable
coefficient: (CGFloat)coefficient;
- (void) addExpression: (GSCSLinearExpression *)expression;
- (void) addExpression: (GSCSLinearExpression *)expression
multiplier: (CGFloat)multiplier;
- (NSArray *) findPivotableVariablesWithMostNegativeCoefficient;
- (void) normalize;
- (BOOL) isConstant;
- (BOOL) isTermForVariable: (GSCSVariable *)variable;
- (GSCSVariable *) anyPivotableVariable;
- (NSArray *) externalVariables;
- (BOOL) containsOnlyDummyVariables;
@end
#endif //_GS_CS_LINEAR_EXPRESSION_H

View file

@ -0,0 +1,317 @@
/* Copyright (C) 2023 Free Software Foundation, Inc.
By: Benjamin Johnson
Date: 19-3-2023
This file is part of the GNUstep Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110 USA.
*/
#import "GSCSLinearExpression.h"
#import "GSCSFloatComparator.h"
#import "GSCSVariable.h"
#import "GSFastEnumeration.h"
@implementation GSCSLinearExpression
- (instancetype) init
{
self = [super init];
if (self)
{
ASSIGN(_terms, [NSMapTable strongToStrongObjectsMapTable]);
ASSIGN(_termVariables, [NSMutableArray array]);
_constant = 0;
}
return self;
}
- (instancetype) initWithVariable: (GSCSVariable *)variable
{
self = [self init];
if (self)
{
[self addVariable: variable coefficient: 1.0];
}
return self;
}
- (instancetype) initWithVariables: (NSArray *)variables
{
self = [self init];
if (self)
{
FOR_IN(GSCSVariable *, variable, variables)
[self addVariable: variable coefficient: 1.0];
END_FOR_IN(variables)
}
return self;
}
- (instancetype) initWithConstant: (CGFloat)constant
{
self = [self init];
if (self)
{
_constant = constant;
}
return self;
}
- (instancetype) initWithVariable: (GSCSVariable *)variable
coefficient: (CGFloat)coefficient
constant: (CGFloat)constant
{
self = [self init];
if (self)
{
[self addVariable: variable coefficient: coefficient];
_constant = constant;
}
return self;
}
- (CGFloat) constant
{
return _constant;
}
- (void) setConstant: (CGFloat)constant
{
_constant = constant;
}
- (NSMapTable *) terms
{
return _terms;
}
- (NSArray *) termVariables
{
return _termVariables;
}
- (void) removeVariable: (GSCSVariable *)variable
{
[_terms removeObjectForKey: variable];
[_termVariables removeObject: variable];
}
- (NSNumber *) multiplierForTerm: (GSCSVariable *)variable
{
return [_terms objectForKey: variable];
}
- (CGFloat) newSubject: (GSCSVariable *)subject
{
CGFloat reciprocal = 1.0 / [self coefficientForTerm: subject];
[self multiplyConstantAndTermsBy:-reciprocal];
[self removeVariable: subject];
return reciprocal;
}
- (void) multiplyConstantAndTermsBy: (CGFloat)value
{
_constant = _constant * value;
NSMutableArray *keys = [NSMutableArray arrayWithCapacity: [_terms count]];
FOR_IN(GSCSVariable *, term, _terms)
[keys addObject: term];
END_FOR_IN(_terms)
FOR_IN(GSCSVariable *, term, keys)
NSNumber *termCoefficent = [_terms objectForKey: term];
CGFloat multipliedTermCoefficent = [termCoefficent doubleValue] * value;
[_terms setObject: [NSNumber numberWithDouble: multipliedTermCoefficent]
forKey: term];
END_FOR_IN(keys)
}
- (void) divideConstantAndTermsBy: (CGFloat)value
{
[self multiplyConstantAndTermsBy: 1 / value];
}
- (CGFloat) coefficientForTerm: (GSCSVariable *)variable
{
return [[self multiplierForTerm: variable] floatValue];
}
- (void) normalize
{
[self multiplyConstantAndTermsBy:-1];
}
- (id) copyWithZone: (NSZone *)zone
{
GSCSLinearExpression *expression = [[[self class] allocWithZone: zone] init];
if (expression)
{
[expression setConstant: [self constant]];
FOR_IN(GSCSVariable *, variable, _termVariables)
[expression addVariable: variable
coefficient: [self coefficientForTerm: variable]];
END_FOR_IN(_termVariables)
}
return expression;
}
- (NSArray *) findPivotableVariablesWithMostNegativeCoefficient
{
CGFloat mostNegativeCoefficient = 0;
FOR_IN(GSCSVariable *, term, _termVariables)
CGFloat coefficientForTerm = [self coefficientForTerm: term];
if ([term isPivotable] && coefficientForTerm < mostNegativeCoefficient)
{
mostNegativeCoefficient = coefficientForTerm;
}
END_FOR_IN(_termVariables)
NSMutableArray *candidates = [NSMutableArray array];
FOR_IN(GSCSVariable *, term, _termVariables)
CGFloat coefficientForTerm = [self coefficientForTerm: term];
if ([term isPivotable] &&
[GSCSFloatComparator isApproxiatelyEqual: coefficientForTerm
b: mostNegativeCoefficient])
{
[candidates addObject: term];
}
END_FOR_IN(_termVariables)
return candidates;
}
- (BOOL) isConstant
{
return [_terms count] == 0;
}
- (BOOL) isTermForVariable: (GSCSVariable *)variable
{
return [_terms objectForKey: variable] != nil;
}
- (GSCSVariable *) anyPivotableVariable
{
if ([self isConstant])
{
[[NSException exceptionWithName: NSInternalInconsistencyException
reason: @"anyPivotableVariable invoked on a "
@"constant expression"
userInfo: nil] raise];
}
FOR_IN(GSCSVariable *, variable, _termVariables)
if ([variable isPivotable])
{
return variable;
}
END_FOR_IN(_termVariables)
return nil;
}
- (BOOL) containsOnlyDummyVariables
{
FOR_IN(GSCSVariable *, term, _termVariables)
if (![term isDummy])
{
return NO;
}
END_FOR_IN(_termVariables)
return YES;
}
- (NSArray *) externalVariables
{
NSMutableArray *externalVariables = [NSMutableArray array];
FOR_IN(GSCSVariable *, variable, _terms)
if ([variable isExternal])
{
[externalVariables addObject: variable];
}
END_FOR_IN(_terms)
return externalVariables;
}
- (void) addVariable: (GSCSVariable *)variable
{
[self addVariable: variable coefficient: 1];
}
- (void) addVariable: (GSCSVariable *)variable
coefficient: (CGFloat)coefficient;
{
if (![GSCSFloatComparator isApproxiatelyZero: coefficient])
{
if ([self isTermForVariable: variable])
{
[_termVariables removeObject: variable];
}
[_terms setObject: [NSNumber numberWithFloat: coefficient]
forKey: variable];
[_termVariables addObject: variable];
}
}
- (NSString *) description
{
NSString *descriptionString = [NSString stringWithFormat:@"%f", _constant];
FOR_IN(GSCSVariable *, term, _termVariables)
descriptionString = [descriptionString
stringByAppendingString:
[NSString stringWithFormat: @" + %f * %@",
[self coefficientForTerm: term],
[term description]]];
END_FOR_IN(_termVariables)
return descriptionString;
}
- (void) addExpression: (GSCSLinearExpression *)expression
{
[self addExpression: expression multiplier: 1];
}
- (void) addExpression: (GSCSLinearExpression *)expression
multiplier: (CGFloat)multiplier
{
[self setConstant: [self constant] + expression.constant * multiplier];
NSArray *termVariables = [expression termVariables];
FOR_IN(GSCSVariable *, term, termVariables)
CGFloat termCoefficient =
[expression coefficientForTerm: term] * multiplier;
[self addVariable: term coefficient: termCoefficient];
END_FOR_IN(termVariables)
}
- (void) dealloc
{
RELEASE(_terms);
RELEASE(_termVariables);
[super dealloc];
}
@end

View file

@ -65,12 +65,13 @@
NSNumber *rhsResult = [solution resultForVariable: variable];
BOOL hasResultForBoth = lhsResult != nil && rhsResult != nil;
if (!hasResultForBoth) {
return NO;
}
if (!hasResultForBoth)
{
return NO;
}
return [GSCSFloatComparator isApproxiatelyEqual: [lhsResult floatValue]
b: [rhsResult floatValue]];
b: [rhsResult floatValue]];
}
- (BOOL) isEqualToCassowarySolverSolution: (GSCSSolution *)solution
@ -91,10 +92,10 @@
return YES;
}
- (void) dealloc
{
RELEASE (_resultsByVariable);
[super dealloc];
}
- (void) dealloc
{
RELEASE(_resultsByVariable);
[super dealloc];
}
@end

52
Source/GSCSStrength.h Normal file
View file

@ -0,0 +1,52 @@
/* Copyright (C) 2023 Free Software Foundation, Inc.
By: Benjamin Johnson
Date: 19-3-2023
This file is part of the GNUstep Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110 USA.
*/
#import <Foundation/Foundation.h>
#ifndef _GS_CS_STRENGTH_H
#define _GS_CS_STRENGTH_H
@interface GSCSStrength : NSObject <NSCopying>
{
NSString *_name;
double _strength;
}
- (NSString *) name;
- (double) strength;
- (instancetype) initWithName: (NSString *)name strength: (double)strength;
+ (instancetype) strengthRequired;
+ (instancetype) strengthStrong;
+ (instancetype) strengthMedium;
+ (instancetype) strengthWeak;
- (BOOL) isRequired;
@end
#endif

112
Source/GSCSStrength.m Normal file
View file

@ -0,0 +1,112 @@
/* Copyright (C) 2023 Free Software Foundation, Inc.
By: Benjamin Johnson
Date: 19-3-2023
This file is part of the GNUstep Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110 USA.
*/
#import "GSCSStrength.h"
#import "GSCSFloatComparator.h"
@implementation GSCSStrength
- (instancetype) initWithName: (NSString *)name strength: (double)strength;
{
if (self = [super init])
{
ASSIGN(_name, name);
_strength = strength;
}
return self;
}
+ (instancetype) strengthRequired
{
return AUTORELEASE([[GSCSStrength alloc] initWithName: @"<Required>" strength: 1000]);
}
+ (instancetype) strengthStrong
{
return AUTORELEASE([[GSCSStrength alloc] initWithName: @"strong" strength: 750]);
}
+ (instancetype) strengthMedium
{
return AUTORELEASE([[GSCSStrength alloc] initWithName: @"medium" strength: 500]);
}
+ (instancetype) strengthWeak
{
return AUTORELEASE([[GSCSStrength alloc] initWithName: @"weak" strength: 250]);
}
- (BOOL) isEqualToStrength: (GSCSStrength *)strength
{
return [_name isEqual: [strength name]] &&
[GSCSFloatComparator isApproxiatelyEqual: _strength
b: [strength strength]];
}
- (BOOL) isEqual: (id)other
{
if (other == nil)
{
return NO;
}
if (other == self)
{
return YES;
}
return [self isEqualToStrength: other];
}
- (BOOL) isRequired
{
return [GSCSFloatComparator
isApproxiatelyEqual: _strength
b: [[GSCSStrength strengthRequired] strength]];
}
- (double) strength
{
return _strength;
}
- (NSString *) name
{
return _name;
}
- (id) copyWithZone: (NSZone *)zone
{
GSCSStrength *copy =
[[[self class] allocWithZone: zone] initWithName: _name
strength: _strength];
return copy;
}
- (void) dealloc
{
RELEASE(_name);
[super dealloc];
}
@end

View file

@ -1,19 +1,19 @@
/* Copyright (C) 2023 Free Software Foundation, Inc.
By: Benjamin Johnson
Date: 19-3-2023
This file is part of the GNUstep Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
@ -25,7 +25,49 @@
#ifndef _GS_CS_VARIABLE_H
#define _GS_CS_VARIABLE_H
enum GSCSVariableType
{
GSCSVariableTypeDummy,
GSCSVariableTypeSlack,
GSCSVaraibleTypeVariable,
GSCSVariableTypeObjective,
GSCSVariableTypeExternal
};
typedef enum GSCSVariableType GSCSVariableType;
@interface GSCSVariable : NSObject
{
GSCSVariableType _type;
NSUInteger _id;
CGFloat _value;
NSString *_name;
}
- (GSCSVariableType) type;
- (NSUInteger) id;
- (CGFloat) value;
- (void) setValue: (CGFloat)value;
- (NSString *) name;
- (BOOL) isExternal;
- (BOOL) isDummy;
- (BOOL) isPivotable;
- (BOOL) isRestricted;
- (instancetype) initWithName: (NSString *)name;
+ (instancetype) variable;
+ (instancetype) variableWithValue: (CGFloat)value;
+ (instancetype) variableWithValue: (CGFloat)value name: (NSString *)name;
@end

View file

@ -1,19 +1,19 @@
/* Copyright (C) 2023 Free Software Foundation, Inc.
By: Benjamin Johnson
Date: 19-3-2023
This file is part of the GNUstep Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
@ -24,4 +24,146 @@
@implementation GSCSVariable
- (instancetype) init
{
self = [super init];
if (self != nil)
{
_type = GSCSVaraibleTypeVariable;
}
return self;
}
- (instancetype) initWithName: (NSString *)name
{
self = [super init];
if (self != nil)
{
ASSIGN(_name, name);
_type = GSCSVaraibleTypeVariable;
}
return self;
}
- (instancetype) initWithName: (NSString *)name type: (GSCSVariableType)type
{
self = [super init];
if (self != nil)
{
ASSIGN(_name, name);
_type = type;
}
return self;
}
+ (instancetype) dummyVariableWithName: (NSString *)name
{
return AUTORELEASE([[GSCSVariable alloc] initWithName: name type: GSCSVariableTypeDummy]);
}
+ (instancetype) slackVariableWithName: (NSString *)name
{
return AUTORELEASE([[GSCSVariable alloc] initWithName: name type: GSCSVariableTypeSlack]);
}
+ (instancetype) objectiveVariableWithName: (NSString *)name
{
return AUTORELEASE([[GSCSVariable alloc] initWithName: name
type: GSCSVariableTypeObjective]);
}
+ (instancetype) variableWithValue: (CGFloat)value
{
return [self variableWithValue: value name: nil];
}
+ (instancetype) variable
{
return [self variableWithValue: 0 name: nil];
}
+ (instancetype) variableWithValue: (CGFloat)value name: (NSString *)name
{
GSCSVariable *variable =
[[GSCSVariable alloc] initWithName: name type: GSCSVariableTypeExternal];
[variable setValue: value];
return AUTORELEASE(variable);
}
- (BOOL) isDummy
{
return _type == GSCSVariableTypeDummy;
}
- (BOOL) isExternal
{
return _type == GSCSVariableTypeExternal;
}
- (BOOL) isPivotable
{
return _type == GSCSVariableTypeSlack;
}
- (BOOL) isRestricted
{
return _type == GSCSVariableTypeExternal || _type == GSCSVariableTypeSlack;
}
- (NSString *) description
{
if (_type == GSCSVariableTypeDummy)
{
return [NSString stringWithFormat: @"[%@:dummy]", _name];
}
else if (_type == GSCSVariableTypeSlack)
{
return [NSString stringWithFormat: @"[%@:slack]", _name];
}
else if (_type == GSCSVariableTypeExternal)
{
return [NSString stringWithFormat: @"[%@:%.02f]", _name, _value];
}
else if (_type == GSCSVariableTypeObjective)
{
return [NSString stringWithFormat: @"[%@:objective]", _name];
}
return [NSString stringWithFormat: @"[%@]", _name];
}
- (GSCSVariableType) type
{
return _type;
}
- (NSUInteger) id
{
return _id;
}
- (CGFloat) value
{
return _value;
}
- (void) setValue: (CGFloat)value
{
_value = value;
}
- (NSString *) name
{
return _name;
}
- (void) dealloc
{
TEST_RELEASE(_name);
[super dealloc];
}
@end